From 33165fe0d5c265c92f2a67fc2b437b567c24e294 Mon Sep 17 00:00:00 2001 From: "liujisi@google.com" Date: Tue, 2 Nov 2010 13:14:58 +0000 Subject: Submit recent changes from internal branch. See CHANGES.txt for more details. --- src/google/protobuf/compiler/code_generator.cc | 11 +- src/google/protobuf/compiler/code_generator.h | 24 +- .../protobuf/compiler/command_line_interface.cc | 82 +- .../protobuf/compiler/command_line_interface.h | 8 +- .../compiler/command_line_interface_unittest.cc | 65 +- .../compiler/cpp/cpp_bootstrap_unittest.cc | 32 +- src/google/protobuf/compiler/cpp/cpp_enum_field.cc | 2 +- src/google/protobuf/compiler/cpp/cpp_file.cc | 1 + src/google/protobuf/compiler/cpp/cpp_generator.cc | 6 +- src/google/protobuf/compiler/cpp/cpp_generator.h | 2 +- src/google/protobuf/compiler/cpp/cpp_message.cc | 265 ++- .../protobuf/compiler/cpp/cpp_message_field.cc | 11 +- .../protobuf/compiler/cpp/cpp_plugin_unittest.cc | 22 +- .../protobuf/compiler/cpp/cpp_primitive_field.cc | 4 +- .../protobuf/compiler/cpp/cpp_string_field.cc | 58 +- .../compiler/cpp/cpp_test_bad_identifiers.proto | 4 + src/google/protobuf/compiler/cpp/cpp_unittest.cc | 46 +- src/google/protobuf/compiler/java/java_enum.cc | 20 +- .../protobuf/compiler/java/java_enum_field.cc | 294 ++- .../protobuf/compiler/java/java_enum_field.h | 24 +- .../protobuf/compiler/java/java_extension.cc | 175 +- src/google/protobuf/compiler/java/java_extension.h | 2 +- src/google/protobuf/compiler/java/java_field.cc | 45 +- src/google/protobuf/compiler/java/java_field.h | 12 +- src/google/protobuf/compiler/java/java_file.cc | 60 +- src/google/protobuf/compiler/java/java_file.h | 6 +- .../protobuf/compiler/java/java_generator.cc | 28 +- src/google/protobuf/compiler/java/java_generator.h | 2 +- src/google/protobuf/compiler/java/java_helpers.cc | 143 +- src/google/protobuf/compiler/java/java_helpers.h | 52 + src/google/protobuf/compiler/java/java_message.cc | 478 ++++- src/google/protobuf/compiler/java/java_message.h | 13 +- .../protobuf/compiler/java/java_message_field.cc | 781 ++++++-- .../protobuf/compiler/java/java_message_field.h | 38 +- .../protobuf/compiler/java/java_plugin_unittest.cc | 19 +- .../protobuf/compiler/java/java_primitive_field.cc | 394 +++- .../protobuf/compiler/java/java_primitive_field.h | 24 +- src/google/protobuf/compiler/java/java_service.cc | 2 +- .../protobuf/compiler/java/java_string_field.cc | 605 ++++++ .../protobuf/compiler/java/java_string_field.h | 120 ++ .../protobuf/compiler/mock_code_generator.cc | 52 +- src/google/protobuf/compiler/mock_code_generator.h | 9 +- src/google/protobuf/compiler/parser.cc | 692 +++++-- src/google/protobuf/compiler/parser.h | 168 +- src/google/protobuf/compiler/parser_unittest.cc | 866 +++++++++ src/google/protobuf/compiler/plugin.cc | 35 +- src/google/protobuf/compiler/plugin.h | 2 +- src/google/protobuf/compiler/plugin.pb.cc | 75 +- src/google/protobuf/compiler/plugin.pb.h | 267 ++- src/google/protobuf/compiler/plugin.proto | 2 +- .../protobuf/compiler/python/python_generator.cc | 26 +- .../protobuf/compiler/python/python_generator.h | 3 +- .../compiler/python/python_plugin_unittest.cc | 14 +- src/google/protobuf/compiler/subprocess.cc | 3 +- src/google/protobuf/compiler/subprocess.h | 3 +- .../protobuf/compiler/zip_output_unittest.sh | 36 +- src/google/protobuf/compiler/zip_writer.cc | 34 +- src/google/protobuf/compiler/zip_writer.h | 34 +- src/google/protobuf/descriptor.cc | 107 +- src/google/protobuf/descriptor.pb.cc | 1394 ++++++++++---- src/google/protobuf/descriptor.pb.h | 2036 ++++++++++++++------ src/google/protobuf/descriptor.proto | 114 +- src/google/protobuf/descriptor_unittest.cc | 102 +- src/google/protobuf/extension_set.cc | 12 + src/google/protobuf/extension_set.h | 4 +- .../protobuf/generated_message_reflection.cc | 3 - src/google/protobuf/generated_message_util.cc | 2 + src/google/protobuf/generated_message_util.h | 9 +- src/google/protobuf/io/coded_stream.cc | 11 +- src/google/protobuf/io/coded_stream.h | 10 +- src/google/protobuf/io/coded_stream_unittest.cc | 28 + src/google/protobuf/io/gzip_stream.cc | 41 +- src/google/protobuf/io/printer.cc | 11 + src/google/protobuf/io/printer.h | 6 +- src/google/protobuf/io/tokenizer.cc | 7 +- src/google/protobuf/io/tokenizer.h | 10 + src/google/protobuf/io/tokenizer_unittest.cc | 95 +- .../protobuf/io/zero_copy_stream_unittest.cc | 141 +- src/google/protobuf/message.h | 1 + src/google/protobuf/repeated_field.cc | 5 +- src/google/protobuf/repeated_field.h | 73 +- src/google/protobuf/repeated_field_unittest.cc | 102 +- src/google/protobuf/text_format.cc | 114 +- src/google/protobuf/text_format.h | 47 +- src/google/protobuf/text_format_unittest.cc | 87 +- src/google/protobuf/unittest.proto | 11 + src/google/protobuf/unittest_custom_options.proto | 91 + .../protobuf/unittest_no_generic_services.proto | 4 +- src/google/protobuf/wire_format_lite_inl.h | 93 +- 89 files changed, 8823 insertions(+), 2249 deletions(-) create mode 100644 src/google/protobuf/compiler/java/java_string_field.cc create mode 100644 src/google/protobuf/compiler/java/java_string_field.h (limited to 'src/google') diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 3413a36a..455c239a 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -42,14 +42,19 @@ namespace protobuf { namespace compiler { CodeGenerator::~CodeGenerator() {} -OutputDirectory::~OutputDirectory() {} +GeneratorContext::~GeneratorContext() {} -io::ZeroCopyOutputStream* OutputDirectory::OpenForInsert( +io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert( const string& filename, const string& insertion_point) { - GOOGLE_LOG(FATAL) << "This OutputDirectory does not support insertion."; + GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion."; return NULL; // make compiler happy } +void GeneratorContext::ListParsedFiles( + vector* output) { + GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles"; +} + // Parses a set of comma-delimited name/value pairs. void ParseGeneratorParameter(const string& text, vector >* output) { diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index ea094cdd..252f68d1 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -53,7 +53,7 @@ namespace compiler { // Defined in this file. class CodeGenerator; -class OutputDirectory; +class GeneratorContext; // The abstract interface to a class which generates code implementing a // particular proto file in a particular language. A number of these may @@ -76,7 +76,7 @@ class LIBPROTOC_EXPORT CodeGenerator { // the problem (e.g. "invalid parameter") and returns false. virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error) const = 0; private: @@ -85,11 +85,12 @@ class LIBPROTOC_EXPORT CodeGenerator { // CodeGenerators generate one or more files in a given directory. This // abstract interface represents the directory to which the CodeGenerator is -// to write. -class LIBPROTOC_EXPORT OutputDirectory { +// to write and other information about the context in which the Generator +// runs. +class LIBPROTOC_EXPORT GeneratorContext { public: - inline OutputDirectory() {} - virtual ~OutputDirectory(); + inline GeneratorContext() {} + virtual ~GeneratorContext(); // Opens the given file, truncating it if it exists, and returns a // ZeroCopyOutputStream that writes to the file. The caller takes ownership @@ -112,10 +113,19 @@ class LIBPROTOC_EXPORT OutputDirectory { virtual io::ZeroCopyOutputStream* OpenForInsert( const string& filename, const string& insertion_point); + // Returns a vector of FileDescriptors for all the files being compiled + // in this run. Useful for languages, such as Go, that treat files + // differently when compiled as a set rather than individually. + virtual void ListParsedFiles(vector* output); + private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext); }; +// The type GeneratorContext was once called OutputDirectory. This typedef +// provides backward compatibility. +typedef GeneratorContext OutputDirectory; + // Several code generators treat the parameter argument as holding a // list of options separated by commas. This helper function parses // a set of comma-delimited name/value pairs: e.g., diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 02c3e0f9..9e9849cf 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -48,6 +48,9 @@ #include #include +#include + +#include #include #include #include @@ -58,12 +61,10 @@ #include #include #include -#include #include #include #include #include -#include namespace google { @@ -182,7 +183,7 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) { class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, public io::ErrorCollector { public: - ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL) + ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL) : format_(format), tree_(tree) {} ~ErrorPrinter() {} @@ -191,8 +192,8 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, const string& message) { // Print full path when running under MSVS - std::string dfile; - if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && + string dfile; + if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && tree_ != NULL && tree_->VirtualFileToDiskFile(filename, &dfile)) { cerr << dfile; @@ -229,12 +230,12 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, // ------------------------------------------------------------------- -// An OutputDirectory implementation that buffers files in memory, then dumps +// A GeneratorContext implementation that buffers files in memory, then dumps // them all to disk on demand. -class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory { +class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { public: - MemoryOutputDirectory(); - ~MemoryOutputDirectory(); + GeneratorContextImpl(const vector& parsed_files); + ~GeneratorContextImpl(); // Write all files in the directory to disk at the given output location, // which must end in a '/'. @@ -248,10 +249,13 @@ class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory { // format, unless one has already been written. void AddJarManifest(); - // implements OutputDirectory -------------------------------------- + // implements GeneratorContext -------------------------------------- io::ZeroCopyOutputStream* Open(const string& filename); io::ZeroCopyOutputStream* OpenForInsert( const string& filename, const string& insertion_point); + void ListParsedFiles(vector* output) { + *output = parsed_files_; + } private: friend class MemoryOutputStream; @@ -259,14 +263,15 @@ class CommandLineInterface::MemoryOutputDirectory : public OutputDirectory { // map instead of hash_map so that files are written in order (good when // writing zips). map files_; + const vector& parsed_files_; bool had_error_; }; class CommandLineInterface::MemoryOutputStream : public io::ZeroCopyOutputStream { public: - MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename); - MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename, + MemoryOutputStream(GeneratorContextImpl* directory, const string& filename); + MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, const string& insertion_point); virtual ~MemoryOutputStream(); @@ -277,7 +282,7 @@ class CommandLineInterface::MemoryOutputStream private: // Where to insert the string when it's done. - MemoryOutputDirectory* directory_; + GeneratorContextImpl* directory_; string filename_; string insertion_point_; @@ -290,14 +295,17 @@ class CommandLineInterface::MemoryOutputStream // ------------------------------------------------------------------- -CommandLineInterface::MemoryOutputDirectory::MemoryOutputDirectory() - : had_error_(false) {} +CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl( + const vector& parsed_files) + : parsed_files_(parsed_files), + had_error_(false) { +} -CommandLineInterface::MemoryOutputDirectory::~MemoryOutputDirectory() { +CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() { STLDeleteValues(&files_); } -bool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk( +bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( const string& prefix) { if (had_error_) { return false; @@ -372,7 +380,7 @@ bool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk( return true; } -bool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip( +bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( const string& filename) { if (had_error_) { return false; @@ -413,7 +421,7 @@ bool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip( return true; } -void CommandLineInterface::MemoryOutputDirectory::AddJarManifest() { +void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { string** map_slot = &files_["META-INF/MANIFEST.MF"]; if (*map_slot == NULL) { *map_slot = new string( @@ -423,13 +431,13 @@ void CommandLineInterface::MemoryOutputDirectory::AddJarManifest() { } } -io::ZeroCopyOutputStream* CommandLineInterface::MemoryOutputDirectory::Open( +io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( const string& filename) { return new MemoryOutputStream(this, filename); } io::ZeroCopyOutputStream* -CommandLineInterface::MemoryOutputDirectory::OpenForInsert( +CommandLineInterface::GeneratorContextImpl::OpenForInsert( const string& filename, const string& insertion_point) { return new MemoryOutputStream(this, filename, insertion_point); } @@ -437,14 +445,14 @@ CommandLineInterface::MemoryOutputDirectory::OpenForInsert( // ------------------------------------------------------------------- CommandLineInterface::MemoryOutputStream::MemoryOutputStream( - MemoryOutputDirectory* directory, const string& filename) + GeneratorContextImpl* directory, const string& filename) : directory_(directory), filename_(filename), inner_(new io::StringOutputStream(&data_)) { } CommandLineInterface::MemoryOutputStream::MemoryOutputStream( - MemoryOutputDirectory* directory, const string& filename, + GeneratorContextImpl* directory, const string& filename, const string& insertion_point) : directory_(directory), filename_(filename), @@ -613,11 +621,11 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } - // We construct a separate OutputDirectory for each output location. Note + // We construct a separate GeneratorContext for each output location. Note // that two code generators may output to the same location, in which case - // they should share a single OutputDirectory (so that OpenForInsert() works). - typedef hash_map OutputDirectoryMap; - OutputDirectoryMap output_directories; + // they should share a single GeneratorContext so that OpenForInsert() works. + typedef hash_map GeneratorContextMap; + GeneratorContextMap output_directories; // Generate output. if (mode_ == MODE_COMPILE) { @@ -627,11 +635,11 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { !HasSuffixString(output_location, ".jar")) { AddTrailingSlash(&output_location); } - MemoryOutputDirectory** map_slot = &output_directories[output_location]; + GeneratorContextImpl** map_slot = &output_directories[output_location]; if (*map_slot == NULL) { // First time we've seen this output location. - *map_slot = new MemoryOutputDirectory; + *map_slot = new GeneratorContextImpl(parsed_files); } if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) { @@ -642,10 +650,10 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } // Write all output to disk. - for (OutputDirectoryMap::iterator iter = output_directories.begin(); + for (GeneratorContextMap::iterator iter = output_directories.begin(); iter != output_directories.end(); ++iter) { const string& location = iter->first; - MemoryOutputDirectory* directory = iter->second; + GeneratorContextImpl* directory = iter->second; if (HasSuffixString(location, "/")) { if (!directory->WriteAllToDisk(location)) { STLDeleteValues(&output_directories); @@ -1107,7 +1115,7 @@ void CommandLineInterface::PrintHelpText() { bool CommandLineInterface::GenerateOutput( const vector& parsed_files, const OutputDirective& output_directive, - OutputDirectory* output_directory) { + GeneratorContext* generator_context) { // Call the generator. string error; if (output_directive.generator == NULL) { @@ -1122,7 +1130,7 @@ bool CommandLineInterface::GenerateOutput( if (!GeneratePluginOutput(parsed_files, plugin_name, output_directive.parameter, - output_directory, &error)) { + generator_context, &error)) { cerr << output_directive.name << ": " << error << endl; return false; } @@ -1131,7 +1139,7 @@ bool CommandLineInterface::GenerateOutput( for (int i = 0; i < parsed_files.size(); i++) { if (!output_directive.generator->Generate( parsed_files[i], output_directive.parameter, - output_directory, &error)) { + generator_context, &error)) { // Generator returned an error. cerr << output_directive.name << ": " << parsed_files[i]->name() << ": " << error << endl; @@ -1147,7 +1155,7 @@ bool CommandLineInterface::GeneratePluginOutput( const vector& parsed_files, const string& plugin_name, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error) { CodeGeneratorRequest request; CodeGeneratorResponse response; @@ -1190,14 +1198,14 @@ bool CommandLineInterface::GeneratePluginOutput( // We reset current_output to NULL first so that the old file is closed // before the new one is opened. current_output.reset(); - current_output.reset(output_directory->OpenForInsert( + current_output.reset(generator_context->OpenForInsert( output_file.name(), output_file.insertion_point())); } else if (!output_file.name().empty()) { // Starting a new file. Open it. // We reset current_output to NULL first so that the old file is closed // before the new one is opened. current_output.reset(); - current_output.reset(output_directory->Open(output_file.name())); + current_output.reset(generator_context->Open(output_file.name())); } else if (current_output == NULL) { *error = strings::Substitute( "$0: First file chunk returned by plugin did not specify a file name.", diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index d25a50e6..0b507d80 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -56,7 +56,7 @@ template class RepeatedPtrField; // repeated_field.h namespace compiler { class CodeGenerator; // code_generator.h -class OutputDirectory; // code_generator.h +class GeneratorContext; // code_generator.h class DiskSourceTree; // importer.h // This class implements the command-line interface to the protocol compiler. @@ -174,7 +174,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // ----------------------------------------------------------------- class ErrorPrinter; - class MemoryOutputDirectory; + class GeneratorContextImpl; class MemoryOutputStream; // Clear state from previous Run(). @@ -212,11 +212,11 @@ class LIBPROTOC_EXPORT CommandLineInterface { struct OutputDirective; // see below bool GenerateOutput(const vector& parsed_files, const OutputDirective& output_directive, - OutputDirectory* output_directory); + GeneratorContext* generator_context); bool GeneratePluginOutput(const vector& parsed_files, const string& plugin_name, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error); // Implements --encode and --decode. diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index bdf37ad1..6634b676 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -143,6 +143,10 @@ class CommandLineInterfaceTest : public testing::Test { const string& proto_name, const string& message_name, const string& output_directory); + void ExpectGeneratedWithMultipleInputs(const string& generator_name, + const string& all_proto_names, + const string& proto_name, + const string& message_name); void ExpectGeneratedWithInsertions(const string& generator_name, const string& parameter, const string& insertions, @@ -190,7 +194,7 @@ class CommandLineInterfaceTest::NullCodeGenerator : public CodeGenerator { // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { called_ = true; parameter_ = parameter; @@ -251,7 +255,6 @@ void CommandLineInterfaceTest::Run(const string& command) { if (!disallow_plugins_) { cli_.AllowPlugins("prefix-"); - const char* possible_paths[] = { // When building with shared libraries, libtool hides the real executable // in .libs and puts a fake wrapper in the current directory. @@ -353,7 +356,8 @@ void CommandLineInterfaceTest::ExpectGenerated( const string& proto_name, const string& message_name) { MockCodeGenerator::ExpectGenerated( - generator_name, parameter, "", proto_name, message_name, temp_directory_); + generator_name, parameter, "", proto_name, message_name, proto_name, + temp_directory_); } void CommandLineInterfaceTest::ExpectGenerated( @@ -363,10 +367,21 @@ void CommandLineInterfaceTest::ExpectGenerated( const string& message_name, const string& output_directory) { MockCodeGenerator::ExpectGenerated( - generator_name, parameter, "", proto_name, message_name, + generator_name, parameter, "", proto_name, message_name, proto_name, temp_directory_ + "/" + output_directory); } +void CommandLineInterfaceTest::ExpectGeneratedWithMultipleInputs( + const string& generator_name, + const string& all_proto_names, + const string& proto_name, + const string& message_name) { + MockCodeGenerator::ExpectGenerated( + generator_name, "", "", proto_name, message_name, + all_proto_names, + temp_directory_); +} + void CommandLineInterfaceTest::ExpectGeneratedWithInsertions( const string& generator_name, const string& parameter, @@ -375,7 +390,7 @@ void CommandLineInterfaceTest::ExpectGeneratedWithInsertions( const string& message_name) { MockCodeGenerator::ExpectGenerated( generator_name, parameter, insertions, proto_name, message_name, - temp_directory_); + proto_name, temp_directory_); } void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled( @@ -455,8 +470,44 @@ TEST_F(CommandLineInterfaceTest, MultipleInputs) { "--proto_path=$tmpdir foo.proto bar.proto"); ExpectNoErrors(); - ExpectGenerated("test_generator", "", "foo.proto", "Foo"); - ExpectGenerated("test_generator", "", "bar.proto", "Bar"); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "bar.proto", "Bar"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "bar.proto", "Bar"); +} + +TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) { + // Test parsing multiple input files with an import of a separate file. + + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"baz.proto\";\n" + "message Bar {\n" + " optional Baz a = 1;\n" + "}\n"); + CreateTempFile("baz.proto", + "syntax = \"proto2\";\n" + "message Baz {}\n"); + + Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir " + "--proto_path=$tmpdir foo.proto bar.proto"); + + ExpectNoErrors(); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto", + "bar.proto", "Bar"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "foo.proto", "Foo"); + ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto", + "bar.proto", "Bar"); } TEST_F(CommandLineInterfaceTest, CreateDirectory) { diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc index 30b1d2bf..bcfa5020 100644 --- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -79,10 +79,10 @@ class MockErrorCollector : public MultiFileErrorCollector { } }; -class MockOutputDirectory : public OutputDirectory { +class MockGeneratorContext : public GeneratorContext { public: - MockOutputDirectory() {} - ~MockOutputDirectory() { + MockGeneratorContext() {} + ~MockGeneratorContext() { STLDeleteValues(&files_); } @@ -102,7 +102,7 @@ class MockOutputDirectory : public OutputDirectory { "to your CL."; } - // implements OutputDirectory -------------------------------------- + // implements GeneratorContext -------------------------------------- virtual io::ZeroCopyOutputStream* Open(const string& filename) { string** map_slot = &files_[filename]; @@ -130,24 +130,24 @@ TEST(BootstrapTest, GeneratedDescriptorMatches) { ASSERT_TRUE(plugin_proto_file != NULL); CppGenerator generator; - MockOutputDirectory output_directory; + MockGeneratorContext context; string error; string parameter; parameter = "dllexport_decl=LIBPROTOBUF_EXPORT"; ASSERT_TRUE(generator.Generate(proto_file, parameter, - &output_directory, &error)); + &context, &error)); parameter = "dllexport_decl=LIBPROTOC_EXPORT"; ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter, - &output_directory, &error)); - - output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.h", - "google/protobuf/descriptor.pb.h"); - output_directory.ExpectFileMatches("google/protobuf/descriptor.pb.cc", - "google/protobuf/descriptor.pb.cc"); - output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h", - "google/protobuf/compiler/plugin.pb.h"); - output_directory.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc", - "google/protobuf/compiler/plugin.pb.cc"); + &context, &error)); + + context.ExpectFileMatches("google/protobuf/descriptor.pb.h", + "google/protobuf/descriptor.pb.h"); + context.ExpectFileMatches("google/protobuf/descriptor.pb.cc", + "google/protobuf/descriptor.pb.cc"); + context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.h", + "google/protobuf/compiler/plugin.pb.h"); + context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc", + "google/protobuf/compiler/plugin.pb.cc"); } } // namespace diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 91ce493a..a369f417 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -85,7 +85,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "}\n" "inline void $classname$::set_$name$($type$ value) {\n" " GOOGLE_DCHECK($type$_IsValid(value));\n" - " _set_bit($index$);\n" + " set_has_$name$();\n" " $name$_ = value;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index e31cb425..22d6fdba 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -283,6 +283,7 @@ void FileGenerator::GenerateSource(io::Printer* printer) { printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "\n" + // The generated code calls accessors that might be deprecated. We don't // want the compiler to warn in generated code. "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index d67d3504..bb84e2ab 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -53,7 +53,7 @@ CppGenerator::~CppGenerator() {} bool CppGenerator::Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error) const { vector > options; ParseGeneratorParameter(parameter, &options); @@ -100,7 +100,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, // Generate header. { scoped_ptr output( - output_directory->Open(basename + ".h")); + generator_context->Open(basename + ".h")); io::Printer printer(output.get(), '$'); file_generator.GenerateHeader(&printer); } @@ -108,7 +108,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, // Generate cc file. { scoped_ptr output( - output_directory->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_generator.h b/src/google/protobuf/compiler/cpp/cpp_generator.h index f52e886a..a90e84d7 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.h +++ b/src/google/protobuf/compiler/cpp/cpp_generator.h @@ -57,7 +57,7 @@ class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator { // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error) const; private: diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index cbdcce8f..c4e6fb2c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -143,6 +144,137 @@ static bool HasRequiredFields(const Descriptor* type) { return HasRequiredFields(type, &already_seen); } +// This returns an estimate of the compiler's alignment for the field. This +// can't guarantee to be correct because the generated code could be compiled on +// different systems with different alignment rules. The estimates below assume +// 64-bit pointers. +int EstimateAlignmentSize(const FieldDescriptor* field) { + if (field == NULL) return 0; + if (field->is_repeated()) return 8; + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: + return 1; + + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_FLOAT: + return 4; + + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + return 8; + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; // Make compiler happy. +} + +// FieldGroup is just a helper for OptimizePadding below. It holds a vector of +// fields that are grouped together because they have compatible alignment, and +// a preferred location in the final field ordering. +class FieldGroup { + public: + FieldGroup() + : preferred_location_(0) {} + + // A group with a single field. + FieldGroup(float preferred_location, const FieldDescriptor* field) + : preferred_location_(preferred_location), + fields_(1, field) {} + + // Append the fields in 'other' to this group. + void Append(const FieldGroup& other) { + if (other.fields_.empty()) { + return; + } + // Preferred location is the average among all the fields, so we weight by + // the number of fields on each FieldGroup object. + preferred_location_ = + (preferred_location_ * fields_.size() + + (other.preferred_location_ * other.fields_.size())) / + (fields_.size() + other.fields_.size()); + fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end()); + } + + void SetPreferredLocation(float location) { preferred_location_ = location; } + const vector& fields() const { return fields_; } + + // FieldGroup objects sort by their preferred location. + bool operator<(const FieldGroup& other) const { + return preferred_location_ < other.preferred_location_; + } + + private: + // "preferred_location_" is an estimate of where this group should go in the + // final list of fields. We compute this by taking the average index of each + // field in this group in the original ordering of fields. This is very + // approximate, but should put this group close to where its member fields + // originally went. + float preferred_location_; + vector fields_; + // We rely on the default copy constructor and operator= so this type can be + // used in a vector. +}; + +// Reorder 'fields' so that if the fields are output into a c++ class in the new +// order, the alignment padding is minimized. We try to do this while keeping +// each field as close as possible to its original position so that we don't +// reduce cache locality much for function that access each field in order. +void OptimizePadding(vector* fields) { + // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes. + vector aligned_to_1, aligned_to_4, aligned_to_8; + for (int i = 0; i < fields->size(); ++i) { + switch (EstimateAlignmentSize((*fields)[i])) { + case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break; + case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break; + case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break; + default: + GOOGLE_LOG(FATAL) << "Unknown alignment size."; + } + } + + // Now group fields aligned to 1 byte into sets of 4, and treat those like a + // single field aligned to 4 bytes. + for (int i = 0; i < aligned_to_1.size(); i += 4) { + FieldGroup field_group; + for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) { + field_group.Append(aligned_to_1[j]); + } + 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()); + + // 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. + for (int i = 0; i < aligned_to_4.size(); i += 2) { + FieldGroup field_group; + for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) { + field_group.Append(aligned_to_4[j]); + } + if (i == aligned_to_4.size() - 1) { + // Move incomplete 4-byte block to the end. + field_group.SetPreferredLocation(fields->size() + 1); + } + 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()); + + // Now pull out all the FieldDescriptors in order. + fields->clear(); + for (int i = 0; i < aligned_to_8.size(); ++i) { + fields->insert(fields->end(), + aligned_to_8[i].fields().begin(), + aligned_to_8[i].fields().end()); + } +} + } // =================================================================== @@ -264,10 +396,20 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { "}\n"); } else { // Singular field. + char buffer[kFastToBufferSize]; + vars["has_array_index"] = SimpleItoa(field->index() / 32); + vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer); printer->Print(vars, "inline bool $classname$::has_$name$() const {\n" - " return _has_bit($index$);\n" - "}\n"); + " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" + "}\n" + "inline void $classname$::set_has_$name$() {\n" + " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" + "}\n" + "inline void $classname$::clear_has_$name$() {\n" + " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" + "}\n" + ); } // Generate clear_$name$() @@ -279,7 +421,8 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { printer->Outdent(); if (!field->is_repeated()) { - printer->Print(vars, " _clear_bit($index$);\n"); + printer->Print(vars, + " clear_has_$name$();\n"); } printer->Print("}\n"); @@ -444,28 +587,74 @@ GenerateClassDefinition(io::Printer* printer) { "// @@protoc_insertion_point(class_scope:$full_name$)\n", "full_name", descriptor_->full_name()); - // Generate private members for fields. + // Generate private members. printer->Outdent(); printer->Print(" private:\n"); printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->is_repeated()) { + 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))); + } + } + printer->Print("\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 + // alignment. + // (3) members assumed to align to 4 bytes. + + // Members assumed to align to 8 bytes: + if (descriptor_->extension_range_count() > 0) { printer->Print( - "::google::protobuf::internal::ExtensionSet _extensions_;\n"); + "::google::protobuf::internal::ExtensionSet _extensions_;\n" + "\n"); } if (HasUnknownFields(descriptor_->file())) { printer->Print( - "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"); + "::google::protobuf::UnknownFieldSet _unknown_fields_;\n" + "\n"); + } + + // Field members: + + vector fields; + for (int i = 0; i < descriptor_->field_count(); i++) { + fields.push_back(descriptor_->field(i)); + } + OptimizePadding(&fields); + for (int i = 0; i < fields.size(); ++i) { + field_generators_.get(fields[i]).GeneratePrivateMembers(printer); } + // Members assumed to align to 4 bytes: + // TODO(kenton): Make _cached_size_ an atomic when C++ supports it. printer->Print( - "mutable int _cached_size_;\n" - "\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GeneratePrivateMembers(printer); + "\n" + "mutable int _cached_size_;\n"); + + // Generate _has_bits_. + if (descriptor_->field_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" + "\n"); } // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as @@ -484,32 +673,7 @@ GenerateClassDefinition(io::Printer* printer) { GlobalAssignDescriptorsName(descriptor_->file()->name()), "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name())); - // Generate offsets and _has_bits_ boilerplate. - if (descriptor_->field_count() > 0) { - printer->Print(vars, - "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\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"); - } - printer->Print( - "\n" - "// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?\n" - "inline bool _has_bit(int index) const {\n" - " return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;\n" - "}\n" - "inline void _set_bit(int index) {\n" - " _has_bits_[index / 32] |= (1u << (index % 32));\n" - "}\n" - "inline void _clear_bit(int index) {\n" - " _has_bits_[index / 32] &= ~(1u << (index % 32));\n" - "}\n" - "\n" "void InitAsDefaultInstance();\n" "static $classname$* default_instance_;\n", "classname", classname_); @@ -961,9 +1125,6 @@ GenerateClear(io::Printer* printer) { const FieldDescriptor* field = descriptor_->field(i); if (!field->is_repeated()) { - map vars; - vars["index"] = SimpleItoa(field->index()); - // 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 @@ -975,8 +1136,9 @@ GenerateClear(io::Printer* printer) { printer->Outdent(); printer->Print("}\n"); } - printer->Print(vars, - "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n"); + printer->Print( + "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n", + "index", SimpleItoa(field->index())); printer->Indent(); } last_index = i; @@ -989,7 +1151,9 @@ GenerateClear(io::Printer* printer) { field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; if (should_check_bit) { - printer->Print(vars, "if (_has_bit($index$)) {\n"); + printer->Print( + "if (has_$name$()) {\n", + "name", FieldName(field)); printer->Indent(); } @@ -1129,24 +1293,23 @@ GenerateMergeFrom(io::Printer* printer) { const FieldDescriptor* field = descriptor_->field(i); if (!field->is_repeated()) { - map vars; - vars["index"] = SimpleItoa(field->index()); - // See above in GenerateClear for an explanation of this. if (i / 8 != last_index / 8 || last_index < 0) { if (last_index >= 0) { printer->Outdent(); printer->Print("}\n"); } - printer->Print(vars, - "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n"); + printer->Print( + "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n", + "index", SimpleItoa(field->index())); printer->Indent(); } last_index = i; - printer->Print(vars, - "if (from._has_bit($index$)) {\n"); + printer->Print( + "if (from.has_$name$()) {\n", + "name", FieldName(field)); printer->Indent(); field_generators_.get(field).GenerateMergingCode(printer); @@ -1423,8 +1586,8 @@ void MessageGenerator::GenerateSerializeOneField( if (!field->is_repeated()) { printer->Print( - "if (_has_bit($index$)) {\n", - "index", SimpleItoa(field->index())); + "if (has_$name$()) {\n", + "name", FieldName(field)); printer->Indent(); } diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index c04bdc66..23e75b87 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -75,7 +75,8 @@ void MessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, "inline const $type$& $name$() const$deprecation$;\n" - "inline $type$* mutable_$name$()$deprecation$;\n"); + "inline $type$* mutable_$name$()$deprecation$;\n" + "inline $type$* release_$name$()$deprecation$;\n"); } void MessageFieldGenerator:: @@ -85,9 +86,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n" "}\n" "inline $type$* $classname$::mutable_$name$() {\n" - " _set_bit($index$);\n" + " set_has_$name$();\n" " if ($name$_ == NULL) $name$_ = new $type$;\n" " return $name$_;\n" + "}\n" + "inline $type$* $classname$::release_$name$() {\n" + " clear_has_$name$();\n" + " $type$* temp = $name$_;\n" + " $name$_ = NULL;\n" + " return temp;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc index 440b7166..5c4aa4fb 100644 --- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc @@ -56,24 +56,24 @@ class TestGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { - TryInsert("test.pb.h", "includes", output_directory); - TryInsert("test.pb.h", "namespace_scope", output_directory); - TryInsert("test.pb.h", "global_scope", output_directory); - TryInsert("test.pb.h", "class_scope:foo.Bar", output_directory); - TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", output_directory); + TryInsert("test.pb.h", "includes", context); + TryInsert("test.pb.h", "namespace_scope", context); + TryInsert("test.pb.h", "global_scope", context); + TryInsert("test.pb.h", "class_scope:foo.Bar", context); + TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", context); - TryInsert("test.pb.cc", "includes", output_directory); - TryInsert("test.pb.cc", "namespace_scope", output_directory); - TryInsert("test.pb.cc", "global_scope", output_directory); + TryInsert("test.pb.cc", "includes", context); + TryInsert("test.pb.cc", "namespace_scope", context); + TryInsert("test.pb.cc", "global_scope", context); return true; } void TryInsert(const string& filename, const string& insertion_point, - OutputDirectory* output_directory) const { + GeneratorContext* context) const { scoped_ptr output( - output_directory->OpenForInsert(filename, insertion_point)); + context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index a69c48b5..5e8df0f4 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -125,7 +125,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return $name$_;\n" "}\n" "inline void $classname$::set_$name$($type$ value) {\n" - " _set_bit($index$);\n" + " set_has_$name$();\n" " $name$_ = value;\n" "}\n"); } @@ -156,7 +156,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" " $type$, $wire_format_field_type$>(\n" " input, &$name$_)));\n" - "_set_bit($index$);\n"); + "set_has_$name$();\n"); } void PrimitiveFieldGenerator:: diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index ea6809a9..67d7eae6 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -50,6 +50,9 @@ void SetStringVariables(const FieldDescriptor* descriptor, SetCommonFieldVariables(descriptor, variables); (*variables)["default"] = "\"" + CEscape(descriptor->default_value_string()) + "\""; + (*variables)["default_variable"] = descriptor->default_value_string().empty() + ? "::google::protobuf::internal::kEmptyString" + : "_default_" + FieldName(descriptor) + "_"; (*variables)["pointer_type"] = descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; } @@ -68,9 +71,10 @@ StringFieldGenerator::~StringFieldGenerator() {} void StringFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::std::string* $name$_;\n" - "static const ::std::string _default_$name$_;\n"); + printer->Print(variables_, "::std::string* $name$_;\n"); + if (!descriptor_->default_value_string().empty()) { + printer->Print(variables_, "static const ::std::string $default_variable$;\n"); + } } void StringFieldGenerator:: @@ -105,7 +109,8 @@ GenerateAccessorDeclarations(io::Printer* printer) const { "inline void set_$name$(const char* value)$deprecation$;\n" "inline void set_$name$(const $pointer_type$* value, size_t size)" "$deprecation$;\n" - "inline ::std::string* mutable_$name$()$deprecation$;\n"); + "inline ::std::string* mutable_$name$()$deprecation$;\n" + "inline ::std::string* release_$name$()$deprecation$;\n"); if (descriptor_->options().ctype() != FieldOptions::STRING) { printer->Outdent(); @@ -121,51 +126,58 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return *$name$_;\n" "}\n" "inline void $classname$::set_$name$(const ::std::string& value) {\n" - " _set_bit($index$);\n" - " if ($name$_ == &_default_$name$_) {\n" + " set_has_$name$();\n" + " if ($name$_ == &$default_variable$) {\n" " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(value);\n" "}\n" "inline void $classname$::set_$name$(const char* value) {\n" - " _set_bit($index$);\n" - " if ($name$_ == &_default_$name$_) {\n" + " set_has_$name$();\n" + " if ($name$_ == &$default_variable$) {\n" " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(value);\n" "}\n" "inline " "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n" - " _set_bit($index$);\n" - " if ($name$_ == &_default_$name$_) {\n" + " set_has_$name$();\n" + " if ($name$_ == &$default_variable$) {\n" " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(reinterpret_cast(value), size);\n" "}\n" "inline ::std::string* $classname$::mutable_$name$() {\n" - " _set_bit($index$);\n" - " if ($name$_ == &_default_$name$_) {\n"); + " set_has_$name$();\n" + " if ($name$_ == &$default_variable$) {\n"); if (descriptor_->default_value_string().empty()) { printer->Print(variables_, " $name$_ = new ::std::string;\n"); } else { printer->Print(variables_, - " $name$_ = new ::std::string(_default_$name$_);\n"); + " $name$_ = new ::std::string($default_variable$);\n"); } printer->Print(variables_, " }\n" " return $name$_;\n" + "}\n" + "inline ::std::string* $classname$::release_$name$() {\n" + " clear_has_$name$();\n" + " if ($name$_ == &$default_variable$) {\n" + " return NULL;\n" + " } else {\n" + " ::std::string* temp = $name$_;\n" + " $name$_ = const_cast< ::std::string*>(&$default_variable$);\n" + " return temp;\n" + " }\n" "}\n"); } void StringFieldGenerator:: GenerateNonInlineAccessorDefinitions(io::Printer* printer) const { - if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "const ::std::string $classname$::_default_$name$_;\n"); - } else { + if (!descriptor_->default_value_string().empty()) { printer->Print(variables_, - "const ::std::string $classname$::_default_$name$_($default$);\n"); + "const ::std::string $classname$::$default_variable$($default$);\n"); } } @@ -173,13 +185,13 @@ void StringFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { if (descriptor_->default_value_string().empty()) { printer->Print(variables_, - "if ($name$_ != &_default_$name$_) {\n" + "if ($name$_ != &$default_variable$) {\n" " $name$_->clear();\n" "}\n"); } else { printer->Print(variables_, - "if ($name$_ != &_default_$name$_) {\n" - " $name$_->assign(_default_$name$_);\n" + "if ($name$_ != &$default_variable$) {\n" + " $name$_->assign($default_variable$);\n" "}\n"); } } @@ -197,13 +209,13 @@ GenerateSwappingCode(io::Printer* printer) const { void StringFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { printer->Print(variables_, - "$name$_ = const_cast< ::std::string*>(&_default_$name$_);\n"); + "$name$_ = const_cast< ::std::string*>(&$default_variable$);\n"); } void StringFieldGenerator:: GenerateDestructorCode(io::Printer* printer) const { printer->Print(variables_, - "if ($name$_ != &_default_$name$_) {\n" + "if ($name$_ != &$default_variable$) {\n" " delete $name$_;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto index 79971a95..54d830fc 100644 --- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto +++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -36,6 +36,10 @@ // though the same identifiers are used internally by the C++ code generator. +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added + // We don't put this in a package within proto2 because we need to make sure // that the generated code doesn't depend on being in the proto2 namespace. package protobuf_unittest; diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index a7e852de..41ba5e43 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -195,6 +195,48 @@ TEST(GeneratedMessageTest, MutableStringDefault) { EXPECT_EQ("hello", *message.mutable_default_string()); } +TEST(GeneratedMessageTest, ReleaseString) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + unittest::TestAllTypes message; + + EXPECT_EQ(NULL, message.release_default_string()); + EXPECT_FALSE(message.has_default_string()); + EXPECT_EQ("hello", message.default_string()); + + message.set_default_string("blah"); + EXPECT_TRUE(message.has_default_string()); + string* 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()); + EXPECT_EQ("hello", message.default_string()); +} + +TEST(GeneratedMessageTest, ReleaseMessage) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + unittest::TestAllTypes message; + + EXPECT_EQ(NULL, message.release_optional_nested_message()); + EXPECT_FALSE(message.has_optional_nested_message()); + + message.mutable_optional_nested_message()->set_bb(1); + unittest::TestAllTypes::NestedMessage* 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()); +} + TEST(GeneratedMessageTest, Clear) { // Set every field to a unique value, clear the message, then check that // it is cleared. @@ -282,6 +324,7 @@ TEST(GeneratedMessageTest, CopyFrom) { TestUtil::ExpectAllFieldsSet(message2); } + TEST(GeneratedMessageTest, SwapWithEmpty) { unittest::TestAllTypes message1, message2; TestUtil::SetAllFields(&message1); @@ -376,7 +419,7 @@ TEST(GeneratedMessageTest, CopyAssignmentOperator) { TestUtil::ExpectAllFieldsSet(message2); // Make sure that self-assignment does something sane. - message2 = message2; + message2.operator=(message2); TestUtil::ExpectAllFieldsSet(message2); } @@ -718,6 +761,7 @@ TEST(GeneratedMessageTest, TestSpaceUsed) { #endif // !PROTOBUF_TEST_NO_DESCRIPTORS + TEST(GeneratedMessageTest, FieldConstantValues) { unittest::TestRequired message; EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1); diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index e796587f..9d7bcab6 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -104,6 +104,15 @@ void EnumGenerator::Generate(io::Printer* printer) { "public static final $classname$ $name$ = $canonical_name$;\n"); } + for (int i = 0; i < descriptor_->value_count(); i++) { + map vars; + vars["name"] = descriptor_->value(i)->name(); + vars["number"] = SimpleItoa(descriptor_->value(i)->number()); + printer->Print(vars, + "public static final int $name$_VALUE = $number$;\n"); + } + printer->Print("\n"); + // ----------------------------------------------------------------- printer->Print( @@ -219,17 +228,6 @@ void EnumGenerator::Generate(io::Printer* printer) { " this.value = value;\n" "}\n"); - if (HasDescriptorMethods(descriptor_)) { - // Force the static initialization code for the file to run, since it may - // initialize static variables declared in this class. - printer->Print( - "\n" - "static {\n" - " $file$.getDescriptor();\n" - "}\n", - "file", ClassName(descriptor_->file())); - } - printer->Print( "\n" "// @@protoc_insertion_point(enum_scope:$full_name$)\n", diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index af6b1cd2..72caa10b 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -52,17 +52,44 @@ 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, 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); (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + // 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)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex); + + // For repated 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); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); } } // namespace @@ -70,51 +97,87 @@ void SetEnumVariables(const FieldDescriptor* descriptor, // =================================================================== EnumFieldGenerator:: -EnumFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetEnumVariables(descriptor, &variables_); +EnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_); } EnumFieldGenerator::~EnumFieldGenerator() {} +int EnumFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int EnumFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void EnumFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n" + "$deprecation$$type$ get$capitalized_name$();\n"); +} + void EnumFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private boolean has$capitalized_name$;\n" "private $type$ $name$_;\n" - "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" - "public $type$ get$capitalized_name$() { return $name$_; }\n"); + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n" + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); } void EnumFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, - "public boolean has$capitalized_name$() {\n" - " return result.has$capitalized_name$();\n" + "private $type$ $name$_ = $default$;\n" + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" "}\n" - "public $type$ get$capitalized_name$() {\n" - " return result.get$capitalized_name$();\n" + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" "}\n" - "public Builder set$capitalized_name$($type$ value) {\n" + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" " if (value == null) {\n" " throw new NullPointerException();\n" " }\n" - " result.has$capitalized_name$ = true;\n" - " result.$name$_ = value;\n" + " $set_has_field_bit_builder$;\n" + " $name$_ = value;\n" + " $on_changed$\n" " return this;\n" "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.has$capitalized_name$ = false;\n" - " result.$name$_ = $default$;\n" + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $clear_has_field_bit_builder$;\n" + " $name$_ = $default$;\n" + " $on_changed$\n" " return this;\n" "}\n"); } +void EnumFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for enums +} + void EnumFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $default$;\n"); } +void EnumFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$;\n"); +} + void EnumFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print(variables_, @@ -125,7 +188,11 @@ GenerateMergingCode(io::Printer* printer) const { void EnumFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - // Nothing to do here for enum types. + 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:: @@ -143,27 +210,42 @@ GenerateParsingCode(io::Printer* printer) const { "if (value != null) {\n"); } printer->Print(variables_, - " set$capitalized_name$(value);\n" + " $set_has_field_bit_builder$;\n" + " $name$_ = value;\n" "}\n"); } void EnumFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " output.writeEnum($number$, get$capitalized_name$().getNumber());\n" + "if ($get_has_field_bit_message$) {\n" + " output.writeEnum($number$, $name$_.getNumber());\n" "}\n"); } void EnumFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" + "if ($get_has_field_bit_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSize($number$, get$capitalized_name$().getNumber());\n" + " .computeEnumSize($number$, $name$_.getNumber());\n" "}\n"); } +void EnumFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result &&\n" + " (get$capitalized_name$() == other.get$capitalized_name$());\n"); +} + +void EnumFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + hashEnum(get$capitalized_name$());\n"); +} + string EnumFieldGenerator::GetBoxedType() const { return ClassName(descriptor_->enum_type()); } @@ -171,23 +253,43 @@ string EnumFieldGenerator::GetBoxedType() const { // =================================================================== RepeatedEnumFieldGenerator:: -RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetEnumVariables(descriptor, &variables_); +RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_); } RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} +int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedEnumFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + printer->Print(variables_, + "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n" + "$deprecation$int get$capitalized_name$Count();\n" + "$deprecation$$type$ get$capitalized_name$(int index);\n"); +} + void RepeatedEnumFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private java.util.List<$type$> $name$_ =\n" - " java.util.Collections.emptyList();\n" - "public java.util.List<$type$> get$capitalized_name$List() {\n" + "private java.util.List<$type$> $name$_;\n" + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" " return $name$_;\n" // note: unmodifiable list "}\n" - "public int get$capitalized_name$Count() { return $name$_.size(); }\n" - "public $type$ get$capitalized_name$(int index) {\n" + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n" + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" " return $name$_.get(index);\n" "}\n"); @@ -201,73 +303,119 @@ GenerateMembers(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, + // One field is the list and the other field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + "private java.util.List<$type$> $name$_ =\n" + " java.util.Collections.emptyList();\n" + + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n" + // Note: We return an unmodifiable list because otherwise the caller // could hold on to the returned list and modify it after the message // has been built, thus mutating the message which is supposed to be // immutable. - "public java.util.List<$type$> get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList(result.$name$_);\n" + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" "}\n" - "public int get$capitalized_name$Count() {\n" - " return result.get$capitalized_name$Count();\n" + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" "}\n" - "public $type$ get$capitalized_name$(int index) {\n" - " return result.get$capitalized_name$(index);\n" + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" "}\n" - "public Builder set$capitalized_name$(int index, $type$ value) {\n" + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value) {\n" " if (value == null) {\n" " throw new NullPointerException();\n" " }\n" - " result.$name$_.set(index, value);\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" " return this;\n" "}\n" - "public Builder add$capitalized_name$($type$ value) {\n" + "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" " if (value == null) {\n" " throw new NullPointerException();\n" " }\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" - " }\n" - " result.$name$_.add(value);\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" " return this;\n" "}\n" - "public Builder addAll$capitalized_name$(\n" + "$deprecation$public Builder addAll$capitalized_name$(\n" " java.lang.Iterable values) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" - " }\n" - " super.addAll(values, result.$name$_);\n" + " ensure$capitalized_name$IsMutable();\n" + " super.addAll(values, $name$_);\n" + " $on_changed$\n" " return this;\n" "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.$name$_ = java.util.Collections.emptyList();\n" + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $name$_ = java.util.Collections.emptyList();\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" " return this;\n" "}\n"); } +void RepeatedEnumFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for enums +} + void RepeatedEnumFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - // Initialized inline. + printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); +} + +void RepeatedEnumFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n"); } void RepeatedEnumFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. printer->Print(variables_, "if (!other.$name$_.isEmpty()) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" " }\n" - " result.$name$_.addAll(other.$name$_);\n" + " $on_changed$\n" "}\n"); } void RepeatedEnumFieldGenerator:: 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 (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n" - " result.$name$_ =\n" - " java.util.Collections.unmodifiableList(result.$name$_);\n" - "}\n"); + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); } void RepeatedEnumFieldGenerator:: @@ -316,13 +464,13 @@ GenerateSerializationCode(io::Printer* printer) const { " output.writeRawVarint32($tag$);\n" " output.writeRawVarint32($name$MemoizedSerializedSize);\n" "}\n" - "for ($type$ element : get$capitalized_name$List()) {\n" - " output.writeEnumNoTag(element.getNumber());\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeEnumNoTag($name$_.get(i).getNumber());\n" "}\n"); } else { printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" - " output.writeEnum($number$, element.getNumber());\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeEnum($number$, $name$_.get(i).getNumber());\n" "}\n"); } } @@ -335,9 +483,9 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Indent(); printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" " dataSize += com.google.protobuf.CodedOutputStream\n" - " .computeEnumSizeNoTag(element.getNumber());\n" + " .computeEnumSizeNoTag($name$_.get(i).getNumber());\n" "}\n"); printer->Print( "size += dataSize;\n"); @@ -350,7 +498,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "}"); } else { printer->Print(variables_, - "size += $tag_size$ * get$capitalized_name$List().size();\n"); + "size += $tag_size$ * $name$_.size();\n"); } // cache the data size for packed fields. @@ -363,6 +511,22 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print("}\n"); } +void RepeatedEnumFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedEnumFieldGenerator:: +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" + "}\n"); +} + string RepeatedEnumFieldGenerator::GetBoxedType() const { return ClassName(descriptor_->enum_type()); } diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h index c54a0faf..0cad6be0 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.h +++ b/src/google/protobuf/compiler/java/java_enum_field.h @@ -46,49 +46,69 @@ namespace java { class EnumFieldGenerator : public FieldGenerator { public: - explicit EnumFieldGenerator(const FieldDescriptor* descriptor); + explicit EnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); ~EnumFieldGenerator(); // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; private: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); }; class RepeatedEnumFieldGenerator : public FieldGenerator { public: - explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor); + explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); ~RepeatedEnumFieldGenerator(); // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingCodeFromPacked(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; private: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); }; diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc index 903b0a9b..9b147c77 100644 --- a/src/google/protobuf/compiler/java/java_extension.cc +++ b/src/google/protobuf/compiler/java/java_extension.cc @@ -86,108 +86,123 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) ExtensionGenerator::~ExtensionGenerator() {} -void ExtensionGenerator::Generate(io::Printer* printer) { - map vars; - vars["name"] = UnderscoresToCamelCase(descriptor_); - vars["containing_type"] = ClassName(descriptor_->containing_type()); - vars["number"] = SimpleItoa(descriptor_->number()); - vars["constant_name"] = FieldConstantName(descriptor_); - vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite"; +// Initializes the vars referenced in the generated code templates. +void InitTemplateVars(const FieldDescriptor* descriptor, + const string& scope, + map* vars_pointer) { + map &vars = *vars_pointer; + vars["scope"] = scope; + vars["name"] = UnderscoresToCamelCase(descriptor); + vars["containing_type"] = ClassName(descriptor->containing_type()); + 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["packed"] = descriptor->options().packed() ? "true" : "false"; + vars["enum_map"] = "null"; + vars["prototype"] = "null"; - JavaType java_type = GetJavaType(descriptor_); + JavaType java_type = GetJavaType(descriptor); string singular_type; switch (java_type) { case JAVATYPE_MESSAGE: - vars["type"] = ClassName(descriptor_->message_type()); + singular_type = ClassName(descriptor->message_type()); + vars["prototype"] = singular_type + ".getDefaultInstance()"; break; case JAVATYPE_ENUM: - vars["type"] = ClassName(descriptor_->enum_type()); + singular_type = ClassName(descriptor->enum_type()); + vars["enum_map"] = singular_type + ".internalGetValueMap()"; break; default: - vars["type"] = BoxedPrimitiveTypeName(java_type); + singular_type = BoxedPrimitiveTypeName(java_type); break; } - - printer->Print(vars, - "public static final int $constant_name$ = $number$;\n"); - if (descriptor_->is_repeated()) { - printer->Print(vars, - "public static final\n" - " com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n" - " $containing_type$,\n" - " java.util.List<$type$>> $name$ =\n" - " com.google.protobuf.GeneratedMessage$lite$\n" - " .newGeneratedExtension();\n"); - } else { - printer->Print(vars, - "public static final\n" - " com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n" - " $containing_type$,\n" - " $type$> $name$ =\n" - " com.google.protobuf.GeneratedMessage$lite$\n" - " .newGeneratedExtension();\n"); - } + vars["type"] = descriptor->is_repeated() ? + "java.util.List<" + singular_type + ">" : singular_type; + vars["singular_type"] = singular_type; } -void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) { +void ExtensionGenerator::Generate(io::Printer* printer) { map vars; - vars["name"] = UnderscoresToCamelCase(descriptor_); - vars["scope"] = scope_; - vars["index"] = SimpleItoa(descriptor_->index()); - vars["extendee"] = ClassName(descriptor_->containing_type()); - vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_); - vars["number"] = SimpleItoa(descriptor_->number()); - vars["type_constant"] = TypeName(GetType(descriptor_)); - vars["packed"] = descriptor_->options().packed() ? "true" : "false"; - vars["enum_map"] = "null"; - vars["prototype"] = "null"; - - JavaType java_type = GetJavaType(descriptor_); - string singular_type; - switch (java_type) { - case JAVATYPE_MESSAGE: - vars["type"] = ClassName(descriptor_->message_type()); - vars["prototype"] = ClassName(descriptor_->message_type()) + - ".getDefaultInstance()"; - break; - case JAVATYPE_ENUM: - vars["type"] = ClassName(descriptor_->enum_type()); - vars["enum_map"] = ClassName(descriptor_->enum_type()) + - ".internalGetValueMap()"; - break; - default: - vars["type"] = BoxedPrimitiveTypeName(java_type); - break; - } + InitTemplateVars(descriptor_, scope_, &vars); + printer->Print(vars, + "public static final int $constant_name$ = $number$;\n"); if (HasDescriptorMethods(descriptor_->file())) { - printer->Print(vars, - "$scope$.$name$.internalInit(\n" - " $scope$.getDescriptor().getExtensions().get($index$),\n" - " $type$.class);\n"); + // Non-lite extensions + if (descriptor_->extension_scope() == NULL) { + // Non-nested + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" + " .newFileScopedGeneratedExtension(\n" + " $singular_type$.class,\n" + " $prototype$);\n"); + } else { + // Nested + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessage\n" + " .newMessageScopedGeneratedExtension(\n" + " $scope$.getDefaultInstance(),\n" + " $index$,\n" + " $singular_type$.class,\n" + " $prototype$);\n"); + } } else { + // Lite extensions if (descriptor_->is_repeated()) { - printer->Print(vars, - "$scope$.$name$.internalInitRepeated(\n" - " $extendee$.getDefaultInstance(),\n" - " $prototype$,\n" - " $enum_map$,\n" - " $number$,\n" - " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" - " $packed$);\n"); + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n" + " .newRepeatedGeneratedExtension(\n" + " $containing_type$.getDefaultInstance(),\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" + " $packed$);\n"); } else { - printer->Print(vars, - "$scope$.$name$.internalInitSingular(\n" - " $extendee$.getDefaultInstance(),\n" - " $default$,\n" - " $prototype$,\n" - " $enum_map$,\n" - " $number$,\n" - " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n"); + printer->Print( + vars, + "public static final\n" + " com.google.protobuf.GeneratedMessageLite.GeneratedExtension<\n" + " $containing_type$,\n" + " $type$> $name$ = com.google.protobuf.GeneratedMessageLite\n" + " .newSingularGeneratedExtension(\n" + " $containing_type$.getDefaultInstance(),\n" + " $default$,\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n"); } } } +void ExtensionGenerator::GenerateNonNestedInitializationCode( + io::Printer* printer) { + if (descriptor_->extension_scope() == NULL && + HasDescriptorMethods(descriptor_->file())) { + // Only applies to non-nested, non-lite extensions. + printer->Print( + "$name$.internalInit(descriptor.getExtensions().get($index$));\n", + "name", UnderscoresToCamelCase(descriptor_), + "index", SimpleItoa(descriptor_->index())); + } +} + void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) { printer->Print( "registry.add($scope$.$name$);\n", diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h index 1e423048..009ed9ff 100644 --- a/src/google/protobuf/compiler/java/java_extension.h +++ b/src/google/protobuf/compiler/java/java_extension.h @@ -60,7 +60,7 @@ class ExtensionGenerator { ~ExtensionGenerator(); void Generate(io::Printer* printer); - void GenerateInitializationCode(io::Printer* printer); + void GenerateNonNestedInitializationCode(io::Printer* printer); void GenerateRegistrationCode(io::Printer* printer); private: diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc index 978c8f33..c7d433c8 100644 --- a/src/google/protobuf/compiler/java/java_field.cc +++ b/src/google/protobuf/compiler/java/java_field.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include namespace google { @@ -63,33 +64,57 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) extension_generators_( new scoped_ptr[descriptor->extension_count()]) { - // Construct all the FieldGenerators. + // 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++) { - field_generators_[i].reset(MakeGenerator(descriptor->field(i))); + FieldGenerator* generator = MakeGenerator(descriptor->field(i), + messageBitIndex, builderBitIndex); + field_generators_[i].reset(generator); + messageBitIndex += generator->GetNumBitsForMessage(); + builderBitIndex += generator->GetNumBitsForBuilder(); } for (int i = 0; i < descriptor->extension_count(); i++) { - extension_generators_[i].reset(MakeGenerator(descriptor->extension(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) { +FieldGenerator* FieldGeneratorMap::MakeGenerator( + const FieldDescriptor* field, int messageBitIndex, int builderBitIndex) { if (field->is_repeated()) { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: - return new RepeatedMessageFieldGenerator(field); + return new RepeatedMessageFieldGenerator( + field, messageBitIndex, builderBitIndex); case JAVATYPE_ENUM: - return new RepeatedEnumFieldGenerator(field); + return new RepeatedEnumFieldGenerator( + field, messageBitIndex, builderBitIndex); + case JAVATYPE_STRING: + return new RepeatedStringFieldGenerator( + field, messageBitIndex, builderBitIndex); default: - return new RepeatedPrimitiveFieldGenerator(field); + return new RepeatedPrimitiveFieldGenerator( + field, messageBitIndex, builderBitIndex); } } else { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: - return new MessageFieldGenerator(field); + return new MessageFieldGenerator( + field, messageBitIndex, builderBitIndex); case JAVATYPE_ENUM: - return new EnumFieldGenerator(field); + return new EnumFieldGenerator( + field, messageBitIndex, builderBitIndex); + case JAVATYPE_STRING: + return new StringFieldGenerator( + field, messageBitIndex, builderBitIndex); default: - return new PrimitiveFieldGenerator(field); + return new PrimitiveFieldGenerator( + field, messageBitIndex, builderBitIndex); } } } diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index f5bef7ab..6097f357 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -55,15 +55,24 @@ class FieldGenerator { FieldGenerator() {} virtual ~FieldGenerator(); + virtual int GetNumBitsForMessage() const = 0; + virtual int GetNumBitsForBuilder() const = 0; + virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0; virtual void GenerateMembers(io::Printer* printer) const = 0; virtual void GenerateBuilderMembers(io::Printer* printer) const = 0; virtual void GenerateInitializationCode(io::Printer* printer) const = 0; + virtual void GenerateBuilderClearCode(io::Printer* printer) const = 0; virtual void GenerateMergingCode(io::Printer* printer) const = 0; virtual void GenerateBuildingCode(io::Printer* printer) const = 0; virtual void GenerateParsingCode(io::Printer* printer) const = 0; virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const; virtual void GenerateSerializationCode(io::Printer* printer) const = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; + virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) + const = 0; + + virtual void GenerateEqualsCode(io::Printer* printer) const = 0; + virtual void GenerateHashCode(io::Printer* printer) const = 0; virtual string GetBoxedType() const = 0; @@ -85,7 +94,8 @@ class FieldGeneratorMap { scoped_array > field_generators_; scoped_array > extension_generators_; - static FieldGenerator* MakeGenerator(const FieldDescriptor* field); + static FieldGenerator* MakeGenerator(const FieldDescriptor* field, + int messageBitIndex, int builderBitIndex); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index 7ea127c0..8968069f 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -88,7 +88,8 @@ bool UsesExtensions(const Message& message) { FileGenerator::FileGenerator(const FileDescriptor* file) : file_(file), java_package_(FileJavaPackage(file)), - classname_(FileClassName(file)) {} + classname_(FileClassName(file)) { +} FileGenerator::~FileGenerator() {} @@ -179,7 +180,9 @@ void FileGenerator::Generate(io::Printer* printer) { EnumGenerator(file_->enum_type(i)).Generate(printer); } for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator(file_->message_type(i)).Generate(printer); + MessageGenerator messageGenerator(file_->message_type(i)); + messageGenerator.GenerateInterface(printer); + messageGenerator.Generate(printer); } if (HasGenericServices(file_)) { for (int i = 0; i < file_->service_count(); i++) { @@ -215,24 +218,11 @@ void FileGenerator::Generate(io::Printer* printer) { .GenerateStaticVariableInitializers(printer); } - for (int i = 0; i < file_->extension_count(); i++) { - // TODO(kenton): Reuse ExtensionGenerator objects? - ExtensionGenerator(file_->extension(i)) - .GenerateInitializationCode(printer); - } - printer->Outdent(); printer->Print( "}\n"); } - // Dummy function we can use to force the static initialization block to - // run. Needed by inner classes. Cannot be private due to - // java_multiple_files option. - printer->Print( - "\n" - "public static void internalForceInit() {}\n"); - printer->Print( "\n" "// @@protoc_insertion_point(outer_class_scope)\n"); @@ -310,11 +300,10 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { MessageGenerator(file_->message_type(i)) .GenerateStaticVariableInitializers(printer); } - for (int i = 0; i < file_->extension_count(); i++) { // TODO(kenton): Reuse ExtensionGenerator objects? ExtensionGenerator(file_->extension(i)) - .GenerateInitializationCode(printer); + .GenerateNonNestedInitializationCode(printer); } if (UsesExtensions(file_proto)) { @@ -325,9 +314,11 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { " com.google.protobuf.ExtensionRegistry.newInstance();\n" "registerAllExtensions(registry);\n"); for (int i = 0; i < file_->dependency_count(); i++) { - printer->Print( - "$dependency$.registerAllExtensions(registry);\n", - "dependency", ClassName(file_->dependency(i))); + if (ShouldIncludeDependency(file_->dependency(i))) { + printer->Print( + "$dependency$.registerAllExtensions(registry);\n", + "dependency", ClassName(file_->dependency(i))); + } } printer->Print( "return registry;\n"); @@ -372,13 +363,14 @@ template static void GenerateSibling(const string& package_dir, const string& java_package, const DescriptorClass* descriptor, - OutputDirectory* output_directory, - vector* file_list) { - string filename = package_dir + descriptor->name() + ".java"; + GeneratorContext* context, + vector* file_list, + const string& name_suffix, + void (GeneratorClass::*pfn)(io::Printer* printer)) { + string filename = package_dir + descriptor->name() + name_suffix + ".java"; file_list->push_back(filename); - scoped_ptr output( - output_directory->Open(filename)); + scoped_ptr output(context->Open(filename)); io::Printer printer(output.get(), '$'); printer.Print( @@ -391,28 +383,36 @@ static void GenerateSibling(const string& package_dir, "package", java_package); } - GeneratorClass(descriptor).Generate(&printer); + GeneratorClass generator(descriptor); + (generator.*pfn)(&printer); } void FileGenerator::GenerateSiblings(const string& package_dir, - OutputDirectory* output_directory, + GeneratorContext* context, vector* file_list) { if (file_->options().java_multiple_files()) { for (int i = 0; i < file_->enum_type_count(); i++) { GenerateSibling(package_dir, java_package_, file_->enum_type(i), - output_directory, file_list); + context, file_list, "", + &EnumGenerator::Generate); } for (int i = 0; i < file_->message_type_count(); i++) { GenerateSibling(package_dir, java_package_, file_->message_type(i), - output_directory, file_list); + context, file_list, "OrBuilder", + &MessageGenerator::GenerateInterface); + GenerateSibling(package_dir, java_package_, + file_->message_type(i), + context, file_list, "", + &MessageGenerator::Generate); } if (HasGenericServices(file_)) { for (int i = 0; i < file_->service_count(); i++) { GenerateSibling(package_dir, java_package_, file_->service(i), - output_directory, file_list); + context, file_list, "", + &ServiceGenerator::Generate); } } } diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h index 9e35d330..59911462 100644 --- a/src/google/protobuf/compiler/java/java_file.h +++ b/src/google/protobuf/compiler/java/java_file.h @@ -46,7 +46,7 @@ namespace protobuf { class Printer; // printer.h } namespace compiler { - class OutputDirectory; // code_generator.h + class GeneratorContext; // code_generator.h } } @@ -70,12 +70,13 @@ class FileGenerator { // files other than the outer file (i.e. one for each message, enum, and // service type). void GenerateSiblings(const string& package_dir, - OutputDirectory* output_directory, + GeneratorContext* generator_context, vector* file_list); const string& java_package() { return java_package_; } const string& classname() { return classname_; } + private: // Returns whether the dependency should be included in the output file. // Always returns true for opensource, but used internally at Google to help @@ -86,6 +87,7 @@ class FileGenerator { string java_package_; string classname_; + 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 745b55ae..e6c79abc 100644 --- a/src/google/protobuf/compiler/java/java_generator.cc +++ b/src/google/protobuf/compiler/java/java_generator.cc @@ -51,11 +51,8 @@ JavaGenerator::~JavaGenerator() {} bool JavaGenerator::Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { - vector > options; - ParseGeneratorParameter(parameter, &options); - // ----------------------------------------------------------------- // parse generator options @@ -63,6 +60,10 @@ bool JavaGenerator::Generate(const FileDescriptor* file, // per line. string output_list_file; + + vector > options; + ParseGeneratorParameter(parameter, &options); + for (int i = 0; i < options.size(); i++) { if (options[i].first == "output_list_file") { output_list_file = options[i].second; @@ -72,18 +73,23 @@ bool JavaGenerator::Generate(const FileDescriptor* file, } } - // ----------------------------------------------------------------- + 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; + } + FileGenerator file_generator(file); if (!file_generator.Validate(error)) { return false; } - string package_dir = - StringReplace(file_generator.java_package(), ".", "/", true); - if (!package_dir.empty()) package_dir += "/"; + string package_dir = JavaPackageToDir(file_generator.java_package()); vector all_files; @@ -94,19 +100,19 @@ bool JavaGenerator::Generate(const FileDescriptor* file, // Generate main java file. scoped_ptr output( - output_directory->Open(java_filename)); + context->Open(java_filename)); io::Printer printer(output.get(), '$'); file_generator.Generate(&printer); // Generate sibling files. - file_generator.GenerateSiblings(package_dir, output_directory, &all_files); + file_generator.GenerateSiblings(package_dir, context, &all_files); // 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( - output_directory->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.h b/src/google/protobuf/compiler/java/java_generator.h index c91c9053..888b8d85 100644 --- a/src/google/protobuf/compiler/java/java_generator.h +++ b/src/google/protobuf/compiler/java/java_generator.h @@ -57,7 +57,7 @@ class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator { // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const; private: diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index 7ed0c3cc..1b6f1653 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -134,16 +134,27 @@ string FileClassName(const FileDescriptor* file) { } string FileJavaPackage(const FileDescriptor* file) { + string result; + if (file->options().has_java_package()) { - return file->options().java_package(); + result = file->options().java_package(); } else { - string result = kDefaultPackage; + result = kDefaultPackage; if (!file->package().empty()) { if (!result.empty()) result += '.'; result += file->package(); } - return result; } + + + return result; +} + +string JavaPackageToDir(string package_name) { + string package_dir = + StringReplace(package_name, ".", "/", true); + if (!package_dir.empty()) package_dir += "/"; + return package_dir; } string ToJavaName(const string& full_name, const FileDescriptor* file) { @@ -335,6 +346,132 @@ string DefaultValue(const FieldDescriptor* field) { return ""; } +bool IsDefaultValueJavaDefault(const FieldDescriptor* field) { + // Switch on CppType since we need to know which default_value_* method + // of FieldDescriptor to call. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return field->default_value_int32() == 0; + case FieldDescriptor::CPPTYPE_UINT32: + return field->default_value_uint32() == 0; + case FieldDescriptor::CPPTYPE_INT64: + return field->default_value_int64() == 0L; + case FieldDescriptor::CPPTYPE_UINT64: + return field->default_value_uint64() == 0L; + case FieldDescriptor::CPPTYPE_DOUBLE: + return field->default_value_double() == 0.0; + case FieldDescriptor::CPPTYPE_FLOAT: + return field->default_value_float() == 0.0; + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() == false; + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_MESSAGE: + return false; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + +const char* bit_masks[] = { + "0x00000001", + "0x00000002", + "0x00000004", + "0x00000008", + "0x00000010", + "0x00000020", + "0x00000040", + "0x00000080", + + "0x00000100", + "0x00000200", + "0x00000400", + "0x00000800", + "0x00001000", + "0x00002000", + "0x00004000", + "0x00008000", + + "0x00010000", + "0x00020000", + "0x00040000", + "0x00080000", + "0x00100000", + "0x00200000", + "0x00400000", + "0x00800000", + + "0x01000000", + "0x02000000", + "0x04000000", + "0x08000000", + "0x10000000", + "0x20000000", + "0x40000000", + "0x80000000", +}; + +string GetBitFieldName(int index) { + string varName = "bitField"; + varName += SimpleItoa(index); + varName += "_"; + return varName; +} + +string GetBitFieldNameForBit(int bitIndex) { + return GetBitFieldName(bitIndex / 32); +} + +string GenerateGetBit(int bitIndex) { + string varName = GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = "((" + varName + " & " + mask + ") == " + mask + ")"; + return result; +} + +string GenerateSetBit(int bitIndex) { + string varName = GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = varName + " |= " + mask; + return result; +} + +string GenerateClearBit(int bitIndex) { + string varName = GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = varName + " = (" + varName + " & ~" + mask + ")"; + return result; +} + +string GenerateGetBitFromLocal(int bitIndex) { + string varName = "from_" + GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = "((" + varName + " & " + mask + ") == " + mask + ")"; + return result; +} + +string GenerateSetBitToLocal(int bitIndex) { + string varName = "to_" + GetBitFieldNameForBit(bitIndex); + int bitInVarIndex = bitIndex % 32; + + string mask = bit_masks[bitInVarIndex]; + string result = varName + " |= " + mask; + return result; +} + } // 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 3c8974c9..4ae07f15 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -68,6 +68,9 @@ string FileClassName(const FileDescriptor* file); // Returns the file's Java package name. string FileJavaPackage(const FileDescriptor* file); +// Returns output directory for the given package name. +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. @@ -118,6 +121,7 @@ JavaType GetJavaType(const FieldDescriptor* field); const char* BoxedPrimitiveTypeName(JavaType type); string DefaultValue(const FieldDescriptor* field); +bool IsDefaultValueJavaDefault(const FieldDescriptor* field); // Does this message class keep track of unknown fields? inline bool HasUnknownFields(const Descriptor* descriptor) { @@ -132,6 +136,11 @@ inline bool HasGeneratedMethods(const Descriptor* descriptor) { FileOptions::CODE_SIZE; } +// Does this message have specialized equals() and hashCode() methods? +inline bool HasEqualsAndHashCode(const Descriptor* descriptor) { + return descriptor->file()->options().java_generate_equals_and_hash(); +} + // Does this message class have descriptor and reflection methods? inline bool HasDescriptorMethods(const Descriptor* descriptor) { return descriptor->file()->options().optimize_for() != @@ -146,6 +155,12 @@ inline bool HasDescriptorMethods(const FileDescriptor* descriptor) { FileOptions::LITE_RUNTIME; } +inline bool HasNestedBuilders(const Descriptor* descriptor) { + // The proto-lite version doesn't support nested builders. + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} + // Should we generate generic services for this file? inline bool HasGenericServices(const FileDescriptor *file) { return file->service_count() > 0 && @@ -153,6 +168,43 @@ inline bool HasGenericServices(const FileDescriptor *file) { file->options().java_generic_services(); } + +// Methods for shared bitfields. + +// Gets the name of the shared bitfield for the given index. +string GetBitFieldName(int index); + +// Gets the name of the shared bitfield for the given bit index. +// Effectively, GetBitFieldName(bitIndex / 32) +string GetBitFieldNameForBit(int bitIndex); + +// Generates the java code for the expression that returns the boolean value +// of the bit of the shared bitfields for the given bit index. +// Example: "((bitField1_ & 0x04) == 0x04)" +string GenerateGetBit(int bitIndex); + +// Generates the java code for the expression that sets the bit of the shared +// bitfields for the given bit index. +// Example: "bitField1_ = (bitField1_ | 0x04)" +string GenerateSetBit(int bitIndex); + +// Generates the java code for the expression that clears the bit of the shared +// bitfields for the given bit index. +// Example: "bitField1_ = (bitField1_ & ~0x04)" +string GenerateClearBit(int bitIndex); + +// Does the same as GenerateGetBit but operates on the bit field on a local +// variable. This is used by the builder to copy the value in the builder to +// the message. +// Example: "((from_bitField1_ & 0x04) == 0x04)" +string GenerateGetBitFromLocal(int bitIndex); + +// Does the same as GenerateSetBit but operates on the bit field on a local +// variable. This is used by the builder to copy the value in the builder to +// the message. +// Example: "to_bitField1_ = (to_bitField1_ | 0x04)" +string GenerateSetBitToLocal(int bitIndex); + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 8b91193f..47ee84cf 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -245,14 +245,54 @@ void MessageGenerator::GenerateStaticVariableInitializers( MessageGenerator(descriptor_->nested_type(i)) .GenerateStaticVariableInitializers(printer); } +} - for (int i = 0; i < descriptor_->extension_count(); i++) { - // TODO(kenton): Reuse ExtensionGenerator objects? - ExtensionGenerator(descriptor_->extension(i)) - .GenerateInitializationCode(printer); +// =================================================================== + +void MessageGenerator::GenerateInterface(io::Printer* printer) { + + if (descriptor_->extension_range_count() > 0) { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public interface $classname$OrBuilder extends\n" + " com.google.protobuf.GeneratedMessage.\n" + " ExtendableMessageOrBuilder<$classname$> {\n", + "classname", descriptor_->name()); + } else { + printer->Print( + "public interface $classname$OrBuilder extends \n" + " com.google.protobuf.GeneratedMessageLite.\n" + " ExtendableMessageOrBuilder<$classname$> {\n", + "classname", descriptor_->name()); + } + } else { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public interface $classname$OrBuilder\n" + " extends com.google.protobuf.MessageOrBuilder {\n", + "classname", descriptor_->name()); + } else { + printer->Print( + "public interface $classname$OrBuilder\n" + " extends com.google.protobuf.MessageLiteOrBuilder {\n", + "classname", descriptor_->name()); + } } + + 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); + } + printer->Outdent(); + + printer->Print("}\n"); } +// =================================================================== + void MessageGenerator::Generate(io::Printer* printer) { bool is_own_file = descriptor_->containing_type() == NULL && @@ -263,14 +303,14 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print( "public $static$ final class $classname$ extends\n" " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" - " $classname$> {\n", + " $classname$> implements $classname$OrBuilder {\n", "static", is_own_file ? "" : "static", "classname", descriptor_->name()); } else { printer->Print( "public $static$ final class $classname$ extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" - " $classname$> {\n", + " $classname$> implements $classname$OrBuilder {\n", "static", is_own_file ? "" : "static", "classname", descriptor_->name()); } @@ -278,13 +318,15 @@ void MessageGenerator::Generate(io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage {\n", + " com.google.protobuf.GeneratedMessage\n" + " implements $classname$OrBuilder {\n", "static", is_own_file ? "" : "static", "classname", descriptor_->name()); } else { printer->Print( "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessageLite {\n", + " com.google.protobuf.GeneratedMessageLite\n" + " implements $classname$OrBuilder {\n", "static", is_own_file ? "" : "static", "classname", descriptor_->name()); } @@ -292,8 +334,8 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Indent(); printer->Print( "// Use $classname$.newBuilder() to construct.\n" - "private $classname$() {\n" - " initFields();\n" + "private $classname$(Builder builder) {\n" + " super(builder);\n" "}\n" // Used when constructing the default instance, which cannot be initialized // immediately because it may cyclically refer to other default instances. @@ -310,33 +352,29 @@ void MessageGenerator::Generate(io::Printer* printer) { "\n", "classname", descriptor_->name()); - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "public static final com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptor() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" - "}\n" - "\n" - "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internalGetFieldAccessorTable() {\n" - " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n" - "}\n" - "\n", - "fileclass", ClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); - } + GenerateDescriptorMethods(printer); - // Nested types and extensions + // Nested types for (int i = 0; i < descriptor_->enum_type_count(); i++) { EnumGenerator(descriptor_->enum_type(i)).Generate(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator(descriptor_->nested_type(i)).Generate(printer); + MessageGenerator messageGenerator(descriptor_->nested_type(i)); + messageGenerator.GenerateInterface(printer); + messageGenerator.Generate(printer); } - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator(descriptor_->extension(i)).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(); + } + 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)); } // Fields @@ -361,35 +399,42 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print("}\n"); if (HasGeneratedMethods(descriptor_)) { - GenerateIsInitialized(printer); + GenerateIsInitialized(printer, MEMOIZE); GenerateMessageSerializationMethods(printer); } + if (HasEqualsAndHashCode(descriptor_)) { + GenerateEqualsAndHashCode(printer); + } + GenerateParseFromMethods(printer); GenerateBuilder(printer); - // Force initialization of outer class. Otherwise, nested extensions may - // not be initialized. Also carefully initialize the default instance in - // such a way that it doesn't conflict with other initialization. + // Carefully initialize the default instance in such a way that it doesn't + // conflict with other initialization. printer->Print( "\n" "static {\n" " defaultInstance = new $classname$(true);\n" - " $file$.internalForceInit();\n" " defaultInstance.initFields();\n" - "}\n", - "file", ClassName(descriptor_->file()), - "classname", descriptor_->name()); - - printer->Print( + "}\n" "\n" "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "classname", descriptor_->name(), "full_name", descriptor_->full_name()); + // Extensions must be declared after the defaultInstance is initialized + // 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); + } + printer->Outdent(); printer->Print("}\n\n"); } + // =================================================================== void MessageGenerator:: @@ -502,6 +547,13 @@ GenerateMessageSerializationMethods(io::Printer* printer) { " return size;\n" "}\n" "\n"); + + printer->Print( + "@java.lang.Override\n" + "protected Object writeReplace() throws java.io.ObjectStreamException {\n" + " return super.writeReplace();\n" + "}\n" + "\n"); } void MessageGenerator:: @@ -605,42 +657,68 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { "\n", "classname", ClassName(descriptor_)); + if (HasNestedBuilders(descriptor_)) { + printer->Print( + "@java.lang.Override\n" + "protected Builder newBuilderForType(\n" + " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" + " Builder builder = new Builder(parent);\n" + " return builder;\n" + "}\n"); + } + if (descriptor_->extension_range_count() > 0) { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" - " $classname$, Builder> {\n", + " $classname$, Builder> implements $classname$OrBuilder {\n", "classname", ClassName(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n" - " $classname$, Builder> {\n", + " $classname$, Builder> implements $classname$OrBuilder {\n", "classname", ClassName(descriptor_)); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.Builder {\n", + " com.google.protobuf.GeneratedMessage.Builder\n" + " implements $classname$OrBuilder {\n", "classname", ClassName(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessageLite.Builder<\n" - " $classname$, Builder> {\n", + " $classname$, Builder>\n" + " implements $classname$OrBuilder {\n", "classname", ClassName(descriptor_)); } } printer->Indent(); + GenerateDescriptorMethods(printer); GenerateCommonBuilderMethods(printer); if (HasGeneratedMethods(descriptor_)) { + GenerateIsInitialized(printer, DONT_MEMOIZE); 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(); + } + 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)); @@ -657,36 +735,92 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print("}\n"); } +void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public static final com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptor() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n" + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internalGetFieldAccessorTable() {\n" + " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n" + "}\n" + "\n", + "fileclass", ClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); + } +} + // =================================================================== void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { printer->Print( - "private $classname$ result;\n" - "\n" "// Construct using $classname$.newBuilder()\n" - "private Builder() {}\n" - "\n" - "private static Builder create() {\n" - " Builder builder = new Builder();\n" - " builder.result = new $classname$();\n" - " return builder;\n" + "private Builder() {\n" + " maybeForceBuilderInitialization();\n" "}\n" - "\n" - "protected $classname$ internalGetResult() {\n" - " return result;\n" + "\n", + "classname", ClassName(descriptor_)); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "private Builder(BuilderParent parent) {\n" + " super(parent);\n" + " maybeForceBuilderInitialization();\n" + "}\n", + "classname", ClassName(descriptor_)); + } + + + if (HasNestedBuilders(descriptor_)) { + printer->Print( + "private void maybeForceBuilderInitialization() {\n" + " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n"); + + printer->Indent(); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateFieldBuilderInitializationCode(printer); + } + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + "}\n"); + } else { + printer->Print( + "private void maybeForceBuilderInitialization() {\n" + "}\n"); + } + + printer->Print( + "private static Builder create() {\n" + " return new Builder();\n" "}\n" "\n" "public Builder clear() {\n" - " if (result == null) {\n" - " throw new IllegalStateException(\n" - " \"Cannot call clear() after build().\");\n" - " }\n" - " result = new $classname$();\n" + " super.clear();\n", + "classname", ClassName(descriptor_)); + + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateBuilderClearCode(printer); + } + + printer->Outdent(); + + printer->Print( " return this;\n" "}\n" "\n" "public Builder clone() {\n" - " return create().mergeFrom(result);\n" + " return create().mergeFrom(buildPartial());\n" "}\n" "\n", "classname", ClassName(descriptor_)); @@ -703,49 +837,78 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "public $classname$ getDefaultInstanceForType() {\n" " return $classname$.getDefaultInstance();\n" "}\n" - "\n" - "public boolean isInitialized() {\n" - " return result.isInitialized();\n" - "}\n", + "\n", "classname", ClassName(descriptor_)); // ----------------------------------------------------------------- printer->Print( "public $classname$ build() {\n" - // If result == null, we'll throw an appropriate exception later. - " if (result != null && !isInitialized()) {\n" + " $classname$ result = buildPartial();\n" + " if (!result.isInitialized()) {\n" " throw newUninitializedMessageException(result);\n" " }\n" - " return buildPartial();\n" + " return result;\n" "}\n" "\n" "private $classname$ buildParsed()\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" - " if (!isInitialized()) {\n" + " $classname$ result = buildPartial();\n" + " if (!result.isInitialized()) {\n" " throw newUninitializedMessageException(\n" " result).asInvalidProtocolBufferException();\n" " }\n" - " return buildPartial();\n" + " return result;\n" "}\n" "\n" "public $classname$ buildPartial() {\n" - " if (result == null) {\n" - " throw new IllegalStateException(\n" - " \"build() has already been called on this Builder.\");\n" - " }\n", + " $classname$ result = new $classname$(this);\n", "classname", ClassName(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)); + 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)); + } + + // Output generation code for each field. for (int i = 0; i < descriptor_->field_count(); i++) { 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)); + } + printer->Outdent(); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + " onBuilt();\n"); + } + printer->Print( - " $classname$ returnMe = result;\n" - " result = null;\n" - " return returnMe;\n" + " return result;\n" "}\n" "\n", "classname", ClassName(descriptor_)); @@ -834,25 +997,31 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { printer->Print( "case 0:\n" // zero signals EOF / limit reached " this.setUnknownFields(unknownFields.build());\n" + " $on_changed$\n" " return this;\n" "default: {\n" " if (!parseUnknownField(input, unknownFields,\n" " extensionRegistry, tag)) {\n" " this.setUnknownFields(unknownFields.build());\n" + " $on_changed$\n" " return this;\n" // it's an endgroup tag " }\n" " break;\n" - "}\n"); + "}\n", + "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : ""); } else { printer->Print( "case 0:\n" // zero signals EOF / limit reached + " $on_changed$\n" " return this;\n" "default: {\n" " if (!parseUnknownField(input, extensionRegistry, tag)) {\n" + " $on_changed$\n" " return this;\n" // it's an endgroup tag " }\n" " break;\n" - "}\n"); + "}\n", + "on_changed", HasDescriptorMethods(descriptor_) ? "onChanged();" : ""); } for (int i = 0; i < descriptor_->field_count(); i++) { @@ -898,16 +1067,33 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { " }\n" // switch (tag) " }\n" // while (true) "}\n" + "\n"); } // =================================================================== -void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { +void MessageGenerator::GenerateIsInitialized( + io::Printer* printer, UseMemoization useMemoization) { + bool memoization = useMemoization == MEMOIZE; + if (memoization) { + // Memoizes whether the protocol buffer is fully initialized (has all + // required fields). -1 means not yet computed. 0 means false and 1 means + // true. + printer->Print( + "private byte memoizedIsInitialized = -1;\n"); + } printer->Print( "public final boolean isInitialized() {\n"); printer->Indent(); + if (memoization) { + printer->Print( + "byte isInitialized = memoizedIsInitialized;\n" + "if (isInitialized != -1) return isInitialized == 1;\n" + "\n"); + } + // Check that all required fields in this message are set. // TODO(kenton): We can optimize this when we switch to putting all the // "has" fields into a single bitfield. @@ -916,8 +1102,12 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { if (field->is_required()) { printer->Print( - "if (!has$name$) return false;\n", - "name", UnderscoresToCapitalizedCamelCase(field)); + "if (!has$name$()) {\n" + " $memoize$\n" + " return false;\n" + "}\n", + "name", UnderscoresToCapitalizedCamelCase(field), + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); } } @@ -929,25 +1119,37 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { switch (field->label()) { case FieldDescriptor::LABEL_REQUIRED: printer->Print( - "if (!get$name$().isInitialized()) return false;\n", + "if (!get$name$().isInitialized()) {\n" + " $memoize$\n" + " return false;\n" + "}\n", "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field)); + "name", UnderscoresToCapitalizedCamelCase(field), + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); break; case FieldDescriptor::LABEL_OPTIONAL: printer->Print( "if (has$name$()) {\n" - " if (!get$name$().isInitialized()) return false;\n" + " if (!get$name$().isInitialized()) {\n" + " $memoize$\n" + " return false;\n" + " }\n" "}\n", "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field)); + "name", UnderscoresToCapitalizedCamelCase(field), + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); break; case FieldDescriptor::LABEL_REPEATED: printer->Print( - "for ($type$ element : get$name$List()) {\n" - " if (!element.isInitialized()) return false;\n" + "for (int i = 0; i < get$name$Count(); i++) {\n" + " if (!get$name$(i).isInitialized()) {\n" + " $memoize$\n" + " return false;\n" + " }\n" "}\n", "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field)); + "name", UnderscoresToCapitalizedCamelCase(field), + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); break; } } @@ -955,10 +1157,20 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { printer->Print( - "if (!extensionsAreInitialized()) return false;\n"); + "if (!extensionsAreInitialized()) {\n" + " $memoize$\n" + " return false;\n" + "}\n", + "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); } printer->Outdent(); + + if (memoization) { + printer->Print( + " memoizedIsInitialized = 1;\n"); + } + printer->Print( " return true;\n" "}\n" @@ -967,6 +1179,94 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { // =================================================================== +void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { + printer->Print( + "@java.lang.Override\n" + "public boolean equals(final Object obj) {\n"); + printer->Indent(); + printer->Print( + "if (obj == this) {\n" + " return true;\n" + "}\n" + "if (!(obj instanceof $classname$)) {\n" + " return super.equals(obj);\n" + "}\n" + "$classname$ other = ($classname$) obj;\n" + "\n", + "classname", ClassName(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()) { + printer->Print( + "result = result && (has$name$() == other.has$name$());\n" + "if (has$name$()) {\n", + "name", UnderscoresToCapitalizedCamelCase(field)); + printer->Indent(); + } + field_generators_.get(field).GenerateEqualsCode(printer); + if (!field->is_repeated()) { + printer->Outdent(); + printer->Print( + "}\n"); + } + } + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "result = result &&\n" + " getUnknownFields().equals(other.getUnknownFields());\n"); + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "result = result &&\n" + " getExtensionFields().equals(other.getExtensionFields());\n"); + } + } + printer->Print( + "return result;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + + printer->Print( + "@java.lang.Override\n" + "public int hashCode() {\n"); + printer->Indent(); + printer->Print( + "int hash = 41;\n" + "hash = (19 * hash) + getDescriptorForType().hashCode();\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!field->is_repeated()) { + printer->Print( + "if (has$name$()) {\n", + "name", UnderscoresToCapitalizedCamelCase(field)); + printer->Indent(); + } + field_generators_.get(field).GenerateHashCode(printer); + if (!field->is_repeated()) { + printer->Outdent(); + printer->Print("}\n"); + } + } + if (HasDescriptorMethods(descriptor_)) { + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "hash = hashFields(hash, getExtensionFields());\n"); + } + } + printer->Print( + "hash = (29 * hash) + getUnknownFields().hashCode();\n" + "return hash;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); +} + +// =================================================================== + void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator(descriptor_->extension(i)) diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index 50ffae08..4c6fbbe5 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -67,11 +67,19 @@ class MessageGenerator { // Generate the class itself. void Generate(io::Printer* printer); + // Generates the base interface that both the class and its builder implement + void GenerateInterface(io::Printer* printer); + // Generate code to register all contained extensions with an // ExtensionRegistry. void GenerateExtensionRegistrationCode(io::Printer* printer); private: + enum UseMemoization { + MEMOIZE, + DONT_MEMOIZE + }; + void GenerateMessageSerializationMethods(io::Printer* printer); void GenerateParseFromMethods(io::Printer* printer); void GenerateSerializeOneField(io::Printer* printer, @@ -81,8 +89,11 @@ class MessageGenerator { void GenerateBuilder(io::Printer* printer); void GenerateCommonBuilderMethods(io::Printer* printer); + void GenerateDescriptorMethods(io::Printer* printer); void GenerateBuilderParsingMethods(io::Printer* printer); - void GenerateIsInitialized(io::Printer* printer); + void GenerateIsInitialized(io::Printer* printer, + UseMemoization useMemoization); + void GenerateEqualsAndHashCode(io::Printer* printer); const Descriptor* descriptor_; FieldGeneratorMap field_generators_; diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index 71edc024..251945af 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -51,16 +51,43 @@ 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, 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()); (*variables)["group_or_message"] = (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + // 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)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex); + + // For repated 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); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); } } // namespace @@ -68,67 +95,243 @@ void SetMessageVariables(const FieldDescriptor* descriptor, // =================================================================== MessageFieldGenerator:: -MessageFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetMessageVariables(descriptor, &variables_); +MessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); } MessageFieldGenerator::~MessageFieldGenerator() {} +int MessageFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int MessageFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void MessageFieldGenerator:: +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. + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n" + "$deprecation$$type$ get$capitalized_name$();\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n"); + } +} + void MessageFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private boolean has$capitalized_name$;\n" "private $type$ $name$_;\n" - "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" - "public $type$ get$capitalized_name$() { return $name$_; }\n"); + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n" + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " return $name$_;\n" + "}\n"); + } +} + +void MessageFieldGenerator::PrintNestedBuilderCondition( + io::Printer* printer, + const char* regular_case, + const char* nested_builder_case) const { + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, "if ($name$Builder_ == null) {\n"); + printer->Indent(); + printer->Print(variables_, regular_case); + printer->Outdent(); + printer->Print("} else {\n"); + printer->Indent(); + printer->Print(variables_, nested_builder_case); + printer->Outdent(); + printer->Print("}\n"); + } else { + printer->Print(variables_, regular_case); + } +} + +void MessageFieldGenerator::PrintNestedBuilderFunction( + io::Printer* printer, + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const { + printer->Print(variables_, method_prototype); + printer->Print(" {\n"); + printer->Indent(); + PrintNestedBuilderCondition(printer, regular_case, nested_builder_case); + if (trailing_code != NULL) { + printer->Print(variables_, trailing_code); + } + printer->Outdent(); + printer->Print("}\n"); } void MessageFieldGenerator:: 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_, - "public boolean has$capitalized_name$() {\n" - " return result.has$capitalized_name$();\n" - "}\n" - "public $type$ get$capitalized_name$() {\n" - " return result.get$capitalized_name$();\n" - "}\n" - "public Builder set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " result.has$capitalized_name$ = true;\n" - " result.$name$_ = value;\n" - " return this;\n" - "}\n" - "public Builder set$capitalized_name$($type$.Builder builderForValue) {\n" - " result.has$capitalized_name$ = true;\n" - " result.$name$_ = builderForValue.build();\n" - " return this;\n" + // Used when the builder is null. + "private $type$ $name$_ = $type$.getDefaultInstance();\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() + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + + // Field getField() + PrintNestedBuilderFunction(printer, + "$deprecation$public $type$ get$capitalized_name$()", + + "return $name$_;\n", + + "return $name$Builder_.getMessage();\n", + + NULL); + + // Field.Builder setField(Field value) + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" "}\n" - "public Builder merge$capitalized_name$($type$ value) {\n" - " if (result.has$capitalized_name$() &&\n" - " result.$name$_ != $type$.getDefaultInstance()) {\n" - " result.$name$_ =\n" - " $type$.newBuilder(result.$name$_).mergeFrom(value).buildPartial();\n" - " } else {\n" - " result.$name$_ = value;\n" - " }\n" - " result.has$capitalized_name$ = true;\n" - " return this;\n" + "$name$_ = value;\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(value);\n", + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder setField(Field.Builder builderForValue) + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "$name$_ = builderForValue.build();\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(builderForValue.build());\n", + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder mergeField(Field value) + 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" - "public Builder clear$capitalized_name$() {\n" - " result.has$capitalized_name$ = false;\n" - " result.$name$_ = $type$.getDefaultInstance();\n" - " return this;\n" - "}\n"); + "$on_changed$\n", + + "$name$Builder_.mergeFrom(value);\n", + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder clearField() + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "$name$_ = $type$.getDefaultInstance();\n" + "$on_changed$\n", + + "$name$Builder_.clear();\n", + + "$clear_has_field_bit_builder$;\n" + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + 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" + "$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" + "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 MessageFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + printer->Print(variables_, + "get$capitalized_name$FieldBuilder();\n"); +} + + void MessageFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n"); } +void MessageFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + PrintNestedBuilderCondition(printer, + "$name$_ = $type$.getDefaultInstance();\n", + + "$name$Builder_.clear();\n"); + printer->Print(variables_, "$clear_has_field_bit_builder$;\n"); +} + void MessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print(variables_, @@ -139,7 +342,16 @@ GenerateMergingCode(io::Printer* printer) const { void MessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - // Nothing to do for singular fields. + + 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", + + "result.$name$_ = $name$Builder_.build();\n"); } void MessageFieldGenerator:: @@ -165,20 +377,34 @@ GenerateParsingCode(io::Printer* printer) const { void MessageFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " output.write$group_or_message$($number$, get$capitalized_name$());\n" + "if ($get_has_field_bit_message$) {\n" + " output.write$group_or_message$($number$, $name$_);\n" "}\n"); } void MessageFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" + "if ($get_has_field_bit_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, get$capitalized_name$());\n" + " .compute$group_or_message$Size($number$, $name$_);\n" "}\n"); } +void MessageFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); +} + +void MessageFieldGenerator:: +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()); } @@ -186,109 +412,416 @@ string MessageFieldGenerator::GetBoxedType() const { // =================================================================== RepeatedMessageFieldGenerator:: -RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetMessageVariables(descriptor, &variables_); +RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} +int RepeatedMessageFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedMessageFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedMessageFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + // TODO(jonp): In the future, consider having methods specific to the + // interface so that builders can choose dynamically to either return a + // message or a nested builder, so that asking for the interface doesn't + // cause a message to ever be built. + printer->Print(variables_, + "$deprecation$java.util.List<$type$> \n" + " get$capitalized_name$List();\n" + "$deprecation$$type$ get$capitalized_name$(int index);\n" + "$deprecation$int get$capitalized_name$Count();\n"); + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + "$deprecation$java.util.List \n" + " get$capitalized_name$OrBuilderList();\n" + "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index);\n"); + } +} + void RepeatedMessageFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private java.util.List<$type$> $name$_ =\n" - " java.util.Collections.emptyList();\n" - "public java.util.List<$type$> get$capitalized_name$List() {\n" + "private java.util.List<$type$> $name$_;\n" + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" " return $name$_;\n" // note: unmodifiable list "}\n" - "public int get$capitalized_name$Count() { return $name$_.size(); }\n" - "public $type$ get$capitalized_name$(int index) {\n" + "$deprecation$public java.util.List \n" + " get$capitalized_name$OrBuilderList() {\n" + " return $name$_;\n" + "}\n" + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n" + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n" + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" " return $name$_.get(index);\n" "}\n"); + +} + +void RepeatedMessageFieldGenerator::PrintNestedBuilderCondition( + io::Printer* printer, + const char* regular_case, + const char* nested_builder_case) const { + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, "if ($name$Builder_ == null) {\n"); + printer->Indent(); + printer->Print(variables_, regular_case); + printer->Outdent(); + printer->Print("} else {\n"); + printer->Indent(); + printer->Print(variables_, nested_builder_case); + printer->Outdent(); + printer->Print("}\n"); + } else { + printer->Print(variables_, regular_case); + } +} + +void RepeatedMessageFieldGenerator::PrintNestedBuilderFunction( + io::Printer* printer, + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const { + printer->Print(variables_, method_prototype); + printer->Print(" {\n"); + printer->Indent(); + PrintNestedBuilderCondition(printer, regular_case, nested_builder_case); + if (trailing_code != NULL) { + printer->Print(variables_, trailing_code); + } + printer->Outdent(); + printer->Print("}\n"); } void RepeatedMessageFieldGenerator:: 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_, - // Note: We return an unmodifiable list because otherwise the caller - // could hold on to the returned list and modify it after the message - // has been built, thus mutating the message which is supposed to be - // immutable. - "public java.util.List<$type$> get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList(result.$name$_);\n" - "}\n" - "public int get$capitalized_name$Count() {\n" - " return result.get$capitalized_name$Count();\n" - "}\n" - "public $type$ get$capitalized_name$(int index) {\n" - " return result.get$capitalized_name$(index);\n" - "}\n" - "public Builder set$capitalized_name$(int index, $type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " result.$name$_.set(index, value);\n" - " return this;\n" - "}\n" - "public Builder set$capitalized_name$(int index, " - "$type$.Builder builderForValue) {\n" - " result.$name$_.set(index, builderForValue.build());\n" - " return this;\n" + // Used when the builder is null. + // One field is the list and the other field keeps track of whether the + // list is immutable. If it's immutable, the invariant is that it must + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + "private java.util.List<$type$> $name$_ =\n" + " java.util.Collections.emptyList();\n" + + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList<$type$>($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" "}\n" - "public Builder add$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" - " }\n" - " result.$name$_.add(value);\n" - " return this;\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() + PrintNestedBuilderFunction(printer, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List()", + + "return java.util.Collections.unmodifiableList($name$_);\n", + "return $name$Builder_.getMessageList();\n", + + NULL); + + // int getRepeatedFieldCount() + PrintNestedBuilderFunction(printer, + "$deprecation$public int get$capitalized_name$Count()", + + "return $name$_.size();\n", + "return $name$Builder_.getCount();\n", + + NULL); + + // Field getRepeatedField(int index) + PrintNestedBuilderFunction(printer, + "$deprecation$public $type$ get$capitalized_name$(int index)", + + "return $name$_.get(index);\n", + + "return $name$Builder_.getMessage(index);\n", + + NULL); + + // Builder setRepeatedField(int index, Field value) + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value)", + "if (value == null) {\n" + " throw new NullPointerException();\n" "}\n" - "public Builder add$capitalized_name$($type$.Builder builderForValue) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" - " }\n" - " result.$name$_.add(builderForValue.build());\n" - " return this;\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, value);\n" + "$on_changed$\n", + "$name$Builder_.setMessage(index, value);\n", + "return this;\n"); + + // Builder setRepeatedField(int index, Field.Builder builderForValue) + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, builderForValue.build());\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(index, builderForValue.build());\n", + + "return this;\n"); + + // Builder addRepeatedField(Field value) + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" "}\n" - "public Builder addAll$capitalized_name$(\n" - " java.lang.Iterable values) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" - " }\n" - " super.addAll(values, result.$name$_);\n" - " return this;\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(value);\n" + + "$on_changed$\n", + + "$name$Builder_.addMessage(value);\n", + + "return this;\n"); + + // Builder addRepeatedField(int index, Field value) + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.$name$_ = java.util.Collections.emptyList();\n" - " return this;\n" - "}\n"); + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, value);\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(index, value);\n", + + "return this;\n"); + + // Builder addRepeatedField(Field.Builder builderForValue) + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(builderForValue.build());\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(builderForValue.build());\n", + + "return this;\n"); + + // Builder addRepeatedField(int index, Field.Builder builderForValue) + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, builderForValue.build());\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(index, builderForValue.build());\n", + + "return this;\n"); + + // Builder addAllRepeatedField(Iterable values) + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values)", + + "ensure$capitalized_name$IsMutable();\n" + "super.addAll(values, $name$_);\n" + "$on_changed$\n", + + "$name$Builder_.addAllMessages(values);\n", + + "return this;\n"); + + // Builder clearAllRepeatedField() + 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) + 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())) { + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" + "}\n" + + "$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" + + "$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" + + "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " $type$.getDefaultInstance());\n" + "}\n" + "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " index, $type$.getDefaultInstance());\n" + "}\n" + "$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 RepeatedMessageFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + printer->Print(variables_, + "get$capitalized_name$FieldBuilder();\n"); } void RepeatedMessageFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - // Initialized inline. + printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + PrintNestedBuilderCondition(printer, + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n", + + "$name$Builder_.clear();\n"); } void RepeatedMessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, + // The code below does two optimizations (non-nested builder case): + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + PrintNestedBuilderCondition(printer, "if (!other.$name$_.isEmpty()) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$type$>();\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n", + + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$Builder_.isEmpty()) {\n" + " $name$Builder_.dispose();\n" + " $name$Builder_ = null;\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " $name$Builder_ = \n" + " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n" + " get$capitalized_name$FieldBuilder() : null;\n" + " } else {\n" + " $name$Builder_.addAllMessages(other.$name$_);\n" " }\n" - " result.$name$_.addAll(other.$name$_);\n" "}\n"); } void RepeatedMessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n" - " result.$name$_ =\n" - " java.util.Collections.unmodifiableList(result.$name$_);\n" - "}\n"); + // 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, + // we make it immutable. + PrintNestedBuilderCondition(printer, + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n", + + "result.$name$_ = $name$Builder_.build();\n"); } void RepeatedMessageFieldGenerator:: @@ -311,17 +844,33 @@ GenerateParsingCode(io::Printer* printer) const { void RepeatedMessageFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" - " output.write$group_or_message$($number$, element);\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$group_or_message$($number$, $name$_.get(i));\n" "}\n"); } void RepeatedMessageFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .compute$group_or_message$Size($number$, element);\n" + " .compute$group_or_message$Size($number$, $name$_.get(i));\n" + "}\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedMessageFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" "}\n"); } diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h index 66bdd884..2efbcd97 100644 --- a/src/google/protobuf/compiler/java/java_message_field.h +++ b/src/google/protobuf/compiler/java/java_message_field.h @@ -46,50 +46,84 @@ namespace java { class MessageFieldGenerator : public FieldGenerator { public: - explicit MessageFieldGenerator(const FieldDescriptor* descriptor); + explicit MessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); ~MessageFieldGenerator(); // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; private: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); + + void PrintNestedBuilderCondition(io::Printer* printer, + const char* regular_case, const char* nested_builder_case) const; + void PrintNestedBuilderFunction(io::Printer* printer, + const char* method_prototype, const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; }; class RepeatedMessageFieldGenerator : public FieldGenerator { public: - explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor); + explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); ~RepeatedMessageFieldGenerator(); // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; private: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); + + void PrintNestedBuilderCondition(io::Printer* printer, + const char* regular_case, const char* nested_builder_case) const; + void PrintNestedBuilderFunction(io::Printer* printer, + const char* method_prototype, const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc index cfe01885..ccc94c9d 100644 --- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc +++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc @@ -56,21 +56,22 @@ class TestGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { - TryInsert("Test.java", "outer_class_scope", output_directory); - TryInsert("Test.java", "class_scope:foo.Bar", output_directory); - TryInsert("Test.java", "class_scope:foo.Bar.Baz", output_directory); - TryInsert("Test.java", "builder_scope:foo.Bar", output_directory); - TryInsert("Test.java", "builder_scope:foo.Bar.Baz", output_directory); - TryInsert("Test.java", "enum_scope:foo.Qux", output_directory); + string filename = "Test.java"; + TryInsert(filename, "outer_class_scope", context); + TryInsert(filename, "class_scope:foo.Bar", context); + TryInsert(filename, "class_scope:foo.Bar.Baz", context); + TryInsert(filename, "builder_scope:foo.Bar", context); + TryInsert(filename, "builder_scope:foo.Bar.Baz", context); + TryInsert(filename, "enum_scope:foo.Qux", context); return true; } void TryInsert(const string& filename, const string& insertion_point, - OutputDirectory* output_directory) const { + GeneratorContext* context) const { scoped_ptr output( - output_directory->OpenForInsert(filename, insertion_point)); + context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index f6179bfa..addb8819 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -154,15 +154,24 @@ int FixedSize(FieldDescriptor::Type type) { } void SetPrimitiveVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, map* variables) { (*variables)["name"] = UnderscoresToCamelCase(descriptor); (*variables)["capitalized_name"] = UnderscoresToCapitalizedCamelCase(descriptor); + (*variables)["constant_name"] = FieldConstantName(descriptor); (*variables)["number"] = SimpleItoa(descriptor->number()); (*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_init"] = IsDefaultValueJavaDefault(descriptor) ? + "" : ("= " + DefaultValue(descriptor)); (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( @@ -175,67 +184,135 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, } else { (*variables)["null_check"] = ""; } + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; int fixed_size = FixedSize(GetType(descriptor)); if (fixed_size != -1) { (*variables)["fixed_size"] = SimpleItoa(fixed_size); } + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + // 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)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex); + + // For repated 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); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); } + } // namespace // =================================================================== PrimitiveFieldGenerator:: -PrimitiveFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, &variables_); +PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} +int PrimitiveFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int PrimitiveFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void PrimitiveFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n" + "$deprecation$$type$ get$capitalized_name$();\n"); +} + void PrimitiveFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private boolean has$capitalized_name$;\n" - "private $type$ $name$_ = $default$;\n" - "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" - "public $type$ get$capitalized_name$() { return $name$_; }\n"); + "private $field_type$ $name$_;\n" + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); } void PrimitiveFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, - "public boolean has$capitalized_name$() {\n" - " return result.has$capitalized_name$();\n" - "}\n" - "public $type$ get$capitalized_name$() {\n" - " return result.get$capitalized_name$();\n" - "}\n" - "public Builder set$capitalized_name$($type$ value) {\n" + "private $field_type$ $name$_ $default_init$;\n" + "$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 $name$_;\n" + "}\n"); + + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" "$null_check$" - " result.has$capitalized_name$ = true;\n" - " result.$name$_ = value;\n" + " $set_has_field_bit_builder$;\n" + " $name$_ = value;\n" + " $on_changed$\n" " return this;\n" "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.has$capitalized_name$ = false;\n"); + "$deprecation$public Builder clear$capitalized_name$() {\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 // it multiple times. Instead, get the default out of the default instance. printer->Print(variables_, - " result.$name$_ = getDefaultInstance().get$capitalized_name$();\n"); + " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); } else { printer->Print(variables_, - " result.$name$_ = $default$;\n"); + " $name$_ = $default$;\n"); } printer->Print(variables_, + " $on_changed$\n" " return this;\n" "}\n"); } +void PrimitiveFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + void PrimitiveFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - // Initialized inline. + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void PrimitiveFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$;\n"); } void PrimitiveFieldGenerator:: @@ -248,32 +325,121 @@ GenerateMergingCode(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - // Nothing to do here for primitive types. + 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:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "set$capitalized_name$(input.read$capitalized_type$());\n"); + "$set_has_field_bit_builder$;\n" + "$name$_ = input.read$capitalized_type$();\n"); } void PrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " output.write$capitalized_type$($number$, get$capitalized_name$());\n" + "if ($get_has_field_bit_message$) {\n" + " output.write$capitalized_type$($number$, $name$_);\n" "}\n"); } void PrimitiveFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if (has$capitalized_name$()) {\n" + "if ($get_has_field_bit_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$Size($number$, get$capitalized_name$());\n" + " .compute$capitalized_type$Size($number$, $name$_);\n" "}\n"); } +void PrimitiveFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + switch (GetJavaType(descriptor_)) { + case JAVATYPE_INT: + case JAVATYPE_LONG: + case JAVATYPE_BOOLEAN: + printer->Print(variables_, + "result = result && (get$capitalized_name$()\n" + " == other.get$capitalized_name$());\n"); + break; + + case JAVATYPE_FLOAT: + printer->Print(variables_, + "result = result && (Float.floatToIntBits(get$capitalized_name$())" + " == Float.floatToIntBits(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"); + break; + + case JAVATYPE_STRING: + case JAVATYPE_BYTES: + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); + break; + + case JAVATYPE_ENUM: + case JAVATYPE_MESSAGE: + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } +} + +void PrimitiveFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n"); + switch (GetJavaType(descriptor_)) { + case JAVATYPE_INT: + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$();\n"); + break; + + case JAVATYPE_LONG: + printer->Print(variables_, + "hash = (53 * hash) + hashLong(get$capitalized_name$());\n"); + break; + + case JAVATYPE_BOOLEAN: + printer->Print(variables_, + "hash = (53 * hash) + hashBoolean(get$capitalized_name$());\n"); + break; + + case JAVATYPE_FLOAT: + printer->Print(variables_, + "hash = (53 * hash) + 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"); + break; + + case JAVATYPE_STRING: + case JAVATYPE_BYTES: + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); + break; + + case JAVATYPE_ENUM: + case JAVATYPE_MESSAGE: + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } +} + string PrimitiveFieldGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } @@ -281,23 +447,46 @@ string PrimitiveFieldGenerator::GetBoxedType() const { // =================================================================== RepeatedPrimitiveFieldGenerator:: -RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { - SetPrimitiveVariables(descriptor, &variables_); +RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); } RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} +int RepeatedPrimitiveFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedPrimitiveFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + printer->Print(variables_, + "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n" + "$deprecation$int get$capitalized_name$Count();\n" + "$deprecation$$type$ get$capitalized_name$(int index);\n"); +} + + void RepeatedPrimitiveFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private java.util.List<$boxed_type$> $name$_ =\n" - " java.util.Collections.emptyList();\n" - "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n" + "private $field_list_type$ $name$_;\n" + "$deprecation$public java.util.List<$boxed_type$>\n" + " get$capitalized_name$List() {\n" " return $name$_;\n" // note: unmodifiable list "}\n" - "public int get$capitalized_name$Count() { return $name$_.size(); }\n" - "public $type$ get$capitalized_name$(int index) {\n" + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n" + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" " return $name$_.get(index);\n" "}\n"); @@ -310,76 +499,125 @@ GenerateMembers(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: 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 + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + printer->Print(variables_, + "private $field_list_type$ $name$_ = $empty_list$;\n"); + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new java.util.ArrayList<$boxed_type$>($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); + // Note: We return an unmodifiable list because otherwise the caller // could hold on to the returned list and modify it after the message // has been built, thus mutating the message which is supposed to be // immutable. - "public java.util.List<$boxed_type$> get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList(result.$name$_);\n" + printer->Print(variables_, + "$deprecation$public java.util.List<$boxed_type$>\n" + " get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" "}\n" - "public int get$capitalized_name$Count() {\n" - " return result.get$capitalized_name$Count();\n" + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" "}\n" - "public $type$ get$capitalized_name$(int index) {\n" - " return result.get$capitalized_name$(index);\n" + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" "}\n" - "public Builder set$capitalized_name$(int index, $type$ value) {\n" + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value) {\n" "$null_check$" - " result.$name$_.set(index, value);\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" " return this;\n" "}\n" - "public Builder add$capitalized_name$($type$ value) {\n" + "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" "$null_check$" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" - " }\n" - " result.$name$_.add(value);\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" " return this;\n" "}\n" - "public Builder addAll$capitalized_name$(\n" + "$deprecation$public Builder addAll$capitalized_name$(\n" " java.lang.Iterable values) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" - " }\n" - " super.addAll(values, result.$name$_);\n" + " ensure$capitalized_name$IsMutable();\n" + " super.addAll(values, $name$_);\n" + " $on_changed$\n" " return this;\n" "}\n" - "public Builder clear$capitalized_name$() {\n" - " result.$name$_ = java.util.Collections.emptyList();\n" + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $name$_ = $empty_list$;\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" " return this;\n" "}\n"); } +void RepeatedPrimitiveFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + void RepeatedPrimitiveFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - // Initialized inline. + printer->Print(variables_, "$name$_ = $empty_list$;\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $empty_list$;\n" + "$clear_mutable_bit_builder$;\n"); } void RepeatedPrimitiveFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. printer->Print(variables_, "if (!other.$name$_.isEmpty()) {\n" - " if (result.$name$_.isEmpty()) {\n" - " result.$name$_ = new java.util.ArrayList<$boxed_type$>();\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" " }\n" - " result.$name$_.addAll(other.$name$_);\n" + " $on_changed$\n" "}\n"); } void RepeatedPrimitiveFieldGenerator:: 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 (result.$name$_ != java.util.Collections.EMPTY_LIST) {\n" - " result.$name$_ =\n" - " java.util.Collections.unmodifiableList(result.$name$_);\n" - "}\n"); + "if ($get_mutable_bit_builder$) {\n" + " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); } void RepeatedPrimitiveFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "add$capitalized_name$(input.read$capitalized_type$());\n"); + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(input.read$capitalized_type$());\n"); } void RepeatedPrimitiveFieldGenerator:: @@ -401,13 +639,13 @@ GenerateSerializationCode(io::Printer* printer) const { " output.writeRawVarint32($tag$);\n" " output.writeRawVarint32($name$MemoizedSerializedSize);\n" "}\n" - "for ($type$ element : get$capitalized_name$List()) {\n" - " output.write$capitalized_type$NoTag(element);\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$NoTag($name$_.get(i));\n" "}\n"); } else { printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" - " output.write$capitalized_type$($number$, element);\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$($number$, $name$_.get(i));\n" "}\n"); } } @@ -421,9 +659,9 @@ GenerateSerializedSizeCode(io::Printer* printer) const { if (FixedSize(GetType(descriptor_)) == -1) { printer->Print(variables_, - "for ($type$ element : get$capitalized_name$List()) {\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" " dataSize += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$SizeNoTag(element);\n" + " .compute$capitalized_type$SizeNoTag($name$_.get(i));\n" "}\n"); } else { printer->Print(variables_, @@ -455,6 +693,22 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print("}\n"); } +void RepeatedPrimitiveFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedPrimitiveFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); +} + string RepeatedPrimitiveFieldGenerator::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 4e482a05..7900fac5 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.h +++ b/src/google/protobuf/compiler/java/java_primitive_field.h @@ -46,49 +46,69 @@ namespace java { class PrimitiveFieldGenerator : public FieldGenerator { public: - explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor); + explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); ~PrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; private: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; class RepeatedPrimitiveFieldGenerator : public FieldGenerator { public: - explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor); + explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); ~RepeatedPrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateBuildingCode(io::Printer* printer) const; void GenerateParsingCode(io::Printer* printer) const; void GenerateParsingCodeFromPacked(io::Printer* printer) const; void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; string GetBoxedType() const; private: const FieldDescriptor* descriptor_; map variables_; + const int messageBitIndex_; + const int builderBitIndex_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); }; diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc index 5545bf7f..1ae4f461 100644 --- a/src/google/protobuf/compiler/java/java_service.cc +++ b/src/google/protobuf/compiler/java/java_service.cc @@ -118,7 +118,7 @@ void ServiceGenerator::GenerateNewReflectiveServiceMethod( for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - printer->Print("@Override\n"); + printer->Print("@java.lang.Override\n"); GenerateMethodSignature(printer, method, IS_CONCRETE); printer->Print( " {\n" diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc new file mode 100644 index 00000000..a93ff434 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -0,0 +1,605 @@ +// 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: kenton@google.com (Kenton Varda) +// Author: jonp@google.com (Jon Perlow) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +void SetPrimitiveVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + map* variables) { + (*variables)["name"] = + UnderscoresToCamelCase(descriptor); + (*variables)["capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor); + (*variables)["constant_name"] = FieldConstantName(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; + + (*variables)["default"] = DefaultValue(descriptor); + (*variables)["default_init"] = ("= " + DefaultValue(descriptor)); + (*variables)["capitalized_type"] = "String"; + (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); + (*variables)["tag_size"] = SimpleItoa( + WireFormat::TagSize(descriptor->number(), GetType(descriptor))); + (*variables)["null_check"] = + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n"; + + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + // 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)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex); + + // For repated 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); + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); +} + +} // namespace + +// =================================================================== + +StringFieldGenerator:: +StringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); +} + +StringFieldGenerator::~StringFieldGenerator() {} + +int StringFieldGenerator::GetNumBitsForMessage() const { + return 1; +} + +int StringFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +// A note about how strings are handled. This code used to just store a String +// in the Message. This had two issues: +// +// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded +// strings, but rather fields that were raw bytes incorrectly marked +// as strings in the proto file. This is common because in the proto1 +// syntax, string was the way to indicate bytes and C++ engineers can +// easily make this mistake without affecting the C++ API. By converting to +// strings immediately, some java code might corrupt these byte arrays as +// it passes through a java server even if the field was never accessed by +// application code. +// +// 2. There's a performance hit to converting between bytes and strings and +// it many cases, the field is never even read by the application code. This +// avoids unnecessary conversions in the common use cases. +// +// So now, the field for String is maintained as an Object reference which can +// either store a String or a ByteString. The code uses an instanceof check +// to see which one it has and converts to the other one if needed. It remembers +// the last value requested (in a thread safe manner) as this is most likely +// the one needed next. The thread safety is such that if two threads both +// convert the field because the changes made by each thread were not visible to +// the other, they may cause a conversion to happen more times than would +// otherwise be necessary. This was deemed better than adding synchronization +// overhead. It will not cause any corruption issues or affect the behavior of +// the API. The instanceof check is also highly optimized in the JVM and we +// decided it was better to reduce the memory overhead by not having two +// separate fields but rather use dynamic type checking. +// +// For single fields, the logic for this is done inside the generated code. For +// repeated fields, the logic is done in LazyStringArrayList and +// UnmodifiableLazyStringList. +void StringFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n" + "$deprecation$String get$capitalized_name$();\n"); +} + +void StringFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private Object $name$_;\n" + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + + printer->Print(variables_, + "$deprecation$public String get$capitalized_name$() {\n" + " Object ref = $name$_;\n" + " if (ref instanceof String) {\n" + " return (String) ref;\n" + " } else {\n" + " com.google.protobuf.ByteString bs = \n" + " (com.google.protobuf.ByteString) ref;\n" + " String s = bs.toStringUtf8();\n" + " if (com.google.protobuf.Internal.isValidUtf8(bs)) {\n" + " $name$_ = s;\n" + " }\n" + " return s;\n" + " }\n" + "}\n" + "private com.google.protobuf.ByteString get$capitalized_name$Bytes() {\n" + " Object ref = $name$_;\n" + " if (ref instanceof String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8((String) ref);\n" + " $name$_ = b;\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + printer->Print(variables_, + "private Object $name$_ $default_init$;\n" + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + + printer->Print(variables_, + "$deprecation$public String get$capitalized_name$() {\n" + " Object ref = $name$_;\n" + " if (!(ref instanceof String)) {\n" + " String s = ((com.google.protobuf.ByteString) ref).toStringUtf8();\n" + " $name$_ = s;\n" + " return s;\n" + " } else {\n" + " return (String) ref;\n" + " }\n" + "}\n"); + + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(String value) {\n" + "$null_check$" + " $set_has_field_bit_builder$;\n" + " $name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n" + "$deprecation$public Builder clear$capitalized_name$() {\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_, + " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); + printer->Print(variables_, + " $on_changed$\n" + " return this;\n" + "}\n"); + + printer->Print(variables_, + "void set$capitalized_name$(com.google.protobuf.ByteString value) {\n" + " $set_has_field_bit_builder$;\n" + " $name$_ = value;\n" + " $on_changed$\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void StringFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void StringFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$;\n"); +} + +void StringFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + 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:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$set_has_field_bit_builder$;\n" + "$name$_ = input.readBytes();\n"); +} + +void StringFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void StringFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); +} + +void StringFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n"); + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); +} + +string StringFieldGenerator::GetBoxedType() const { + return "String"; +} + + +// =================================================================== + +RepeatedStringFieldGenerator:: +RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + &variables_); +} + +RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {} + +int RepeatedStringFieldGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedStringFieldGenerator::GetNumBitsForBuilder() const { + return 1; +} + +void RepeatedStringFieldGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + printer->Print(variables_, + "$deprecation$java.util.List get$capitalized_name$List();\n" + "$deprecation$int get$capitalized_name$Count();\n" + "$deprecation$String get$capitalized_name$(int index);\n"); +} + + +void RepeatedStringFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private com.google.protobuf.LazyStringList $name$_;\n" + "$deprecation$public java.util.List\n" + " get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n" + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n" + "$deprecation$public String get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + + if (descriptor_->options().packed() && + HasGeneratedMethods(descriptor_->containing_type())) { + printer->Print(variables_, + "private int $name$MemoizedSerializedSize = -1;\n"); + } +} + +void RepeatedStringFieldGenerator:: +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 + // either an instance of Collections.emptyList() or it's an ArrayList + // wrapped in a Collections.unmodifiableList() wrapper and nobody else has + // a refererence to the underlying ArrayList. This invariant allows us to + // share instances of lists between protocol buffers avoiding expensive + // memory allocations. Note, immutable is a strong guarantee here -- not + // just that the list cannot be modified via the reference but that the + // list can never be modified. + printer->Print(variables_, + "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n"); + + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n"); + + // Note: We return an unmodifiable list because otherwise the caller + // could hold on to the returned list and modify it after the message + // has been built, thus mutating the message which is supposed to be + // immutable. + printer->Print(variables_, + "$deprecation$public java.util.List\n" + " get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + "}\n" + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n" + "$deprecation$public String get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n" + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + " $on_changed$\n" + " return this;\n" + "}\n" + "$deprecation$public Builder add$capitalized_name$(String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + " return this;\n" + "}\n" + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " super.addAll(values, $name$_);\n" + " $on_changed$\n" + " return this;\n" + "}\n" + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $name$_ = $empty_list$;\n" + " $clear_mutable_bit_builder$;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + + printer->Print(variables_, + "void add$capitalized_name$(com.google.protobuf.ByteString value) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + " $on_changed$\n" + "}\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void RepeatedStringFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $empty_list$;\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_ = $empty_list$;\n" + "$clear_mutable_bit_builder$;\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + printer->Print(variables_, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $clear_mutable_bit_builder$;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); +} + +void RepeatedStringFieldGenerator:: +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" + " $clear_mutable_bit_builder$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(input.readBytes());\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + printer->Print(variables_, + "int length = input.readRawVarint32();\n" + "int limit = input.pushLimit(length);\n" + "while (input.getBytesUntilLimit() > 0) {\n" + " add$capitalized_name$(input.read$capitalized_type$());\n" + "}\n" + "input.popLimit(limit);\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (get$capitalized_name$List().size() > 0) {\n" + " output.writeRawVarint32($tag$);\n" + " output.writeRawVarint32($name$MemoizedSerializedSize);\n" + "}\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$NoTag($name$_.get(i));\n" + "}\n"); + } else { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeBytes($number$, $name$_.getByteString(i));\n" + "}\n"); + } +} + +void RepeatedStringFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "{\n" + " int dataSize = 0;\n"); + printer->Indent(); + + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSizeNoTag($name$_.getByteString(i));\n" + "}\n"); + + printer->Print( + "size += dataSize;\n"); + + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (!get$capitalized_name$List().isEmpty()) {\n" + " size += $tag_size$;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeInt32SizeNoTag(dataSize);\n" + "}\n"); + } else { + printer->Print(variables_, + "size += $tag_size$ * get$capitalized_name$List().size();\n"); + } + + // cache the data size for packed fields. + if (descriptor_->options().packed()) { + printer->Print(variables_, + "$name$MemoizedSerializedSize = dataSize;\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedStringFieldGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); +} + +string RepeatedStringFieldGenerator::GetBoxedType() const { + return "String"; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h new file mode 100644 index 00000000..8cb41469 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_string_field.h @@ -0,0 +1,120 @@ +// 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: kenton@google.com (Kenton Varda) +// Author: jonp@google.com (Jon Perlow) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +class StringFieldGenerator : public FieldGenerator { + public: + explicit StringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); + ~StringFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator); +}; + +class RepeatedStringFieldGenerator : public FieldGenerator { + public: + explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex); + ~RepeatedStringFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingCodeFromPacked(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index 83d5a4e4..5b76af25 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -45,6 +45,16 @@ namespace google { namespace protobuf { namespace compiler { +// Returns the list of the names of files in all_files in the form of a +// comma-separated string. +string CommaSeparatedList(const vector all_files) { + vector names; + for (int i = 0; i < all_files.size(); i++) { + names.push_back(all_files[i]->name()); + } + return JoinStrings(names, ","); +} + static const char* kFirstInsertionPointName = "first_mock_insertion_point"; static const char* kSecondInsertionPointName = "second_mock_insertion_point"; static const char* kFirstInsertionPoint = @@ -63,6 +73,7 @@ void MockCodeGenerator::ExpectGenerated( const string& insertions, const string& file, const string& first_message_name, + const string& first_parsed_file_name, const string& output_directory) { string content; ASSERT_TRUE(File::ReadFileToString( @@ -84,7 +95,8 @@ void MockCodeGenerator::ExpectGenerated( } ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2); - EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_message_name), + EXPECT_EQ(GetOutputFileContent(name, parameter, file, + first_parsed_file_name, first_message_name), lines[0]); EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]); @@ -92,12 +104,12 @@ void MockCodeGenerator::ExpectGenerated( for (int i = 0; i < insertion_list.size(); i++) { EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert", - file, first_message_name), + file, file, first_message_name), lines[1 + i]); // Second insertion point is indented, so the inserted text should // automatically be indented too. EXPECT_EQ(" " + GetOutputFileContent(insertion_list[i], "second_insert", - file, first_message_name), + file, file, first_message_name), lines[2 + insertion_list.size() + i]); } } @@ -105,7 +117,7 @@ void MockCodeGenerator::ExpectGenerated( bool MockCodeGenerator::Generate( const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { for (int i = 0; i < file->message_type_count(); i++) { if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) { @@ -134,11 +146,12 @@ bool MockCodeGenerator::Generate( for (int i = 0; i < insert_into.size(); i++) { { scoped_ptr output( - output_directory->OpenForInsert( + context->OpenForInsert( GetOutputFileName(insert_into[i], file), kFirstInsertionPointName)); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, "first_insert", file)); + printer.PrintRaw(GetOutputFileContent(name_, "first_insert", + file, context)); if (printer.failed()) { *error = "MockCodeGenerator detected write error."; return false; @@ -147,11 +160,12 @@ bool MockCodeGenerator::Generate( { scoped_ptr output( - output_directory->OpenForInsert( + context->OpenForInsert( GetOutputFileName(insert_into[i], file), kSecondInsertionPointName)); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, "second_insert", file)); + printer.PrintRaw(GetOutputFileContent(name_, "second_insert", + file, context)); if (printer.failed()) { *error = "MockCodeGenerator detected write error."; return false; @@ -160,10 +174,11 @@ bool MockCodeGenerator::Generate( } } else { scoped_ptr output( - output_directory->Open(GetOutputFileName(name_, file))); + context->Open(GetOutputFileName(name_, file))); io::Printer printer(output.get(), '$'); - printer.PrintRaw(GetOutputFileContent(name_, parameter, file)); + printer.PrintRaw(GetOutputFileContent(name_, parameter, + file, context)); printer.PrintRaw(kFirstInsertionPoint); printer.PrintRaw(kSecondInsertionPoint); @@ -186,11 +201,16 @@ string MockCodeGenerator::GetOutputFileName(const string& generator_name, return file + ".MockCodeGenerator." + generator_name; } -string MockCodeGenerator::GetOutputFileContent(const string& generator_name, - const string& parameter, - const FileDescriptor* file) { +string MockCodeGenerator::GetOutputFileContent( + const string& generator_name, + const string& parameter, + const FileDescriptor* file, + GeneratorContext *context) { + vector all_files; + context->ListParsedFiles(&all_files); return GetOutputFileContent( generator_name, parameter, file->name(), + CommaSeparatedList(all_files), file->message_type_count() > 0 ? file->message_type(0)->name() : "(none)"); } @@ -199,9 +219,11 @@ string MockCodeGenerator::GetOutputFileContent( const string& generator_name, const string& parameter, const string& file, + const string& parsed_file_list, const string& first_message_name) { - return strings::Substitute("$0: $1, $2, $3\n", - generator_name, parameter, file, first_message_name); + return strings::Substitute("$0: $1, $2, $3, $4\n", + generator_name, parameter, file, + first_message_name, parsed_file_list); } } // namespace compiler diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h index 01d69dd2..5c7942bd 100644 --- a/src/google/protobuf/compiler/mock_code_generator.h +++ b/src/google/protobuf/compiler/mock_code_generator.h @@ -69,11 +69,14 @@ class MockCodeGenerator : public CodeGenerator { // // |insertions| is a comma-separated list of names of MockCodeGenerators which // should have inserted lines into this file. + // |parsed_file_list| is a comma-separated list of names of the files + // that are being compiled together in this run. static void ExpectGenerated(const string& name, const string& parameter, const string& insertions, const string& file, const string& first_message_name, + const string& parsed_file_list, const string& output_directory); // Get the name of the file which would be written by the given generator. @@ -86,7 +89,7 @@ class MockCodeGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const; private: @@ -94,10 +97,12 @@ class MockCodeGenerator : public CodeGenerator { static string GetOutputFileContent(const string& generator_name, const string& parameter, - const FileDescriptor* file); + const FileDescriptor* file, + GeneratorContext *context); static string GetOutputFileContent(const string& generator_name, const string& parameter, const string& file, + const string& parsed_file_list, const string& first_message_name); }; diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 9fcb1314..34317b1f 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -250,20 +250,69 @@ void Parser::AddError(const string& error) { AddError(input_->current().line, input_->current().column, error); } -void Parser::RecordLocation( - const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location, - int line, int column) { - if (source_location_table_ != NULL) { - source_location_table_->Add(descriptor, location, line, column); +// ------------------------------------------------------------------- + +Parser::LocationRecorder::LocationRecorder(Parser* parser) + : parser_(parser), + location_(parser_->source_code_info_->add_location()) { + location_->add_span(parser_->input_->current().line); + location_->add_span(parser_->input_->current().column); +} + +Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent) { + Init(parent); +} + +Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, + int path1) { + Init(parent); + AddPath(path1); +} + +Parser::LocationRecorder::LocationRecorder(const LocationRecorder& parent, + int path1, int path2) { + Init(parent); + AddPath(path1); + AddPath(path2); +} + +void Parser::LocationRecorder::Init(const LocationRecorder& parent) { + parser_ = parent.parser_; + location_ = parser_->source_code_info_->add_location(); + location_->mutable_path()->CopyFrom(parent.location_->path()); + + location_->add_span(parser_->input_->current().line); + location_->add_span(parser_->input_->current().column); +} + +Parser::LocationRecorder::~LocationRecorder() { + if (location_->span_size() <= 2) { + EndAt(parser_->input_->previous()); } } -void Parser::RecordLocation( - const Message* descriptor, +void Parser::LocationRecorder::AddPath(int path_component) { + location_->add_path(path_component); +} + +void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) { + location_->set_span(0, token.line); + location_->set_span(1, token.column); +} + +void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) { + if (token.line != location_->span(0)) { + location_->add_span(token.line); + } + location_->add_span(token.end_column); +} + +void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor, DescriptorPool::ErrorCollector::ErrorLocation location) { - RecordLocation(descriptor, location, - input_->current().line, input_->current().column); + if (parser_->source_location_table_ != NULL) { + parser_->source_location_table_->Add( + descriptor, location, location_->span(0), location_->span(1)); + } } // ------------------------------------------------------------------- @@ -308,38 +357,51 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { had_errors_ = false; syntax_identifier_.clear(); + // Note that |file| could be NULL at this point if + // stop_after_syntax_identifier_ is true. So, we conservatively allocate + // SourceCodeInfo on the stack, then swap it into the FileDescriptorProto + // later on. + SourceCodeInfo source_code_info; + source_code_info_ = &source_code_info; + if (LookingAtType(io::Tokenizer::TYPE_START)) { // Advance to first token. input_->Next(); } - if (require_syntax_identifier_ || LookingAt("syntax")) { - if (!ParseSyntaxIdentifier()) { - // Don't attempt to parse the file if we didn't recognize the syntax - // identifier. - return false; + { + LocationRecorder root_location(this); + + if (require_syntax_identifier_ || LookingAt("syntax")) { + if (!ParseSyntaxIdentifier()) { + // Don't attempt to parse the file if we didn't recognize the syntax + // identifier. + return false; + } + } else if (!stop_after_syntax_identifier_) { + syntax_identifier_ = "proto2"; } - } else if (!stop_after_syntax_identifier_) { - syntax_identifier_ = "proto2"; - } - if (stop_after_syntax_identifier_) return !had_errors_; + if (stop_after_syntax_identifier_) return !had_errors_; - // Repeatedly parse statements until we reach the end of the file. - while (!AtEnd()) { - if (!ParseTopLevelStatement(file)) { - // This statement failed to parse. Skip it, but keep looping to parse - // other statements. - SkipStatement(); + // Repeatedly parse statements until we reach the end of the file. + while (!AtEnd()) { + if (!ParseTopLevelStatement(file, root_location)) { + // This statement failed to parse. Skip it, but keep looping to parse + // other statements. + SkipStatement(); - if (LookingAt("}")) { - AddError("Unmatched \"}\"."); - input_->Next(); + if (LookingAt("}")) { + AddError("Unmatched \"}\"."); + input_->Next(); + } } } } input_ = NULL; + source_code_info_ = NULL; + source_code_info.Swap(file->mutable_source_code_info()); return !had_errors_; } @@ -363,25 +425,40 @@ bool Parser::ParseSyntaxIdentifier() { return true; } -bool Parser::ParseTopLevelStatement(FileDescriptorProto* file) { +bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, + const LocationRecorder& root_location) { if (TryConsume(";")) { // empty statement; ignore return true; } else if (LookingAt("message")) { - return ParseMessageDefinition(file->add_message_type()); + LocationRecorder location(root_location, + FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size()); + return ParseMessageDefinition(file->add_message_type(), location); } else if (LookingAt("enum")) { - return ParseEnumDefinition(file->add_enum_type()); + LocationRecorder location(root_location, + FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size()); + return ParseEnumDefinition(file->add_enum_type(), location); } else if (LookingAt("service")) { - return ParseServiceDefinition(file->add_service()); + LocationRecorder location(root_location, + FileDescriptorProto::kServiceFieldNumber, file->service_size()); + return ParseServiceDefinition(file->add_service(), location); } else if (LookingAt("extend")) { + LocationRecorder location(root_location, + FileDescriptorProto::kExtensionFieldNumber); return ParseExtend(file->mutable_extension(), - file->mutable_message_type()); + file->mutable_message_type(), + root_location, + FileDescriptorProto::kMessageTypeFieldNumber, + location); } else if (LookingAt("import")) { - return ParseImport(file->add_dependency()); + int index = file->dependency_size(); + return ParseImport(file->add_dependency(), root_location, index); } else if (LookingAt("package")) { - return ParsePackage(file); + return ParsePackage(file, root_location); } else if (LookingAt("option")) { - return ParseOption(file->mutable_options()); + LocationRecorder location(root_location, + FileDescriptorProto::kOptionsFieldNumber); + return ParseOption(file->mutable_options(), location); } else { AddError("Expected top-level statement (e.g. \"message\")."); return false; @@ -391,15 +468,22 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file) { // ------------------------------------------------------------------- // Messages -bool Parser::ParseMessageDefinition(DescriptorProto* message) { +bool Parser::ParseMessageDefinition(DescriptorProto* message, + const LocationRecorder& message_location) { DO(Consume("message")); - RecordLocation(message, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); - DO(ParseMessageBlock(message)); + { + LocationRecorder location(message_location, + DescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + message, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); + } + DO(ParseMessageBlock(message, message_location)); return true; } -bool Parser::ParseMessageBlock(DescriptorProto* message) { +bool Parser::ParseMessageBlock(DescriptorProto* message, + const LocationRecorder& message_location) { DO(Consume("{")); while (!TryConsume("}")) { @@ -408,7 +492,7 @@ bool Parser::ParseMessageBlock(DescriptorProto* message) { return false; } - if (!ParseMessageStatement(message)) { + if (!ParseMessageStatement(message, message_location)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -418,66 +502,133 @@ bool Parser::ParseMessageBlock(DescriptorProto* message) { return true; } -bool Parser::ParseMessageStatement(DescriptorProto* message) { +bool Parser::ParseMessageStatement(DescriptorProto* message, + const LocationRecorder& message_location) { if (TryConsume(";")) { // empty statement; ignore return true; } else if (LookingAt("message")) { - return ParseMessageDefinition(message->add_nested_type()); + LocationRecorder location(message_location, + DescriptorProto::kNestedTypeFieldNumber, + message->nested_type_size()); + return ParseMessageDefinition(message->add_nested_type(), location); } else if (LookingAt("enum")) { - return ParseEnumDefinition(message->add_enum_type()); + LocationRecorder location(message_location, + DescriptorProto::kEnumTypeFieldNumber, + message->enum_type_size()); + return ParseEnumDefinition(message->add_enum_type(), location); } else if (LookingAt("extensions")) { - return ParseExtensions(message); + LocationRecorder location(message_location, + DescriptorProto::kExtensionRangeFieldNumber); + return ParseExtensions(message, location); } else if (LookingAt("extend")) { + LocationRecorder location(message_location, + DescriptorProto::kExtensionFieldNumber); return ParseExtend(message->mutable_extension(), - message->mutable_nested_type()); + message->mutable_nested_type(), + message_location, + DescriptorProto::kNestedTypeFieldNumber, + location); } else if (LookingAt("option")) { - return ParseOption(message->mutable_options()); + LocationRecorder location(message_location, + DescriptorProto::kOptionsFieldNumber); + return ParseOption(message->mutable_options(), location); } else { + LocationRecorder location(message_location, + DescriptorProto::kFieldFieldNumber, + message->field_size()); return ParseMessageField(message->add_field(), - message->mutable_nested_type()); + message->mutable_nested_type(), + message_location, + DescriptorProto::kNestedTypeFieldNumber, + location); } } bool Parser::ParseMessageField(FieldDescriptorProto* field, - RepeatedPtrField* messages) { + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& field_location) { // Parse label and type. - FieldDescriptorProto::Label label; - DO(ParseLabel(&label)); - field->set_label(label); - - RecordLocation(field, DescriptorPool::ErrorCollector::TYPE); - FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32; - string type_name; - DO(ParseType(&type, &type_name)); - if (type_name.empty()) { - field->set_type(type); - } else { - field->set_type_name(type_name); + io::Tokenizer::Token label_token = input_->current(); + { + LocationRecorder location(field_location, + FieldDescriptorProto::kLabelFieldNumber); + FieldDescriptorProto::Label label; + DO(ParseLabel(&label)); + field->set_label(label); + } + + { + LocationRecorder location(field_location); // add path later + location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE); + + FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32; + string type_name; + DO(ParseType(&type, &type_name)); + if (type_name.empty()) { + location.AddPath(FieldDescriptorProto::kTypeFieldNumber); + field->set_type(type); + } else { + location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber); + field->set_type_name(type_name); + } } // Parse name and '='. - RecordLocation(field, DescriptorPool::ErrorCollector::NAME); io::Tokenizer::Token name_token = input_->current(); - DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); + { + LocationRecorder location(field_location, + FieldDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); + } DO(Consume("=", "Missing field number.")); // Parse field number. - RecordLocation(field, DescriptorPool::ErrorCollector::NUMBER); - int number; - DO(ConsumeInteger(&number, "Expected field number.")); - field->set_number(number); + { + LocationRecorder location(field_location, + FieldDescriptorProto::kNumberFieldNumber); + location.RecordLegacyLocation( + field, DescriptorPool::ErrorCollector::NUMBER); + int number; + DO(ConsumeInteger(&number, "Expected field number.")); + field->set_number(number); + } // Parse options. - DO(ParseFieldOptions(field)); + DO(ParseFieldOptions(field, field_location)); // Deal with groups. - if (type_name.empty() && type == FieldDescriptorProto::TYPE_GROUP) { + 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.AddPath(location_field_number_for_nested_type); + group_location.AddPath(messages->size()); + DescriptorProto* group = messages->Add(); group->set_name(field->name()); + // Record name location to match the field name's location. - RecordLocation(group, DescriptorPool::ErrorCollector::NAME, - name_token.line, name_token.column); + { + LocationRecorder location(group_location, + DescriptorProto::kNameFieldNumber); + location.StartAt(name_token); + location.EndAt(name_token); + location.RecordLegacyLocation( + group, DescriptorPool::ErrorCollector::NAME); + } + + // The field's type_name also comes from the name. Confusing! + { + LocationRecorder location(field_location, + FieldDescriptorProto::kTypeNameFieldNumber); + location.StartAt(name_token); + location.EndAt(name_token); + } // As a hack for backwards-compatibility, we force the group name to start // with a capital letter and lower-case the field name. New code should @@ -490,7 +641,7 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field, field->set_type_name(group->name()); if (LookingAt("{")) { - DO(ParseMessageBlock(group)); + DO(ParseMessageBlock(group, group_location)); } else { AddError("Missing group body."); return false; @@ -502,15 +653,23 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field, return true; } -bool Parser::ParseFieldOptions(FieldDescriptorProto* field) { - if (!TryConsume("[")) return true; +bool Parser::ParseFieldOptions(FieldDescriptorProto* field, + const LocationRecorder& field_location) { + if (!LookingAt("[")) return true; + + LocationRecorder location(field_location, + FieldDescriptorProto::kOptionsFieldNumber); + + DO(Consume("[")); // Parse field options. do { if (LookingAt("default")) { - DO(ParseDefaultAssignment(field)); + // We intentionally pass field_location rather than location here, since + // the default value is not actually an option. + DO(ParseDefaultAssignment(field, field_location)); } else { - DO(ParseOptionAssignment(field->mutable_options())); + DO(ParseOptionAssignment(field->mutable_options(), location)); } } while (TryConsume(",")); @@ -518,7 +677,8 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field) { return true; } -bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { +bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field, + const LocationRecorder& field_location) { if (field->has_default_value()) { AddError("Already set option \"default\"."); field->clear_default_value(); @@ -527,7 +687,10 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { DO(Consume("default")); DO(Consume("=")); - RecordLocation(field, DescriptorPool::ErrorCollector::DEFAULT_VALUE); + LocationRecorder location(field_location, + FieldDescriptorProto::kDefaultValueFieldNumber); + location.RecordLegacyLocation( + field, DescriptorPool::ErrorCollector::DEFAULT_VALUE); string* default_value = field->mutable_default_value(); if (!field->has_type()) { @@ -634,26 +797,35 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field) { return true; } -bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option) { +bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option, + const LocationRecorder& part_location) { UninterpretedOption::NamePart* name = uninterpreted_option->add_name(); string identifier; // We parse identifiers into this string. if (LookingAt("(")) { // This is an extension. DO(Consume("(")); - // An extension name consists of dot-separated identifiers, and may begin - // with a dot. - if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { - DO(ConsumeIdentifier(&identifier, "Expected identifier.")); - name->mutable_name_part()->append(identifier); - } - while (LookingAt(".")) { - DO(Consume(".")); - name->mutable_name_part()->append("."); - DO(ConsumeIdentifier(&identifier, "Expected identifier.")); - name->mutable_name_part()->append(identifier); + + { + LocationRecorder location( + part_location, UninterpretedOption::NamePart::kNamePartFieldNumber); + // An extension name consists of dot-separated identifiers, and may begin + // with a dot. + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + name->mutable_name_part()->append(identifier); + } + while (LookingAt(".")) { + DO(Consume(".")); + name->mutable_name_part()->append("."); + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + name->mutable_name_part()->append(identifier); + } } + DO(Consume(")")); name->set_is_extension(true); } else { // This is a regular field. + LocationRecorder location( + part_location, UninterpretedOption::NamePart::kNamePartFieldNumber); DO(ConsumeIdentifier(&identifier, "Expected identifier.")); name->mutable_name_part()->append(identifier); name->set_is_extension(false); @@ -661,34 +833,75 @@ bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option) { return true; } +bool Parser::ParseUninterpretedBlock(string* value) { + // Note that enclosing braces are not added to *value. + DO(Consume("{")); + int brace_depth = 1; + while (!AtEnd()) { + if (LookingAt("{")) { + brace_depth++; + } else if (LookingAt("}")) { + brace_depth--; + if (brace_depth == 0) { + input_->Next(); + return true; + } + } + // TODO(sanjay): Interpret line/column numbers to preserve formatting + if (!value->empty()) value->push_back(' '); + value->append(input_->current().text); + input_->Next(); + } + AddError("Unexpected end of stream while parsing aggregate value."); + return false; +} + // We don't interpret the option here. Instead we store it in an // UninterpretedOption, to be interpreted later. -bool Parser::ParseOptionAssignment(Message* options) { +bool Parser::ParseOptionAssignment(Message* options, + const LocationRecorder& options_location) { // Create an entry in the uninterpreted_option field. const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()-> FindFieldByName("uninterpreted_option"); GOOGLE_CHECK(uninterpreted_option_field != NULL) << "No field named \"uninterpreted_option\" in the Options proto."; + const Reflection* reflection = options->GetReflection(); + + LocationRecorder location( + options_location, uninterpreted_option_field->number(), + reflection->FieldSize(*options, uninterpreted_option_field)); + UninterpretedOption* uninterpreted_option = down_cast( options->GetReflection()->AddMessage(options, uninterpreted_option_field)); // Parse dot-separated name. - RecordLocation(uninterpreted_option, - DescriptorPool::ErrorCollector::OPTION_NAME); - - DO(ParseOptionNamePart(uninterpreted_option)); + { + LocationRecorder name_location(location, + UninterpretedOption::kNameFieldNumber); + name_location.RecordLegacyLocation( + uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_NAME); + + { + LocationRecorder part_location(name_location, + uninterpreted_option->name_size()); + DO(ParseOptionNamePart(uninterpreted_option, part_location)); + } - while (LookingAt(".")) { - DO(Consume(".")); - DO(ParseOptionNamePart(uninterpreted_option)); + while (LookingAt(".")) { + DO(Consume(".")); + LocationRecorder part_location(name_location, + uninterpreted_option->name_size()); + DO(ParseOptionNamePart(uninterpreted_option, part_location)); + } } DO(Consume("=")); - RecordLocation(uninterpreted_option, - DescriptorPool::ErrorCollector::OPTION_VALUE); + LocationRecorder value_location(location); + value_location.RecordLegacyLocation( + uninterpreted_option, DescriptorPool::ErrorCollector::OPTION_VALUE); // All values are a single token, except for negative numbers, which consist // of a single '-' symbol, followed by a positive number. @@ -704,6 +917,7 @@ bool Parser::ParseOptionAssignment(Message* options) { return false; case io::Tokenizer::TYPE_IDENTIFIER: { + value_location.AddPath(UninterpretedOption::kIdentifierValueFieldNumber); if (is_negative) { AddError("Invalid '-' symbol before identifier."); return false; @@ -720,15 +934,19 @@ bool Parser::ParseOptionAssignment(Message* options) { is_negative ? static_cast(kint64max) + 1 : kuint64max; DO(ConsumeInteger64(max_value, &value, "Expected integer.")); if (is_negative) { - uninterpreted_option->set_negative_int_value( - -static_cast(value)); + value_location.AddPath( + UninterpretedOption::kNegativeIntValueFieldNumber); + uninterpreted_option->set_negative_int_value(-static_cast(value)); } else { + value_location.AddPath( + UninterpretedOption::kPositiveIntValueFieldNumber); uninterpreted_option->set_positive_int_value(value); } break; } case io::Tokenizer::TYPE_FLOAT: { + value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber); double value; DO(ConsumeNumber(&value, "Expected number.")); uninterpreted_option->set_double_value(is_negative ? -value : value); @@ -736,6 +954,7 @@ bool Parser::ParseOptionAssignment(Message* options) { } case io::Tokenizer::TYPE_STRING: { + value_location.AddPath(UninterpretedOption::kStringValueFieldNumber); if (is_negative) { AddError("Invalid '-' symbol before string."); return false; @@ -747,31 +966,57 @@ bool Parser::ParseOptionAssignment(Message* options) { } case io::Tokenizer::TYPE_SYMBOL: - AddError("Expected option value."); - return false; + if (LookingAt("{")) { + value_location.AddPath(UninterpretedOption::kAggregateValueFieldNumber); + DO(ParseUninterpretedBlock( + uninterpreted_option->mutable_aggregate_value())); + } else { + AddError("Expected option value."); + return false; + } + break; } return true; } -bool Parser::ParseExtensions(DescriptorProto* message) { +bool Parser::ParseExtensions(DescriptorProto* message, + const LocationRecorder& extensions_location) { // Parse the declaration. DO(Consume("extensions")); do { + // Note that kExtensionRangeFieldNumber was already pushed by the parent. + LocationRecorder location(extensions_location, + message->extension_range_size()); + DescriptorProto::ExtensionRange* range = message->add_extension_range(); - RecordLocation(range, DescriptorPool::ErrorCollector::NUMBER); + location.RecordLegacyLocation( + range, DescriptorPool::ErrorCollector::NUMBER); int start, end; - DO(ConsumeInteger(&start, "Expected field number range.")); + io::Tokenizer::Token start_token; + + { + LocationRecorder start_location( + location, DescriptorProto::ExtensionRange::kStartFieldNumber); + start_token = input_->current(); + DO(ConsumeInteger(&start, "Expected field number range.")); + } if (TryConsume("to")) { + LocationRecorder end_location( + location, DescriptorProto::ExtensionRange::kEndFieldNumber); if (TryConsume("max")) { end = FieldDescriptor::kMaxNumber; } else { DO(ConsumeInteger(&end, "Expected integer.")); } } else { + LocationRecorder end_location( + location, DescriptorProto::ExtensionRange::kEndFieldNumber); + end_location.StartAt(start_token); + end_location.EndAt(start_token); end = start; } @@ -788,16 +1033,17 @@ bool Parser::ParseExtensions(DescriptorProto* message) { } bool Parser::ParseExtend(RepeatedPtrField* extensions, - RepeatedPtrField* messages) { + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& extend_location) { DO(Consume("extend")); - // We expect to see at least one extension field defined in the extend block. - // We need to create it now so we can record the extendee's location. - FieldDescriptorProto* first_field = extensions->Add(); - // Parse the extendee type. - RecordLocation(first_field, DescriptorPool::ErrorCollector::EXTENDEE); - DO(ParseUserDefinedType(first_field->mutable_extendee())); + io::Tokenizer::Token extendee_start = input_->current(); + string extendee; + DO(ParseUserDefinedType(&extendee)); + io::Tokenizer::Token extendee_end = input_->previous(); // Parse the block. DO(Consume("{")); @@ -810,16 +1056,29 @@ bool Parser::ParseExtend(RepeatedPtrField* extensions, return false; } - FieldDescriptorProto* field; - if (is_first) { - field = first_field; - is_first = false; - } else { - field = extensions->Add(); - field->set_extendee(first_field->extendee()); + // Note that kExtensionFieldNumber was already pushed by the parent. + LocationRecorder location(extend_location, extensions->size()); + + FieldDescriptorProto* field = extensions->Add(); + + { + LocationRecorder extendee_location( + location, FieldDescriptorProto::kExtendeeFieldNumber); + extendee_location.StartAt(extendee_start); + extendee_location.EndAt(extendee_end); + + if (is_first) { + extendee_location.RecordLegacyLocation( + field, DescriptorPool::ErrorCollector::EXTENDEE); + is_first = false; + } } - if (!ParseMessageField(field, messages)) { + field->set_extendee(extendee); + + if (!ParseMessageField(field, messages, parent_location, + location_field_number_for_nested_type, + location)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -832,15 +1091,24 @@ bool Parser::ParseExtend(RepeatedPtrField* extensions, // ------------------------------------------------------------------- // Enums -bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type) { +bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location) { DO(Consume("enum")); - RecordLocation(enum_type, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); - DO(ParseEnumBlock(enum_type)); + + { + LocationRecorder location(enum_location, + EnumDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + enum_type, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); + } + + DO(ParseEnumBlock(enum_type, enum_location)); return true; } -bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type) { +bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location) { DO(Consume("{")); while (!TryConsume("}")) { @@ -849,7 +1117,7 @@ bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type) { return false; } - if (!ParseEnumStatement(enum_type)) { + if (!ParseEnumStatement(enum_type, enum_location)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -859,41 +1127,69 @@ bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type) { return true; } -bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type) { +bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location) { if (TryConsume(";")) { // empty statement; ignore return true; } else if (LookingAt("option")) { - return ParseOption(enum_type->mutable_options()); + LocationRecorder location(enum_location, + EnumDescriptorProto::kOptionsFieldNumber); + return ParseOption(enum_type->mutable_options(), location); } else { - return ParseEnumConstant(enum_type->add_value()); + LocationRecorder location(enum_location, + EnumDescriptorProto::kValueFieldNumber, enum_type->value_size()); + return ParseEnumConstant(enum_type->add_value(), location); } } -bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value) { - RecordLocation(enum_value, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(enum_value->mutable_name(), - "Expected enum constant name.")); +bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, + const LocationRecorder& enum_value_location) { + // Parse name. + { + LocationRecorder location(enum_value_location, + EnumValueDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + enum_value, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(enum_value->mutable_name(), + "Expected enum constant name.")); + } + DO(Consume("=", "Missing numeric value for enum constant.")); - bool is_negative = TryConsume("-"); - int number; - DO(ConsumeInteger(&number, "Expected integer.")); - if (is_negative) number *= -1; - enum_value->set_number(number); + // Parse value. + { + LocationRecorder location( + enum_value_location, EnumValueDescriptorProto::kNumberFieldNumber); + location.RecordLegacyLocation( + enum_value, DescriptorPool::ErrorCollector::NUMBER); + + bool is_negative = TryConsume("-"); + int number; + DO(ConsumeInteger(&number, "Expected integer.")); + if (is_negative) number *= -1; + enum_value->set_number(number); + } - DO(ParseEnumConstantOptions(enum_value)); + DO(ParseEnumConstantOptions(enum_value, enum_value_location)); DO(Consume(";")); return true; } -bool Parser::ParseEnumConstantOptions(EnumValueDescriptorProto* value) { - if (!TryConsume("[")) return true; +bool Parser::ParseEnumConstantOptions( + EnumValueDescriptorProto* value, + const LocationRecorder& enum_value_location) { + if (!LookingAt("[")) return true; + + LocationRecorder location( + enum_value_location, EnumValueDescriptorProto::kOptionsFieldNumber); + + DO(Consume("[")); do { - DO(ParseOptionAssignment(value->mutable_options())); + DO(ParseOptionAssignment(value->mutable_options(), location)); } while (TryConsume(",")); DO(Consume("]")); @@ -903,15 +1199,24 @@ bool Parser::ParseEnumConstantOptions(EnumValueDescriptorProto* value) { // ------------------------------------------------------------------- // Services -bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service) { +bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service, + const LocationRecorder& service_location) { DO(Consume("service")); - RecordLocation(service, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); - DO(ParseServiceBlock(service)); + + { + LocationRecorder location(service_location, + ServiceDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + service, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); + } + + DO(ParseServiceBlock(service, service_location)); return true; } -bool Parser::ParseServiceBlock(ServiceDescriptorProto* service) { +bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, + const LocationRecorder& service_location) { DO(Consume("{")); while (!TryConsume("}")) { @@ -920,7 +1225,7 @@ bool Parser::ParseServiceBlock(ServiceDescriptorProto* service) { return false; } - if (!ParseServiceStatement(service)) { + if (!ParseServiceStatement(service, service_location)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -930,33 +1235,55 @@ bool Parser::ParseServiceBlock(ServiceDescriptorProto* service) { return true; } -bool Parser::ParseServiceStatement(ServiceDescriptorProto* service) { +bool Parser::ParseServiceStatement(ServiceDescriptorProto* service, + const LocationRecorder& service_location) { if (TryConsume(";")) { // empty statement; ignore return true; } else if (LookingAt("option")) { - return ParseOption(service->mutable_options()); + LocationRecorder location( + service_location, ServiceDescriptorProto::kOptionsFieldNumber); + return ParseOption(service->mutable_options(), location); } else { - return ParseServiceMethod(service->add_method()); + LocationRecorder location(service_location, + ServiceDescriptorProto::kMethodFieldNumber, service->method_size()); + return ParseServiceMethod(service->add_method(), location); } } -bool Parser::ParseServiceMethod(MethodDescriptorProto* method) { +bool Parser::ParseServiceMethod(MethodDescriptorProto* method, + const LocationRecorder& method_location) { DO(Consume("rpc")); - RecordLocation(method, DescriptorPool::ErrorCollector::NAME); - DO(ConsumeIdentifier(method->mutable_name(), "Expected method name.")); + + { + LocationRecorder location(method_location, + MethodDescriptorProto::kNameFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::NAME); + DO(ConsumeIdentifier(method->mutable_name(), "Expected method name.")); + } // Parse input type. DO(Consume("(")); - RecordLocation(method, DescriptorPool::ErrorCollector::INPUT_TYPE); - DO(ParseUserDefinedType(method->mutable_input_type())); + { + LocationRecorder location(method_location, + MethodDescriptorProto::kInputTypeFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::INPUT_TYPE); + DO(ParseUserDefinedType(method->mutable_input_type())); + } DO(Consume(")")); // Parse output type. DO(Consume("returns")); DO(Consume("(")); - RecordLocation(method, DescriptorPool::ErrorCollector::OUTPUT_TYPE); - DO(ParseUserDefinedType(method->mutable_output_type())); + { + LocationRecorder location(method_location, + MethodDescriptorProto::kOutputTypeFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::OUTPUT_TYPE); + DO(ParseUserDefinedType(method->mutable_output_type())); + } DO(Consume(")")); if (TryConsume("{")) { @@ -970,7 +1297,9 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method) { if (TryConsume(";")) { // empty statement; ignore } else { - if (!ParseOption(method->mutable_options())) { + LocationRecorder location(method_location, + MethodDescriptorProto::kOptionsFieldNumber); + if (!ParseOption(method->mutable_options(), location)) { // This statement failed to parse. Skip it, but keep looping to // parse other statements. SkipStatement(); @@ -1054,7 +1383,8 @@ bool Parser::ParseUserDefinedType(string* type_name) { // =================================================================== -bool Parser::ParsePackage(FileDescriptorProto* file) { +bool Parser::ParsePackage(FileDescriptorProto* file, + const LocationRecorder& root_location) { if (file->has_package()) { AddError("Multiple package definitions."); // Don't append the new package to the old one. Just replace it. Not @@ -1064,31 +1394,43 @@ bool Parser::ParsePackage(FileDescriptorProto* file) { DO(Consume("package")); - RecordLocation(file, DescriptorPool::ErrorCollector::NAME); + { + LocationRecorder location(root_location, + FileDescriptorProto::kPackageFieldNumber); + location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::NAME); - while (true) { - string identifier; - DO(ConsumeIdentifier(&identifier, "Expected identifier.")); - file->mutable_package()->append(identifier); - if (!TryConsume(".")) break; - file->mutable_package()->append("."); + while (true) { + string identifier; + DO(ConsumeIdentifier(&identifier, "Expected identifier.")); + file->mutable_package()->append(identifier); + if (!TryConsume(".")) break; + file->mutable_package()->append("."); + } } DO(Consume(";")); return true; } -bool Parser::ParseImport(string* import_filename) { +bool Parser::ParseImport(string* import_filename, + const LocationRecorder& root_location, + int index) { DO(Consume("import")); - DO(ConsumeString(import_filename, - "Expected a string naming the file to import.")); + { + LocationRecorder location(root_location, + FileDescriptorProto::kDependencyFieldNumber, + index); + DO(ConsumeString(import_filename, + "Expected a string naming the file to import.")); + } DO(Consume(";")); return true; } -bool Parser::ParseOption(Message* options) { +bool Parser::ParseOption(Message* options, + const LocationRecorder& options_location) { DO(Consume("option")); - DO(ParseOptionAssignment(options)); + DO(ParseOptionAssignment(options, options_location)); DO(Consume(";")); return true; } diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h index 72c96d04..4cc90a29 100644 --- a/src/google/protobuf/compiler/parser.h +++ b/src/google/protobuf/compiler/parser.h @@ -74,6 +74,9 @@ class LIBPROTOBUF_EXPORT Parser { // Optional fetaures: + // DEPRECATED: New code should use the SourceCodeInfo embedded in the + // FileDescriptorProto. + // // Requests that locations of certain definitions be recorded to the given // SourceLocationTable while parsing. This can be used to look up exact line // and column numbers for errors reported by DescriptorPool during validation. @@ -82,7 +85,7 @@ class LIBPROTOBUF_EXPORT Parser { source_location_table_ = location_table; } - // Requsets that errors be recorded to the given ErrorCollector while + // Requests that errors be recorded to the given ErrorCollector while // parsing. Set to NULL (the default) to discard error messages. void RecordErrorsTo(io::ErrorCollector* error_collector) { error_collector_ = error_collector; @@ -180,16 +183,56 @@ class LIBPROTOBUF_EXPORT Parser { // of the current token. void AddError(const string& error); - // Record the given line and column and associate it with this descriptor - // in the SourceLocationTable. - void RecordLocation(const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location, - int line, int column); - - // Record the current line and column and associate it with this descriptor - // in the SourceLocationTable. - void RecordLocation(const Message* descriptor, - DescriptorPool::ErrorCollector::ErrorLocation location); + // Records a location in the SourceCodeInfo.location table (see + // descriptor.proto). We use RAII to ensure that the start and end locations + // are recorded -- the constructor records the start location and the + // destructor records the end location. Since the parser is + // recursive-descent, this works out beautifully. + class LIBPROTOBUF_EXPORT LocationRecorder { + public: + // Construct the file's "root" location. + LocationRecorder(Parser* parser); + + // Construct a location that represents a declaration nested within the + // given parent. E.g. a field's location is nested within the location + // for a message type. The parent's path will be copied, so you should + // call AddPath() only to add the path components leading from the parent + // to the child (as opposed to leading from the root to the child). + LocationRecorder(const LocationRecorder& parent); + + // Convenience constructors that call AddPath() one or two times. + LocationRecorder(const LocationRecorder& parent, int path1); + LocationRecorder(const LocationRecorder& parent, int path1, int path2); + + ~LocationRecorder(); + + // Add a path component. See SourceCodeInfo.Location.path in + // descriptor.proto. + void AddPath(int path_component); + + // By default the location is considered to start at the current token at + // the time the LocationRecorder is created. StartAt() sets the start + // location to the given token instead. + void StartAt(const io::Tokenizer::Token& token); + + // 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. + void EndAt(const io::Tokenizer::Token& token); + + // Records the start point of this location to the SourceLocationTable that + // was passed to RecordSourceLocationsTo(), if any. SourceLocationTable + // is an older way of keeping track of source locations which is still + // used in some places. + void RecordLegacyLocation(const Message* descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location); + + private: + Parser* parser_; + SourceCodeInfo::Location* location_; + + void Init(const LocationRecorder& parent); + }; // ================================================================= // Parsers for various language constructs @@ -210,50 +253,81 @@ class LIBPROTOBUF_EXPORT Parser { // makes logic much simpler for the caller. // Parse a top-level message, enum, service, etc. - bool ParseTopLevelStatement(FileDescriptorProto* file); + bool ParseTopLevelStatement(FileDescriptorProto* file, + const LocationRecorder& root_location); // Parse various language high-level language construrcts. - bool ParseMessageDefinition(DescriptorProto* message); - bool ParseEnumDefinition(EnumDescriptorProto* enum_type); - bool ParseServiceDefinition(ServiceDescriptorProto* service); - bool ParsePackage(FileDescriptorProto* file); - bool ParseImport(string* import_filename); - bool ParseOption(Message* options); + bool ParseMessageDefinition(DescriptorProto* message, + const LocationRecorder& message_location); + bool ParseEnumDefinition(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location); + bool ParseServiceDefinition(ServiceDescriptorProto* service, + const LocationRecorder& service_location); + bool ParsePackage(FileDescriptorProto* file, + const LocationRecorder& root_location); + bool ParseImport(string* import_filename, + const LocationRecorder& root_location, + int index); + bool ParseOption(Message* options, + const LocationRecorder& options_location); // 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); - bool ParseEnumBlock(EnumDescriptorProto* enum_type); - bool ParseServiceBlock(ServiceDescriptorProto* service); + bool ParseMessageBlock(DescriptorProto* message, + const LocationRecorder& message_location); + bool ParseEnumBlock(EnumDescriptorProto* enum_type, + const LocationRecorder& enum_location); + bool ParseServiceBlock(ServiceDescriptorProto* service, + const LocationRecorder& service_location); // Parse one statement within a message, enum, or service block, inclunding // final semicolon. - bool ParseMessageStatement(DescriptorProto* message); - bool ParseEnumStatement(EnumDescriptorProto* message); - bool ParseServiceStatement(ServiceDescriptorProto* message); + bool ParseMessageStatement(DescriptorProto* message, + const LocationRecorder& message_location); + bool ParseEnumStatement(EnumDescriptorProto* message, + const LocationRecorder& enum_location); + bool ParseServiceStatement(ServiceDescriptorProto* message, + const LocationRecorder& service_location); // Parse a field of a message. If the field is a group, its type will be // added to "messages". + // + // parent_location and location_field_number_for_nested_type are needed when + // parsing groups -- we need to generate a nested message type within the + // parent and record its location accordingly. Since the parent could be + // either a FileDescriptorProto or a DescriptorProto, we must pass in the + // correct field number to use. bool ParseMessageField(FieldDescriptorProto* field, - RepeatedPtrField* messages); + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& field_location); // Parse an "extensions" declaration. - bool ParseExtensions(DescriptorProto* message); + bool ParseExtensions(DescriptorProto* message, + const LocationRecorder& extensions_location); - // Parse an "extend" declaration. + // Parse an "extend" declaration. (See also comments for + // ParseMessageField().) bool ParseExtend(RepeatedPtrField* extensions, - RepeatedPtrField* messages); + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& extend_location); // Parse a single enum value within an enum block. - bool ParseEnumConstant(EnumValueDescriptorProto* enum_value); + bool ParseEnumConstant(EnumValueDescriptorProto* enum_value, + const LocationRecorder& enum_value_location); // Parse enum constant options, i.e. the list in square brackets at the end // of the enum constant value definition. - bool ParseEnumConstantOptions(EnumValueDescriptorProto* value); + bool ParseEnumConstantOptions(EnumValueDescriptorProto* value, + const LocationRecorder& enum_value_location); // Parse a single method within a service definition. - bool ParseServiceMethod(MethodDescriptorProto* method); + bool ParseServiceMethod(MethodDescriptorProto* method, + const LocationRecorder& method_location); // Parse "required", "optional", or "repeated" and fill in "label" // with the value. @@ -269,28 +343,45 @@ 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); + bool ParseFieldOptions(FieldDescriptorProto* field, + const LocationRecorder& field_location); // Parse the "default" option. This needs special handling because its // type is the field's type. - bool ParseDefaultAssignment(FieldDescriptorProto* field); + bool ParseDefaultAssignment(FieldDescriptorProto* field, + const LocationRecorder& field_location); // Parse a single option name/value pair, e.g. "ctype = CORD". The name // identifies a field of the given Message, and the value of that field // is set to the parsed value. - bool ParseOptionAssignment(Message* options); + bool ParseOptionAssignment(Message* options, + const LocationRecorder& options_location); // Parses a single part of a multipart option name. A multipart name consists // of names separated by dots. Each name is either an identifier or a series // of identifiers separated by dots and enclosed in parentheses. E.g., // "foo.(bar.baz).qux". - bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option); + bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option, + const LocationRecorder& part_location); + + // Parses a string surrounded by balanced braces. Strips off the outer + // braces and stores the enclosed string in *value. + // E.g., + // { foo } *value gets 'foo' + // { foo { bar: box } } *value gets 'foo { bar: box }' + // {} *value gets '' + // + // REQUIRES: LookingAt("{") + // When finished successfully, we are looking at the first token past + // the ending brace. + bool ParseUninterpretedBlock(string* value); // ================================================================= io::Tokenizer* input_; io::ErrorCollector* error_collector_; - SourceLocationTable* source_location_table_; + SourceCodeInfo* source_code_info_; + SourceLocationTable* source_location_table_; // legacy bool had_errors_; bool require_syntax_identifier_; bool stop_after_syntax_identifier_; @@ -302,6 +393,11 @@ class LIBPROTOBUF_EXPORT Parser { // A table mapping (descriptor, ErrorLocation) pairs -- as reported by // DescriptorPool when validating descriptors -- to line and column numbers // within the original source code. +// +// This is semi-obsolete: FileDescriptorProto.source_code_info now contains +// far more complete information about source locations. However, as of this +// writing you still need to use SourceLocationTable when integrating with +// DescriptorPool. class LIBPROTOBUF_EXPORT SourceLocationTable { public: SourceLocationTable(); diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index e2262b8b..156c0dc3 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -34,6 +34,7 @@ #include #include +#include #include @@ -45,6 +46,7 @@ #include #include #include +#include #include #include @@ -118,6 +120,9 @@ class ParserTest : public testing::Test { EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); ASSERT_EQ("", error_collector_.text_); + // We don't cover SourceCodeInfo in these tests. + actual.clear_source_code_info(); + // Parse the ASCII representation in order to canonicalize it. We could // just compare directly to actual.DebugString(), but that would require // that the caller precisely match the formatting that DebugString() @@ -930,6 +935,12 @@ TEST_F(ParseErrorTest, MultipleParseErrors) { "3:25: Expected \";\".\n"); } +TEST_F(ParseErrorTest, EofInAggregateValue) { + ExpectHasErrors( + "option (fileopt) = { i:100\n", + "1:0: Unexpected end of stream while parsing aggregate value.\n"); +} + // ------------------------------------------------------------------- // Enum errors @@ -1247,6 +1258,861 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { EXPECT_EQ(expected.DebugString(), parsed.DebugString()); } +// =================================================================== +// SourceCodeInfo tests. + +// Follows a path -- as defined by SourceCodeInfo.Location.path -- from a +// message to a particular sub-field. +// * If the target is itself a message, sets *output_message to point at it, +// *output_field to NULL, and *output_index to -1. +// * Otherwise, if the target is an element of a repeated field, sets +// *output_message to the containing message, *output_field to the descriptor +// of the field, and *output_index to the index of the element. +// * Otherwise, the target is a field (possibly a repeated field, but not any +// one element). Sets *output_message to the containing message, +// *output_field to the descriptor of the field, and *output_index to -1. +// Returns true if the path was valid, false otherwise. A gTest failure is +// recorded before returning false. +bool FollowPath(const Message& root, + const int* path_begin, const int* path_end, + const Message** output_message, + const FieldDescriptor** output_field, + int* output_index) { + if (path_begin == path_end) { + // Path refers to this whole message. + *output_message = &root; + *output_field = NULL; + *output_index = -1; + return true; + } + + const Descriptor* descriptor = root.GetDescriptor(); + const Reflection* reflection = root.GetReflection(); + + const FieldDescriptor* field = descriptor->FindFieldByNumber(*path_begin); + + if (field == NULL) { + ADD_FAILURE() << descriptor->name() << " has no field number: " + << *path_begin; + return false; + } + + ++path_begin; + + if (field->is_repeated()) { + if (path_begin == path_end) { + // Path refers to the whole repeated field. + *output_message = &root; + *output_field = field; + *output_index = -1; + return true; + } + + int index = *path_begin++; + int size = reflection->FieldSize(root, field); + + if (index >= size) { + ADD_FAILURE() << descriptor->name() << "." << field->name() + << " has size " << size << ", but path contained index: " + << index; + return false; + } + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Descend into child message. + const Message& child = reflection->GetRepeatedMessage(root, field, index); + return FollowPath(child, path_begin, path_end, + output_message, output_field, output_index); + } else if (path_begin == path_end) { + // Path refers to this element. + *output_message = &root; + *output_field = field; + *output_index = index; + return true; + } else { + ADD_FAILURE() << descriptor->name() << "." << field->name() + << " is not a message; cannot descend into it."; + return false; + } + } else { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + const Message& child = reflection->GetMessage(root, field); + return FollowPath(child, path_begin, path_end, + output_message, output_field, output_index); + } else if (path_begin == path_end) { + // Path refers to this field. + *output_message = &root; + *output_field = field; + *output_index = -1; + return true; + } else { + ADD_FAILURE() << descriptor->name() << "." << field->name() + << " is not a message; cannot descend into it."; + return false; + } + } +} + +// Split some text on line breaks. The line breaks are retained in the output, +// so each line (except the last) ends with a '\n', and the lines can be +// concatenated to produce the original text. +// +// I couldn't find the proper string utility function for this. Our +// split-on-delimiter functions don't include the delimiter in the output. +void SplitLines(const string& text, vector* lines) { + string::size_type pos = 0; + + while (pos != string::npos) { + string::size_type last_pos = pos; + pos = text.find_first_of('\n', pos); + if (pos != string::npos) ++pos; + lines->push_back(text.substr(last_pos, pos - last_pos)); + } +} + +// Look for the given tags in the given text and construct a span (as defined +// by SourceCodeInfo.Location.span) from them. E.g. for text like: +// /*a*/message /*b*/Foo/*c*/ {}/*d*/ +// There are four tags: "a", "b", "c", and "d". The constructed span starts +// immediately after the start tag's trailing '/' and ends immediately before +// the end tags leading '/'. +void MakeExpectedSpan(const vector& lines, + const string& start_tag, const string& end_tag, + RepeatedField* output) { + string start_comment = "/*" + start_tag + "*/"; + string end_comment = "/*" + end_tag + "*/"; + + int start_line = -1; + int start_column = -1; + for (int i = 0; i < lines.size(); i++) { + string::size_type pos = lines[i].find(start_comment); + if (pos != string::npos) { + start_line = i; + start_column = pos + start_comment.size(); + break; + } + } + ASSERT_NE(start_line, -1) + << "Tag \"" << start_comment << "\" not found in text."; + + int end_line = -1; + int end_column = -1; + for (int i = start_line; i < lines.size(); i++) { + string::size_type pos = lines[i].find(end_comment); + if (pos != string::npos) { + end_line = i; + end_column = pos; + break; + } + } + ASSERT_NE(end_line, -1) + << "Tag \"" << end_comment << "\" not found in text."; + + output->Add(start_line); + output->Add(start_column); + if (end_line != start_line) output->Add(end_line); + output->Add(end_column); +} + +// Check if two spans are equal. +bool CompareSpans(const RepeatedField& span1, + const RepeatedField& span2) { + if (span1.size() != span2.size()) return false; + for (int i = 0; i < span1.size(); i++) { + if (span1.Get(i) != span2.Get(i)) return false; + } + return true; +} + +// Test fixture for source info tests, which check that source locations are +// recorded correctly in FileDescriptorProto.source_code_info.location. +class SourceInfoTest : public ParserTest { + protected: + // The parsed file (initialized by Parse()). + FileDescriptorProto file_; + + // Parse the given text as a .proto file and populate the spans_ map with + // all the source location spans in its SourceCodeInfo table. + bool Parse(const char* text) { + SetupParser(text); + SplitLines(text, &lines_); + if (!parser_->Parse(input_.get(), &file_)) { + return false; + } + + const SourceCodeInfo& source_info = file_.source_code_info(); + for (int i = 0; i < source_info.location_size(); i++) { + const SourceCodeInfo::Location& location = source_info.location(i); + const Message* descriptor_proto = NULL; + const FieldDescriptor* field = NULL; + int index = 0; + if (!FollowPath(file_, location.path().begin(), location.path().end(), + &descriptor_proto, &field, &index)) { + return false; + } + + spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index), + &location)); + } + + return true; + } + + virtual void TearDown() { + EXPECT_TRUE(spans_.empty()) + << "Forgot to call HasSpan() for:\n" + << spans_.begin()->second->DebugString(); + } + + // ----------------------------------------------------------------- + // HasSpan() checks that the span of source code delimited by the given + // tags (comments) correspond via the SourceCodeInfo table to the given + // part of the FileDescriptorProto. (If unclear, look at the actual tests; + // it should quickly become obvious.) + + bool HasSpan(const char* start_tag, const char* end_tag, + const Message& descriptor_proto) { + return HasSpan(start_tag, end_tag, descriptor_proto, NULL, -1); + } + + bool HasSpan(const char* start_tag, const char* end_tag, + const Message& descriptor_proto, const string& field_name) { + return HasSpan(start_tag, end_tag, descriptor_proto, field_name, -1); + } + + bool HasSpan(const char* start_tag, const char* end_tag, + const Message& descriptor_proto, const string& field_name, + int index) { + const FieldDescriptor* field = + descriptor_proto.GetDescriptor()->FindFieldByName(field_name); + if (field == NULL) { + ADD_FAILURE() << descriptor_proto.GetDescriptor()->name() + << " has no such field: " << field_name; + return false; + } + + return HasSpan(start_tag, end_tag, descriptor_proto, field, index); + } + + bool HasSpan(const Message& descriptor_proto) { + return HasSpan(NULL, NULL, descriptor_proto, NULL, -1); + } + + bool HasSpan(const Message& descriptor_proto, const string& field_name) { + return HasSpan(NULL, NULL, descriptor_proto, field_name, -1); + } + + bool HasSpan(const Message& descriptor_proto, const string& field_name, + int index) { + return HasSpan(NULL, NULL, descriptor_proto, field_name, index); + } + + bool HasSpan(const char* start_tag, const char* end_tag, + const Message& descriptor_proto, const FieldDescriptor* field, + int index) { + pair range = + spans_.equal_range(SpanKey(descriptor_proto, field, index)); + + if (start_tag == NULL) { + if (range.first == range.second) { + return false; + } else { + spans_.erase(range.first); + return true; + } + } else { + RepeatedField expected_span; + MakeExpectedSpan(lines_, start_tag, end_tag, &expected_span); + + for (SpanMap::iterator iter = range.first; iter != range.second; ++iter) { + if (CompareSpans(expected_span, iter->second->span())) { + spans_.erase(iter); + return true; + } + } + + return false; + } + } + + private: + struct SpanKey { + const Message* descriptor_proto; + const FieldDescriptor* field; + int index; + + inline SpanKey() {} + inline SpanKey(const Message& descriptor_proto, + const FieldDescriptor* field, + int index) + : descriptor_proto(&descriptor_proto), field(field), index(index) {} + + inline bool operator<(const SpanKey& other) const { + if (descriptor_proto < other.descriptor_proto) return true; + if (descriptor_proto > other.descriptor_proto) return false; + if (field < other.field) return true; + if (field > other.field) return false; + return index < other.index; + } + }; + + typedef multimap SpanMap; + SpanMap spans_; + vector lines_; +}; + +TEST_F(SourceInfoTest, BasicFileDecls) { + EXPECT_TRUE(Parse( + "/*a*/syntax = \"proto2\";\n" + "package /*b*/foo.bar/*c*/;\n" + "import /*d*/\"baz.proto\"/*e*/;\n" + "import /*f*/\"qux.proto\"/*g*/;/*h*/\n" + "// comment ignored\n")); + + EXPECT_TRUE(HasSpan("a", "h", file_)); + EXPECT_TRUE(HasSpan("b", "c", file_, "package")); + EXPECT_TRUE(HasSpan("d", "e", file_, "dependency", 0)); + EXPECT_TRUE(HasSpan("f", "g", file_, "dependency", 1)); +} + +TEST_F(SourceInfoTest, Messages) { + EXPECT_TRUE(Parse( + "/*a*/message /*b*/Foo/*c*/ {}/*d*/\n" + "/*e*/message /*f*/Bar/*g*/ {}/*h*/\n")); + + EXPECT_TRUE(HasSpan("a", "d", file_.message_type(0))); + EXPECT_TRUE(HasSpan("b", "c", file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan("e", "h", file_.message_type(1))); + EXPECT_TRUE(HasSpan("f", "g", file_.message_type(1), "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + +TEST_F(SourceInfoTest, Fields) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " /*a*/optional/*b*/ /*c*/int32/*d*/ /*e*/bar/*f*/ = /*g*/1/*h*/;/*i*/\n" + " /*j*/repeated/*k*/ /*l*/X.Y/*m*/ /*n*/baz/*o*/ = /*p*/2/*q*/;/*r*/\n" + "}\n")); + + const FieldDescriptorProto& field1 = file_.message_type(0).field(0); + const FieldDescriptorProto& field2 = file_.message_type(0).field(1); + + EXPECT_TRUE(HasSpan("a", "i", field1)); + EXPECT_TRUE(HasSpan("a", "b", field1, "label")); + EXPECT_TRUE(HasSpan("c", "d", field1, "type")); + EXPECT_TRUE(HasSpan("e", "f", field1, "name")); + EXPECT_TRUE(HasSpan("g", "h", field1, "number")); + + EXPECT_TRUE(HasSpan("j", "r", field2)); + EXPECT_TRUE(HasSpan("j", "k", field2, "label")); + EXPECT_TRUE(HasSpan("l", "m", field2, "type_name")); + EXPECT_TRUE(HasSpan("n", "o", field2, "name")); + EXPECT_TRUE(HasSpan("p", "q", field2, "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, Extensions) { + EXPECT_TRUE(Parse( + "/*a*/extend /*b*/Foo/*c*/ {\n" + " /*d*/optional/*e*/ int32 bar = 1;/*f*/\n" + " /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n" + "}/*j*/\n" + "/*k*/extend /*l*/Bar/*m*/ {\n" + " /*n*/optional int32 qux = 1;/*o*/\n" + "}/*p*/\n")); + + const FieldDescriptorProto& field1 = file_.extension(0); + const FieldDescriptorProto& field2 = file_.extension(1); + const FieldDescriptorProto& field3 = file_.extension(2); + + EXPECT_TRUE(HasSpan("a", "j", file_, "extension")); + EXPECT_TRUE(HasSpan("k", "p", file_, "extension")); + + EXPECT_TRUE(HasSpan("d", "f", field1)); + EXPECT_TRUE(HasSpan("d", "e", field1, "label")); + EXPECT_TRUE(HasSpan("b", "c", field1, "extendee")); + + EXPECT_TRUE(HasSpan("g", "i", field2)); + EXPECT_TRUE(HasSpan("g", "h", field2, "label")); + EXPECT_TRUE(HasSpan("b", "c", field2, "extendee")); + + EXPECT_TRUE(HasSpan("n", "o", field3)); + EXPECT_TRUE(HasSpan("l", "m", field3, "extendee")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(field1, "type")); + EXPECT_TRUE(HasSpan(field1, "name")); + EXPECT_TRUE(HasSpan(field1, "number")); + EXPECT_TRUE(HasSpan(field2, "type_name")); + EXPECT_TRUE(HasSpan(field2, "name")); + EXPECT_TRUE(HasSpan(field2, "number")); + EXPECT_TRUE(HasSpan(field3, "label")); + EXPECT_TRUE(HasSpan(field3, "type")); + EXPECT_TRUE(HasSpan(field3, "name")); + EXPECT_TRUE(HasSpan(field3, "number")); +} + +TEST_F(SourceInfoTest, NestedExtensions) { + EXPECT_TRUE(Parse( + "message Message {\n" + " /*a*/extend /*b*/Foo/*c*/ {\n" + " /*d*/optional/*e*/ int32 bar = 1;/*f*/\n" + " /*g*/repeated/*h*/ X.Y baz = 2;/*i*/\n" + " }/*j*/\n" + " /*k*/extend /*l*/Bar/*m*/ {\n" + " /*n*/optional int32 qux = 1;/*o*/\n" + " }/*p*/\n" + "}\n")); + + const FieldDescriptorProto& field1 = file_.message_type(0).extension(0); + const FieldDescriptorProto& field2 = file_.message_type(0).extension(1); + const FieldDescriptorProto& field3 = file_.message_type(0).extension(2); + + EXPECT_TRUE(HasSpan("a", "j", file_.message_type(0), "extension")); + EXPECT_TRUE(HasSpan("k", "p", file_.message_type(0), "extension")); + + EXPECT_TRUE(HasSpan("d", "f", field1)); + EXPECT_TRUE(HasSpan("d", "e", field1, "label")); + EXPECT_TRUE(HasSpan("b", "c", field1, "extendee")); + + EXPECT_TRUE(HasSpan("g", "i", field2)); + EXPECT_TRUE(HasSpan("g", "h", field2, "label")); + EXPECT_TRUE(HasSpan("b", "c", field2, "extendee")); + + EXPECT_TRUE(HasSpan("n", "o", field3)); + EXPECT_TRUE(HasSpan("l", "m", field3, "extendee")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(field1, "type")); + EXPECT_TRUE(HasSpan(field1, "name")); + EXPECT_TRUE(HasSpan(field1, "number")); + EXPECT_TRUE(HasSpan(field2, "type_name")); + EXPECT_TRUE(HasSpan(field2, "name")); + EXPECT_TRUE(HasSpan(field2, "number")); + EXPECT_TRUE(HasSpan(field3, "label")); + EXPECT_TRUE(HasSpan(field3, "type")); + EXPECT_TRUE(HasSpan(field3, "name")); + EXPECT_TRUE(HasSpan(field3, "number")); +} + +TEST_F(SourceInfoTest, ExtensionRanges) { + EXPECT_TRUE(Parse( + "message Message {\n" + " /*a*/extensions /*b*/1/*c*/ to /*d*/4/*e*/, /*f*/6/*g*/;/*h*/\n" + " /*i*/extensions /*j*/8/*k*/ to /*l*/max/*m*/;/*n*/\n" + "}\n")); + + const DescriptorProto::ExtensionRange& range1 = + file_.message_type(0).extension_range(0); + const DescriptorProto::ExtensionRange& range2 = + file_.message_type(0).extension_range(1); + const DescriptorProto::ExtensionRange& range3 = + file_.message_type(0).extension_range(2); + + EXPECT_TRUE(HasSpan("a", "h", file_.message_type(0), "extension_range")); + EXPECT_TRUE(HasSpan("i", "n", file_.message_type(0), "extension_range")); + + EXPECT_TRUE(HasSpan("b", "e", range1)); + EXPECT_TRUE(HasSpan("b", "c", range1, "start")); + EXPECT_TRUE(HasSpan("d", "e", range1, "end")); + + EXPECT_TRUE(HasSpan("f", "g", range2)); + EXPECT_TRUE(HasSpan("f", "g", range2, "start")); + EXPECT_TRUE(HasSpan("f", "g", range2, "end")); + + EXPECT_TRUE(HasSpan("j", "m", range3)); + EXPECT_TRUE(HasSpan("j", "k", range3, "start")); + EXPECT_TRUE(HasSpan("l", "m", range3, "end")); + + // 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" + " /*a*/message /*b*/Bar/*c*/ {\n" + " /*d*/message /*e*/Baz/*f*/ {}/*g*/\n" + " }/*h*/\n" + " /*i*/message /*j*/Qux/*k*/ {}/*l*/\n" + "}\n")); + + const DescriptorProto& bar = file_.message_type(0).nested_type(0); + const DescriptorProto& baz = bar.nested_type(0); + const DescriptorProto& qux = file_.message_type(0).nested_type(1); + + EXPECT_TRUE(HasSpan("a", "h", bar)); + EXPECT_TRUE(HasSpan("b", "c", bar, "name")); + EXPECT_TRUE(HasSpan("d", "g", baz)); + EXPECT_TRUE(HasSpan("e", "f", baz, "name")); + EXPECT_TRUE(HasSpan("i", "l", qux)); + EXPECT_TRUE(HasSpan("j", "k", qux, "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, Groups) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " message Bar {}\n" + " /*a*/optional/*b*/ /*c*/group/*d*/ /*e*/Baz/*f*/ = /*g*/1/*h*/ {\n" + " /*i*/message Qux {}/*j*/\n" + " }/*k*/\n" + "}\n")); + + const DescriptorProto& bar = file_.message_type(0).nested_type(0); + const DescriptorProto& baz = file_.message_type(0).nested_type(1); + const DescriptorProto& qux = baz.nested_type(0); + const FieldDescriptorProto& field = file_.message_type(0).field(0); + + EXPECT_TRUE(HasSpan("a", "k", field)); + EXPECT_TRUE(HasSpan("a", "b", field, "label")); + EXPECT_TRUE(HasSpan("c", "d", field, "type")); + EXPECT_TRUE(HasSpan("e", "f", field, "name")); + EXPECT_TRUE(HasSpan("e", "f", field, "type_name")); + EXPECT_TRUE(HasSpan("g", "h", field, "number")); + + EXPECT_TRUE(HasSpan("a", "k", baz)); + EXPECT_TRUE(HasSpan("e", "f", baz, "name")); + EXPECT_TRUE(HasSpan("i", "j", qux)); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(bar)); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(qux, "name")); +} + +TEST_F(SourceInfoTest, Enums) { + EXPECT_TRUE(Parse( + "/*a*/enum /*b*/Foo/*c*/ {}/*d*/\n" + "/*e*/enum /*f*/Bar/*g*/ {}/*h*/\n")); + + EXPECT_TRUE(HasSpan("a", "d", file_.enum_type(0))); + EXPECT_TRUE(HasSpan("b", "c", file_.enum_type(0), "name")); + EXPECT_TRUE(HasSpan("e", "h", file_.enum_type(1))); + EXPECT_TRUE(HasSpan("f", "g", file_.enum_type(1), "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + +TEST_F(SourceInfoTest, EnumValues) { + EXPECT_TRUE(Parse( + "enum Foo {\n" + " /*a*/BAR/*b*/ = /*c*/1/*d*/;/*e*/\n" + " /*f*/BAZ/*g*/ = /*h*/2/*i*/;/*j*/\n" + "}")); + + const EnumValueDescriptorProto& bar = file_.enum_type(0).value(0); + const EnumValueDescriptorProto& baz = file_.enum_type(0).value(1); + + EXPECT_TRUE(HasSpan("a", "e", bar)); + EXPECT_TRUE(HasSpan("a", "b", bar, "name")); + EXPECT_TRUE(HasSpan("c", "d", bar, "number")); + EXPECT_TRUE(HasSpan("f", "j", baz)); + EXPECT_TRUE(HasSpan("f", "g", baz, "name")); + EXPECT_TRUE(HasSpan("h", "i", baz, "number")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.enum_type(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); +} + +TEST_F(SourceInfoTest, NestedEnums) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " /*a*/enum /*b*/Bar/*c*/ {}/*d*/\n" + " /*e*/enum /*f*/Baz/*g*/ {}/*h*/\n" + "}\n")); + + const EnumDescriptorProto& bar = file_.message_type(0).enum_type(0); + const EnumDescriptorProto& baz = file_.message_type(0).enum_type(1); + + EXPECT_TRUE(HasSpan("a", "d", bar)); + EXPECT_TRUE(HasSpan("b", "c", bar, "name")); + EXPECT_TRUE(HasSpan("e", "h", baz)); + EXPECT_TRUE(HasSpan("f", "g", baz, "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + +TEST_F(SourceInfoTest, Services) { + EXPECT_TRUE(Parse( + "/*a*/service /*b*/Foo/*c*/ {}/*d*/\n" + "/*e*/service /*f*/Bar/*g*/ {}/*h*/\n")); + + EXPECT_TRUE(HasSpan("a", "d", file_.service(0))); + EXPECT_TRUE(HasSpan("b", "c", file_.service(0), "name")); + EXPECT_TRUE(HasSpan("e", "h", file_.service(1))); + EXPECT_TRUE(HasSpan("f", "g", file_.service(1), "name")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + +TEST_F(SourceInfoTest, Methods) { + EXPECT_TRUE(Parse( + "service Foo {\n" + " /*a*/rpc /*b*/Bar/*c*/(/*d*/X/*e*/) returns(/*f*/Y/*g*/);/*h*/" + " /*i*/rpc /*j*/Baz/*k*/(/*l*/Z/*m*/) returns(/*n*/W/*o*/);/*p*/" + "}")); + + const MethodDescriptorProto& bar = file_.service(0).method(0); + const MethodDescriptorProto& baz = file_.service(0).method(1); + + EXPECT_TRUE(HasSpan("a", "h", bar)); + EXPECT_TRUE(HasSpan("b", "c", bar, "name")); + EXPECT_TRUE(HasSpan("d", "e", bar, "input_type")); + EXPECT_TRUE(HasSpan("f", "g", bar, "output_type")); + + EXPECT_TRUE(HasSpan("i", "p", baz)); + EXPECT_TRUE(HasSpan("j", "k", baz, "name")); + EXPECT_TRUE(HasSpan("l", "m", baz, "input_type")); + EXPECT_TRUE(HasSpan("n", "o", baz, "output_type")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.service(0))); + 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*/ = " + "/*h*/123/*i*/;/*j*/\n" + "/*k*/option qux = /*l*/-123/*m*/;/*n*/\n" + "/*o*/option corge = /*p*/abc/*q*/;/*r*/\n" + "/*s*/option grault = /*t*/'blah'/*u*/;/*v*/\n" + "/*w*/option garply = /*x*/{ yadda yadda }/*y*/;/*z*/\n" + "/*0*/option waldo = /*1*/123.0/*2*/;/*3*/\n" + )); + + const UninterpretedOption& option1 = file_.options().uninterpreted_option(0); + const UninterpretedOption& option2 = file_.options().uninterpreted_option(1); + const UninterpretedOption& option3 = file_.options().uninterpreted_option(2); + const UninterpretedOption& option4 = file_.options().uninterpreted_option(3); + const UninterpretedOption& option5 = file_.options().uninterpreted_option(4); + const UninterpretedOption& option6 = file_.options().uninterpreted_option(5); + + EXPECT_TRUE(HasSpan("a", "j", file_.options())); + EXPECT_TRUE(HasSpan("b", "i", option1)); + EXPECT_TRUE(HasSpan("b", "g", option1, "name")); + EXPECT_TRUE(HasSpan("b", "c", option1.name(0))); + EXPECT_TRUE(HasSpan("b", "c", option1.name(0), "name_part")); + EXPECT_TRUE(HasSpan("d", "g", option1.name(1))); + EXPECT_TRUE(HasSpan("e", "f", option1.name(1), "name_part")); + EXPECT_TRUE(HasSpan("h", "i", option1, "positive_int_value")); + + EXPECT_TRUE(HasSpan("k", "n", file_.options())); + EXPECT_TRUE(HasSpan("l", "m", option2, "negative_int_value")); + + EXPECT_TRUE(HasSpan("o", "r", file_.options())); + EXPECT_TRUE(HasSpan("p", "q", option3, "identifier_value")); + + EXPECT_TRUE(HasSpan("s", "v", file_.options())); + EXPECT_TRUE(HasSpan("t", "u", option4, "string_value")); + + EXPECT_TRUE(HasSpan("w", "z", file_.options())); + EXPECT_TRUE(HasSpan("x", "y", option5, "aggregate_value")); + + EXPECT_TRUE(HasSpan("0", "3", file_.options())); + EXPECT_TRUE(HasSpan("1", "2", option6, "double_value")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(option2)); + EXPECT_TRUE(HasSpan(option3)); + EXPECT_TRUE(HasSpan(option4)); + EXPECT_TRUE(HasSpan(option5)); + EXPECT_TRUE(HasSpan(option6)); + EXPECT_TRUE(HasSpan(option2, "name")); + EXPECT_TRUE(HasSpan(option3, "name")); + EXPECT_TRUE(HasSpan(option4, "name")); + EXPECT_TRUE(HasSpan(option5, "name")); + EXPECT_TRUE(HasSpan(option6, "name")); + EXPECT_TRUE(HasSpan(option2.name(0))); + EXPECT_TRUE(HasSpan(option3.name(0))); + EXPECT_TRUE(HasSpan(option4.name(0))); + EXPECT_TRUE(HasSpan(option5.name(0))); + EXPECT_TRUE(HasSpan(option6.name(0))); + EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option3.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option4.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option5.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option6.name(0), "name_part")); +} + +TEST_F(SourceInfoTest, ScopedOptions) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " /*a*/option mopt = 1;/*b*/\n" + "}\n" + "enum Bar {\n" + " /*c*/option eopt = 1;/*d*/\n" + "}\n" + "service Baz {\n" + " /*e*/option sopt = 1;/*f*/\n" + " rpc M(X) returns(Y) {\n" + " /*g*/option mopt = 1;/*h*/\n" + " }\n" + "}\n")); + + EXPECT_TRUE(HasSpan("a", "b", file_.message_type(0).options())); + EXPECT_TRUE(HasSpan("c", "d", file_.enum_type(0).options())); + EXPECT_TRUE(HasSpan("e", "f", file_.service(0).options())); + EXPECT_TRUE(HasSpan("g", "h", file_.service(0).method(0).options())); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.message_type(0).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.enum_type(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.enum_type(0).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.service(0))); + EXPECT_TRUE(HasSpan(file_.service(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0))); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.service(0).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0), "input_type")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0), "output_type")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() + .uninterpreted_option(0), "positive_int_value")); +} + +TEST_F(SourceInfoTest, FieldOptions) { + // The actual "name = value" pairs are parsed by the same code as for + // top-level options so we won't re-test that -- just make sure that the + // syntax used for field options is understood. + EXPECT_TRUE(Parse( + "message Foo {" + " optional int32 bar = 1 " + "/*a*/[default=/*b*/123/*c*/,/*d*/opt1=123/*e*/," + "/*f*/opt2='hi'/*g*/]/*h*/;" + "}\n" + )); + + const FieldDescriptorProto& field = file_.message_type(0).field(0); + const UninterpretedOption& option1 = field.options().uninterpreted_option(0); + const UninterpretedOption& option2 = field.options().uninterpreted_option(1); + + EXPECT_TRUE(HasSpan("a", "h", field.options())); + EXPECT_TRUE(HasSpan("b", "c", field, "default_value")); + EXPECT_TRUE(HasSpan("d", "e", option1)); + EXPECT_TRUE(HasSpan("f", "g", option2)); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); + EXPECT_TRUE(HasSpan(field)); + EXPECT_TRUE(HasSpan(field, "label")); + EXPECT_TRUE(HasSpan(field, "type")); + EXPECT_TRUE(HasSpan(field, "name")); + EXPECT_TRUE(HasSpan(field, "number")); + EXPECT_TRUE(HasSpan(option1, "name")); + EXPECT_TRUE(HasSpan(option2, "name")); + EXPECT_TRUE(HasSpan(option1.name(0))); + EXPECT_TRUE(HasSpan(option2.name(0))); + EXPECT_TRUE(HasSpan(option1.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option1, "positive_int_value")); + EXPECT_TRUE(HasSpan(option2, "string_value")); +} + +TEST_F(SourceInfoTest, EnumValueOptions) { + // The actual "name = value" pairs are parsed by the same code as for + // top-level options so we won't re-test that -- just make sure that the + // syntax used for enum options is understood. + EXPECT_TRUE(Parse( + "enum Foo {" + " BAR = 1 /*a*/[/*b*/opt1=123/*c*/,/*d*/opt2='hi'/*e*/]/*f*/;" + "}\n" + )); + + const EnumValueDescriptorProto& value = file_.enum_type(0).value(0); + const UninterpretedOption& option1 = value.options().uninterpreted_option(0); + const UninterpretedOption& option2 = value.options().uninterpreted_option(1); + + EXPECT_TRUE(HasSpan("a", "f", value.options())); + EXPECT_TRUE(HasSpan("b", "c", option1)); + EXPECT_TRUE(HasSpan("d", "e", option2)); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.enum_type(0))); + EXPECT_TRUE(HasSpan(file_.enum_type(0), "name")); + EXPECT_TRUE(HasSpan(value)); + EXPECT_TRUE(HasSpan(value, "name")); + EXPECT_TRUE(HasSpan(value, "number")); + EXPECT_TRUE(HasSpan(option1, "name")); + EXPECT_TRUE(HasSpan(option2, "name")); + EXPECT_TRUE(HasSpan(option1.name(0))); + EXPECT_TRUE(HasSpan(option2.name(0))); + EXPECT_TRUE(HasSpan(option1.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option2.name(0), "name_part")); + EXPECT_TRUE(HasSpan(option1, "positive_int_value")); + EXPECT_TRUE(HasSpan(option2, "string_value")); +} + // =================================================================== } // anonymous namespace diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index a4aedafb..727f9421 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -59,13 +59,15 @@ namespace google { namespace protobuf { namespace compiler { -class GeneratorResponseOutputDirectory : public OutputDirectory { +class GeneratorResponseContext : public GeneratorContext { public: - GeneratorResponseOutputDirectory(CodeGeneratorResponse* response) - : response_(response) {} - virtual ~GeneratorResponseOutputDirectory() {} + GeneratorResponseContext(CodeGeneratorResponse* response, + const vector& parsed_files) + : response_(response), + parsed_files_(parsed_files) {} + virtual ~GeneratorResponseContext() {} - // implements OutputDirectory -------------------------------------- + // implements GeneratorContext -------------------------------------- virtual io::ZeroCopyOutputStream* Open(const string& filename) { CodeGeneratorResponse::File* file = response_->add_file(); @@ -81,8 +83,13 @@ class GeneratorResponseOutputDirectory : public OutputDirectory { return new io::StringOutputStream(file->mutable_content()); } + void ListParsedFiles(vector* output) { + *output = parsed_files_; + } + private: CodeGeneratorResponse* response_; + const vector& parsed_files_; }; int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { @@ -112,22 +119,26 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { } } - CodeGeneratorResponse response; - GeneratorResponseOutputDirectory output_directory(&response); - + vector parsed_files; for (int i = 0; i < request.file_to_generate_size(); i++) { - const FileDescriptor* file = - pool.FindFileByName(request.file_to_generate(i)); - if (file == NULL) { + parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i))); + if (parsed_files.back() == NULL) { cerr << argv[0] << ": protoc asked plugin to generate a file but " "did not provide a descriptor for the file: " << request.file_to_generate(i) << endl; return 1; } + } + + CodeGeneratorResponse response; + GeneratorResponseContext context(&response, parsed_files); + + for (int i = 0; i < parsed_files.size(); i++) { + const FileDescriptor* file = parsed_files[i]; string error; bool succeeded = generator->Generate( - file, request.parameter(), &output_directory, &error); + file, request.parameter(), &context, &error); if (!succeeded && error.empty()) { error = "Code generator returned false but provided no error " diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h index 7c403332..64dfb1d2 100644 --- a/src/google/protobuf/compiler/plugin.h +++ b/src/google/protobuf/compiler/plugin.h @@ -64,7 +64,7 @@ namespace compiler { class CodeGenerator; // code_generator.h // Implements main() for a protoc plugin exposing the given code generator. -LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator); +int PluginMain(int argc, char* argv[], const CodeGenerator* generator); } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 13d35c68..ad4b4deb 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -158,7 +158,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto // =================================================================== -const ::std::string CodeGeneratorRequest::_default_parameter_; #ifndef _MSC_VER const int CodeGeneratorRequest::kFileToGenerateFieldNumber; const int CodeGeneratorRequest::kParameterFieldNumber; @@ -181,7 +180,7 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from) void CodeGeneratorRequest::SharedCtor() { _cached_size_ = 0; - parameter_ = const_cast< ::std::string*>(&_default_parameter_); + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -190,7 +189,7 @@ CodeGeneratorRequest::~CodeGeneratorRequest() { } void CodeGeneratorRequest::SharedDtor() { - if (parameter_ != &_default_parameter_) { + if (parameter_ != &::google::protobuf::internal::kEmptyString) { delete parameter_; } if (this != default_instance_) { @@ -219,8 +218,8 @@ CodeGeneratorRequest* CodeGeneratorRequest::New() const { void CodeGeneratorRequest::Clear() { if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { - if (_has_bit(1)) { - if (parameter_ != &_default_parameter_) { + if (has_parameter()) { + if (parameter_ != &::google::protobuf::internal::kEmptyString) { parameter_->clear(); } } @@ -315,7 +314,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes( } // optional string parameter = 2; - if (_has_bit(1)) { + if (has_parameter()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->parameter().data(), this->parameter().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -347,7 +346,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes( } // optional string parameter = 2; - if (_has_bit(1)) { + if (has_parameter()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->parameter().data(), this->parameter().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -425,7 +424,7 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) { file_to_generate_.MergeFrom(from.file_to_generate_); proto_file_.MergeFrom(from.proto_file_); if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { - if (from._has_bit(1)) { + if (from.has_parameter()) { set_parameter(from.parameter()); } } @@ -474,9 +473,6 @@ void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) { // =================================================================== -const ::std::string CodeGeneratorResponse_File::_default_name_; -const ::std::string CodeGeneratorResponse_File::_default_insertion_point_; -const ::std::string CodeGeneratorResponse_File::_default_content_; #ifndef _MSC_VER const int CodeGeneratorResponse_File::kNameFieldNumber; const int CodeGeneratorResponse_File::kInsertionPointFieldNumber; @@ -499,9 +495,9 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon void CodeGeneratorResponse_File::SharedCtor() { _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); - insertion_point_ = const_cast< ::std::string*>(&_default_insertion_point_); - content_ = const_cast< ::std::string*>(&_default_content_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -510,13 +506,13 @@ CodeGeneratorResponse_File::~CodeGeneratorResponse_File() { } void CodeGeneratorResponse_File::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { delete name_; } - if (insertion_point_ != &_default_insertion_point_) { + if (insertion_point_ != &::google::protobuf::internal::kEmptyString) { delete insertion_point_; } - if (content_ != &_default_content_) { + if (content_ != &::google::protobuf::internal::kEmptyString) { delete content_; } if (this != default_instance_) { @@ -545,18 +541,18 @@ CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const { void CodeGeneratorResponse_File::Clear() { if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } } - if (_has_bit(1)) { - if (insertion_point_ != &_default_insertion_point_) { + if (has_insertion_point()) { + if (insertion_point_ != &::google::protobuf::internal::kEmptyString) { insertion_point_->clear(); } } - if (_has_bit(2)) { - if (content_ != &_default_content_) { + if (has_content()) { + if (content_ != &::google::protobuf::internal::kEmptyString) { content_->clear(); } } @@ -640,7 +636,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream( void CodeGeneratorResponse_File::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -649,7 +645,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( } // optional string insertion_point = 2; - if (_has_bit(1)) { + if (has_insertion_point()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->insertion_point().data(), this->insertion_point().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -658,7 +654,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( } // optional string content = 15; - if (_has_bit(2)) { + if (has_content()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->content().data(), this->content().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -675,7 +671,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( ::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -685,7 +681,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( } // optional string insertion_point = 2; - if (_has_bit(1)) { + if (has_insertion_point()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->insertion_point().data(), this->insertion_point().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -695,7 +691,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( } // optional string content = 15; - if (_has_bit(2)) { + if (has_content()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->content().data(), this->content().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -763,13 +759,13 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(1)) { + if (from.has_insertion_point()) { set_insertion_point(from.insertion_point()); } - if (from._has_bit(2)) { + if (from.has_content()) { set_content(from.content()); } } @@ -815,7 +811,6 @@ void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) { // ------------------------------------------------------------------- -const ::std::string CodeGeneratorResponse::_default_error_; #ifndef _MSC_VER const int CodeGeneratorResponse::kErrorFieldNumber; const int CodeGeneratorResponse::kFileFieldNumber; @@ -837,7 +832,7 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from) void CodeGeneratorResponse::SharedCtor() { _cached_size_ = 0; - error_ = const_cast< ::std::string*>(&_default_error_); + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -846,7 +841,7 @@ CodeGeneratorResponse::~CodeGeneratorResponse() { } void CodeGeneratorResponse::SharedDtor() { - if (error_ != &_default_error_) { + if (error_ != &::google::protobuf::internal::kEmptyString) { delete error_; } if (this != default_instance_) { @@ -875,8 +870,8 @@ CodeGeneratorResponse* CodeGeneratorResponse::New() const { void CodeGeneratorResponse::Clear() { if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (error_ != &_default_error_) { + if (has_error()) { + if (error_ != &::google::protobuf::internal::kEmptyString) { error_->clear(); } } @@ -942,7 +937,7 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream( void CodeGeneratorResponse::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional string error = 1; - if (_has_bit(0)) { + if (has_error()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->error().data(), this->error().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -965,7 +960,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes( ::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional string error = 1; - if (_has_bit(0)) { + if (has_error()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->error().data(), this->error().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -1035,7 +1030,7 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) { GOOGLE_CHECK_NE(&from, this); file_.MergeFrom(from.file_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_error()) { set_error(from.error()); } } diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index bd6bf63c..c307bfd4 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -120,6 +120,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message inline void set_parameter(const char* value); inline void set_parameter(const char* value, size_t size); inline ::std::string* mutable_parameter(); + inline ::std::string* release_parameter(); // repeated .google.protobuf.FileDescriptorProto proto_file = 15; inline int proto_file_size() const; @@ -135,29 +136,21 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) private: + inline void set_has_parameter(); + inline void clear_has_parameter(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_; ::std::string* parameter_; - static const ::std::string _default_parameter_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_; - 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(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static CodeGeneratorRequest* default_instance_; @@ -227,6 +220,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M 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(); // optional string insertion_point = 2; inline bool has_insertion_point() const; @@ -237,6 +231,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M inline void set_insertion_point(const char* value); inline void set_insertion_point(const char* value, size_t size); inline ::std::string* mutable_insertion_point(); + inline ::std::string* release_insertion_point(); // optional string content = 15; inline bool has_content() const; @@ -247,34 +242,29 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M inline void set_content(const char* value); inline void set_content(const char* value, size_t size); inline ::std::string* mutable_content(); + inline ::std::string* release_content(); // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_insertion_point(); + inline void clear_has_insertion_point(); + inline void set_has_content(); + inline void clear_has_content(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* name_; - static const ::std::string _default_name_; ::std::string* insertion_point_; - static const ::std::string _default_insertion_point_; ::std::string* content_; - static const ::std::string _default_content_; - 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(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static CodeGeneratorResponse_File* default_instance_; @@ -346,6 +336,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag inline void set_error(const char* value); inline void set_error(const char* value, size_t size); inline ::std::string* mutable_error(); + inline ::std::string* release_error(); // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; inline int file_size() const; @@ -361,28 +352,20 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) private: + inline void set_has_error(); + inline void clear_has_error(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* error_; - static const ::std::string _default_error_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_; - 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(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static CodeGeneratorResponse* default_instance_; @@ -440,45 +423,61 @@ CodeGeneratorRequest::mutable_file_to_generate() { // optional string parameter = 2; inline bool CodeGeneratorRequest::has_parameter() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void CodeGeneratorRequest::set_has_parameter() { + _has_bits_[0] |= 0x00000002u; +} +inline void CodeGeneratorRequest::clear_has_parameter() { + _has_bits_[0] &= ~0x00000002u; } inline void CodeGeneratorRequest::clear_parameter() { - if (parameter_ != &_default_parameter_) { + if (parameter_ != &::google::protobuf::internal::kEmptyString) { parameter_->clear(); } - _clear_bit(1); + clear_has_parameter(); } inline const ::std::string& CodeGeneratorRequest::parameter() const { return *parameter_; } inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) { - _set_bit(1); - if (parameter_ == &_default_parameter_) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::kEmptyString) { parameter_ = new ::std::string; } parameter_->assign(value); } inline void CodeGeneratorRequest::set_parameter(const char* value) { - _set_bit(1); - if (parameter_ == &_default_parameter_) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::kEmptyString) { parameter_ = new ::std::string; } parameter_->assign(value); } inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { - _set_bit(1); - if (parameter_ == &_default_parameter_) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::kEmptyString) { parameter_ = new ::std::string; } parameter_->assign(reinterpret_cast(value), size); } inline ::std::string* CodeGeneratorRequest::mutable_parameter() { - _set_bit(1); - if (parameter_ == &_default_parameter_) { + set_has_parameter(); + if (parameter_ == &::google::protobuf::internal::kEmptyString) { parameter_ = new ::std::string; } return parameter_; } +inline ::std::string* CodeGeneratorRequest::release_parameter() { + clear_has_parameter(); + if (parameter_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = parameter_; + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // repeated .google.protobuf.FileDescriptorProto proto_file = 15; inline int CodeGeneratorRequest::proto_file_size() const { @@ -511,129 +510,177 @@ CodeGeneratorRequest::mutable_proto_file() { // optional string name = 1; inline bool CodeGeneratorResponse_File::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void CodeGeneratorResponse_File::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void CodeGeneratorResponse_File::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void CodeGeneratorResponse_File::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& CodeGeneratorResponse_File::name() const { return *name_; } inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void CodeGeneratorResponse_File::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); } inline ::std::string* CodeGeneratorResponse_File::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } return name_; } +inline ::std::string* CodeGeneratorResponse_File::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional string insertion_point = 2; inline bool CodeGeneratorResponse_File::has_insertion_point() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void CodeGeneratorResponse_File::set_has_insertion_point() { + _has_bits_[0] |= 0x00000002u; +} +inline void CodeGeneratorResponse_File::clear_has_insertion_point() { + _has_bits_[0] &= ~0x00000002u; } inline void CodeGeneratorResponse_File::clear_insertion_point() { - if (insertion_point_ != &_default_insertion_point_) { + if (insertion_point_ != &::google::protobuf::internal::kEmptyString) { insertion_point_->clear(); } - _clear_bit(1); + clear_has_insertion_point(); } inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const { return *insertion_point_; } inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) { - _set_bit(1); - if (insertion_point_ == &_default_insertion_point_) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::kEmptyString) { insertion_point_ = new ::std::string; } insertion_point_->assign(value); } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) { - _set_bit(1); - if (insertion_point_ == &_default_insertion_point_) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::kEmptyString) { insertion_point_ = new ::std::string; } insertion_point_->assign(value); } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { - _set_bit(1); - if (insertion_point_ == &_default_insertion_point_) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::kEmptyString) { insertion_point_ = new ::std::string; } insertion_point_->assign(reinterpret_cast(value), size); } inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { - _set_bit(1); - if (insertion_point_ == &_default_insertion_point_) { + set_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::kEmptyString) { insertion_point_ = new ::std::string; } return insertion_point_; } +inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() { + clear_has_insertion_point(); + if (insertion_point_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = insertion_point_; + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional string content = 15; inline bool CodeGeneratorResponse_File::has_content() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void CodeGeneratorResponse_File::set_has_content() { + _has_bits_[0] |= 0x00000004u; +} +inline void CodeGeneratorResponse_File::clear_has_content() { + _has_bits_[0] &= ~0x00000004u; } inline void CodeGeneratorResponse_File::clear_content() { - if (content_ != &_default_content_) { + if (content_ != &::google::protobuf::internal::kEmptyString) { content_->clear(); } - _clear_bit(2); + clear_has_content(); } inline const ::std::string& CodeGeneratorResponse_File::content() const { return *content_; } inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) { - _set_bit(2); - if (content_ == &_default_content_) { + set_has_content(); + if (content_ == &::google::protobuf::internal::kEmptyString) { content_ = new ::std::string; } content_->assign(value); } inline void CodeGeneratorResponse_File::set_content(const char* value) { - _set_bit(2); - if (content_ == &_default_content_) { + set_has_content(); + if (content_ == &::google::protobuf::internal::kEmptyString) { content_ = new ::std::string; } content_->assign(value); } inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { - _set_bit(2); - if (content_ == &_default_content_) { + set_has_content(); + if (content_ == &::google::protobuf::internal::kEmptyString) { content_ = new ::std::string; } content_->assign(reinterpret_cast(value), size); } inline ::std::string* CodeGeneratorResponse_File::mutable_content() { - _set_bit(2); - if (content_ == &_default_content_) { + set_has_content(); + if (content_ == &::google::protobuf::internal::kEmptyString) { content_ = new ::std::string; } return content_; } +inline ::std::string* CodeGeneratorResponse_File::release_content() { + clear_has_content(); + if (content_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = content_; + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // ------------------------------------------------------------------- @@ -641,45 +688,61 @@ inline ::std::string* CodeGeneratorResponse_File::mutable_content() { // optional string error = 1; inline bool CodeGeneratorResponse::has_error() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void CodeGeneratorResponse::set_has_error() { + _has_bits_[0] |= 0x00000001u; +} +inline void CodeGeneratorResponse::clear_has_error() { + _has_bits_[0] &= ~0x00000001u; } inline void CodeGeneratorResponse::clear_error() { - if (error_ != &_default_error_) { + if (error_ != &::google::protobuf::internal::kEmptyString) { error_->clear(); } - _clear_bit(0); + clear_has_error(); } inline const ::std::string& CodeGeneratorResponse::error() const { return *error_; } inline void CodeGeneratorResponse::set_error(const ::std::string& value) { - _set_bit(0); - if (error_ == &_default_error_) { + set_has_error(); + if (error_ == &::google::protobuf::internal::kEmptyString) { error_ = new ::std::string; } error_->assign(value); } inline void CodeGeneratorResponse::set_error(const char* value) { - _set_bit(0); - if (error_ == &_default_error_) { + set_has_error(); + if (error_ == &::google::protobuf::internal::kEmptyString) { error_ = new ::std::string; } error_->assign(value); } inline void CodeGeneratorResponse::set_error(const char* value, size_t size) { - _set_bit(0); - if (error_ == &_default_error_) { + set_has_error(); + if (error_ == &::google::protobuf::internal::kEmptyString) { error_ = new ::std::string; } error_->assign(reinterpret_cast(value), size); } inline ::std::string* CodeGeneratorResponse::mutable_error() { - _set_bit(0); - if (error_ == &_default_error_) { + set_has_error(); + if (error_ == &::google::protobuf::internal::kEmptyString) { error_ = new ::std::string; } return error_; } +inline ::std::string* CodeGeneratorResponse::release_error() { + clear_has_error(); + if (error_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = error_; + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; inline int CodeGeneratorResponse::file_size() const { diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto index 4e928b0d..651ed10c 100644 --- a/src/google/protobuf/compiler/plugin.proto +++ b/src/google/protobuf/compiler/plugin.proto @@ -131,7 +131,7 @@ message CodeGeneratorResponse { // in order to work correctly in that context. // // The code generator that generates the initial file and the one which - // inserts into it must both run as part of a single invocatino of protoc. + // inserts into it must both run as part of a single invocation of protoc. // Code generators are executed in the order in which they appear on the // command line. // diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index fae83a37..9b109378 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -230,7 +230,7 @@ Generator::~Generator() { bool Generator::Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { // Completely serialize all Generate() calls on this instance. The @@ -252,20 +252,18 @@ bool Generator::Generate(const FileDescriptor* file, fdp.SerializeToString(&file_descriptor_serialized_); - scoped_ptr output(output_directory->Open(filename)); + scoped_ptr output(context->Open(filename)); GOOGLE_CHECK(output.get()); io::Printer printer(output.get(), '$'); printer_ = &printer; PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto()); + PrintImports(); PrintFileDescriptor(); PrintTopLevelEnums(); PrintTopLevelExtensions(); PrintAllNestedEnumsInFile(); PrintMessageDescriptors(); - // We have to print the imports after the descriptors, so that mutually - // recursive protos in separate files can successfully reference each other. - PrintImports(); FixForeignFieldsInDescriptors(); PrintMessages(); // We have to fix up the extensions after the message classes themselves, @@ -377,7 +375,7 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { printer_->Print("containing_type=None,\n"); printer_->Print("options=$options_value$,\n", "options_value", - OptionsValue("EnumOptions", CEscape(options_string))); + OptionsValue("EnumOptions", options_string)); EnumDescriptorProto edp; PrintSerializedPbInterval(enum_descriptor, edp); printer_->Outdent(); @@ -674,6 +672,17 @@ void Generator::FixForeignFieldsInDescriptor( } } +void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { + map m; + m["descriptor_name"] = kDescriptorKey; + m["message_name"] = descriptor.name(); + m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor); + const char file_descriptor_template[] = + "$descriptor_name$.message_types_by_name['$message_name$'] = " + "$message_descriptor_name$\n"; + printer_->Print(m, file_descriptor_template); +} + // Sets any necessary message_type and enum_type attributes // for the Python version of |field|. // @@ -752,6 +761,9 @@ void Generator::FixForeignFieldsInDescriptors() const { for (int i = 0; i < file_->message_type_count(); ++i) { FixForeignFieldsInDescriptor(*file_->message_type(i), NULL); } + for (int i = 0; i < file_->message_type_count(); ++i) { + AddMessageToFileDescriptor(*file_->message_type(i)); + } printer_->Print("\n"); } @@ -823,6 +835,8 @@ void Generator::PrintEnumValueDescriptor( " type=None)"); } +// Returns a Python expression that calls descriptor._ParseOptions using +// the given descriptor class name and serialized options protobuf string. string Generator::OptionsValue( const string& class_name, const string& serialized_options) const { if (serialized_options.length() == 0 || GeneratingDescriptorProto()) { diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h index 43c20876..84eaf8ab 100644 --- a/src/google/protobuf/compiler/python/python_generator.h +++ b/src/google/protobuf/compiler/python/python_generator.h @@ -66,7 +66,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { // CodeGenerator methods. virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* generator_context, string* error) const; private: @@ -104,6 +104,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void FixForeignFieldsInField(const Descriptor* containing_type, const FieldDescriptor& field, const string& python_dict_name) const; + void AddMessageToFileDescriptor(const Descriptor& 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 fde88761..da619ad3 100644 --- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc +++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc @@ -56,19 +56,19 @@ class TestGenerator : public CodeGenerator { virtual bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { - TryInsert("test_pb2.py", "imports", output_directory); - TryInsert("test_pb2.py", "module_scope", output_directory); - TryInsert("test_pb2.py", "class_scope:foo.Bar", output_directory); - TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", output_directory); + TryInsert("test_pb2.py", "imports", context); + TryInsert("test_pb2.py", "module_scope", context); + TryInsert("test_pb2.py", "class_scope:foo.Bar", context); + TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context); return true; } void TryInsert(const string& filename, const string& insertion_point, - OutputDirectory* output_directory) const { + GeneratorContext* context) const { scoped_ptr output( - output_directory->OpenForInsert(filename, insertion_point)); + context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index dbd813e1..5fb5d5cb 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -32,6 +32,8 @@ #include +#include + #ifndef _WIN32 #include #include @@ -39,7 +41,6 @@ #include #endif -#include #include #include #include diff --git a/src/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h index 7a6fa70c..de9fce9e 100644 --- a/src/google/protobuf/compiler/subprocess.h +++ b/src/google/protobuf/compiler/subprocess.h @@ -40,9 +40,10 @@ #include #include #endif // !_WIN32 +#include #include -#include + namespace google { namespace protobuf { diff --git a/src/google/protobuf/compiler/zip_output_unittest.sh b/src/google/protobuf/compiler/zip_output_unittest.sh index 259d5d21..3a024364 100755 --- a/src/google/protobuf/compiler/zip_output_unittest.sh +++ b/src/google/protobuf/compiler/zip_output_unittest.sh @@ -39,45 +39,51 @@ fail() { exit 1 } +TEST_TMPDIR=. +PROTOC=./protoc + echo ' + syntax = "proto2"; option java_multiple_files = true; option java_package = "test.jar"; option java_outer_classname = "Outer"; message Foo {} message Bar {} -' > testzip.proto +' > $TEST_TMPDIR/testzip.proto -./protoc --cpp_out=testzip.zip --python_out=testzip.zip --java_out=testzip.jar \ - testzip.proto || fail 'protoc failed.' +$PROTOC \ + --cpp_out=$TEST_TMPDIR/testzip.zip --python_out=$TEST_TMPDIR/testzip.zip \ + --java_out=$TEST_TMPDIR/testzip.jar -I$TEST_TMPDIR testzip.proto \ + || fail 'protoc failed.' echo "Testing output to zip..." if unzip -h > /dev/null; then - unzip -t testzip.zip > testzip.list || fail 'unzip failed.' + unzip -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list || fail 'unzip failed.' - grep 'testing: testzip\.pb\.cc *OK$' testzip.list > /dev/null \ + grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'testzip.pb.cc not found in output zip.' - grep 'testing: testzip\.pb\.h *OK$' testzip.list > /dev/null \ + grep 'testing: testzip\.pb\.h *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'testzip.pb.h not found in output zip.' - grep 'testing: testzip_pb2\.py *OK$' testzip.list > /dev/null \ + grep 'testing: testzip_pb2\.py *OK$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'testzip_pb2.py not found in output zip.' - grep -i 'manifest' testzip.list > /dev/null \ + grep -i 'manifest' $TEST_TMPDIR/testzip.list > /dev/null \ && fail 'Zip file contained manifest.' else echo "Warning: 'unzip' command not available. Skipping test." fi echo "Testing output to jar..." -if jar c testzip.proto > /dev/null; then - jar tf testzip.jar > testzip.list || fail 'jar failed.' +if jar c $TEST_TMPDIR/testzip.proto > /dev/null; then + jar tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list || fail 'jar failed.' - grep '^test/jar/Foo\.java$' testzip.list > /dev/null \ + grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'Foo.java not found in output jar.' - grep '^test/jar/Bar\.java$' testzip.list > /dev/null \ + grep '^test/jar/Bar\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'Bar.java not found in output jar.' - grep '^test/jar/Outer\.java$' testzip.list > /dev/null \ + grep '^test/jar/Outer\.java$' $TEST_TMPDIR/testzip.list > /dev/null \ || fail 'Outer.java not found in output jar.' - grep '^META-INF/MANIFEST\.MF$' testzip.list > /dev/null \ - || fail 'Manifest not ofund in output jar.' + grep '^META-INF/MANIFEST\.MF$' $TEST_TMPDIR/testzip.list > /dev/null \ + || fail 'Manifest not found in output jar.' else echo "Warning: 'jar' command not available. Skipping test." fi diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc index 53c18771..65d73527 100644 --- a/src/google/protobuf/compiler/zip_writer.cc +++ b/src/google/protobuf/compiler/zip_writer.cc @@ -28,6 +28,36 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// 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: ambrose@google.com (Ambrose Feinstein), // kenton@google.com (Kenton Varda) // @@ -183,6 +213,6 @@ bool ZipWriter::WriteDirectory() { return output.HadError(); } -} // namespace google -} // namespace protobuf } // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h index 42895530..be73972a 100644 --- a/src/google/protobuf/compiler/zip_writer.h +++ b/src/google/protobuf/compiler/zip_writer.h @@ -28,6 +28,36 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// 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: kenton@google.com (Kenton Varda) #include @@ -58,6 +88,6 @@ class ZipWriter { vector files_; }; -} // namespace google -} // namespace protobuf } // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 9226dfbc..76b7219f 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -42,10 +42,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -2056,6 +2058,8 @@ class DescriptorBuilder { // Otherwise returns true. bool InterpretOptions(OptionsToInterpret* options_to_interpret); + class AggregateOptionFinder; + private: // Interprets uninterpreted_option_ on the specified message, which // must be the mutable copy of the original options message to which @@ -2082,6 +2086,11 @@ class DescriptorBuilder { bool SetOptionValue(const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields); + // Parses an aggregate value for a CPPTYPE_MESSAGE option and + // saves it into *unknown_fields. + bool SetAggregateOption(const FieldDescriptor* option_field, + UnknownFieldSet* unknown_fields); + // Convenience functions to set an int field the right way, depending on // its wire type (a single int CppType can represent multiple wire types). void SetInt32(int number, int32 value, FieldDescriptor::Type type, @@ -2128,6 +2137,10 @@ class DescriptorBuilder { // can use it to find locations recorded by the parser. const UninterpretedOption* uninterpreted_option_; + // Factory used to create the dynamic messages we need to parse + // any aggregate option values we encounter. + DynamicMessageFactory dynamic_factory_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter); }; @@ -2139,6 +2152,8 @@ class DescriptorBuilder { // redundantly declare OptionInterpreter a friend just to make things extra // clear for these bad compilers. friend class OptionInterpreter; + friend class OptionInterpreter::AggregateOptionFinder; + static inline bool get_allow_unknown(const DescriptorPool* pool) { return pool->allow_unknown_; } @@ -3973,9 +3988,6 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( intermediate_fields.push_back(field); descriptor = field->message_type(); } - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - return AddNameError("Option field \"" + debug_msg_name + - "\" cannot be of message type."); } } @@ -4310,18 +4322,95 @@ bool DescriptorBuilder::OptionInterpreter::SetOptionValue( break; case FieldDescriptor::CPPTYPE_MESSAGE: - // We don't currently support defining a message-typed option, so we - // should never actually get here. - return AddValueError("Option \"" + option_field->full_name() + - "\" is a message. To set fields within it, use " - "syntax like \"" + option_field->name() + - ".foo = value\"."); + if (!SetAggregateOption(option_field, unknown_fields)) { + return false; + } break; } return true; } +class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder + : public TextFormat::Finder { + public: + DescriptorBuilder* builder_; + + virtual const FieldDescriptor* FindExtension( + Message* message, const string& name) const { + if (builder_->pool_->mutex_ != NULL) { + builder_->pool_->mutex_->AssertHeld(); + } + Symbol result = builder_->LookupSymbolNoPlaceholder( + name, message->GetDescriptor()->full_name()); + if (result.type == Symbol::FIELD && + result.field_descriptor->is_extension()) { + return result.field_descriptor; + } else { + return NULL; + } + } +}; + +// A custom error collector to record any text-format parsing errors +namespace { +class AggregateErrorCollector : public io::ErrorCollector { + public: + string error_; + + virtual void AddError(int line, int column, const string& message) { + if (!error_.empty()) { + error_ += "; "; + } + error_ += message; + } + + virtual void AddWarning(int line, int column, const string& message) { + // Ignore warnings + } +}; +} + +// We construct a dynamic message of the type corresponding to +// option_field, parse the supplied text-format string into this +// message, and serialize the resulting message to produce the value. +bool DescriptorBuilder::OptionInterpreter::SetAggregateOption( + const FieldDescriptor* option_field, + UnknownFieldSet* unknown_fields) { + if (!uninterpreted_option_->has_aggregate_value()) { + return AddValueError("Option \"" + option_field->full_name() + + "\" is a message. To set the entire message, use " + "syntax like \"" + option_field->name() + + " = { }\". " + "To set fields within it, use " + "syntax like \"" + option_field->name() + + ".foo = value\"."); + } + + const Descriptor* type = option_field->message_type(); + scoped_ptr dynamic(dynamic_factory_.GetPrototype(type)->New()); + GOOGLE_CHECK(dynamic.get() != NULL) + << "Could not create an instance of " << option_field->DebugString(); + + AggregateErrorCollector collector; + AggregateOptionFinder finder; + finder.builder_ = builder_; + TextFormat::Parser parser; + parser.RecordErrorsTo(&collector); + parser.SetFinder(&finder); + if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(), + dynamic.get())) { + AddValueError("Error while parsing option value for \"" + + option_field->name() + "\": " + collector.error_); + return false; + } else { + string serial; + dynamic->SerializeToString(&serial); // Never fails + unknown_fields->AddLengthDelimited(option_field->number(), serial); + return true; + } +} + void DescriptorBuilder::OptionInterpreter::SetInt32(int number, int32 value, FieldDescriptor::Type type, UnknownFieldSet* unknown_fields) { switch (type) { diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 922237f5..87303ef8 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -76,6 +76,12 @@ const ::google::protobuf::internal::GeneratedMessageReflection* const ::google::protobuf::Descriptor* UninterpretedOption_NamePart_descriptor_ = NULL; const ::google::protobuf::internal::GeneratedMessageReflection* UninterpretedOption_NamePart_reflection_ = NULL; +const ::google::protobuf::Descriptor* SourceCodeInfo_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + SourceCodeInfo_reflection_ = NULL; +const ::google::protobuf::Descriptor* SourceCodeInfo_Location_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + SourceCodeInfo_Location_reflection_ = NULL; } // namespace @@ -102,7 +108,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(FileDescriptorSet)); FileDescriptorProto_descriptor_ = file->message_type(1); - static const int FileDescriptorProto_offsets_[8] = { + static const int FileDescriptorProto_offsets_[9] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, dependency_), @@ -111,6 +117,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, service_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, extension_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, options_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, source_code_info_), }; FileDescriptorProto_reflection_ = new ::google::protobuf::internal::GeneratedMessageReflection( @@ -254,10 +261,11 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(MethodDescriptorProto)); FileOptions_descriptor_ = file->message_type(8); - static const int FileOptions_offsets_[8] = { + static const int FileOptions_offsets_[9] = { 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, optimize_for_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_), @@ -374,13 +382,14 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(MethodOptions)); UninterpretedOption_descriptor_ = file->message_type(15); - static const int UninterpretedOption_offsets_[6] = { + static const int UninterpretedOption_offsets_[7] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, identifier_value_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, positive_int_value_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, negative_int_value_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, double_value_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, string_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, aggregate_value_), }; UninterpretedOption_reflection_ = new ::google::protobuf::internal::GeneratedMessageReflection( @@ -409,6 +418,37 @@ 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); + static const int SourceCodeInfo_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_), + }; + SourceCodeInfo_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + SourceCodeInfo_descriptor_, + SourceCodeInfo::default_instance_, + SourceCodeInfo_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(SourceCodeInfo)); + SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0); + static const int SourceCodeInfo_Location_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_), + }; + SourceCodeInfo_Location_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + SourceCodeInfo_Location_descriptor_, + SourceCodeInfo_Location::default_instance_, + SourceCodeInfo_Location_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(SourceCodeInfo_Location)); } namespace { @@ -457,6 +497,10 @@ void protobuf_RegisterTypes(const ::std::string&) { UninterpretedOption_descriptor_, &UninterpretedOption::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( UninterpretedOption_NamePart_descriptor_, &UninterpretedOption_NamePart::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + SourceCodeInfo_descriptor_, &SourceCodeInfo::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + SourceCodeInfo_Location_descriptor_, &SourceCodeInfo_Location::default_instance()); } } // namespace @@ -498,6 +542,10 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() { delete UninterpretedOption_reflection_; delete UninterpretedOption_NamePart::default_instance_; delete UninterpretedOption_NamePart_reflection_; + delete SourceCodeInfo::default_instance_; + delete SourceCodeInfo_reflection_; + delete SourceCodeInfo_Location::default_instance_; + delete SourceCodeInfo_Location_reflection_; } void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { @@ -510,7 +558,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "\n google/protobuf/descriptor.proto\022\017goog" "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file" "\030\001 \003(\0132$.google.protobuf.FileDescriptorP" - "roto\"\334\002\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" + "roto\"\227\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001" "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022" "6\n\014message_type\030\004 \003(\0132 .google.protobuf." "DescriptorProto\0227\n\tenum_type\030\005 \003(\0132$.goo" @@ -518,88 +566,94 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "ice\030\006 \003(\0132\'.google.protobuf.ServiceDescr" "iptorProto\0228\n\textension\030\007 \003(\0132%.google.p" "rotobuf.FieldDescriptorProto\022-\n\007options\030" - "\010 \001(\0132\034.google.protobuf.FileOptions\"\251\003\n\017" - "DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005field\030\002" - " \003(\0132%.google.protobuf.FieldDescriptorPr" - "oto\0228\n\textension\030\006 \003(\0132%.google.protobuf" - ".FieldDescriptorProto\0225\n\013nested_type\030\003 \003" - "(\0132 .google.protobuf.DescriptorProto\0227\n\t" - "enum_type\030\004 \003(\0132$.google.protobuf.EnumDe" - "scriptorProto\022H\n\017extension_range\030\005 \003(\0132/" - ".google.protobuf.DescriptorProto.Extensi" - "onRange\0220\n\007options\030\007 \001(\0132\037.google.protob" - "uf.MessageOptions\032,\n\016ExtensionRange\022\r\n\005s" - "tart\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\224\005\n\024FieldDescrip" - "torProto\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.FieldDes" - "criptorProto.Label\0228\n\004type\030\005 \001(\0162*.googl" - "e.protobuf.FieldDescriptorProto.Type\022\021\n\t" - "type_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdef" - "ault_value\030\007 \001(\t\022.\n\007options\030\010 \001(\0132\035.goog" - "le.protobuf.FieldOptions\"\266\002\n\004Type\022\017\n\013TYP" - "E_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64" - "\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014T" - "YPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_" - "BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022" - "\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYP" - "E_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED" - "32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021" - "\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTI" - "ONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPE" - "ATED\020\003\"\214\001\n\023EnumDescriptorProto\022\014\n\004name\030\001" - " \001(\t\0228\n\005value\030\002 \003(\0132).google.protobuf.En" - "umValueDescriptorProto\022-\n\007options\030\003 \001(\0132" - "\034.google.protobuf.EnumOptions\"l\n\030EnumVal" - "ueDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006numbe" - "r\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.google.protob" - "uf.EnumValueOptions\"\220\001\n\026ServiceDescripto" - "rProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.g" - "oogle.protobuf.MethodDescriptorProto\0220\n\007" - "options\030\003 \001(\0132\037.google.protobuf.ServiceO" - "ptions\"\177\n\025MethodDescriptorProto\022\014\n\004name\030" - "\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013output_type" - "\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.protobu" - "f.MethodOptions\"\244\003\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" - "F\n\014optimize_for\030\t \001(\0162).google.protobuf." - "FileOptions.OptimizeMode:\005SPEED\022!\n\023cc_ge" - "neric_services\030\020 \001(\010:\004true\022#\n\025java_gener" - "ic_services\030\021 \001(\010:\004true\022!\n\023py_generic_se" - "rvices\030\022 \001(\010:\004true\022C\n\024uninterpreted_opti" - "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete" - "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO" - "DE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270" - "\001\n\016MessageOptions\022&\n\027message_set_wire_fo" - "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip" - "tor_accessor\030\002 \001(\010:\005false\022C\n\024uninterpret" + "\010 \001(\0132\034.google.protobuf.FileOptions\0229\n\020s" + "ource_code_info\030\t \001(\0132\037.google.protobuf." + "SourceCodeInfo\"\251\003\n\017DescriptorProto\022\014\n\004na" + "me\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.google.protobu" + "f.FieldDescriptorProto\0228\n\textension\030\006 \003(" + "\0132%.google.protobuf.FieldDescriptorProto" + "\0225\n\013nested_type\030\003 \003(\0132 .google.protobuf." + "DescriptorProto\0227\n\tenum_type\030\004 \003(\0132$.goo" + "gle.protobuf.EnumDescriptorProto\022H\n\017exte" + "nsion_range\030\005 \003(\0132/.google.protobuf.Desc" + "riptorProto.ExtensionRange\0220\n\007options\030\007 " + "\001(\0132\037.google.protobuf.MessageOptions\032,\n\016" + "ExtensionRange\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+.googl" + "e.protobuf.FieldDescriptorProto.Label\0228\n" + "\004type\030\005 \001(\0162*.google.protobuf.FieldDescr" + "iptorProto.Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010ex" + "tendee\030\002 \001(\t\022\025\n\rdefault_value\030\007 \001(\t\022.\n\007o" + "ptions\030\010 \001(\0132\035.google.protobuf.FieldOpti" + "ons\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FL" + "OAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016" + "\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE" + "_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING" + "\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\n" + "TYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_EN" + "UM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64" + "\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005" + "Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LABEL_REQUI" + "RED\020\002\022\022\n\016LABEL_REPEATED\020\003\"\214\001\n\023EnumDescri" + "ptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002 \003(\0132)" + ".google.protobuf.EnumValueDescriptorProt" + "o\022-\n\007options\030\003 \001(\0132\034.google.protobuf.Enu" + "mOptions\"l\n\030EnumValueDescriptorProto\022\014\n\004" + "name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 " + "\001(\0132!.google.protobuf.EnumValueOptions\"\220" + "\001\n\026ServiceDescriptorProto\022\014\n\004name\030\001 \001(\t\022" + "6\n\006method\030\002 \003(\0132&.google.protobuf.Method" + "DescriptorProto\0220\n\007options\030\003 \001(\0132\037.googl" + "e.protobuf.ServiceOptions\"\177\n\025MethodDescr" + "iptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002" + " \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007options\030\004 \001" + "(\0132\036.google.protobuf.MethodOptions\"\325\003\n\013F" + "ileOptions\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java" + "_outer_classname\030\010 \001(\t\022\"\n\023java_multiple_" + "files\030\n \001(\010:\005false\022,\n\035java_generate_equa" + "ls_and_hash\030\024 \001(\010:\005false\022F\n\014optimize_for" + "\030\t \001(\0162).google.protobuf.FileOptions.Opt" + "imizeMode:\005SPEED\022\"\n\023cc_generic_services\030" + "\020 \001(\010:\005false\022$\n\025java_generic_services\030\021 " + "\001(\010:\005false\022\"\n\023py_generic_services\030\022 \001(\010:" + "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." + "google.protobuf.UninterpretedOption\":\n\014O" + "ptimizeMode\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\"\270\001\n\016MessageOp" + "tions\022&\n\027message_set_wire_format\030\001 \001(\010:\005" + "false\022.\n\037no_standard_descriptor_accessor" + "\030\002 \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\"\224\002\n\014FieldOptions\022:\n\005ctype\030" + "\001 \001(\0162#.google.protobuf.FieldOptions.CTy" + "pe:\006STRING\022\016\n\006packed\030\002 \001(\010\022\031\n\ndeprecated" + "\030\003 \001(\010:\005false\022\034\n\024experimental_map_key\030\t " + "\001(\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo" + "gle.protobuf.UninterpretedOption\"/\n\005CTyp" + "e\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020" + "\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022C\n\024uninterpr" + "eted_option\030\347\007 \003(\0132$.google.protobuf.Uni" + "nterpretedOption*\t\010\350\007\020\200\200\200\200\002\"b\n\020EnumValue" + "Options\022C\n\024uninterpreted_option\030\347\007 \003(\0132$" + ".google.protobuf.UninterpretedOption*\t\010\350" + "\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n\024uninterpret" "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint" - "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"\224\002\n\014FieldOptio" - "ns\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Fiel" - "dOptions.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\031" - "\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experimenta" - "l_map_key\030\t \001(\t\022C\n\024uninterpreted_option\030" - "\347\007 \003(\0132$.google.protobuf.UninterpretedOp" - "tion\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014S" - "TRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"]\n\013EnumOptions\022" - "C\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\024uninterpreted_opt" - "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret" - "edOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceOptions\022C\n" - "\024uninterpreted_option\030\347\007 \003(\0132$.google.pr" - "otobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n" - "\rMethodOptions\022C\n\024uninterpreted_option\030\347" - "\007 \003(\0132$.google.protobuf.UninterpretedOpt" - "ion*\t\010\350\007\020\200\200\200\200\002\"\205\002\n\023UninterpretedOption\022;" - "\n\004name\030\002 \003(\0132-.google.protobuf.Uninterpr" - "etedOption.NamePart\022\030\n\020identifier_value\030" - "\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022neg" - "ative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 " - "\001(\001\022\024\n\014string_value\030\007 \001(\014\0323\n\010NamePart\022\021\n" - "\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010B)" - "\n\023com.google.protobufB\020DescriptorProtosH" - "\001", 3681); + "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"_\n\rMethodOptio" + "ns\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goog" + "le.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200" + "\200\002\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\013" + "2-.google.protobuf.UninterpretedOption.N" + "amePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022pos" + "itive_int_value\030\004 \001(\004\022\032\n\022negative_int_va" + "lue\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014strin" + "g_value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323" + "\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_exte" + "nsion\030\002 \002(\010\"|\n\016SourceCodeInfo\022:\n\010locatio" + "n\030\001 \003(\0132(.google.protobuf.SourceCodeInfo" + ".Location\032.\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022" + "\020\n\004span\030\002 \003(\005B\002\020\001B)\n\023com.google.protobuf" + "B\020DescriptorProtosH\001", 3940); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -620,6 +674,8 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { MethodOptions::default_instance_ = new MethodOptions(); UninterpretedOption::default_instance_ = new UninterpretedOption(); UninterpretedOption_NamePart::default_instance_ = new UninterpretedOption_NamePart(); + SourceCodeInfo::default_instance_ = new SourceCodeInfo(); + SourceCodeInfo_Location::default_instance_ = new SourceCodeInfo_Location(); FileDescriptorSet::default_instance_->InitAsDefaultInstance(); FileDescriptorProto::default_instance_->InitAsDefaultInstance(); DescriptorProto::default_instance_->InitAsDefaultInstance(); @@ -638,6 +694,8 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { MethodOptions::default_instance_->InitAsDefaultInstance(); UninterpretedOption::default_instance_->InitAsDefaultInstance(); UninterpretedOption_NamePart::default_instance_->InitAsDefaultInstance(); + SourceCodeInfo::default_instance_->InitAsDefaultInstance(); + SourceCodeInfo_Location::default_instance_->InitAsDefaultInstance(); ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto); } @@ -856,8 +914,6 @@ void FileDescriptorSet::Swap(FileDescriptorSet* other) { // =================================================================== -const ::std::string FileDescriptorProto::_default_name_; -const ::std::string FileDescriptorProto::_default_package_; #ifndef _MSC_VER const int FileDescriptorProto::kNameFieldNumber; const int FileDescriptorProto::kPackageFieldNumber; @@ -867,6 +923,7 @@ const int FileDescriptorProto::kEnumTypeFieldNumber; const int FileDescriptorProto::kServiceFieldNumber; const int FileDescriptorProto::kExtensionFieldNumber; const int FileDescriptorProto::kOptionsFieldNumber; +const int FileDescriptorProto::kSourceCodeInfoFieldNumber; #endif // !_MSC_VER FileDescriptorProto::FileDescriptorProto() @@ -876,6 +933,7 @@ FileDescriptorProto::FileDescriptorProto() void FileDescriptorProto::InitAsDefaultInstance() { options_ = const_cast< ::google::protobuf::FileOptions*>(&::google::protobuf::FileOptions::default_instance()); + source_code_info_ = const_cast< ::google::protobuf::SourceCodeInfo*>(&::google::protobuf::SourceCodeInfo::default_instance()); } FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) @@ -886,9 +944,10 @@ FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) void FileDescriptorProto::SharedCtor() { _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); - package_ = const_cast< ::std::string*>(&_default_package_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); options_ = NULL; + source_code_info_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -897,14 +956,15 @@ FileDescriptorProto::~FileDescriptorProto() { } void FileDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { delete name_; } - if (package_ != &_default_package_) { + if (package_ != &::google::protobuf::internal::kEmptyString) { delete package_; } if (this != default_instance_) { delete options_; + delete source_code_info_; } } @@ -930,20 +990,25 @@ FileDescriptorProto* FileDescriptorProto::New() const { void FileDescriptorProto::Clear() { if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } } - if (_has_bit(1)) { - if (package_ != &_default_package_) { + if (has_package()) { + if (package_ != &::google::protobuf::internal::kEmptyString) { package_->clear(); } } - if (_has_bit(7)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); } } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (has_source_code_info()) { + if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); + } + } dependency_.Clear(); message_type_.Clear(); enum_type_.Clear(); @@ -1080,6 +1145,20 @@ bool FileDescriptorProto::MergePartialFromCodedStream( } else { goto handle_uninterpreted; } + if (input->ExpectTag(74)) goto parse_source_code_info; + break; + } + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + case 9: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_source_code_info: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, mutable_source_code_info())); + } else { + goto handle_uninterpreted; + } if (input->ExpectAtEnd()) return true; break; } @@ -1103,7 +1182,7 @@ bool FileDescriptorProto::MergePartialFromCodedStream( void FileDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -1112,7 +1191,7 @@ void FileDescriptorProto::SerializeWithCachedSizes( } // optional string package = 2; - if (_has_bit(1)) { + if (has_package()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->package().data(), this->package().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -1154,11 +1233,17 @@ void FileDescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.FileOptions options = 8; - if (_has_bit(7)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 8, this->options(), output); } + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (has_source_code_info()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 9, this->source_code_info(), output); + } + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); @@ -1168,7 +1253,7 @@ void FileDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* FileDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -1178,7 +1263,7 @@ void FileDescriptorProto::SerializeWithCachedSizes( } // optional string package = 2; - if (_has_bit(1)) { + if (has_package()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->package().data(), this->package().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -1225,12 +1310,19 @@ void FileDescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.FileOptions options = 8; - if (_has_bit(7)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 8, this->options(), target); } + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (has_source_code_info()) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 9, this->source_code_info(), target); + } + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); @@ -1263,6 +1355,15 @@ int FileDescriptorProto::ByteSize() const { this->options()); } + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + if (has_source_code_info()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->source_code_info()); + } + } // repeated string dependency = 3; total_size += 1 * this->dependency_size(); @@ -1334,16 +1435,21 @@ void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) { service_.MergeFrom(from.service_); extension_.MergeFrom(from.extension_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(1)) { + if (from.has_package()) { set_package(from.package()); } - if (from._has_bit(7)) { + if (from.has_options()) { mutable_options()->::google::protobuf::FileOptions::MergeFrom(from.options()); } } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { + if (from.has_source_code_info()) { + mutable_source_code_info()->::google::protobuf::SourceCodeInfo::MergeFrom(from.source_code_info()); + } + } mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -1389,6 +1495,7 @@ void FileDescriptorProto::Swap(FileDescriptorProto* other) { service_.Swap(&other->service_); extension_.Swap(&other->extension_); std::swap(options_, other->options_); + std::swap(source_code_info_, other->source_code_info_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); std::swap(_cached_size_, other->_cached_size_); @@ -1483,7 +1590,7 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &start_))); - _set_bit(0); + set_has_start(); } else { goto handle_uninterpreted; } @@ -1499,7 +1606,7 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &end_))); - _set_bit(1); + set_has_end(); } else { goto handle_uninterpreted; } @@ -1526,12 +1633,12 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional int32 start = 1; - if (_has_bit(0)) { + if (has_start()) { ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output); } // optional int32 end = 2; - if (_has_bit(1)) { + if (has_end()) { ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output); } @@ -1544,12 +1651,12 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( ::google::protobuf::uint8* DescriptorProto_ExtensionRange::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional int32 start = 1; - if (_has_bit(0)) { + if (has_start()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target); } // optional int32 end = 2; - if (_has_bit(1)) { + if (has_end()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target); } @@ -1605,10 +1712,10 @@ void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_start()) { set_start(from.start()); } - if (from._has_bit(1)) { + if (from.has_end()) { set_end(from.end()); } } @@ -1653,7 +1760,6 @@ void DescriptorProto_ExtensionRange::Swap(DescriptorProto_ExtensionRange* other) // ------------------------------------------------------------------- -const ::std::string DescriptorProto::_default_name_; #ifndef _MSC_VER const int DescriptorProto::kNameFieldNumber; const int DescriptorProto::kFieldFieldNumber; @@ -1681,7 +1787,7 @@ DescriptorProto::DescriptorProto(const DescriptorProto& from) void DescriptorProto::SharedCtor() { _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -1691,7 +1797,7 @@ DescriptorProto::~DescriptorProto() { } void DescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { delete name_; } if (this != default_instance_) { @@ -1721,12 +1827,12 @@ DescriptorProto* DescriptorProto::New() const { void DescriptorProto::Clear() { if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } } - if (_has_bit(6)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); } } @@ -1869,7 +1975,7 @@ bool DescriptorProto::MergePartialFromCodedStream( void DescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -1908,7 +2014,7 @@ void DescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.MessageOptions options = 7; - if (_has_bit(6)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 7, this->options(), output); } @@ -1922,7 +2028,7 @@ void DescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* DescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -1967,7 +2073,7 @@ void DescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.MessageOptions options = 7; - if (_has_bit(6)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 7, this->options(), target); @@ -2070,10 +2176,10 @@ void DescriptorProto::MergeFrom(const DescriptorProto& from) { enum_type_.MergeFrom(from.enum_type_); extension_range_.MergeFrom(from.extension_range_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(6)) { + if (from.has_options()) { mutable_options()->::google::protobuf::MessageOptions::MergeFrom(from.options()); } } @@ -2214,10 +2320,6 @@ const FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN; const FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX; const int FieldDescriptorProto::Label_ARRAYSIZE; #endif // _MSC_VER -const ::std::string FieldDescriptorProto::_default_name_; -const ::std::string FieldDescriptorProto::_default_type_name_; -const ::std::string FieldDescriptorProto::_default_extendee_; -const ::std::string FieldDescriptorProto::_default_default_value_; #ifndef _MSC_VER const int FieldDescriptorProto::kNameFieldNumber; const int FieldDescriptorProto::kNumberFieldNumber; @@ -2246,13 +2348,13 @@ FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) void FieldDescriptorProto::SharedCtor() { _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); number_ = 0; label_ = 1; type_ = 1; - type_name_ = const_cast< ::std::string*>(&_default_type_name_); - extendee_ = const_cast< ::std::string*>(&_default_extendee_); - default_value_ = const_cast< ::std::string*>(&_default_default_value_); + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -2262,16 +2364,16 @@ FieldDescriptorProto::~FieldDescriptorProto() { } void FieldDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { delete name_; } - if (type_name_ != &_default_type_name_) { + if (type_name_ != &::google::protobuf::internal::kEmptyString) { delete type_name_; } - if (extendee_ != &_default_extendee_) { + if (extendee_ != &::google::protobuf::internal::kEmptyString) { delete extendee_; } - if (default_value_ != &_default_default_value_) { + if (default_value_ != &::google::protobuf::internal::kEmptyString) { delete default_value_; } if (this != default_instance_) { @@ -2301,30 +2403,30 @@ FieldDescriptorProto* FieldDescriptorProto::New() const { void FieldDescriptorProto::Clear() { if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } } number_ = 0; label_ = 1; type_ = 1; - if (_has_bit(4)) { - if (type_name_ != &_default_type_name_) { + if (has_type_name()) { + if (type_name_ != &::google::protobuf::internal::kEmptyString) { type_name_->clear(); } } - if (_has_bit(5)) { - if (extendee_ != &_default_extendee_) { + if (has_extendee()) { + if (extendee_ != &::google::protobuf::internal::kEmptyString) { extendee_->clear(); } } - if (_has_bit(6)) { - if (default_value_ != &_default_default_value_) { + if (has_default_value()) { + if (default_value_ != &::google::protobuf::internal::kEmptyString) { default_value_->clear(); } } - if (_has_bit(7)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); } } @@ -2379,7 +2481,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &number_))); - _set_bit(1); + set_has_number(); } else { goto handle_uninterpreted; } @@ -2496,7 +2598,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( void FieldDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -2505,7 +2607,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( } // optional string extendee = 2; - if (_has_bit(5)) { + if (has_extendee()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->extendee().data(), this->extendee().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -2514,24 +2616,24 @@ void FieldDescriptorProto::SerializeWithCachedSizes( } // optional int32 number = 3; - if (_has_bit(1)) { + if (has_number()) { ::google::protobuf::internal::WireFormatLite::WriteInt32(3, this->number(), output); } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - if (_has_bit(2)) { + if (has_label()) { ::google::protobuf::internal::WireFormatLite::WriteEnum( 4, this->label(), output); } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - if (_has_bit(3)) { + if (has_type()) { ::google::protobuf::internal::WireFormatLite::WriteEnum( 5, this->type(), output); } // optional string type_name = 6; - if (_has_bit(4)) { + if (has_type_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->type_name().data(), this->type_name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -2540,7 +2642,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( } // optional string default_value = 7; - if (_has_bit(6)) { + if (has_default_value()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->default_value().data(), this->default_value().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -2549,7 +2651,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.FieldOptions options = 8; - if (_has_bit(7)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 8, this->options(), output); } @@ -2563,7 +2665,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* FieldDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -2573,7 +2675,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( } // optional string extendee = 2; - if (_has_bit(5)) { + if (has_extendee()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->extendee().data(), this->extendee().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -2583,24 +2685,24 @@ void FieldDescriptorProto::SerializeWithCachedSizes( } // optional int32 number = 3; - if (_has_bit(1)) { + if (has_number()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(3, this->number(), target); } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - if (_has_bit(2)) { + if (has_label()) { target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( 4, this->label(), target); } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - if (_has_bit(3)) { + if (has_type()) { target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( 5, this->type(), target); } // optional string type_name = 6; - if (_has_bit(4)) { + if (has_type_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->type_name().data(), this->type_name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -2610,7 +2712,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( } // optional string default_value = 7; - if (_has_bit(6)) { + if (has_default_value()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->default_value().data(), this->default_value().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -2620,7 +2722,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.FieldOptions options = 8; - if (_has_bit(7)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 8, this->options(), target); @@ -2718,28 +2820,28 @@ void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(1)) { + if (from.has_number()) { set_number(from.number()); } - if (from._has_bit(2)) { + if (from.has_label()) { set_label(from.label()); } - if (from._has_bit(3)) { + if (from.has_type()) { set_type(from.type()); } - if (from._has_bit(4)) { + if (from.has_type_name()) { set_type_name(from.type_name()); } - if (from._has_bit(5)) { + if (from.has_extendee()) { set_extendee(from.extendee()); } - if (from._has_bit(6)) { + if (from.has_default_value()) { set_default_value(from.default_value()); } - if (from._has_bit(7)) { + if (from.has_options()) { mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options()); } } @@ -2793,7 +2895,6 @@ void FieldDescriptorProto::Swap(FieldDescriptorProto* other) { // =================================================================== -const ::std::string EnumDescriptorProto::_default_name_; #ifndef _MSC_VER const int EnumDescriptorProto::kNameFieldNumber; const int EnumDescriptorProto::kValueFieldNumber; @@ -2817,7 +2918,7 @@ EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from) void EnumDescriptorProto::SharedCtor() { _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -2827,7 +2928,7 @@ EnumDescriptorProto::~EnumDescriptorProto() { } void EnumDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { delete name_; } if (this != default_instance_) { @@ -2857,12 +2958,12 @@ EnumDescriptorProto* EnumDescriptorProto::New() const { void EnumDescriptorProto::Clear() { if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } } - if (_has_bit(2)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); } } @@ -2941,7 +3042,7 @@ bool EnumDescriptorProto::MergePartialFromCodedStream( void EnumDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -2956,7 +3057,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.EnumOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 3, this->options(), output); } @@ -2970,7 +3071,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* EnumDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -2987,7 +3088,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.EnumOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 3, this->options(), target); @@ -3054,10 +3155,10 @@ void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); value_.MergeFrom(from.value_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(2)) { + if (from.has_options()) { mutable_options()->::google::protobuf::EnumOptions::MergeFrom(from.options()); } } @@ -3109,7 +3210,6 @@ void EnumDescriptorProto::Swap(EnumDescriptorProto* other) { // =================================================================== -const ::std::string EnumValueDescriptorProto::_default_name_; #ifndef _MSC_VER const int EnumValueDescriptorProto::kNameFieldNumber; const int EnumValueDescriptorProto::kNumberFieldNumber; @@ -3133,7 +3233,7 @@ EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProt void EnumValueDescriptorProto::SharedCtor() { _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); number_ = 0; options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); @@ -3144,7 +3244,7 @@ EnumValueDescriptorProto::~EnumValueDescriptorProto() { } void EnumValueDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { delete name_; } if (this != default_instance_) { @@ -3174,13 +3274,13 @@ EnumValueDescriptorProto* EnumValueDescriptorProto::New() const { void EnumValueDescriptorProto::Clear() { if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } } number_ = 0; - if (_has_bit(2)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); } } @@ -3218,7 +3318,7 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &number_))); - _set_bit(1); + set_has_number(); } else { goto handle_uninterpreted; } @@ -3259,7 +3359,7 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream( void EnumValueDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -3268,12 +3368,12 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( } // optional int32 number = 2; - if (_has_bit(1)) { + if (has_number()) { ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->number(), output); } // optional .google.protobuf.EnumValueOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 3, this->options(), output); } @@ -3287,7 +3387,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* EnumValueDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -3297,12 +3397,12 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( } // optional int32 number = 2; - if (_has_bit(1)) { + if (has_number()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->number(), target); } // optional .google.protobuf.EnumValueOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 3, this->options(), target); @@ -3367,13 +3467,13 @@ void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(1)) { + if (from.has_number()) { set_number(from.number()); } - if (from._has_bit(2)) { + if (from.has_options()) { mutable_options()->::google::protobuf::EnumValueOptions::MergeFrom(from.options()); } } @@ -3422,7 +3522,6 @@ void EnumValueDescriptorProto::Swap(EnumValueDescriptorProto* other) { // =================================================================== -const ::std::string ServiceDescriptorProto::_default_name_; #ifndef _MSC_VER const int ServiceDescriptorProto::kNameFieldNumber; const int ServiceDescriptorProto::kMethodFieldNumber; @@ -3446,7 +3545,7 @@ ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& fro void ServiceDescriptorProto::SharedCtor() { _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -3456,7 +3555,7 @@ ServiceDescriptorProto::~ServiceDescriptorProto() { } void ServiceDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { delete name_; } if (this != default_instance_) { @@ -3486,12 +3585,12 @@ ServiceDescriptorProto* ServiceDescriptorProto::New() const { void ServiceDescriptorProto::Clear() { if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } } - if (_has_bit(2)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); } } @@ -3570,7 +3669,7 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream( void ServiceDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -3585,7 +3684,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.ServiceOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 3, this->options(), output); } @@ -3599,7 +3698,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* ServiceDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -3616,7 +3715,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.ServiceOptions options = 3; - if (_has_bit(2)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 3, this->options(), target); @@ -3683,10 +3782,10 @@ void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); method_.MergeFrom(from.method_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(2)) { + if (from.has_options()) { mutable_options()->::google::protobuf::ServiceOptions::MergeFrom(from.options()); } } @@ -3738,9 +3837,6 @@ void ServiceDescriptorProto::Swap(ServiceDescriptorProto* other) { // =================================================================== -const ::std::string MethodDescriptorProto::_default_name_; -const ::std::string MethodDescriptorProto::_default_input_type_; -const ::std::string MethodDescriptorProto::_default_output_type_; #ifndef _MSC_VER const int MethodDescriptorProto::kNameFieldNumber; const int MethodDescriptorProto::kInputTypeFieldNumber; @@ -3765,9 +3861,9 @@ MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) void MethodDescriptorProto::SharedCtor() { _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&_default_name_); - input_type_ = const_cast< ::std::string*>(&_default_input_type_); - output_type_ = const_cast< ::std::string*>(&_default_output_type_); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -3777,13 +3873,13 @@ MethodDescriptorProto::~MethodDescriptorProto() { } void MethodDescriptorProto::SharedDtor() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { delete name_; } - if (input_type_ != &_default_input_type_) { + if (input_type_ != &::google::protobuf::internal::kEmptyString) { delete input_type_; } - if (output_type_ != &_default_output_type_) { + if (output_type_ != &::google::protobuf::internal::kEmptyString) { delete output_type_; } if (this != default_instance_) { @@ -3813,22 +3909,22 @@ MethodDescriptorProto* MethodDescriptorProto::New() const { void MethodDescriptorProto::Clear() { if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_ != &_default_name_) { + if (has_name()) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } } - if (_has_bit(1)) { - if (input_type_ != &_default_input_type_) { + if (has_input_type()) { + if (input_type_ != &::google::protobuf::internal::kEmptyString) { input_type_->clear(); } } - if (_has_bit(2)) { - if (output_type_ != &_default_output_type_) { + if (has_output_type()) { + if (output_type_ != &::google::protobuf::internal::kEmptyString) { output_type_->clear(); } } - if (_has_bit(3)) { + if (has_options()) { if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); } } @@ -3925,7 +4021,7 @@ bool MethodDescriptorProto::MergePartialFromCodedStream( void MethodDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -3934,7 +4030,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( } // optional string input_type = 2; - if (_has_bit(1)) { + if (has_input_type()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->input_type().data(), this->input_type().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -3943,7 +4039,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( } // optional string output_type = 3; - if (_has_bit(2)) { + if (has_output_type()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->output_type().data(), this->output_type().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -3952,7 +4048,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.MethodOptions options = 4; - if (_has_bit(3)) { + if (has_options()) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 4, this->options(), output); } @@ -3966,7 +4062,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::uint8* MethodDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional string name = 1; - if (_has_bit(0)) { + if (has_name()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name().data(), this->name().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -3976,7 +4072,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( } // optional string input_type = 2; - if (_has_bit(1)) { + if (has_input_type()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->input_type().data(), this->input_type().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -3986,7 +4082,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( } // optional string output_type = 3; - if (_has_bit(2)) { + if (has_output_type()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->output_type().data(), this->output_type().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -3996,7 +4092,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( } // optional .google.protobuf.MethodOptions options = 4; - if (_has_bit(3)) { + if (has_options()) { target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( 4, this->options(), target); @@ -4068,16 +4164,16 @@ void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name()) { set_name(from.name()); } - if (from._has_bit(1)) { + if (from.has_input_type()) { set_input_type(from.input_type()); } - if (from._has_bit(2)) { + if (from.has_output_type()) { set_output_type(from.output_type()); } - if (from._has_bit(3)) { + if (from.has_options()) { mutable_options()->::google::protobuf::MethodOptions::MergeFrom(from.options()); } } @@ -4150,12 +4246,11 @@ const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; const int FileOptions::OptimizeMode_ARRAYSIZE; #endif // _MSC_VER -const ::std::string FileOptions::_default_java_package_; -const ::std::string FileOptions::_default_java_outer_classname_; #ifndef _MSC_VER const int FileOptions::kJavaPackageFieldNumber; const int FileOptions::kJavaOuterClassnameFieldNumber; const int FileOptions::kJavaMultipleFilesFieldNumber; +const int FileOptions::kJavaGenerateEqualsAndHashFieldNumber; const int FileOptions::kOptimizeForFieldNumber; const int FileOptions::kCcGenericServicesFieldNumber; const int FileOptions::kJavaGenericServicesFieldNumber; @@ -4179,13 +4274,14 @@ FileOptions::FileOptions(const FileOptions& from) void FileOptions::SharedCtor() { _cached_size_ = 0; - java_package_ = const_cast< ::std::string*>(&_default_java_package_); - java_outer_classname_ = const_cast< ::std::string*>(&_default_java_outer_classname_); + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); java_multiple_files_ = false; + java_generate_equals_and_hash_ = false; optimize_for_ = 1; - cc_generic_services_ = true; - java_generic_services_ = true; - py_generic_services_ = true; + cc_generic_services_ = false; + java_generic_services_ = false; + py_generic_services_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -4194,10 +4290,10 @@ FileOptions::~FileOptions() { } void FileOptions::SharedDtor() { - if (java_package_ != &_default_java_package_) { + if (java_package_ != &::google::protobuf::internal::kEmptyString) { delete java_package_; } - if (java_outer_classname_ != &_default_java_outer_classname_) { + if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) { delete java_outer_classname_; } if (this != default_instance_) { @@ -4227,21 +4323,22 @@ FileOptions* FileOptions::New() const { void FileOptions::Clear() { _extensions_.Clear(); if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (java_package_ != &_default_java_package_) { + if (has_java_package()) { + if (java_package_ != &::google::protobuf::internal::kEmptyString) { java_package_->clear(); } } - if (_has_bit(1)) { - if (java_outer_classname_ != &_default_java_outer_classname_) { + if (has_java_outer_classname()) { + if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) { java_outer_classname_->clear(); } } java_multiple_files_ = false; + java_generate_equals_and_hash_ = false; optimize_for_ = 1; - cc_generic_services_ = true; - java_generic_services_ = true; - py_generic_services_ = true; + cc_generic_services_ = false; + java_generic_services_ = false; + py_generic_services_ = false; } uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); @@ -4316,7 +4413,7 @@ bool FileOptions::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &java_multiple_files_))); - _set_bit(2); + set_has_java_multiple_files(); } else { goto handle_uninterpreted; } @@ -4324,7 +4421,7 @@ bool FileOptions::MergePartialFromCodedStream( break; } - // optional bool cc_generic_services = 16 [default = true]; + // optional bool cc_generic_services = 16 [default = false]; case 16: { if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { @@ -4332,7 +4429,7 @@ bool FileOptions::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &cc_generic_services_))); - _set_bit(4); + set_has_cc_generic_services(); } else { goto handle_uninterpreted; } @@ -4340,7 +4437,7 @@ bool FileOptions::MergePartialFromCodedStream( break; } - // optional bool java_generic_services = 17 [default = true]; + // optional bool java_generic_services = 17 [default = false]; case 17: { if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { @@ -4348,7 +4445,7 @@ bool FileOptions::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &java_generic_services_))); - _set_bit(5); + set_has_java_generic_services(); } else { goto handle_uninterpreted; } @@ -4356,7 +4453,7 @@ bool FileOptions::MergePartialFromCodedStream( break; } - // optional bool py_generic_services = 18 [default = true]; + // optional bool py_generic_services = 18 [default = false]; case 18: { if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { @@ -4364,7 +4461,23 @@ bool FileOptions::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &py_generic_services_))); - _set_bit(6); + set_has_py_generic_services(); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(160)) goto parse_java_generate_equals_and_hash; + break; + } + + // 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) { + 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; } @@ -4411,7 +4524,7 @@ bool FileOptions::MergePartialFromCodedStream( void FileOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional string java_package = 1; - if (_has_bit(0)) { + if (has_java_package()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->java_package().data(), this->java_package().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -4420,7 +4533,7 @@ void FileOptions::SerializeWithCachedSizes( } // optional string java_outer_classname = 8; - if (_has_bit(1)) { + if (has_java_outer_classname()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->java_outer_classname().data(), this->java_outer_classname().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -4429,31 +4542,36 @@ void FileOptions::SerializeWithCachedSizes( } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - if (_has_bit(3)) { + if (has_optimize_for()) { ::google::protobuf::internal::WireFormatLite::WriteEnum( 9, this->optimize_for(), output); } // optional bool java_multiple_files = 10 [default = false]; - if (_has_bit(2)) { + if (has_java_multiple_files()) { ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output); } - // optional bool cc_generic_services = 16 [default = true]; - if (_has_bit(4)) { + // optional bool cc_generic_services = 16 [default = false]; + if (has_cc_generic_services()) { ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output); } - // optional bool java_generic_services = 17 [default = true]; - if (_has_bit(5)) { + // optional bool java_generic_services = 17 [default = false]; + if (has_java_generic_services()) { ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output); } - // optional bool py_generic_services = 18 [default = true]; - if (_has_bit(6)) { + // optional bool py_generic_services = 18 [default = false]; + if (has_py_generic_services()) { ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output); } + // optional bool java_generate_equals_and_hash = 20 [default = false]; + if (has_java_generate_equals_and_hash()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -4473,7 +4591,7 @@ void FileOptions::SerializeWithCachedSizes( ::google::protobuf::uint8* FileOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional string java_package = 1; - if (_has_bit(0)) { + if (has_java_package()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->java_package().data(), this->java_package().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -4483,7 +4601,7 @@ void FileOptions::SerializeWithCachedSizes( } // optional string java_outer_classname = 8; - if (_has_bit(1)) { + if (has_java_outer_classname()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->java_outer_classname().data(), this->java_outer_classname().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -4493,31 +4611,36 @@ void FileOptions::SerializeWithCachedSizes( } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - if (_has_bit(3)) { + if (has_optimize_for()) { target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( 9, this->optimize_for(), target); } // optional bool java_multiple_files = 10 [default = false]; - if (_has_bit(2)) { + if (has_java_multiple_files()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target); } - // optional bool cc_generic_services = 16 [default = true]; - if (_has_bit(4)) { + // optional bool cc_generic_services = 16 [default = false]; + if (has_cc_generic_services()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target); } - // optional bool java_generic_services = 17 [default = true]; - if (_has_bit(5)) { + // optional bool java_generic_services = 17 [default = false]; + if (has_java_generic_services()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target); } - // optional bool py_generic_services = 18 [default = true]; - if (_has_bit(6)) { + // optional bool py_generic_services = 18 [default = false]; + if (has_py_generic_services()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target); } + // optional bool java_generate_equals_and_hash = 20 [default = false]; + if (has_java_generate_equals_and_hash()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -4559,23 +4682,28 @@ int FileOptions::ByteSize() const { total_size += 1 + 1; } + // optional bool java_generate_equals_and_hash = 20 [default = false]; + if (has_java_generate_equals_and_hash()) { + total_size += 2 + 1; + } + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; if (has_optimize_for()) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::EnumSize(this->optimize_for()); } - // optional bool cc_generic_services = 16 [default = true]; + // optional bool cc_generic_services = 16 [default = false]; if (has_cc_generic_services()) { total_size += 2 + 1; } - // optional bool java_generic_services = 17 [default = true]; + // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; } - // optional bool py_generic_services = 18 [default = true]; + // optional bool py_generic_services = 18 [default = false]; if (has_py_generic_services()) { total_size += 2 + 1; } @@ -4618,25 +4746,28 @@ void FileOptions::MergeFrom(const FileOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_java_package()) { set_java_package(from.java_package()); } - if (from._has_bit(1)) { + if (from.has_java_outer_classname()) { set_java_outer_classname(from.java_outer_classname()); } - if (from._has_bit(2)) { + if (from.has_java_multiple_files()) { set_java_multiple_files(from.java_multiple_files()); } - if (from._has_bit(3)) { + if (from.has_java_generate_equals_and_hash()) { + set_java_generate_equals_and_hash(from.java_generate_equals_and_hash()); + } + if (from.has_optimize_for()) { set_optimize_for(from.optimize_for()); } - if (from._has_bit(4)) { + if (from.has_cc_generic_services()) { set_cc_generic_services(from.cc_generic_services()); } - if (from._has_bit(5)) { + if (from.has_java_generic_services()) { set_java_generic_services(from.java_generic_services()); } - if (from._has_bit(6)) { + if (from.has_py_generic_services()) { set_py_generic_services(from.py_generic_services()); } } @@ -4670,6 +4801,7 @@ void FileOptions::Swap(FileOptions* other) { std::swap(java_package_, other->java_package_); 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(optimize_for_, other->optimize_for_); std::swap(cc_generic_services_, other->cc_generic_services_); std::swap(java_generic_services_, other->java_generic_services_); @@ -4773,7 +4905,7 @@ bool MessageOptions::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &message_set_wire_format_))); - _set_bit(0); + set_has_message_set_wire_format(); } else { goto handle_uninterpreted; } @@ -4789,7 +4921,7 @@ bool MessageOptions::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &no_standard_descriptor_accessor_))); - _set_bit(1); + set_has_no_standard_descriptor_accessor(); } else { goto handle_uninterpreted; } @@ -4836,12 +4968,12 @@ bool MessageOptions::MergePartialFromCodedStream( void MessageOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional bool message_set_wire_format = 1 [default = false]; - if (_has_bit(0)) { + if (has_message_set_wire_format()) { ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output); } // optional bool no_standard_descriptor_accessor = 2 [default = false]; - if (_has_bit(1)) { + if (has_no_standard_descriptor_accessor()) { ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output); } @@ -4864,12 +4996,12 @@ void MessageOptions::SerializeWithCachedSizes( ::google::protobuf::uint8* MessageOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional bool message_set_wire_format = 1 [default = false]; - if (_has_bit(0)) { + if (has_message_set_wire_format()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target); } // optional bool no_standard_descriptor_accessor = 2 [default = false]; - if (_has_bit(1)) { + if (has_no_standard_descriptor_accessor()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target); } @@ -4943,10 +5075,10 @@ void MessageOptions::MergeFrom(const MessageOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_message_set_wire_format()) { set_message_set_wire_format(from.message_set_wire_format()); } - if (from._has_bit(1)) { + if (from.has_no_standard_descriptor_accessor()) { set_no_standard_descriptor_accessor(from.no_standard_descriptor_accessor()); } } @@ -5021,7 +5153,6 @@ const FieldOptions_CType FieldOptions::CType_MIN; const FieldOptions_CType FieldOptions::CType_MAX; const int FieldOptions::CType_ARRAYSIZE; #endif // _MSC_VER -const ::std::string FieldOptions::_default_experimental_map_key_; #ifndef _MSC_VER const int FieldOptions::kCtypeFieldNumber; const int FieldOptions::kPackedFieldNumber; @@ -5049,7 +5180,7 @@ void FieldOptions::SharedCtor() { ctype_ = 0; packed_ = false; deprecated_ = false; - experimental_map_key_ = const_cast< ::std::string*>(&_default_experimental_map_key_); + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -5058,7 +5189,7 @@ FieldOptions::~FieldOptions() { } void FieldOptions::SharedDtor() { - if (experimental_map_key_ != &_default_experimental_map_key_) { + if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) { delete experimental_map_key_; } if (this != default_instance_) { @@ -5091,8 +5222,8 @@ void FieldOptions::Clear() { ctype_ = 0; packed_ = false; deprecated_ = false; - if (_has_bit(3)) { - if (experimental_map_key_ != &_default_experimental_map_key_) { + if (has_experimental_map_key()) { + if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) { experimental_map_key_->clear(); } } @@ -5136,7 +5267,7 @@ bool FieldOptions::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &packed_))); - _set_bit(1); + set_has_packed(); } else { goto handle_uninterpreted; } @@ -5152,7 +5283,7 @@ bool FieldOptions::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &deprecated_))); - _set_bit(2); + set_has_deprecated(); } else { goto handle_uninterpreted; } @@ -5216,23 +5347,23 @@ bool FieldOptions::MergePartialFromCodedStream( void FieldOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - if (_has_bit(0)) { + if (has_ctype()) { ::google::protobuf::internal::WireFormatLite::WriteEnum( 1, this->ctype(), output); } // optional bool packed = 2; - if (_has_bit(1)) { + if (has_packed()) { ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->packed(), output); } // optional bool deprecated = 3 [default = false]; - if (_has_bit(2)) { + if (has_deprecated()) { ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); } // optional string experimental_map_key = 9; - if (_has_bit(3)) { + if (has_experimental_map_key()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->experimental_map_key().data(), this->experimental_map_key().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -5259,23 +5390,23 @@ void FieldOptions::SerializeWithCachedSizes( ::google::protobuf::uint8* FieldOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - if (_has_bit(0)) { + if (has_ctype()) { target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( 1, this->ctype(), target); } // optional bool packed = 2; - if (_has_bit(1)) { + if (has_packed()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->packed(), target); } // optional bool deprecated = 3 [default = false]; - if (_has_bit(2)) { + if (has_deprecated()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); } // optional string experimental_map_key = 9; - if (_has_bit(3)) { + if (has_experimental_map_key()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->experimental_map_key().data(), this->experimental_map_key().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -5367,16 +5498,16 @@ void FieldOptions::MergeFrom(const FieldOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_ctype()) { set_ctype(from.ctype()); } - if (from._has_bit(1)) { + if (from.has_packed()) { set_packed(from.packed()); } - if (from._has_bit(2)) { + if (from.has_deprecated()) { set_deprecated(from.deprecated()); } - if (from._has_bit(3)) { + if (from.has_experimental_map_key()) { set_experimental_map_key(from.experimental_map_key()); } } @@ -6326,7 +6457,6 @@ void MethodOptions::Swap(MethodOptions* other) { // =================================================================== -const ::std::string UninterpretedOption_NamePart::_default_name_part_; #ifndef _MSC_VER const int UninterpretedOption_NamePart::kNamePartFieldNumber; const int UninterpretedOption_NamePart::kIsExtensionFieldNumber; @@ -6348,7 +6478,7 @@ UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOp void UninterpretedOption_NamePart::SharedCtor() { _cached_size_ = 0; - name_part_ = const_cast< ::std::string*>(&_default_name_part_); + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); is_extension_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -6358,7 +6488,7 @@ UninterpretedOption_NamePart::~UninterpretedOption_NamePart() { } void UninterpretedOption_NamePart::SharedDtor() { - if (name_part_ != &_default_name_part_) { + if (name_part_ != &::google::protobuf::internal::kEmptyString) { delete name_part_; } if (this != default_instance_) { @@ -6387,8 +6517,8 @@ UninterpretedOption_NamePart* UninterpretedOption_NamePart::New() const { void UninterpretedOption_NamePart::Clear() { if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (_has_bit(0)) { - if (name_part_ != &_default_name_part_) { + if (has_name_part()) { + if (name_part_ != &::google::protobuf::internal::kEmptyString) { name_part_->clear(); } } @@ -6428,7 +6558,7 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &is_extension_))); - _set_bit(1); + set_has_is_extension(); } else { goto handle_uninterpreted; } @@ -6455,7 +6585,7 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream( void UninterpretedOption_NamePart::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // required string name_part = 1; - if (_has_bit(0)) { + if (has_name_part()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name_part().data(), this->name_part().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -6464,7 +6594,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes( } // required bool is_extension = 2; - if (_has_bit(1)) { + if (has_is_extension()) { ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_extension(), output); } @@ -6477,7 +6607,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes( ::google::protobuf::uint8* UninterpretedOption_NamePart::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { // required string name_part = 1; - if (_has_bit(0)) { + if (has_name_part()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->name_part().data(), this->name_part().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -6487,7 +6617,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes( } // required bool is_extension = 2; - if (_has_bit(1)) { + if (has_is_extension()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_extension(), target); } @@ -6541,10 +6671,10 @@ void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) { GOOGLE_CHECK_NE(&from, this); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (from._has_bit(0)) { + if (from.has_name_part()) { set_name_part(from.name_part()); } - if (from._has_bit(1)) { + if (from.has_is_extension()) { set_is_extension(from.is_extension()); } } @@ -6590,8 +6720,6 @@ void UninterpretedOption_NamePart::Swap(UninterpretedOption_NamePart* other) { // ------------------------------------------------------------------- -const ::std::string UninterpretedOption::_default_identifier_value_; -const ::std::string UninterpretedOption::_default_string_value_; #ifndef _MSC_VER const int UninterpretedOption::kNameFieldNumber; const int UninterpretedOption::kIdentifierValueFieldNumber; @@ -6599,6 +6727,7 @@ const int UninterpretedOption::kPositiveIntValueFieldNumber; const int UninterpretedOption::kNegativeIntValueFieldNumber; const int UninterpretedOption::kDoubleValueFieldNumber; const int UninterpretedOption::kStringValueFieldNumber; +const int UninterpretedOption::kAggregateValueFieldNumber; #endif // !_MSC_VER UninterpretedOption::UninterpretedOption() @@ -6617,11 +6746,12 @@ UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) void UninterpretedOption::SharedCtor() { _cached_size_ = 0; - identifier_value_ = const_cast< ::std::string*>(&_default_identifier_value_); + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); positive_int_value_ = GOOGLE_ULONGLONG(0); negative_int_value_ = GOOGLE_LONGLONG(0); double_value_ = 0; - string_value_ = const_cast< ::std::string*>(&_default_string_value_); + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -6630,12 +6760,15 @@ UninterpretedOption::~UninterpretedOption() { } void UninterpretedOption::SharedDtor() { - if (identifier_value_ != &_default_identifier_value_) { + if (identifier_value_ != &::google::protobuf::internal::kEmptyString) { delete identifier_value_; } - if (string_value_ != &_default_string_value_) { + if (string_value_ != &::google::protobuf::internal::kEmptyString) { delete string_value_; } + if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) { + delete aggregate_value_; + } if (this != default_instance_) { } } @@ -6662,19 +6795,24 @@ UninterpretedOption* UninterpretedOption::New() const { void UninterpretedOption::Clear() { if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { - if (_has_bit(1)) { - if (identifier_value_ != &_default_identifier_value_) { + if (has_identifier_value()) { + if (identifier_value_ != &::google::protobuf::internal::kEmptyString) { identifier_value_->clear(); } } positive_int_value_ = GOOGLE_ULONGLONG(0); negative_int_value_ = GOOGLE_LONGLONG(0); double_value_ = 0; - if (_has_bit(5)) { - if (string_value_ != &_default_string_value_) { + if (has_string_value()) { + if (string_value_ != &::google::protobuf::internal::kEmptyString) { string_value_->clear(); } } + if (has_aggregate_value()) { + if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) { + aggregate_value_->clear(); + } + } } name_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); @@ -6727,7 +6865,7 @@ bool UninterpretedOption::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>( input, &positive_int_value_))); - _set_bit(2); + set_has_positive_int_value(); } else { goto handle_uninterpreted; } @@ -6743,7 +6881,7 @@ bool UninterpretedOption::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( input, &negative_int_value_))); - _set_bit(3); + set_has_negative_int_value(); } else { goto handle_uninterpreted; } @@ -6759,7 +6897,7 @@ bool UninterpretedOption::MergePartialFromCodedStream( DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( input, &double_value_))); - _set_bit(4); + set_has_double_value(); } else { goto handle_uninterpreted; } @@ -6777,6 +6915,23 @@ bool UninterpretedOption::MergePartialFromCodedStream( } else { goto handle_uninterpreted; } + if (input->ExpectTag(66)) goto parse_aggregate_value; + break; + } + + // optional string aggregate_value = 8; + case 8: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + parse_aggregate_value: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_aggregate_value())); + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->aggregate_value().data(), this->aggregate_value().length(), + ::google::protobuf::internal::WireFormat::PARSE); + } else { + goto handle_uninterpreted; + } if (input->ExpectAtEnd()) return true; break; } @@ -6806,7 +6961,7 @@ void UninterpretedOption::SerializeWithCachedSizes( } // optional string identifier_value = 3; - if (_has_bit(1)) { + if (has_identifier_value()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->identifier_value().data(), this->identifier_value().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -6815,26 +6970,35 @@ void UninterpretedOption::SerializeWithCachedSizes( } // optional uint64 positive_int_value = 4; - if (_has_bit(2)) { + if (has_positive_int_value()) { ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->positive_int_value(), output); } // optional int64 negative_int_value = 5; - if (_has_bit(3)) { + if (has_negative_int_value()) { ::google::protobuf::internal::WireFormatLite::WriteInt64(5, this->negative_int_value(), output); } // optional double double_value = 6; - if (_has_bit(4)) { + if (has_double_value()) { ::google::protobuf::internal::WireFormatLite::WriteDouble(6, this->double_value(), output); } // optional bytes string_value = 7; - if (_has_bit(5)) { + if (has_string_value()) { ::google::protobuf::internal::WireFormatLite::WriteBytes( 7, this->string_value(), output); } + // optional string aggregate_value = 8; + if (has_aggregate_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->aggregate_value().data(), this->aggregate_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormatLite::WriteString( + 8, this->aggregate_value(), output); + } + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); @@ -6851,7 +7015,7 @@ void UninterpretedOption::SerializeWithCachedSizes( } // optional string identifier_value = 3; - if (_has_bit(1)) { + if (has_identifier_value()) { ::google::protobuf::internal::WireFormat::VerifyUTF8String( this->identifier_value().data(), this->identifier_value().length(), ::google::protobuf::internal::WireFormat::SERIALIZE); @@ -6861,27 +7025,37 @@ void UninterpretedOption::SerializeWithCachedSizes( } // optional uint64 positive_int_value = 4; - if (_has_bit(2)) { + if (has_positive_int_value()) { target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->positive_int_value(), target); } // optional int64 negative_int_value = 5; - if (_has_bit(3)) { + if (has_negative_int_value()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(5, this->negative_int_value(), target); } // optional double double_value = 6; - if (_has_bit(4)) { + if (has_double_value()) { target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(6, this->double_value(), target); } // optional bytes string_value = 7; - if (_has_bit(5)) { + if (has_string_value()) { target = ::google::protobuf::internal::WireFormatLite::WriteBytesToArray( 7, this->string_value(), target); } + // optional string aggregate_value = 8; + if (has_aggregate_value()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8String( + this->aggregate_value().data(), this->aggregate_value().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 8, this->aggregate_value(), target); + } + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); @@ -6926,6 +7100,13 @@ int UninterpretedOption::ByteSize() const { this->string_value()); } + // optional string aggregate_value = 8; + if (has_aggregate_value()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->aggregate_value()); + } + } // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; total_size += 1 * this->name_size(); @@ -6962,21 +7143,24 @@ void UninterpretedOption::MergeFrom(const UninterpretedOption& from) { GOOGLE_CHECK_NE(&from, this); name_.MergeFrom(from.name_); if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { - if (from._has_bit(1)) { + if (from.has_identifier_value()) { set_identifier_value(from.identifier_value()); } - if (from._has_bit(2)) { + if (from.has_positive_int_value()) { set_positive_int_value(from.positive_int_value()); } - if (from._has_bit(3)) { + if (from.has_negative_int_value()) { set_negative_int_value(from.negative_int_value()); } - if (from._has_bit(4)) { + if (from.has_double_value()) { set_double_value(from.double_value()); } - if (from._has_bit(5)) { + if (from.has_string_value()) { set_string_value(from.string_value()); } + if (from.has_aggregate_value()) { + set_aggregate_value(from.aggregate_value()); + } } mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -7009,6 +7193,7 @@ void UninterpretedOption::Swap(UninterpretedOption* other) { std::swap(negative_int_value_, other->negative_int_value_); std::swap(double_value_, other->double_value_); std::swap(string_value_, other->string_value_); + std::swap(aggregate_value_, other->aggregate_value_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); std::swap(_cached_size_, other->_cached_size_); @@ -7024,6 +7209,497 @@ void UninterpretedOption::Swap(UninterpretedOption* other) { } +// =================================================================== + +#ifndef _MSC_VER +const int SourceCodeInfo_Location::kPathFieldNumber; +const int SourceCodeInfo_Location::kSpanFieldNumber; +#endif // !_MSC_VER + +SourceCodeInfo_Location::SourceCodeInfo_Location() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void SourceCodeInfo_Location::InitAsDefaultInstance() { +} + +SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void SourceCodeInfo_Location::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +SourceCodeInfo_Location::~SourceCodeInfo_Location() { + SharedDtor(); +} + +void SourceCodeInfo_Location::SharedDtor() { + if (this != default_instance_) { + } +} + +void SourceCodeInfo_Location::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* SourceCodeInfo_Location::descriptor() { + protobuf_AssignDescriptorsOnce(); + return SourceCodeInfo_Location_descriptor_; +} + +const SourceCodeInfo_Location& SourceCodeInfo_Location::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; +} + +SourceCodeInfo_Location* SourceCodeInfo_Location::default_instance_ = NULL; + +SourceCodeInfo_Location* SourceCodeInfo_Location::New() const { + return new SourceCodeInfo_Location; +} + +void SourceCodeInfo_Location::Clear() { + path_.Clear(); + span_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool SourceCodeInfo_Location::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + 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) { + 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) { + 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; + } + if (input->ExpectTag(18)) goto parse_span; + break; + } + + // repeated int32 span = 2 [packed = true]; + case 2: { + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + 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) { + 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; + } + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void SourceCodeInfo_Location::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // 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); + output->WriteVarint32(_path_cached_byte_size_); + } + for (int i = 0; i < this->path_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag( + this->path(i), output); + } + + // repeated int32 span = 2 [packed = true]; + if (this->span_size() > 0) { + ::google::protobuf::internal::WireFormatLite::WriteTag(2, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); + output->WriteVarint32(_span_cached_byte_size_); + } + for (int i = 0; i < this->span_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag( + this->span(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* SourceCodeInfo_Location::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated int32 path = 1 [packed = true]; + if (this->path_size() > 0) { + target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( + 1, + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + target); + target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( + _path_cached_byte_size_, target); + } + for (int i = 0; i < this->path_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32NoTagToArray(this->path(i), target); + } + + // repeated int32 span = 2 [packed = true]; + if (this->span_size() > 0) { + target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( + 2, + ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + target); + target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray( + _span_cached_byte_size_, target); + } + for (int i = 0; i < this->span_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteInt32NoTagToArray(this->span(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int SourceCodeInfo_Location::ByteSize() const { + int total_size = 0; + + // repeated int32 path = 1 [packed = true]; + { + int data_size = 0; + for (int i = 0; i < this->path_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + Int32Size(this->path(i)); + } + if (data_size > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); + } + _path_cached_byte_size_ = data_size; + total_size += data_size; + } + + // repeated int32 span = 2 [packed = true]; + { + int data_size = 0; + for (int i = 0; i < this->span_size(); i++) { + data_size += ::google::protobuf::internal::WireFormatLite:: + Int32Size(this->span(i)); + } + if (data_size > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size(data_size); + } + _span_cached_byte_size_ = data_size; + total_size += data_size; + } + + 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 SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const SourceCodeInfo_Location* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) { + GOOGLE_CHECK_NE(&from, this); + path_.MergeFrom(from.path_); + span_.MergeFrom(from.span_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void SourceCodeInfo_Location::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SourceCodeInfo_Location::IsInitialized() const { + + return true; +} + +void SourceCodeInfo_Location::Swap(SourceCodeInfo_Location* other) { + if (other != this) { + path_.Swap(&other->path_); + span_.Swap(&other->span_); + 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 SourceCodeInfo_Location::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = SourceCodeInfo_Location_descriptor_; + metadata.reflection = SourceCodeInfo_Location_reflection_; + return metadata; +} + + +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int SourceCodeInfo::kLocationFieldNumber; +#endif // !_MSC_VER + +SourceCodeInfo::SourceCodeInfo() + : ::google::protobuf::Message() { + SharedCtor(); +} + +void SourceCodeInfo::InitAsDefaultInstance() { +} + +SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); +} + +void SourceCodeInfo::SharedCtor() { + _cached_size_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +SourceCodeInfo::~SourceCodeInfo() { + SharedDtor(); +} + +void SourceCodeInfo::SharedDtor() { + if (this != default_instance_) { + } +} + +void SourceCodeInfo::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* SourceCodeInfo::descriptor() { + protobuf_AssignDescriptorsOnce(); + return SourceCodeInfo_descriptor_; +} + +const SourceCodeInfo& SourceCodeInfo::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); return *default_instance_; +} + +SourceCodeInfo* SourceCodeInfo::default_instance_ = NULL; + +SourceCodeInfo* SourceCodeInfo::New() const { + return new SourceCodeInfo; +} + +void SourceCodeInfo::Clear() { + location_.Clear(); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool SourceCodeInfo::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) return false + ::google::protobuf::uint32 tag; + while ((tag = input->ReadTag()) != 0) { + 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) { + parse_location: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_location())); + } else { + goto handle_uninterpreted; + } + if (input->ExpectTag(10)) goto parse_location; + if (input->ExpectAtEnd()) return true; + break; + } + + default: { + handle_uninterpreted: + if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } + return true; +#undef DO_ +} + +void SourceCodeInfo::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + for (int i = 0; i < this->location_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, this->location(i), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } +} + +::google::protobuf::uint8* SourceCodeInfo::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + for (int i = 0; i < this->location_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 1, this->location(i), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + return target; +} + +int SourceCodeInfo::ByteSize() const { + int total_size = 0; + + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + total_size += 1 * this->location_size(); + for (int i = 0; i < this->location_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->location(i)); + } + + 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 SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const SourceCodeInfo* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) { + GOOGLE_CHECK_NE(&from, this); + location_.MergeFrom(from.location_); + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void SourceCodeInfo::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SourceCodeInfo::IsInitialized() const { + + return true; +} + +void SourceCodeInfo::Swap(SourceCodeInfo* other) { + if (other != this) { + location_.Swap(&other->location_); + 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 SourceCodeInfo::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = SourceCodeInfo_descriptor_; + metadata.reflection = SourceCodeInfo_reflection_; + return metadata; +} + + // @@protoc_insertion_point(namespace_scope) } // namespace protobuf diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 205c5476..e85a9336 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -51,6 +51,8 @@ class ServiceOptions; class MethodOptions; class UninterpretedOption; class UninterpretedOption_NamePart; +class SourceCodeInfo; +class SourceCodeInfo_Location; enum FieldDescriptorProto_Type { FieldDescriptorProto_Type_TYPE_DOUBLE = 1, @@ -217,26 +219,17 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) private: + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::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(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static FileDescriptorSet* default_instance_; @@ -306,6 +299,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag 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(); // optional string package = 2; inline bool has_package() const; @@ -316,6 +310,7 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag inline void set_package(const char* value); inline void set_package(const char* value, size_t size); inline ::std::string* mutable_package(); + inline ::std::string* release_package(); // repeated string dependency = 3; inline int dependency_size() const; @@ -387,39 +382,46 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag static const int kOptionsFieldNumber = 8; inline const ::google::protobuf::FileOptions& options() const; inline ::google::protobuf::FileOptions* mutable_options(); + inline ::google::protobuf::FileOptions* release_options(); + + // optional .google.protobuf.SourceCodeInfo source_code_info = 9; + inline bool has_source_code_info() const; + inline void clear_source_code_info(); + static const int kSourceCodeInfoFieldNumber = 9; + inline const ::google::protobuf::SourceCodeInfo& source_code_info() const; + inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info(); + inline ::google::protobuf::SourceCodeInfo* release_source_code_info(); // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_package(); + inline void clear_has_package(); + inline void set_has_options(); + inline void clear_has_options(); + inline void set_has_source_code_info(); + inline void clear_has_source_code_info(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* name_; - static const ::std::string _default_name_; ::std::string* package_; - static const ::std::string _default_package_; ::google::protobuf::RepeatedPtrField< ::std::string> dependency_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > message_type_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto > service_; ::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_[(9 + 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(); - ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - void InitAsDefaultInstance(); static FileDescriptorProto* default_instance_; }; @@ -495,27 +497,22 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) private: + inline void set_has_start(); + inline void clear_has_start(); + inline void set_has_end(); + inline void clear_has_end(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::google::protobuf::int32 start_; ::google::protobuf::int32 end_; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static DescriptorProto_ExtensionRange* default_instance_; @@ -587,6 +584,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { 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(); // repeated .google.protobuf.FieldDescriptorProto field = 2; inline int field_size() const; @@ -654,36 +652,31 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { static const int kOptionsFieldNumber = 7; inline const ::google::protobuf::MessageOptions& options() const; inline ::google::protobuf::MessageOptions* mutable_options(); + inline ::google::protobuf::MessageOptions* release_options(); // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* name_; - static const ::std::string _default_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::MessageOptions* options_; - 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_[(7 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static DescriptorProto* default_instance_; @@ -818,6 +811,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa 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(); // optional int32 number = 3; inline bool has_number() const; @@ -849,6 +843,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa inline void set_type_name(const char* value); inline void set_type_name(const char* value, size_t size); inline ::std::string* mutable_type_name(); + inline ::std::string* release_type_name(); // optional string extendee = 2; inline bool has_extendee() const; @@ -859,6 +854,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa inline void set_extendee(const char* value); inline void set_extendee(const char* value, size_t size); inline ::std::string* mutable_extendee(); + inline ::std::string* release_extendee(); // optional string default_value = 7; inline bool has_default_value() const; @@ -869,6 +865,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa inline void set_default_value(const char* value); inline void set_default_value(const char* value, size_t size); inline ::std::string* mutable_default_value(); + inline ::std::string* release_default_value(); // optional .google.protobuf.FieldOptions options = 8; inline bool has_options() const; @@ -876,40 +873,44 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa static const int kOptionsFieldNumber = 8; inline const ::google::protobuf::FieldOptions& options() const; inline ::google::protobuf::FieldOptions* mutable_options(); + inline ::google::protobuf::FieldOptions* release_options(); // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_number(); + inline void clear_has_number(); + inline void set_has_label(); + inline void clear_has_label(); + inline void set_has_type(); + inline void clear_has_type(); + inline void set_has_type_name(); + inline void clear_has_type_name(); + inline void set_has_extendee(); + inline void clear_has_extendee(); + inline void set_has_default_value(); + inline void clear_has_default_value(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* name_; - static const ::std::string _default_name_; ::google::protobuf::int32 number_; int label_; - int type_; ::std::string* type_name_; - static const ::std::string _default_type_name_; ::std::string* extendee_; - static const ::std::string _default_extendee_; ::std::string* default_value_; - static const ::std::string _default_default_value_; ::google::protobuf::FieldOptions* options_; - 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(); + int type_; + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static FieldDescriptorProto* default_instance_; @@ -979,6 +980,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag 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(); // repeated .google.protobuf.EnumValueDescriptorProto value = 2; inline int value_size() const; @@ -998,32 +1000,27 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag static const int kOptionsFieldNumber = 3; inline const ::google::protobuf::EnumOptions& options() const; inline ::google::protobuf::EnumOptions* mutable_options(); + inline ::google::protobuf::EnumOptions* release_options(); // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* name_; - static const ::std::string _default_name_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_; ::google::protobuf::EnumOptions* options_; - 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_[(3 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static EnumDescriptorProto* default_instance_; @@ -1093,6 +1090,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M 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(); // optional int32 number = 2; inline bool has_number() const; @@ -1107,32 +1105,29 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M static const int kOptionsFieldNumber = 3; inline const ::google::protobuf::EnumValueOptions& options() const; inline ::google::protobuf::EnumValueOptions* mutable_options(); + inline ::google::protobuf::EnumValueOptions* release_options(); // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_number(); + inline void clear_has_number(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* name_; - static const ::std::string _default_name_; - ::google::protobuf::int32 number_; ::google::protobuf::EnumValueOptions* options_; - 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(); + ::google::protobuf::int32 number_; + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static EnumValueDescriptorProto* default_instance_; @@ -1202,6 +1197,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes 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(); // repeated .google.protobuf.MethodDescriptorProto method = 2; inline int method_size() const; @@ -1221,32 +1217,27 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes static const int kOptionsFieldNumber = 3; inline const ::google::protobuf::ServiceOptions& options() const; inline ::google::protobuf::ServiceOptions* mutable_options(); + inline ::google::protobuf::ServiceOptions* release_options(); // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* name_; - static const ::std::string _default_name_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_; ::google::protobuf::ServiceOptions* options_; - 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_[(3 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static ServiceDescriptorProto* default_instance_; @@ -1316,6 +1307,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess 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(); // optional string input_type = 2; inline bool has_input_type() const; @@ -1326,6 +1318,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess inline void set_input_type(const char* value); inline void set_input_type(const char* value, size_t size); inline ::std::string* mutable_input_type(); + inline ::std::string* release_input_type(); // optional string output_type = 3; inline bool has_output_type() const; @@ -1336,6 +1329,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess inline void set_output_type(const char* value); inline void set_output_type(const char* value, size_t size); inline ::std::string* mutable_output_type(); + inline ::std::string* release_output_type(); // optional .google.protobuf.MethodOptions options = 4; inline bool has_options() const; @@ -1343,35 +1337,32 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess static const int kOptionsFieldNumber = 4; inline const ::google::protobuf::MethodOptions& options() const; inline ::google::protobuf::MethodOptions* mutable_options(); + inline ::google::protobuf::MethodOptions* release_options(); // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto) private: + inline void set_has_name(); + inline void clear_has_name(); + inline void set_has_input_type(); + inline void clear_has_input_type(); + inline void set_has_output_type(); + inline void clear_has_output_type(); + inline void set_has_options(); + inline void clear_has_options(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* name_; - static const ::std::string _default_name_; ::std::string* input_type_; - static const ::std::string _default_input_type_; ::std::string* output_type_; - static const ::std::string _default_output_type_; ::google::protobuf::MethodOptions* options_; - 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_[(4 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static MethodDescriptorProto* default_instance_; @@ -1466,6 +1457,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void set_java_package(const char* value); inline void set_java_package(const char* value, size_t size); inline ::std::string* mutable_java_package(); + inline ::std::string* release_java_package(); // optional string java_outer_classname = 8; inline bool has_java_outer_classname() const; @@ -1476,6 +1468,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void set_java_outer_classname(const char* value); inline void set_java_outer_classname(const char* value, size_t size); inline ::std::string* mutable_java_outer_classname(); + inline ::std::string* release_java_outer_classname(); // optional bool java_multiple_files = 10 [default = false]; inline bool has_java_multiple_files() const; @@ -1484,6 +1477,13 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline bool java_multiple_files() const; inline void set_java_multiple_files(bool value); + // optional bool java_generate_equals_and_hash = 20 [default = false]; + inline bool has_java_generate_equals_and_hash() const; + inline void clear_java_generate_equals_and_hash(); + static const int kJavaGenerateEqualsAndHashFieldNumber = 20; + inline bool java_generate_equals_and_hash() const; + inline void set_java_generate_equals_and_hash(bool value); + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; inline bool has_optimize_for() const; inline void clear_optimize_for(); @@ -1491,21 +1491,21 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const; inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value); - // optional bool cc_generic_services = 16 [default = true]; + // optional bool cc_generic_services = 16 [default = false]; inline bool has_cc_generic_services() const; inline void clear_cc_generic_services(); static const int kCcGenericServicesFieldNumber = 16; inline bool cc_generic_services() const; inline void set_cc_generic_services(bool value); - // optional bool java_generic_services = 17 [default = true]; + // optional bool java_generic_services = 17 [default = false]; inline bool has_java_generic_services() const; inline void clear_java_generic_services(); static const int kJavaGenericServicesFieldNumber = 17; inline bool java_generic_services() const; inline void set_java_generic_services(bool value); - // optional bool py_generic_services = 18 [default = true]; + // optional bool py_generic_services = 18 [default = false]; inline bool has_py_generic_services() const; inline void clear_py_generic_services(); static const int kPyGenericServicesFieldNumber = 18; @@ -1527,37 +1527,44 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions) // @@protoc_insertion_point(class_scope:google.protobuf.FileOptions) private: + inline void set_has_java_package(); + inline void clear_has_java_package(); + inline void set_has_java_outer_classname(); + inline void clear_has_java_outer_classname(); + inline void set_has_java_multiple_files(); + 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_optimize_for(); + inline void clear_has_optimize_for(); + inline void set_has_cc_generic_services(); + inline void clear_has_cc_generic_services(); + inline void set_has_java_generic_services(); + inline void clear_has_java_generic_services(); + inline void set_has_py_generic_services(); + inline void clear_has_py_generic_services(); + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* java_package_; - static const ::std::string _default_java_package_; ::std::string* java_outer_classname_; - static const ::std::string _default_java_outer_classname_; - bool java_multiple_files_; int optimize_for_; + bool java_multiple_files_; + bool java_generate_equals_and_hash_; bool cc_generic_services_; bool java_generic_services_; - bool py_generic_services_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool py_generic_services_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(9 + 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(); - ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32]; - - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); - } - void InitAsDefaultInstance(); static FileOptions* default_instance_; }; @@ -1646,29 +1653,25 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions) // @@protoc_insertion_point(class_scope:google.protobuf.MessageOptions) private: + inline void set_has_message_set_wire_format(); + inline void clear_has_message_set_wire_format(); + inline void set_has_no_standard_descriptor_accessor(); + inline void clear_has_no_standard_descriptor_accessor(); + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; bool message_set_wire_format_; bool no_standard_descriptor_accessor_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static MessageOptions* default_instance_; @@ -1784,6 +1787,7 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { inline void set_experimental_map_key(const char* value); inline void set_experimental_map_key(const char* value, size_t size); inline ::std::string* mutable_experimental_map_key(); + inline ::std::string* release_experimental_map_key(); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; @@ -1800,32 +1804,31 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions) // @@protoc_insertion_point(class_scope:google.protobuf.FieldOptions) private: + inline void set_has_ctype(); + inline void clear_has_ctype(); + inline void set_has_packed(); + inline void clear_has_packed(); + inline void set_has_deprecated(); + inline void clear_has_deprecated(); + inline void set_has_experimental_map_key(); + inline void clear_has_experimental_map_key(); + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; int ctype_; bool packed_; bool deprecated_; ::std::string* experimental_map_key_; - static const ::std::string _default_experimental_map_key_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(5 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static FieldOptions* default_instance_; @@ -1901,27 +1904,19 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions) // @@protoc_insertion_point(class_scope:google.protobuf.EnumOptions) private: + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static EnumOptions* default_instance_; @@ -1997,27 +1992,19 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions) // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions) private: + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static EnumValueOptions* default_instance_; @@ -2093,27 +2080,19 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions) // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions) private: + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static ServiceOptions* default_instance_; @@ -2189,27 +2168,19 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions) // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions) private: + ::google::protobuf::internal::ExtensionSet _extensions_; + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); - friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + mutable int _cached_size_; ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static MethodOptions* default_instance_; @@ -2279,6 +2250,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu inline void set_name_part(const char* value); inline void set_name_part(const char* value, size_t size); inline ::std::string* mutable_name_part(); + inline ::std::string* release_name_part(); // required bool is_extension = 2; inline bool has_is_extension() const; @@ -2289,28 +2261,22 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart) private: + inline void set_has_name_part(); + inline void clear_has_name_part(); + inline void set_has_is_extension(); + inline void clear_has_is_extension(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::std::string* name_part_; - static const ::std::string _default_name_part_; bool is_extension_; - 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_[(2 + 31) / 32]; - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; - } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); - } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 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(); void InitAsDefaultInstance(); static UninterpretedOption_NamePart* default_instance_; @@ -2394,6 +2360,7 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag inline void set_identifier_value(const char* value); inline void set_identifier_value(const char* value, size_t size); inline ::std::string* mutable_identifier_value(); + inline ::std::string* release_identifier_value(); // optional uint64 positive_int_value = 4; inline bool has_positive_int_value() const; @@ -2425,51 +2392,252 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag inline void set_string_value(const char* value); inline void set_string_value(const void* value, size_t size); inline ::std::string* mutable_string_value(); + inline ::std::string* release_string_value(); + + // optional string aggregate_value = 8; + inline bool has_aggregate_value() const; + inline void clear_aggregate_value(); + static const int kAggregateValueFieldNumber = 8; + inline const ::std::string& aggregate_value() const; + inline void set_aggregate_value(const ::std::string& value); + inline void set_aggregate_value(const char* value); + inline void set_aggregate_value(const char* value, size_t size); + inline ::std::string* mutable_aggregate_value(); + inline ::std::string* release_aggregate_value(); // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption) private: + inline void set_has_identifier_value(); + inline void clear_has_identifier_value(); + inline void set_has_positive_int_value(); + inline void clear_has_positive_int_value(); + inline void set_has_negative_int_value(); + inline void clear_has_negative_int_value(); + inline void set_has_double_value(); + inline void clear_has_double_value(); + inline void set_has_string_value(); + inline void clear_has_string_value(); + inline void set_has_aggregate_value(); + inline void clear_has_aggregate_value(); + ::google::protobuf::UnknownFieldSet _unknown_fields_; - mutable int _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_; ::std::string* identifier_value_; - static const ::std::string _default_identifier_value_; ::google::protobuf::uint64 positive_int_value_; ::google::protobuf::int64 negative_int_value_; double double_value_; ::std::string* string_value_; - static const ::std::string _default_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(); - ::google::protobuf::uint32 _has_bits_[(6 + 31) / 32]; + void InitAsDefaultInstance(); + static UninterpretedOption* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Message { + public: + SourceCodeInfo_Location(); + virtual ~SourceCodeInfo_Location(); + + SourceCodeInfo_Location(const SourceCodeInfo_Location& from); - // WHY DOES & HAVE LOWER PRECEDENCE THAN != !? - inline bool _has_bit(int index) const { - return (_has_bits_[index / 32] & (1u << (index % 32))) != 0; + inline SourceCodeInfo_Location& operator=(const SourceCodeInfo_Location& from) { + CopyFrom(from); + return *this; } - inline void _set_bit(int index) { - _has_bits_[index / 32] |= (1u << (index % 32)); + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; } - inline void _clear_bit(int index) { - _has_bits_[index / 32] &= ~(1u << (index % 32)); + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; } - void InitAsDefaultInstance(); - static UninterpretedOption* default_instance_; -}; -// =================================================================== - - -// =================================================================== - -// FileDescriptorSet - -// repeated .google.protobuf.FileDescriptorProto file = 1; -inline int FileDescriptorSet::file_size() const { - return file_.size(); -} + static const ::google::protobuf::Descriptor* descriptor(); + static const SourceCodeInfo_Location& default_instance(); + + void Swap(SourceCodeInfo_Location* other); + + // implements Message ---------------------------------------------- + + SourceCodeInfo_Location* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const SourceCodeInfo_Location& from); + void MergeFrom(const SourceCodeInfo_Location& 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 ------------------------------------------------------- + + // repeated int32 path = 1 [packed = true]; + inline int path_size() const; + inline void clear_path(); + static const int kPathFieldNumber = 1; + inline ::google::protobuf::int32 path(int index) const; + inline void set_path(int index, ::google::protobuf::int32 value); + inline void add_path(::google::protobuf::int32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + path() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + mutable_path(); + + // repeated int32 span = 2 [packed = true]; + inline int span_size() const; + inline void clear_span(); + static const int kSpanFieldNumber = 2; + inline ::google::protobuf::int32 span(int index) const; + inline void set_span(int index, ::google::protobuf::int32 value); + inline void add_span(::google::protobuf::int32 value); + inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + span() const; + inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + mutable_span(); + + // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::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_; + + 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(); + + void InitAsDefaultInstance(); + static SourceCodeInfo_Location* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message { + public: + SourceCodeInfo(); + virtual ~SourceCodeInfo(); + + SourceCodeInfo(const SourceCodeInfo& from); + + inline SourceCodeInfo& operator=(const SourceCodeInfo& 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 SourceCodeInfo& default_instance(); + + void Swap(SourceCodeInfo* other); + + // implements Message ---------------------------------------------- + + SourceCodeInfo* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const SourceCodeInfo& from); + void MergeFrom(const SourceCodeInfo& 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 ---------------------------------------------------- + + typedef SourceCodeInfo_Location Location; + + // accessors ------------------------------------------------------- + + // repeated .google.protobuf.SourceCodeInfo.Location location = 1; + inline int location_size() const; + inline void clear_location(); + static const int kLocationFieldNumber = 1; + inline const ::google::protobuf::SourceCodeInfo_Location& location(int index) const; + inline ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index); + inline ::google::protobuf::SourceCodeInfo_Location* add_location(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& + location() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* + mutable_location(); + + // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) + private: + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + + ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_; + + mutable int _cached_size_; + ::google::protobuf::uint32 _has_bits_[(1 + 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(); + + void InitAsDefaultInstance(); + static SourceCodeInfo* default_instance_; +}; +// =================================================================== + + +// =================================================================== + +// FileDescriptorSet + +// repeated .google.protobuf.FileDescriptorProto file = 1; +inline int FileDescriptorSet::file_size() const { + return file_.size(); +} inline void FileDescriptorSet::clear_file() { file_.Clear(); } @@ -2497,87 +2665,119 @@ FileDescriptorSet::mutable_file() { // optional string name = 1; inline bool FileDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FileDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void FileDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void FileDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& FileDescriptorProto::name() const { return *name_; } inline void FileDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void FileDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void FileDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); } inline ::std::string* FileDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } return name_; } +inline ::std::string* FileDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional string package = 2; inline bool FileDescriptorProto::has_package() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FileDescriptorProto::set_has_package() { + _has_bits_[0] |= 0x00000002u; +} +inline void FileDescriptorProto::clear_has_package() { + _has_bits_[0] &= ~0x00000002u; } inline void FileDescriptorProto::clear_package() { - if (package_ != &_default_package_) { + if (package_ != &::google::protobuf::internal::kEmptyString) { package_->clear(); } - _clear_bit(1); + clear_has_package(); } inline const ::std::string& FileDescriptorProto::package() const { return *package_; } inline void FileDescriptorProto::set_package(const ::std::string& value) { - _set_bit(1); - if (package_ == &_default_package_) { + set_has_package(); + if (package_ == &::google::protobuf::internal::kEmptyString) { package_ = new ::std::string; } package_->assign(value); } inline void FileDescriptorProto::set_package(const char* value) { - _set_bit(1); - if (package_ == &_default_package_) { + set_has_package(); + if (package_ == &::google::protobuf::internal::kEmptyString) { package_ = new ::std::string; } package_->assign(value); } inline void FileDescriptorProto::set_package(const char* value, size_t size) { - _set_bit(1); - if (package_ == &_default_package_) { + set_has_package(); + if (package_ == &::google::protobuf::internal::kEmptyString) { package_ = new ::std::string; } package_->assign(reinterpret_cast(value), size); } inline ::std::string* FileDescriptorProto::mutable_package() { - _set_bit(1); - if (package_ == &_default_package_) { + set_has_package(); + if (package_ == &::google::protobuf::internal::kEmptyString) { package_ = new ::std::string; } return package_; } +inline ::std::string* FileDescriptorProto::release_package() { + clear_has_package(); + if (package_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = package_; + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // repeated string dependency = 3; inline int FileDescriptorProto::dependency_size() const { @@ -2725,20 +2925,61 @@ FileDescriptorProto::mutable_extension() { // optional .google.protobuf.FileOptions options = 8; inline bool FileDescriptorProto::has_options() const { - return _has_bit(7); + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void FileDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000080u; +} +inline void FileDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000080u; } inline void FileDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); - _clear_bit(7); + clear_has_options(); } inline const ::google::protobuf::FileOptions& FileDescriptorProto::options() const { return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { - _set_bit(7); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::FileOptions; return options_; } +inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::FileOptions* temp = options_; + options_ = NULL; + return temp; +} + +// optional .google.protobuf.SourceCodeInfo source_code_info = 9; +inline bool FileDescriptorProto::has_source_code_info() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} +inline void FileDescriptorProto::set_has_source_code_info() { + _has_bits_[0] |= 0x00000100u; +} +inline void FileDescriptorProto::clear_has_source_code_info() { + _has_bits_[0] &= ~0x00000100u; +} +inline void FileDescriptorProto::clear_source_code_info() { + if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); + clear_has_source_code_info(); +} +inline const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const { + 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; + return source_code_info_; +} +inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { + clear_has_source_code_info(); + ::google::protobuf::SourceCodeInfo* temp = source_code_info_; + source_code_info_ = NULL; + return temp; +} // ------------------------------------------------------------------- @@ -2746,33 +2987,45 @@ inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { // optional int32 start = 1; inline bool DescriptorProto_ExtensionRange::has_start() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void DescriptorProto_ExtensionRange::set_has_start() { + _has_bits_[0] |= 0x00000001u; +} +inline void DescriptorProto_ExtensionRange::clear_has_start() { + _has_bits_[0] &= ~0x00000001u; } inline void DescriptorProto_ExtensionRange::clear_start() { start_ = 0; - _clear_bit(0); + clear_has_start(); } inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const { return start_; } inline void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) { - _set_bit(0); + set_has_start(); start_ = value; } // optional int32 end = 2; inline bool DescriptorProto_ExtensionRange::has_end() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void DescriptorProto_ExtensionRange::set_has_end() { + _has_bits_[0] |= 0x00000002u; +} +inline void DescriptorProto_ExtensionRange::clear_has_end() { + _has_bits_[0] &= ~0x00000002u; } inline void DescriptorProto_ExtensionRange::clear_end() { end_ = 0; - _clear_bit(1); + clear_has_end(); } inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const { return end_; } inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) { - _set_bit(1); + set_has_end(); end_ = value; } @@ -2782,45 +3035,61 @@ inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 va // optional string name = 1; inline bool DescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void DescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void DescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void DescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& DescriptorProto::name() const { return *name_; } inline void DescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void DescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void DescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); } inline ::std::string* DescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } return name_; } +inline ::std::string* DescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // repeated .google.protobuf.FieldDescriptorProto field = 2; inline int DescriptorProto::field_size() const { @@ -2949,20 +3218,32 @@ DescriptorProto::mutable_extension_range() { // optional .google.protobuf.MessageOptions options = 7; inline bool DescriptorProto::has_options() const { - return _has_bit(6); + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void DescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000040u; +} +inline void DescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000040u; } inline void DescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); - _clear_bit(6); + clear_has_options(); } inline const ::google::protobuf::MessageOptions& DescriptorProto::options() const { return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { - _set_bit(6); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::MessageOptions; return options_; } +inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::MessageOptions* temp = options_; + options_ = NULL; + return temp; +} // ------------------------------------------------------------------- @@ -2970,238 +3251,332 @@ inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { // optional string name = 1; inline bool FieldDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FieldDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void FieldDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void FieldDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& FieldDescriptorProto::name() const { return *name_; } inline void FieldDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void FieldDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void FieldDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); } inline ::std::string* FieldDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } return name_; } +inline ::std::string* FieldDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional int32 number = 3; inline bool FieldDescriptorProto::has_number() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FieldDescriptorProto::set_has_number() { + _has_bits_[0] |= 0x00000002u; +} +inline void FieldDescriptorProto::clear_has_number() { + _has_bits_[0] &= ~0x00000002u; } inline void FieldDescriptorProto::clear_number() { number_ = 0; - _clear_bit(1); + clear_has_number(); } inline ::google::protobuf::int32 FieldDescriptorProto::number() const { return number_; } inline void FieldDescriptorProto::set_number(::google::protobuf::int32 value) { - _set_bit(1); + set_has_number(); number_ = value; } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; inline bool FieldDescriptorProto::has_label() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FieldDescriptorProto::set_has_label() { + _has_bits_[0] |= 0x00000004u; +} +inline void FieldDescriptorProto::clear_has_label() { + _has_bits_[0] &= ~0x00000004u; } inline void FieldDescriptorProto::clear_label() { label_ = 1; - _clear_bit(2); + clear_has_label(); } inline ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const { return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_); } inline void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) { GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Label_IsValid(value)); - _set_bit(2); + set_has_label(); label_ = value; } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; inline bool FieldDescriptorProto::has_type() const { - return _has_bit(3); + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void FieldDescriptorProto::set_has_type() { + _has_bits_[0] |= 0x00000008u; +} +inline void FieldDescriptorProto::clear_has_type() { + _has_bits_[0] &= ~0x00000008u; } inline void FieldDescriptorProto::clear_type() { type_ = 1; - _clear_bit(3); + clear_has_type(); } inline ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const { return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_); } inline void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) { GOOGLE_DCHECK(::google::protobuf::FieldDescriptorProto_Type_IsValid(value)); - _set_bit(3); + set_has_type(); type_ = value; } // optional string type_name = 6; inline bool FieldDescriptorProto::has_type_name() const { - return _has_bit(4); + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void FieldDescriptorProto::set_has_type_name() { + _has_bits_[0] |= 0x00000010u; +} +inline void FieldDescriptorProto::clear_has_type_name() { + _has_bits_[0] &= ~0x00000010u; } inline void FieldDescriptorProto::clear_type_name() { - if (type_name_ != &_default_type_name_) { + if (type_name_ != &::google::protobuf::internal::kEmptyString) { type_name_->clear(); } - _clear_bit(4); + clear_has_type_name(); } inline const ::std::string& FieldDescriptorProto::type_name() const { return *type_name_; } inline void FieldDescriptorProto::set_type_name(const ::std::string& value) { - _set_bit(4); - if (type_name_ == &_default_type_name_) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::kEmptyString) { type_name_ = new ::std::string; } type_name_->assign(value); } inline void FieldDescriptorProto::set_type_name(const char* value) { - _set_bit(4); - if (type_name_ == &_default_type_name_) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::kEmptyString) { type_name_ = new ::std::string; } type_name_->assign(value); } inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) { - _set_bit(4); - if (type_name_ == &_default_type_name_) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::kEmptyString) { type_name_ = new ::std::string; } type_name_->assign(reinterpret_cast(value), size); } inline ::std::string* FieldDescriptorProto::mutable_type_name() { - _set_bit(4); - if (type_name_ == &_default_type_name_) { + set_has_type_name(); + if (type_name_ == &::google::protobuf::internal::kEmptyString) { type_name_ = new ::std::string; } return type_name_; } +inline ::std::string* FieldDescriptorProto::release_type_name() { + clear_has_type_name(); + if (type_name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = type_name_; + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional string extendee = 2; inline bool FieldDescriptorProto::has_extendee() const { - return _has_bit(5); + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void FieldDescriptorProto::set_has_extendee() { + _has_bits_[0] |= 0x00000020u; +} +inline void FieldDescriptorProto::clear_has_extendee() { + _has_bits_[0] &= ~0x00000020u; } inline void FieldDescriptorProto::clear_extendee() { - if (extendee_ != &_default_extendee_) { + if (extendee_ != &::google::protobuf::internal::kEmptyString) { extendee_->clear(); } - _clear_bit(5); + clear_has_extendee(); } inline const ::std::string& FieldDescriptorProto::extendee() const { return *extendee_; } inline void FieldDescriptorProto::set_extendee(const ::std::string& value) { - _set_bit(5); - if (extendee_ == &_default_extendee_) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::kEmptyString) { extendee_ = new ::std::string; } extendee_->assign(value); } inline void FieldDescriptorProto::set_extendee(const char* value) { - _set_bit(5); - if (extendee_ == &_default_extendee_) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::kEmptyString) { extendee_ = new ::std::string; } extendee_->assign(value); } inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) { - _set_bit(5); - if (extendee_ == &_default_extendee_) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::kEmptyString) { extendee_ = new ::std::string; } extendee_->assign(reinterpret_cast(value), size); } inline ::std::string* FieldDescriptorProto::mutable_extendee() { - _set_bit(5); - if (extendee_ == &_default_extendee_) { + set_has_extendee(); + if (extendee_ == &::google::protobuf::internal::kEmptyString) { extendee_ = new ::std::string; } return extendee_; } +inline ::std::string* FieldDescriptorProto::release_extendee() { + clear_has_extendee(); + if (extendee_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = extendee_; + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional string default_value = 7; inline bool FieldDescriptorProto::has_default_value() const { - return _has_bit(6); + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void FieldDescriptorProto::set_has_default_value() { + _has_bits_[0] |= 0x00000040u; +} +inline void FieldDescriptorProto::clear_has_default_value() { + _has_bits_[0] &= ~0x00000040u; } inline void FieldDescriptorProto::clear_default_value() { - if (default_value_ != &_default_default_value_) { + if (default_value_ != &::google::protobuf::internal::kEmptyString) { default_value_->clear(); } - _clear_bit(6); + clear_has_default_value(); } inline const ::std::string& FieldDescriptorProto::default_value() const { return *default_value_; } inline void FieldDescriptorProto::set_default_value(const ::std::string& value) { - _set_bit(6); - if (default_value_ == &_default_default_value_) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::kEmptyString) { default_value_ = new ::std::string; } default_value_->assign(value); } inline void FieldDescriptorProto::set_default_value(const char* value) { - _set_bit(6); - if (default_value_ == &_default_default_value_) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::kEmptyString) { default_value_ = new ::std::string; } default_value_->assign(value); } inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) { - _set_bit(6); - if (default_value_ == &_default_default_value_) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::kEmptyString) { default_value_ = new ::std::string; } default_value_->assign(reinterpret_cast(value), size); } inline ::std::string* FieldDescriptorProto::mutable_default_value() { - _set_bit(6); - if (default_value_ == &_default_default_value_) { + set_has_default_value(); + if (default_value_ == &::google::protobuf::internal::kEmptyString) { default_value_ = new ::std::string; } return default_value_; } +inline ::std::string* FieldDescriptorProto::release_default_value() { + clear_has_default_value(); + if (default_value_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = default_value_; + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional .google.protobuf.FieldOptions options = 8; inline bool FieldDescriptorProto::has_options() const { - return _has_bit(7); + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void FieldDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000080u; +} +inline void FieldDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000080u; } inline void FieldDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); - _clear_bit(7); + clear_has_options(); } inline const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const { return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() { - _set_bit(7); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::FieldOptions; return options_; } +inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::FieldOptions* temp = options_; + options_ = NULL; + return temp; +} // ------------------------------------------------------------------- @@ -3209,45 +3584,61 @@ inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() // optional string name = 1; inline bool EnumDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EnumDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void EnumDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void EnumDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& EnumDescriptorProto::name() const { return *name_; } inline void EnumDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void EnumDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void EnumDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); } inline ::std::string* EnumDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } return name_; } +inline ::std::string* EnumDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // repeated .google.protobuf.EnumValueDescriptorProto value = 2; inline int EnumDescriptorProto::value_size() const { @@ -3276,20 +3667,32 @@ EnumDescriptorProto::mutable_value() { // optional .google.protobuf.EnumOptions options = 3; inline bool EnumDescriptorProto::has_options() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void EnumDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} +inline void EnumDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; } inline void EnumDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); - _clear_bit(2); + clear_has_options(); } inline const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const { return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { - _set_bit(2); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::EnumOptions; return options_; } +inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::EnumOptions* temp = options_; + options_ = NULL; + return temp; +} // ------------------------------------------------------------------- @@ -3297,78 +3700,112 @@ inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { // optional string name = 1; inline bool EnumValueDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EnumValueDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void EnumValueDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void EnumValueDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& EnumValueDescriptorProto::name() const { return *name_; } inline void EnumValueDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void EnumValueDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); } inline ::std::string* EnumValueDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } return name_; } +inline ::std::string* EnumValueDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional int32 number = 2; inline bool EnumValueDescriptorProto::has_number() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void EnumValueDescriptorProto::set_has_number() { + _has_bits_[0] |= 0x00000002u; +} +inline void EnumValueDescriptorProto::clear_has_number() { + _has_bits_[0] &= ~0x00000002u; } inline void EnumValueDescriptorProto::clear_number() { number_ = 0; - _clear_bit(1); + clear_has_number(); } inline ::google::protobuf::int32 EnumValueDescriptorProto::number() const { return number_; } inline void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) { - _set_bit(1); + set_has_number(); number_ = value; } // optional .google.protobuf.EnumValueOptions options = 3; inline bool EnumValueDescriptorProto::has_options() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void EnumValueDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} +inline void EnumValueDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; } inline void EnumValueDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); - _clear_bit(2); + clear_has_options(); } inline const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const { return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { - _set_bit(2); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::EnumValueOptions; return options_; } +inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::EnumValueOptions* temp = options_; + options_ = NULL; + return temp; +} // ------------------------------------------------------------------- @@ -3376,45 +3813,61 @@ inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_o // optional string name = 1; inline bool ServiceDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ServiceDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void ServiceDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void ServiceDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& ServiceDescriptorProto::name() const { return *name_; } inline void ServiceDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void ServiceDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void ServiceDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); } inline ::std::string* ServiceDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } return name_; } +inline ::std::string* ServiceDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // repeated .google.protobuf.MethodDescriptorProto method = 2; inline int ServiceDescriptorProto::method_size() const { @@ -3443,20 +3896,32 @@ ServiceDescriptorProto::mutable_method() { // optional .google.protobuf.ServiceOptions options = 3; inline bool ServiceDescriptorProto::has_options() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void ServiceDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} +inline void ServiceDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; } inline void ServiceDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); - _clear_bit(2); + clear_has_options(); } inline const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const { return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() { - _set_bit(2); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::ServiceOptions; return options_; } +inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::ServiceOptions* temp = options_; + options_ = NULL; + return temp; +} // ------------------------------------------------------------------- @@ -3464,146 +3929,206 @@ inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_optio // optional string name = 1; inline bool MethodDescriptorProto::has_name() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void MethodDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void MethodDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; } inline void MethodDescriptorProto::clear_name() { - if (name_ != &_default_name_) { + if (name_ != &::google::protobuf::internal::kEmptyString) { name_->clear(); } - _clear_bit(0); + clear_has_name(); } inline const ::std::string& MethodDescriptorProto::name() const { return *name_; } inline void MethodDescriptorProto::set_name(const ::std::string& value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void MethodDescriptorProto::set_name(const char* value) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(value); } inline void MethodDescriptorProto::set_name(const char* value, size_t size) { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); } inline ::std::string* MethodDescriptorProto::mutable_name() { - _set_bit(0); - if (name_ == &_default_name_) { + set_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { name_ = new ::std::string; } return name_; } +inline ::std::string* MethodDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional string input_type = 2; inline bool MethodDescriptorProto::has_input_type() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void MethodDescriptorProto::set_has_input_type() { + _has_bits_[0] |= 0x00000002u; +} +inline void MethodDescriptorProto::clear_has_input_type() { + _has_bits_[0] &= ~0x00000002u; } inline void MethodDescriptorProto::clear_input_type() { - if (input_type_ != &_default_input_type_) { + if (input_type_ != &::google::protobuf::internal::kEmptyString) { input_type_->clear(); } - _clear_bit(1); + clear_has_input_type(); } inline const ::std::string& MethodDescriptorProto::input_type() const { return *input_type_; } inline void MethodDescriptorProto::set_input_type(const ::std::string& value) { - _set_bit(1); - if (input_type_ == &_default_input_type_) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::kEmptyString) { input_type_ = new ::std::string; } input_type_->assign(value); } inline void MethodDescriptorProto::set_input_type(const char* value) { - _set_bit(1); - if (input_type_ == &_default_input_type_) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::kEmptyString) { input_type_ = new ::std::string; } input_type_->assign(value); } inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) { - _set_bit(1); - if (input_type_ == &_default_input_type_) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::kEmptyString) { input_type_ = new ::std::string; } input_type_->assign(reinterpret_cast(value), size); } inline ::std::string* MethodDescriptorProto::mutable_input_type() { - _set_bit(1); - if (input_type_ == &_default_input_type_) { + set_has_input_type(); + if (input_type_ == &::google::protobuf::internal::kEmptyString) { input_type_ = new ::std::string; } return input_type_; } +inline ::std::string* MethodDescriptorProto::release_input_type() { + clear_has_input_type(); + if (input_type_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = input_type_; + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional string output_type = 3; inline bool MethodDescriptorProto::has_output_type() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void MethodDescriptorProto::set_has_output_type() { + _has_bits_[0] |= 0x00000004u; +} +inline void MethodDescriptorProto::clear_has_output_type() { + _has_bits_[0] &= ~0x00000004u; } inline void MethodDescriptorProto::clear_output_type() { - if (output_type_ != &_default_output_type_) { + if (output_type_ != &::google::protobuf::internal::kEmptyString) { output_type_->clear(); } - _clear_bit(2); + clear_has_output_type(); } inline const ::std::string& MethodDescriptorProto::output_type() const { return *output_type_; } inline void MethodDescriptorProto::set_output_type(const ::std::string& value) { - _set_bit(2); - if (output_type_ == &_default_output_type_) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::kEmptyString) { output_type_ = new ::std::string; } output_type_->assign(value); } inline void MethodDescriptorProto::set_output_type(const char* value) { - _set_bit(2); - if (output_type_ == &_default_output_type_) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::kEmptyString) { output_type_ = new ::std::string; } output_type_->assign(value); } inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) { - _set_bit(2); - if (output_type_ == &_default_output_type_) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::kEmptyString) { output_type_ = new ::std::string; } output_type_->assign(reinterpret_cast(value), size); } inline ::std::string* MethodDescriptorProto::mutable_output_type() { - _set_bit(2); - if (output_type_ == &_default_output_type_) { + set_has_output_type(); + if (output_type_ == &::google::protobuf::internal::kEmptyString) { output_type_ = new ::std::string; } return output_type_; } +inline ::std::string* MethodDescriptorProto::release_output_type() { + clear_has_output_type(); + if (output_type_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = output_type_; + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional .google.protobuf.MethodOptions options = 4; inline bool MethodDescriptorProto::has_options() const { - return _has_bit(3); + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void MethodDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000008u; +} +inline void MethodDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000008u; } inline void MethodDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); - _clear_bit(3); + clear_has_options(); } inline const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const { return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() { - _set_bit(3); + set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::MethodOptions; return options_; } +inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::MethodOptions* temp = options_; + options_ = NULL; + return temp; +} // ------------------------------------------------------------------- @@ -3611,166 +4136,250 @@ inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options // optional string java_package = 1; inline bool FileOptions::has_java_package() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FileOptions::set_has_java_package() { + _has_bits_[0] |= 0x00000001u; +} +inline void FileOptions::clear_has_java_package() { + _has_bits_[0] &= ~0x00000001u; } inline void FileOptions::clear_java_package() { - if (java_package_ != &_default_java_package_) { + if (java_package_ != &::google::protobuf::internal::kEmptyString) { java_package_->clear(); } - _clear_bit(0); + clear_has_java_package(); } inline const ::std::string& FileOptions::java_package() const { return *java_package_; } inline void FileOptions::set_java_package(const ::std::string& value) { - _set_bit(0); - if (java_package_ == &_default_java_package_) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::kEmptyString) { java_package_ = new ::std::string; } java_package_->assign(value); } inline void FileOptions::set_java_package(const char* value) { - _set_bit(0); - if (java_package_ == &_default_java_package_) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::kEmptyString) { java_package_ = new ::std::string; } java_package_->assign(value); } inline void FileOptions::set_java_package(const char* value, size_t size) { - _set_bit(0); - if (java_package_ == &_default_java_package_) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::kEmptyString) { java_package_ = new ::std::string; } java_package_->assign(reinterpret_cast(value), size); } inline ::std::string* FileOptions::mutable_java_package() { - _set_bit(0); - if (java_package_ == &_default_java_package_) { + set_has_java_package(); + if (java_package_ == &::google::protobuf::internal::kEmptyString) { java_package_ = new ::std::string; } return java_package_; } +inline ::std::string* FileOptions::release_java_package() { + clear_has_java_package(); + if (java_package_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = java_package_; + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional string java_outer_classname = 8; inline bool FileOptions::has_java_outer_classname() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FileOptions::set_has_java_outer_classname() { + _has_bits_[0] |= 0x00000002u; +} +inline void FileOptions::clear_has_java_outer_classname() { + _has_bits_[0] &= ~0x00000002u; } inline void FileOptions::clear_java_outer_classname() { - if (java_outer_classname_ != &_default_java_outer_classname_) { + if (java_outer_classname_ != &::google::protobuf::internal::kEmptyString) { java_outer_classname_->clear(); } - _clear_bit(1); + clear_has_java_outer_classname(); } inline const ::std::string& FileOptions::java_outer_classname() const { return *java_outer_classname_; } inline void FileOptions::set_java_outer_classname(const ::std::string& value) { - _set_bit(1); - if (java_outer_classname_ == &_default_java_outer_classname_) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) { java_outer_classname_ = new ::std::string; } java_outer_classname_->assign(value); } inline void FileOptions::set_java_outer_classname(const char* value) { - _set_bit(1); - if (java_outer_classname_ == &_default_java_outer_classname_) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) { java_outer_classname_ = new ::std::string; } java_outer_classname_->assign(value); } inline void FileOptions::set_java_outer_classname(const char* value, size_t size) { - _set_bit(1); - if (java_outer_classname_ == &_default_java_outer_classname_) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) { java_outer_classname_ = new ::std::string; } java_outer_classname_->assign(reinterpret_cast(value), size); } inline ::std::string* FileOptions::mutable_java_outer_classname() { - _set_bit(1); - if (java_outer_classname_ == &_default_java_outer_classname_) { + set_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) { java_outer_classname_ = new ::std::string; } return java_outer_classname_; } +inline ::std::string* FileOptions::release_java_outer_classname() { + clear_has_java_outer_classname(); + if (java_outer_classname_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = java_outer_classname_; + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional bool java_multiple_files = 10 [default = false]; inline bool FileOptions::has_java_multiple_files() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FileOptions::set_has_java_multiple_files() { + _has_bits_[0] |= 0x00000004u; +} +inline void FileOptions::clear_has_java_multiple_files() { + _has_bits_[0] &= ~0x00000004u; } inline void FileOptions::clear_java_multiple_files() { java_multiple_files_ = false; - _clear_bit(2); + clear_has_java_multiple_files(); } inline bool FileOptions::java_multiple_files() const { return java_multiple_files_; } inline void FileOptions::set_java_multiple_files(bool value) { - _set_bit(2); + set_has_java_multiple_files(); java_multiple_files_ = value; } +// optional bool java_generate_equals_and_hash = 20 [default = false]; +inline bool FileOptions::has_java_generate_equals_and_hash() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void FileOptions::set_has_java_generate_equals_and_hash() { + _has_bits_[0] |= 0x00000008u; +} +inline void FileOptions::clear_has_java_generate_equals_and_hash() { + _has_bits_[0] &= ~0x00000008u; +} +inline void FileOptions::clear_java_generate_equals_and_hash() { + java_generate_equals_and_hash_ = false; + clear_has_java_generate_equals_and_hash(); +} +inline bool FileOptions::java_generate_equals_and_hash() const { + 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; +} + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; inline bool FileOptions::has_optimize_for() const { - return _has_bit(3); + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void FileOptions::set_has_optimize_for() { + _has_bits_[0] |= 0x00000010u; +} +inline void FileOptions::clear_has_optimize_for() { + _has_bits_[0] &= ~0x00000010u; } inline void FileOptions::clear_optimize_for() { optimize_for_ = 1; - _clear_bit(3); + clear_has_optimize_for(); } inline ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const { return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_); } inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) { GOOGLE_DCHECK(::google::protobuf::FileOptions_OptimizeMode_IsValid(value)); - _set_bit(3); + set_has_optimize_for(); optimize_for_ = value; } -// optional bool cc_generic_services = 16 [default = true]; +// optional bool cc_generic_services = 16 [default = false]; inline bool FileOptions::has_cc_generic_services() const { - return _has_bit(4); + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void FileOptions::set_has_cc_generic_services() { + _has_bits_[0] |= 0x00000020u; +} +inline void FileOptions::clear_has_cc_generic_services() { + _has_bits_[0] &= ~0x00000020u; } inline void FileOptions::clear_cc_generic_services() { - cc_generic_services_ = true; - _clear_bit(4); + cc_generic_services_ = false; + clear_has_cc_generic_services(); } inline bool FileOptions::cc_generic_services() const { return cc_generic_services_; } inline void FileOptions::set_cc_generic_services(bool value) { - _set_bit(4); + set_has_cc_generic_services(); cc_generic_services_ = value; } -// optional bool java_generic_services = 17 [default = true]; +// optional bool java_generic_services = 17 [default = false]; inline bool FileOptions::has_java_generic_services() const { - return _has_bit(5); + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void FileOptions::set_has_java_generic_services() { + _has_bits_[0] |= 0x00000040u; +} +inline void FileOptions::clear_has_java_generic_services() { + _has_bits_[0] &= ~0x00000040u; } inline void FileOptions::clear_java_generic_services() { - java_generic_services_ = true; - _clear_bit(5); + java_generic_services_ = false; + clear_has_java_generic_services(); } inline bool FileOptions::java_generic_services() const { return java_generic_services_; } inline void FileOptions::set_java_generic_services(bool value) { - _set_bit(5); + set_has_java_generic_services(); java_generic_services_ = value; } -// optional bool py_generic_services = 18 [default = true]; +// optional bool py_generic_services = 18 [default = false]; inline bool FileOptions::has_py_generic_services() const { - return _has_bit(6); + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void FileOptions::set_has_py_generic_services() { + _has_bits_[0] |= 0x00000080u; +} +inline void FileOptions::clear_has_py_generic_services() { + _has_bits_[0] &= ~0x00000080u; } inline void FileOptions::clear_py_generic_services() { - py_generic_services_ = true; - _clear_bit(6); + py_generic_services_ = false; + clear_has_py_generic_services(); } inline bool FileOptions::py_generic_services() const { return py_generic_services_; } inline void FileOptions::set_py_generic_services(bool value) { - _set_bit(6); + set_has_py_generic_services(); py_generic_services_ = value; } @@ -3805,33 +4414,45 @@ FileOptions::mutable_uninterpreted_option() { // optional bool message_set_wire_format = 1 [default = false]; inline bool MessageOptions::has_message_set_wire_format() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void MessageOptions::set_has_message_set_wire_format() { + _has_bits_[0] |= 0x00000001u; +} +inline void MessageOptions::clear_has_message_set_wire_format() { + _has_bits_[0] &= ~0x00000001u; } inline void MessageOptions::clear_message_set_wire_format() { message_set_wire_format_ = false; - _clear_bit(0); + clear_has_message_set_wire_format(); } inline bool MessageOptions::message_set_wire_format() const { return message_set_wire_format_; } inline void MessageOptions::set_message_set_wire_format(bool value) { - _set_bit(0); + set_has_message_set_wire_format(); message_set_wire_format_ = value; } // optional bool no_standard_descriptor_accessor = 2 [default = false]; inline bool MessageOptions::has_no_standard_descriptor_accessor() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void MessageOptions::set_has_no_standard_descriptor_accessor() { + _has_bits_[0] |= 0x00000002u; +} +inline void MessageOptions::clear_has_no_standard_descriptor_accessor() { + _has_bits_[0] &= ~0x00000002u; } inline void MessageOptions::clear_no_standard_descriptor_accessor() { no_standard_descriptor_accessor_ = false; - _clear_bit(1); + clear_has_no_standard_descriptor_accessor(); } inline bool MessageOptions::no_standard_descriptor_accessor() const { return no_standard_descriptor_accessor_; } inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) { - _set_bit(1); + set_has_no_standard_descriptor_accessor(); no_standard_descriptor_accessor_ = value; } @@ -3866,94 +4487,128 @@ MessageOptions::mutable_uninterpreted_option() { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; inline bool FieldOptions::has_ctype() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void FieldOptions::set_has_ctype() { + _has_bits_[0] |= 0x00000001u; +} +inline void FieldOptions::clear_has_ctype() { + _has_bits_[0] &= ~0x00000001u; } inline void FieldOptions::clear_ctype() { ctype_ = 0; - _clear_bit(0); + clear_has_ctype(); } inline ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const { return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_); } inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) { GOOGLE_DCHECK(::google::protobuf::FieldOptions_CType_IsValid(value)); - _set_bit(0); + set_has_ctype(); ctype_ = value; } // optional bool packed = 2; inline bool FieldOptions::has_packed() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void FieldOptions::set_has_packed() { + _has_bits_[0] |= 0x00000002u; +} +inline void FieldOptions::clear_has_packed() { + _has_bits_[0] &= ~0x00000002u; } inline void FieldOptions::clear_packed() { packed_ = false; - _clear_bit(1); + clear_has_packed(); } inline bool FieldOptions::packed() const { return packed_; } inline void FieldOptions::set_packed(bool value) { - _set_bit(1); + set_has_packed(); packed_ = value; } // optional bool deprecated = 3 [default = false]; inline bool FieldOptions::has_deprecated() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FieldOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000004u; +} +inline void FieldOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000004u; } inline void FieldOptions::clear_deprecated() { deprecated_ = false; - _clear_bit(2); + clear_has_deprecated(); } inline bool FieldOptions::deprecated() const { return deprecated_; } inline void FieldOptions::set_deprecated(bool value) { - _set_bit(2); + set_has_deprecated(); deprecated_ = value; } // optional string experimental_map_key = 9; inline bool FieldOptions::has_experimental_map_key() const { - return _has_bit(3); + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void FieldOptions::set_has_experimental_map_key() { + _has_bits_[0] |= 0x00000008u; +} +inline void FieldOptions::clear_has_experimental_map_key() { + _has_bits_[0] &= ~0x00000008u; } inline void FieldOptions::clear_experimental_map_key() { - if (experimental_map_key_ != &_default_experimental_map_key_) { + if (experimental_map_key_ != &::google::protobuf::internal::kEmptyString) { experimental_map_key_->clear(); } - _clear_bit(3); + clear_has_experimental_map_key(); } inline const ::std::string& FieldOptions::experimental_map_key() const { return *experimental_map_key_; } inline void FieldOptions::set_experimental_map_key(const ::std::string& value) { - _set_bit(3); - if (experimental_map_key_ == &_default_experimental_map_key_) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) { experimental_map_key_ = new ::std::string; } experimental_map_key_->assign(value); } inline void FieldOptions::set_experimental_map_key(const char* value) { - _set_bit(3); - if (experimental_map_key_ == &_default_experimental_map_key_) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) { experimental_map_key_ = new ::std::string; } experimental_map_key_->assign(value); } inline void FieldOptions::set_experimental_map_key(const char* value, size_t size) { - _set_bit(3); - if (experimental_map_key_ == &_default_experimental_map_key_) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) { experimental_map_key_ = new ::std::string; } experimental_map_key_->assign(reinterpret_cast(value), size); } inline ::std::string* FieldOptions::mutable_experimental_map_key() { - _set_bit(3); - if (experimental_map_key_ == &_default_experimental_map_key_) { + set_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) { experimental_map_key_ = new ::std::string; } return experimental_map_key_; } +inline ::std::string* FieldOptions::release_experimental_map_key() { + clear_has_experimental_map_key(); + if (experimental_map_key_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = experimental_map_key_; + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int FieldOptions::uninterpreted_option_size() const { @@ -4102,59 +4757,81 @@ MethodOptions::mutable_uninterpreted_option() { // required string name_part = 1; inline bool UninterpretedOption_NamePart::has_name_part() const { - return _has_bit(0); + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void UninterpretedOption_NamePart::set_has_name_part() { + _has_bits_[0] |= 0x00000001u; +} +inline void UninterpretedOption_NamePart::clear_has_name_part() { + _has_bits_[0] &= ~0x00000001u; } inline void UninterpretedOption_NamePart::clear_name_part() { - if (name_part_ != &_default_name_part_) { + if (name_part_ != &::google::protobuf::internal::kEmptyString) { name_part_->clear(); } - _clear_bit(0); + clear_has_name_part(); } inline const ::std::string& UninterpretedOption_NamePart::name_part() const { return *name_part_; } inline void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) { - _set_bit(0); - if (name_part_ == &_default_name_part_) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::kEmptyString) { name_part_ = new ::std::string; } name_part_->assign(value); } inline void UninterpretedOption_NamePart::set_name_part(const char* value) { - _set_bit(0); - if (name_part_ == &_default_name_part_) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::kEmptyString) { name_part_ = new ::std::string; } name_part_->assign(value); } inline void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) { - _set_bit(0); - if (name_part_ == &_default_name_part_) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::kEmptyString) { name_part_ = new ::std::string; } name_part_->assign(reinterpret_cast(value), size); } inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() { - _set_bit(0); - if (name_part_ == &_default_name_part_) { + set_has_name_part(); + if (name_part_ == &::google::protobuf::internal::kEmptyString) { name_part_ = new ::std::string; } return name_part_; } +inline ::std::string* UninterpretedOption_NamePart::release_name_part() { + clear_has_name_part(); + if (name_part_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = name_part_; + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // required bool is_extension = 2; inline bool UninterpretedOption_NamePart::has_is_extension() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void UninterpretedOption_NamePart::set_has_is_extension() { + _has_bits_[0] |= 0x00000002u; +} +inline void UninterpretedOption_NamePart::clear_has_is_extension() { + _has_bits_[0] &= ~0x00000002u; } inline void UninterpretedOption_NamePart::clear_is_extension() { is_extension_ = false; - _clear_bit(1); + clear_has_is_extension(); } inline bool UninterpretedOption_NamePart::is_extension() const { return is_extension_; } inline void UninterpretedOption_NamePart::set_is_extension(bool value) { - _set_bit(1); + set_has_is_extension(); is_extension_ = value; } @@ -4189,135 +4866,326 @@ UninterpretedOption::mutable_name() { // optional string identifier_value = 3; inline bool UninterpretedOption::has_identifier_value() const { - return _has_bit(1); + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void UninterpretedOption::set_has_identifier_value() { + _has_bits_[0] |= 0x00000002u; +} +inline void UninterpretedOption::clear_has_identifier_value() { + _has_bits_[0] &= ~0x00000002u; } inline void UninterpretedOption::clear_identifier_value() { - if (identifier_value_ != &_default_identifier_value_) { + if (identifier_value_ != &::google::protobuf::internal::kEmptyString) { identifier_value_->clear(); } - _clear_bit(1); + clear_has_identifier_value(); } inline const ::std::string& UninterpretedOption::identifier_value() const { return *identifier_value_; } inline void UninterpretedOption::set_identifier_value(const ::std::string& value) { - _set_bit(1); - if (identifier_value_ == &_default_identifier_value_) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::kEmptyString) { identifier_value_ = new ::std::string; } identifier_value_->assign(value); } inline void UninterpretedOption::set_identifier_value(const char* value) { - _set_bit(1); - if (identifier_value_ == &_default_identifier_value_) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::kEmptyString) { identifier_value_ = new ::std::string; } identifier_value_->assign(value); } inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) { - _set_bit(1); - if (identifier_value_ == &_default_identifier_value_) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::kEmptyString) { identifier_value_ = new ::std::string; } identifier_value_->assign(reinterpret_cast(value), size); } inline ::std::string* UninterpretedOption::mutable_identifier_value() { - _set_bit(1); - if (identifier_value_ == &_default_identifier_value_) { + set_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::kEmptyString) { identifier_value_ = new ::std::string; } return identifier_value_; } +inline ::std::string* UninterpretedOption::release_identifier_value() { + clear_has_identifier_value(); + if (identifier_value_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = identifier_value_; + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} // optional uint64 positive_int_value = 4; inline bool UninterpretedOption::has_positive_int_value() const { - return _has_bit(2); + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void UninterpretedOption::set_has_positive_int_value() { + _has_bits_[0] |= 0x00000004u; +} +inline void UninterpretedOption::clear_has_positive_int_value() { + _has_bits_[0] &= ~0x00000004u; } inline void UninterpretedOption::clear_positive_int_value() { positive_int_value_ = GOOGLE_ULONGLONG(0); - _clear_bit(2); + clear_has_positive_int_value(); } inline ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const { return positive_int_value_; } inline void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) { - _set_bit(2); + set_has_positive_int_value(); positive_int_value_ = value; } // optional int64 negative_int_value = 5; inline bool UninterpretedOption::has_negative_int_value() const { - return _has_bit(3); + return (_has_bits_[0] & 0x00000008u) != 0; +} +inline void UninterpretedOption::set_has_negative_int_value() { + _has_bits_[0] |= 0x00000008u; +} +inline void UninterpretedOption::clear_has_negative_int_value() { + _has_bits_[0] &= ~0x00000008u; } inline void UninterpretedOption::clear_negative_int_value() { negative_int_value_ = GOOGLE_LONGLONG(0); - _clear_bit(3); + clear_has_negative_int_value(); } inline ::google::protobuf::int64 UninterpretedOption::negative_int_value() const { return negative_int_value_; } inline void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) { - _set_bit(3); + set_has_negative_int_value(); negative_int_value_ = value; } // optional double double_value = 6; inline bool UninterpretedOption::has_double_value() const { - return _has_bit(4); + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void UninterpretedOption::set_has_double_value() { + _has_bits_[0] |= 0x00000010u; +} +inline void UninterpretedOption::clear_has_double_value() { + _has_bits_[0] &= ~0x00000010u; } inline void UninterpretedOption::clear_double_value() { double_value_ = 0; - _clear_bit(4); + clear_has_double_value(); } inline double UninterpretedOption::double_value() const { return double_value_; } inline void UninterpretedOption::set_double_value(double value) { - _set_bit(4); + set_has_double_value(); double_value_ = value; } // optional bytes string_value = 7; inline bool UninterpretedOption::has_string_value() const { - return _has_bit(5); + return (_has_bits_[0] & 0x00000020u) != 0; +} +inline void UninterpretedOption::set_has_string_value() { + _has_bits_[0] |= 0x00000020u; +} +inline void UninterpretedOption::clear_has_string_value() { + _has_bits_[0] &= ~0x00000020u; } inline void UninterpretedOption::clear_string_value() { - if (string_value_ != &_default_string_value_) { + if (string_value_ != &::google::protobuf::internal::kEmptyString) { string_value_->clear(); } - _clear_bit(5); + clear_has_string_value(); } inline const ::std::string& UninterpretedOption::string_value() const { return *string_value_; } inline void UninterpretedOption::set_string_value(const ::std::string& value) { - _set_bit(5); - if (string_value_ == &_default_string_value_) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::kEmptyString) { string_value_ = new ::std::string; } string_value_->assign(value); } inline void UninterpretedOption::set_string_value(const char* value) { - _set_bit(5); - if (string_value_ == &_default_string_value_) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::kEmptyString) { string_value_ = new ::std::string; } string_value_->assign(value); } inline void UninterpretedOption::set_string_value(const void* value, size_t size) { - _set_bit(5); - if (string_value_ == &_default_string_value_) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::kEmptyString) { string_value_ = new ::std::string; } string_value_->assign(reinterpret_cast(value), size); } inline ::std::string* UninterpretedOption::mutable_string_value() { - _set_bit(5); - if (string_value_ == &_default_string_value_) { + set_has_string_value(); + if (string_value_ == &::google::protobuf::internal::kEmptyString) { string_value_ = new ::std::string; } return string_value_; } +inline ::std::string* UninterpretedOption::release_string_value() { + clear_has_string_value(); + if (string_value_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = string_value_; + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// optional string aggregate_value = 8; +inline bool UninterpretedOption::has_aggregate_value() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} +inline void UninterpretedOption::set_has_aggregate_value() { + _has_bits_[0] |= 0x00000040u; +} +inline void UninterpretedOption::clear_has_aggregate_value() { + _has_bits_[0] &= ~0x00000040u; +} +inline void UninterpretedOption::clear_aggregate_value() { + if (aggregate_value_ != &::google::protobuf::internal::kEmptyString) { + aggregate_value_->clear(); + } + clear_has_aggregate_value(); +} +inline const ::std::string& UninterpretedOption::aggregate_value() const { + return *aggregate_value_; +} +inline void UninterpretedOption::set_aggregate_value(const ::std::string& value) { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) { + aggregate_value_ = new ::std::string; + } + aggregate_value_->assign(value); +} +inline void UninterpretedOption::set_aggregate_value(const char* value) { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) { + aggregate_value_ = new ::std::string; + } + aggregate_value_->assign(value); +} +inline void UninterpretedOption::set_aggregate_value(const char* value, size_t size) { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) { + aggregate_value_ = new ::std::string; + } + aggregate_value_->assign(reinterpret_cast(value), size); +} +inline ::std::string* UninterpretedOption::mutable_aggregate_value() { + set_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) { + aggregate_value_ = new ::std::string; + } + return aggregate_value_; +} +inline ::std::string* UninterpretedOption::release_aggregate_value() { + clear_has_aggregate_value(); + if (aggregate_value_ == &::google::protobuf::internal::kEmptyString) { + return NULL; + } else { + ::std::string* temp = aggregate_value_; + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::kEmptyString); + return temp; + } +} + +// ------------------------------------------------------------------- + +// SourceCodeInfo_Location + +// repeated int32 path = 1 [packed = true]; +inline int SourceCodeInfo_Location::path_size() const { + return path_.size(); +} +inline void SourceCodeInfo_Location::clear_path() { + path_.Clear(); +} +inline ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const { + return path_.Get(index); +} +inline void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) { + path_.Set(index, value); +} +inline void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) { + path_.Add(value); +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +SourceCodeInfo_Location::path() const { + return path_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +SourceCodeInfo_Location::mutable_path() { + return &path_; +} + +// repeated int32 span = 2 [packed = true]; +inline int SourceCodeInfo_Location::span_size() const { + return span_.size(); +} +inline void SourceCodeInfo_Location::clear_span() { + span_.Clear(); +} +inline ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const { + return span_.Get(index); +} +inline void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) { + span_.Set(index, value); +} +inline void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) { + span_.Add(value); +} +inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +SourceCodeInfo_Location::span() const { + return span_; +} +inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +SourceCodeInfo_Location::mutable_span() { + return &span_; +} + +// ------------------------------------------------------------------- + +// SourceCodeInfo + +// repeated .google.protobuf.SourceCodeInfo.Location location = 1; +inline int SourceCodeInfo::location_size() const { + return location_.size(); +} +inline void SourceCodeInfo::clear_location() { + location_.Clear(); +} +inline const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { + return location_.Get(index); +} +inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) { + return location_.Mutable(index); +} +inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() { + return location_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& +SourceCodeInfo::location() const { + return location_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* +SourceCodeInfo::mutable_location() { + return &location_; +} // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index cc04aa8e..233f8794 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -67,6 +67,12 @@ message FileDescriptorProto { repeated FieldDescriptorProto extension = 7; optional FileOptions options = 8; + + // This field contains optional information about the original source code. + // You may safely remove this entire field whithout harming runtime + // functionality of the descriptors -- the information is needed only by + // development tools. + optional SourceCodeInfo source_code_info = 9; } // Describes a message type. @@ -245,6 +251,12 @@ message FileOptions { // top-level extensions defined in the file. 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. + optional bool java_generate_equals_and_hash = 20 [default=false]; + // Generated classes can be optimized for speed or code size. enum OptimizeMode { SPEED = 1; // Generate complete code for parsing, serialization, @@ -264,13 +276,12 @@ message FileOptions { // early versions of proto2. // // Generic services are now considered deprecated in favor of using plugins - // that generate code specific to your particular RPC system. If you are - // using such a plugin, set these to false. In the future, we may change - // the default to false, so if you explicitly want generic services, you - // should explicitly set these to true. - optional bool cc_generic_services = 16 [default=true]; - optional bool java_generic_services = 17 [default=true]; - optional bool py_generic_services = 18 [default=true]; + // that generate code specific to your particular RPC system. Therefore, + // these default to false. Old code which depends on generic services should + // explicitly set them to true. + optional bool cc_generic_services = 16 [default=false]; + optional bool java_generic_services = 17 [default=false]; + optional bool py_generic_services = 18 [default=false]; // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -430,4 +441,93 @@ message UninterpretedOption { optional int64 negative_int_value = 5; optional double double_value = 6; optional bytes string_value = 7; + optional string aggregate_value = 8; +} + +// =================================================================== +// Optional source code info + +// Encapsulates information about the original source file from which a +// FileDescriptorProto was generated. +message SourceCodeInfo { + // A Location identifies a piece of source code in a .proto file which + // corresponds to a particular definition. This information is intended + // to be useful to IDEs, code indexers, documentation generators, and similar + // tools. + // + // For example, say we have a file like: + // message Foo { + // optional string foo = 1; + // } + // Let's look at just the field definition: + // optional string foo = 1; + // ^ ^^ ^^ ^ ^^^ + // a bc de f ghi + // We have the following locations: + // span path represents + // [a,i) [ 4, 0, 2, 0 ] The whole field definition. + // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). + // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). + // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). + // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). + // + // Notes: + // - A location may refer to a repeated field itself (i.e. not to any + // particular index within it). This is used whenever a set of elements are + // logically enclosed in a single code segment. For example, an entire + // extend block (possibly containing multiple extension definitions) will + // have an outer location whose path refers to the "extensions" repeated + // field without an index. + // - Multiple locations may have the same path. This happens when a single + // logical declaration is spread out across multiple places. The most + // obvious example is the "extend" block again -- there may be multiple + // extend blocks in the same scope, each of which will have the same path. + // - A location's span is not always a subset of its parent's span. For + // example, the "extendee" of an extension declaration appears at the + // beginning of the "extend" block and is shared by all extensions within + // the block. + // - Just because a location's span is a subset of some other location's span + // does not mean that it is a descendent. For example, a "group" defines + // both a type and a field in a single declaration. Thus, the locations + // corresponding to the type and field and their components will overlap. + // - Code which tries to interpret locations should probably be designed to + // ignore those that it doesn't understand, as more types of locations could + // be recorded in the future. + repeated Location location = 1; + message Location { + // Identifies which part of the FileDescriptorProto was defined at this + // location. + // + // Each element is a field number or an index. They form a path from + // the root FileDescriptorProto to the place where the definition. For + // example, this path: + // [ 4, 3, 2, 7, 1 ] + // refers to: + // file.message_type(3) // 4, 3 + // .field(7) // 2, 7 + // .name() // 1 + // This is because FileDescriptorProto.message_type has field number 4: + // repeated DescriptorProto message_type = 4; + // and DescriptorProto.field has field number 2: + // repeated FieldDescriptorProto field = 2; + // and FieldDescriptorProto.name has field number 1: + // optional string name = 1; + // + // Thus, the above path gives the location of a field name. If we removed + // the last element: + // [ 4, 3, 2, 7 ] + // this path refers to the whole field declaration (from the beginning + // of the label to the terminating semicolon). + repeated int32 path = 1 [packed=true]; + + // Always has exactly three or four elements: start line, start column, + // end line (optional, otherwise assumed same as start line), end column. + // These are packed into a single field for efficiency. Note that line + // and column numbers are zero-based -- typically you will want to add + // 1 to each before displaying to a user. + repeated int32 span = 2 [packed=true]; + + // TODO(kenton): Record comments appearing before and after the + // declaration. + } } diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index d70c9bf1..55aebfd1 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -2212,6 +2212,45 @@ TEST(CustomOptions, MessageOptionThreeFieldsSet) { EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo()); } +// Check that aggregate options were parsed and saved correctly in +// the appropriate descriptors. +TEST(CustomOptions, AggregateOptions) { + const Descriptor* msg = protobuf_unittest::AggregateMessage::descriptor(); + const FileDescriptor* file = msg->file(); + const FieldDescriptor* field = msg->FindFieldByName("fieldname"); + const EnumDescriptor* enumd = file->FindEnumTypeByName("AggregateEnum"); + const EnumValueDescriptor* enumv = enumd->FindValueByName("VALUE"); + const ServiceDescriptor* service = file->FindServiceByName( + "AggregateService"); + const MethodDescriptor* method = service->FindMethodByName("Method"); + + // Tests for the different types of data embedded in fileopt + const protobuf_unittest::Aggregate& file_options = + file->options().GetExtension(protobuf_unittest::fileopt); + EXPECT_EQ(100, file_options.i()); + EXPECT_EQ("FileAnnotation", file_options.s()); + EXPECT_EQ("NestedFileAnnotation", file_options.sub().s()); + EXPECT_EQ("FileExtensionAnnotation", + file_options.file().GetExtension(protobuf_unittest::fileopt).s()); + EXPECT_EQ("EmbeddedMessageSetElement", + file_options.mset().GetExtension( + protobuf_unittest::AggregateMessageSetElement + ::message_set_extension).s()); + + // Simple tests for all the other types of annotations + EXPECT_EQ("MessageAnnotation", + msg->options().GetExtension(protobuf_unittest::msgopt).s()); + EXPECT_EQ("FieldAnnotation", + field->options().GetExtension(protobuf_unittest::fieldopt).s()); + EXPECT_EQ("EnumAnnotation", + enumd->options().GetExtension(protobuf_unittest::enumopt).s()); + EXPECT_EQ("EnumValueAnnotation", + enumv->options().GetExtension(protobuf_unittest::enumvalopt).s()); + EXPECT_EQ("ServiceAnnotation", + service->options().GetExtension(protobuf_unittest::serviceopt).s()); + EXPECT_EQ("MethodAnnotation", + method->options().GetExtension(protobuf_unittest::methodopt).s()); +} // =================================================================== @@ -3425,25 +3464,50 @@ TEST_F(ValidationErrorTest, StringOptionValueIsNotString) { "string option \"foo\".\n"); } -TEST_F(ValidationErrorTest, TryingToSetMessageValuedOption) { +// Helper function for tests that check for aggregate value parsing +// errors. The "value" argument is embedded inside the +// "uninterpreted_option" portion of the result. +static string EmbedAggregateValue(const char* value) { + return strings::Substitute( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "message_type { name: \"Foo\" } " + "extension { name: \"foo\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_MESSAGE type_name: \"Foo\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"foo\" " + " is_extension: true } " + " $0 } }", + value); +} + +TEST_F(ValidationErrorTest, AggregateValueNotFound) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( - "name: \"foo.proto\" " - "dependency: \"google/protobuf/descriptor.proto\" " - "message_type { " - " name: \"TestMessage\" " - " field { name:\"baz\" number:1 label:LABEL_OPTIONAL type:TYPE_STRING }" - "}" - "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL " - " type: TYPE_MESSAGE type_name: \"TestMessage\" " - " extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"bar\" " - " is_extension: true } " - " identifier_value: \"QUUX\" } }", + EmbedAggregateValue("string_value: \"\""), + "foo.proto: foo.proto: OPTION_VALUE: Option \"foo\" is a message. " + "To set the entire message, use syntax like " + "\"foo = { }\". To set fields within it, use " + "syntax like \"foo.foo = value\".\n"); +} - "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" cannot be of " - "message type.\n"); +TEST_F(ValidationErrorTest, AggregateValueParseError) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + EmbedAggregateValue("aggregate_value: \"1+2\""), + "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option " + "value for \"foo\": Expected identifier.\n"); +} + +TEST_F(ValidationErrorTest, AggregateValueUnknownFields) { + BuildDescriptorMessagesInTestPool(); + + BuildFileWithErrors( + EmbedAggregateValue("aggregate_value: \"x:100\""), + "foo.proto: foo.proto: OPTION_VALUE: Error while parsing option " + "value for \"foo\": Message type \"Foo\" has no field named \"x\".\n"); } TEST_F(ValidationErrorTest, NotLiteImportsLite) { @@ -3483,7 +3547,11 @@ TEST_F(ValidationErrorTest, LiteExtendsNotLite) { TEST_F(ValidationErrorTest, NoLiteServices) { BuildFileWithErrors( "name: \"foo.proto\" " - "options { optimize_for: LITE_RUNTIME } " + "options {" + " optimize_for: LITE_RUNTIME" + " cc_generic_services: true" + " java_generic_services: true" + "} " "service { name: \"Foo\" }", "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot " @@ -3497,7 +3565,7 @@ TEST_F(ValidationErrorTest, NoLiteServices) { " cc_generic_services: false" " java_generic_services: false" "} " - "service { name: \"Foo\" }"); + "service { name: \"Bar\" }"); } TEST_F(ValidationErrorTest, RollbackAfterError) { diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 6084885b..1a6f5dfc 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -186,6 +186,18 @@ int ExtensionSet::ExtensionSize(int number) const { return iter->second.GetSize(); } +FieldType ExtensionSet::ExtensionType(int number) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end()) { + GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (1). "; + return 0; + } + if (iter->second.is_cleared) { + GOOGLE_LOG(DFATAL) << "Don't lookup extension types if they aren't present (2). "; + } + return iter->second.type; +} + void ExtensionSet::ClearExtension(int number) { map::iterator iter = extensions_.find(number); if (iter == extensions_.end()) return; diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index 14d5d150..ac1ada02 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -39,11 +39,11 @@ #define GOOGLE_PROTOBUF_EXTENSION_SET_H__ #include -#include #include #include #include + #include namespace google { @@ -214,6 +214,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { bool Has(int number) const; int ExtensionSize(int number) const; // Size of a repeated extension. + FieldType ExtensionType(int number) const; void ClearExtension(int number); // singular fields ------------------------------------------------- @@ -451,6 +452,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { int SpaceUsedExcludingSelf() const; }; + // Gets the extension with the given number, creating it if it does not // already exist. Returns true if the extension did not already exist. bool MaybeNewExtension(int number, const FieldDescriptor* descriptor, diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 0f065ff2..a0dd75c6 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -45,8 +45,6 @@ namespace google { namespace protobuf { namespace internal { -namespace { const string kEmptyString; } - int StringSpaceUsedExcludingSelf(const string& str) { const void* start = &str; const void* end = &str + 1; @@ -69,7 +67,6 @@ bool ParseNamedEnum(const EnumDescriptor* descriptor, } const string& NameOfEnum(const EnumDescriptor* descriptor, int value) { - static string kEmptyString; const EnumValueDescriptor* d = descriptor->FindValueByNumber(value); return (d == NULL ? kEmptyString : d->name()); } diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc index 7ac015d0..76e547bb 100644 --- a/src/google/protobuf/generated_message_util.cc +++ b/src/google/protobuf/generated_message_util.cc @@ -47,6 +47,8 @@ double NaN() { return std::numeric_limits::quiet_NaN(); } +const ::std::string kEmptyString; + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h index daa16f77..1a2343d4 100644 --- a/src/google/protobuf/generated_message_util.h +++ b/src/google/protobuf/generated_message_util.h @@ -38,6 +38,8 @@ #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ +#include + #include @@ -66,8 +68,11 @@ namespace internal { // Constants for special floating point values. -LIBPROTOBUF_EXPORT double Infinity(); -LIBPROTOBUF_EXPORT double NaN(); +double Infinity(); +double NaN(); + +// Constant used for empty default strings. +extern const ::std::string kEmptyString; } // namespace internal diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index 6a91a13d..57d486f9 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -56,6 +56,15 @@ static const int kMaxVarintBytes = 10; static const int kMaxVarint32Bytes = 5; +inline bool NextNonEmpty(ZeroCopyInputStream* input, + const void** data, int* size) { + bool success; + do { + success = input->Next(data, size); + } while (success && *size == 0); + return success; +} + } // namespace // CodedInputStream ================================================== @@ -489,7 +498,7 @@ bool CodedInputStream::Refresh() { const void* void_buffer; int buffer_size; - if (input_->Next(&void_buffer, &buffer_size)) { + if (NextNonEmpty(input_, &void_buffer, &buffer_size)) { buffer_ = reinterpret_cast(void_buffer); buffer_end_ = buffer_ + buffer_size; GOOGLE_CHECK_GE(buffer_size, 0); diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 93effc87..73a54ddd 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -129,8 +129,8 @@ #endif #include -namespace google { +namespace google { namespace protobuf { class DescriptorPool; @@ -782,7 +782,8 @@ inline const uint8* CodedInputStream::ReadLittleEndian64FromArray( } inline bool CodedInputStream::ReadLittleEndian32(uint32* value) { -#if defined(PROTOBUF_LITTLE_ENDIAN) +#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \ + defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { memcpy(value, buffer_, sizeof(*value)); Advance(sizeof(*value)); @@ -796,7 +797,8 @@ inline bool CodedInputStream::ReadLittleEndian32(uint32* value) { } inline bool CodedInputStream::ReadLittleEndian64(uint64* value) { -#if defined(PROTOBUF_LITTLE_ENDIAN) +#if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) && \ + defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN if (GOOGLE_PREDICT_TRUE(BufferSize() >= static_cast(sizeof(*value)))) { memcpy(value, buffer_, sizeof(*value)); Advance(sizeof(*value)); @@ -1093,10 +1095,10 @@ inline CodedInputStream::~CodedInputStream() { } // namespace io } // namespace protobuf -} // namespace google #if defined(_MSC_VER) && _MSC_VER >= 1300 #pragma runtime_checks("c", restore) #endif // _MSC_VER +} // namespace google #endif // GOOGLE_PROTOBUF_IO_CODED_STREAM_H__ diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc index 7d298332..ff268ab9 100644 --- a/src/google/protobuf/io/coded_stream_unittest.cc +++ b/src/google/protobuf/io/coded_stream_unittest.cc @@ -208,6 +208,33 @@ TEST_2D(CodedStreamTest, ReadTag, kVarintCases, kBlockSizes) { EXPECT_EQ(kVarintCases_case.size, input.ByteCount()); } +// This is the regression test that verifies that there is no issues +// with the empty input buffers handling. +TEST_F(CodedStreamTest, EmptyInputBeforeEos) { + class In : public ZeroCopyInputStream { + public: + In() : count_(0) {} + private: + virtual bool Next(const void** data, int* size) { + *data = NULL; + *size = 0; + return count_++ < 2; + } + virtual void BackUp(int count) { + GOOGLE_LOG(FATAL) << "Tests never call this."; + } + virtual bool Skip(int count) { + GOOGLE_LOG(FATAL) << "Tests never call this."; + return false; + } + virtual int64 ByteCount() const { return 0; } + int count_; + } in; + CodedInputStream input(&in); + input.ReadTag(); + EXPECT_TRUE(input.ConsumedEntireMessage()); +} + TEST_1D(CodedStreamTest, ExpectTag, kVarintCases) { // Leave one byte at the beginning of the buffer so we can read it // to force the first buffer to be loaded. @@ -995,6 +1022,7 @@ TEST_F(CodedStreamTest, TotalBytesLimitNotValidMessageEnd) { EXPECT_FALSE(coded_input.ConsumedEntireMessage()); } + TEST_F(CodedStreamTest, RecursionLimit) { ArrayInputStream input(buffer_, sizeof(buffer_)); CodedInputStream coded_input(&input); diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc index 84d277f4..0f1ff872 100644 --- a/src/google/protobuf/io/gzip_stream.cc +++ b/src/google/protobuf/io/gzip_stream.cc @@ -73,6 +73,17 @@ GzipInputStream::~GzipInputStream() { zerror_ = inflateEnd(&zcontext_); } +static inline int internalInflateInit2( + z_stream* zcontext, GzipInputStream::Format format) { + int windowBitsFormat = 0; + switch (format) { + case GzipInputStream::GZIP: windowBitsFormat = 16; break; + case GzipInputStream::AUTO: windowBitsFormat = 32; break; + case GzipInputStream::ZLIB: windowBitsFormat = 0; break; + } + return inflateInit2(zcontext, /* windowBits */15 | windowBitsFormat); +} + int GzipInputStream::Inflate(int flush) { if ((zerror_ == Z_OK) && (zcontext_.avail_out == 0)) { // previous inflate filled output buffer. don't change input params yet. @@ -89,14 +100,7 @@ int GzipInputStream::Inflate(int flush) { zcontext_.next_in = static_cast(const_cast(in)); zcontext_.avail_in = in_size; if (first) { - int windowBitsFormat = 0; - switch (format_) { - case GZIP: windowBitsFormat = 16; break; - case AUTO: windowBitsFormat = 32; break; - case ZLIB: windowBitsFormat = 0; break; - } - int error = inflateInit2(&zcontext_, - /* windowBits */15 | windowBitsFormat); + int error = internalInflateInit2(&zcontext_, format_); if (error != Z_OK) { return error; } @@ -127,9 +131,21 @@ bool GzipInputStream::Next(const void** data, int* size) { return true; } if (zerror_ == Z_STREAM_END) { - *data = NULL; - *size = 0; - return false; + if (zcontext_.next_out != NULL) { + // sub_stream_ may have concatenated streams to follow + zerror_ = inflateEnd(&zcontext_); + if (zerror_ != Z_OK) { + return false; + } + zerror_ = internalInflateInit2(&zcontext_, format_); + if (zerror_ != Z_OK) { + return false; + } + } else { + *data = NULL; + *size = 0; + return false; + } } zerror_ = Inflate(Z_NO_FLUSH); if ((zerror_ == Z_STREAM_END) && (zcontext_.next_out == NULL)) { @@ -251,8 +267,7 @@ int GzipOutputStream::Deflate(int flush) { } error = deflate(&zcontext_, flush); } while (error == Z_OK && zcontext_.avail_out == 0); - if (((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) - && (zcontext_.avail_out != sub_data_size_)) { + if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) { // Notify lower layer of data. sub_stream_->BackUp(zcontext_.avail_out); // We don't own the buffer anymore. diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc index c7d3074d..9ab90dee 100644 --- a/src/google/protobuf/io/printer.cc +++ b/src/google/protobuf/io/printer.cc @@ -132,6 +132,17 @@ void Printer::Print(const char* text, Print(vars, text); } +void Printer::Print(const char* text, + const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3) { + map vars; + vars[variable1] = value1; + vars[variable2] = value2; + vars[variable3] = value3; + Print(vars, text); +} + void Printer::Indent() { indent_ += " "; } diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h index de085389..5be48543 100644 --- a/src/google/protobuf/io/printer.h +++ b/src/google/protobuf/io/printer.h @@ -82,7 +82,11 @@ class LIBPROTOBUF_EXPORT Printer { // Like the first Print(), except the substitutions are given as parameters. void Print(const char* text, const char* variable1, const string& value1, const char* variable2, const string& value2); - // TODO(kenton): Overloaded versions with more variables? Two seems + // Like the first Print(), except the substitutions are given as parameters. + void Print(const char* text, const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3); + // TODO(kenton): Overloaded versions with more variables? Three seems // to be enough. // Indent text by two spaces. After calling Indent(), two spaces will be diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc index 38fa351c..513831d5 100644 --- a/src/google/protobuf/io/tokenizer.cc +++ b/src/google/protobuf/io/tokenizer.cc @@ -193,6 +193,7 @@ Tokenizer::Tokenizer(ZeroCopyInputStream* input, current_.line = 0; current_.column = 0; + current_.end_column = 0; current_.type = TYPE_START; Refresh(); @@ -277,6 +278,7 @@ inline void Tokenizer::EndToken() { current_.text.append(buffer_ + token_start_, buffer_pos_ - token_start_); } token_start_ = -1; + current_.end_column = column_; } // ------------------------------------------------------------------- @@ -462,7 +464,7 @@ void Tokenizer::ConsumeBlockComment() { // ------------------------------------------------------------------- bool Tokenizer::Next() { - TokenType last_token_type = current_.type; + previous_ = current_; // Did we skip any characters after the last token? bool skipped_stuff = false; @@ -517,7 +519,7 @@ bool Tokenizer::Next() { if (TryConsumeOne()) { // It's a floating-point number. - if (last_token_type == TYPE_IDENTIFIER && !skipped_stuff) { + if (previous_.type == TYPE_IDENTIFIER && !skipped_stuff) { // We don't accept syntax like "blah.123". error_collector_->AddError(line_, column_ - 2, "Need space between identifier and decimal point."); @@ -551,6 +553,7 @@ bool Tokenizer::Next() { current_.text.clear(); current_.line = line_; current_.column = column_; + current_.end_column = column_; return false; } diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h index d115161f..8f759abb 100644 --- a/src/google/protobuf/io/tokenizer.h +++ b/src/google/protobuf/io/tokenizer.h @@ -122,12 +122,17 @@ class LIBPROTOBUF_EXPORT Tokenizer { // the token within the input stream. They are zero-based. int line; int column; + int end_column; }; // Get the current token. This is updated when Next() is called. Before // the first call to Next(), current() has type TYPE_START and no contents. const Token& current(); + // Return the previous token -- i.e. what current() returned before the + // previous call to Next(). + const Token& previous(); + // Advance to the next token. Returns false if the end of the input is // reached. bool Next(); @@ -180,6 +185,7 @@ class LIBPROTOBUF_EXPORT Tokenizer { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer); Token current_; // Returned by current(). + Token previous_; // Returned by previous(). ZeroCopyInputStream* input_; ErrorCollector* error_collector_; @@ -291,6 +297,10 @@ inline const Tokenizer::Token& Tokenizer::current() { return current_; } +inline const Tokenizer::Token& Tokenizer::previous() { + return previous_; +} + inline void Tokenizer::ParseString(const string& text, string* output) { output->clear(); ParseStringAppend(text, output); diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc index 358ec567..106d080f 100644 --- a/src/google/protobuf/io/tokenizer_unittest.cc +++ b/src/google/protobuf/io/tokenizer_unittest.cc @@ -257,6 +257,7 @@ TEST_2D(TokenizerTest, SimpleTokens, kSimpleTokenCases, kBlockSizes) { EXPECT_EQ("", tokenizer.current().text); EXPECT_EQ(0, tokenizer.current().line); EXPECT_EQ(0, tokenizer.current().column); + EXPECT_EQ(0, tokenizer.current().end_column); // Parse the token. ASSERT_TRUE(tokenizer.Next()); @@ -268,6 +269,8 @@ TEST_2D(TokenizerTest, SimpleTokens, kSimpleTokenCases, kBlockSizes) { // Check that it is located at the beginning of the input EXPECT_EQ(0, tokenizer.current().line); EXPECT_EQ(0, tokenizer.current().column); + EXPECT_EQ(kSimpleTokenCases_case.input.size(), + tokenizer.current().end_column); // There should be no more input. EXPECT_FALSE(tokenizer.Next()); @@ -277,6 +280,8 @@ TEST_2D(TokenizerTest, SimpleTokens, kSimpleTokenCases, kBlockSizes) { EXPECT_EQ("", tokenizer.current().text); EXPECT_EQ(0, tokenizer.current().line); EXPECT_EQ(kSimpleTokenCases_case.input.size(), tokenizer.current().column); + EXPECT_EQ(kSimpleTokenCases_case.input.size(), + tokenizer.current().end_column); // There should be no errors. EXPECT_TRUE(error_collector.text_.empty()); @@ -339,76 +344,83 @@ MultiTokenCase kMultiTokenCases[] = { // Test all token types at the same time. { "foo 1 1.2 + 'bar'", { - { Tokenizer::TYPE_IDENTIFIER, "foo" , 0, 0 }, - { Tokenizer::TYPE_INTEGER , "1" , 0, 4 }, - { Tokenizer::TYPE_FLOAT , "1.2" , 0, 6 }, - { Tokenizer::TYPE_SYMBOL , "+" , 0, 10 }, - { Tokenizer::TYPE_STRING , "'bar'", 0, 12 }, - { Tokenizer::TYPE_END , "" , 0, 17 }, + { Tokenizer::TYPE_IDENTIFIER, "foo" , 0, 0, 3 }, + { Tokenizer::TYPE_INTEGER , "1" , 0, 4, 5 }, + { Tokenizer::TYPE_FLOAT , "1.2" , 0, 6, 9 }, + { Tokenizer::TYPE_SYMBOL , "+" , 0, 10, 11 }, + { Tokenizer::TYPE_STRING , "'bar'", 0, 12, 17 }, + { Tokenizer::TYPE_END , "" , 0, 17, 17 }, }}, // Test that consecutive symbols are parsed as separate tokens. { "!@+%", { - { Tokenizer::TYPE_SYMBOL , "!" , 0, 0 }, - { Tokenizer::TYPE_SYMBOL , "@" , 0, 1 }, - { Tokenizer::TYPE_SYMBOL , "+" , 0, 2 }, - { Tokenizer::TYPE_SYMBOL , "%" , 0, 3 }, - { Tokenizer::TYPE_END , "" , 0, 4 }, + { Tokenizer::TYPE_SYMBOL , "!" , 0, 0, 1 }, + { Tokenizer::TYPE_SYMBOL , "@" , 0, 1, 2 }, + { Tokenizer::TYPE_SYMBOL , "+" , 0, 2, 3 }, + { Tokenizer::TYPE_SYMBOL , "%" , 0, 3, 4 }, + { Tokenizer::TYPE_END , "" , 0, 4, 4 }, }}, // Test that newlines affect line numbers correctly. { "foo bar\nrab oof", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 4 }, - { Tokenizer::TYPE_IDENTIFIER, "rab", 1, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "oof", 1, 4 }, - { Tokenizer::TYPE_END , "" , 1, 7 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 4, 7 }, + { Tokenizer::TYPE_IDENTIFIER, "rab", 1, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "oof", 1, 4, 7 }, + { Tokenizer::TYPE_END , "" , 1, 7, 7 }, }}, // Test that tabs affect column numbers correctly. { "foo\tbar \tbaz", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 8 }, - { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16 }, - { Tokenizer::TYPE_END , "" , 0, 19 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 8, 11 }, + { Tokenizer::TYPE_IDENTIFIER, "baz", 0, 16, 19 }, + { Tokenizer::TYPE_END , "" , 0, 19, 19 }, + }}, + + // Test that tabs in string literals affect column numbers correctly. + { "\"foo\tbar\" baz", { + { Tokenizer::TYPE_STRING , "\"foo\tbar\"", 0, 0, 12 }, + { Tokenizer::TYPE_IDENTIFIER, "baz" , 0, 13, 16 }, + { Tokenizer::TYPE_END , "" , 0, 16, 16 }, }}, // Test that line comments are ignored. { "foo // This is a comment\n" "bar // This is another comment", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 0 }, - { Tokenizer::TYPE_END , "" , 1, 30 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 0, 3 }, + { Tokenizer::TYPE_END , "" , 1, 30, 30 }, }}, // Test that block comments are ignored. { "foo /* This is a block comment */ bar", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34 }, - { Tokenizer::TYPE_END , "" , 0, 37 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 34, 37 }, + { Tokenizer::TYPE_END , "" , 0, 37, 37 }, }}, // Test that sh-style comments are not ignored by default. { "foo # bar\n" "baz", { - { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0 }, - { Tokenizer::TYPE_SYMBOL , "#" , 0, 4 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 6 }, - { Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0 }, - { Tokenizer::TYPE_END , "" , 1, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_SYMBOL , "#" , 0, 4, 5 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 0, 6, 9 }, + { Tokenizer::TYPE_IDENTIFIER, "baz", 1, 0, 3 }, + { 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 }, - { Tokenizer::TYPE_END , "" , 0, 1 }, + { 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 }, - { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11 }, - { Tokenizer::TYPE_END , "" , 1, 14 }, + { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, + { Tokenizer::TYPE_IDENTIFIER, "bar", 1, 11, 14 }, + { Tokenizer::TYPE_END , "" , 1, 14, 14 }, }}, }; @@ -425,6 +437,7 @@ TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) { EXPECT_EQ("", tokenizer.current().text); EXPECT_EQ(0, tokenizer.current().line); EXPECT_EQ(0, tokenizer.current().column); + EXPECT_EQ(0, tokenizer.current().end_column); // Loop through all expected tokens. int i = 0; @@ -434,6 +447,8 @@ TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) { SCOPED_TRACE(testing::Message() << "Token #" << i << ": " << token.text); + Tokenizer::Token previous = tokenizer.current(); + // Next() should only return false when it hits the end token. if (token.type != Tokenizer::TYPE_END) { ASSERT_TRUE(tokenizer.Next()); @@ -441,11 +456,19 @@ TEST_2D(TokenizerTest, MultipleTokens, kMultiTokenCases, kBlockSizes) { ASSERT_FALSE(tokenizer.Next()); } + // Check that the previous token is set correctly. + EXPECT_EQ(previous.type, tokenizer.previous().type); + EXPECT_EQ(previous.text, tokenizer.previous().text); + EXPECT_EQ(previous.line, tokenizer.previous().line); + EXPECT_EQ(previous.column, tokenizer.previous().column); + EXPECT_EQ(previous.end_column, tokenizer.previous().end_column); + // Check that the token matches the expected one. EXPECT_EQ(token.type, tokenizer.current().type); EXPECT_EQ(token.text, tokenizer.current().text); EXPECT_EQ(token.line, tokenizer.current().line); EXPECT_EQ(token.column, tokenizer.current().column); + EXPECT_EQ(token.end_column, tokenizer.current().end_column); } while (token.type != Tokenizer::TYPE_END); diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index 8229ee6d..5196d905 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -61,6 +61,7 @@ #include #include +#include #if HAVE_ZLIB #include @@ -285,6 +286,57 @@ TEST_F(IoTest, ArrayIo) { } } +TEST_F(IoTest, TwoSessionWrite) { + // Test that two concatenated write sessions read correctly + + static const char* strA = "0123456789"; + static const char* strB = "WhirledPeas"; + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + char* temp_buffer = new char[40]; + + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + ArrayOutputStream* output = + new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]); + CodedOutputStream* coded_output = new CodedOutputStream(output); + coded_output->WriteVarint32(strlen(strA)); + coded_output->WriteRaw(strA, strlen(strA)); + delete coded_output; // flush + int64 pos = output->ByteCount(); + delete output; + output = new ArrayOutputStream( + buffer + pos, kBufferSize - pos, kBlockSizes[i]); + coded_output = new CodedOutputStream(output); + coded_output->WriteVarint32(strlen(strB)); + coded_output->WriteRaw(strB, strlen(strB)); + delete coded_output; // flush + int64 size = pos + output->ByteCount(); + delete output; + + ArrayInputStream* input = + new ArrayInputStream(buffer, size, kBlockSizes[j]); + CodedInputStream* coded_input = new CodedInputStream(input); + uint32 insize; + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strA), insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strA, insize)); + + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strB), insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strB, insize)); + + delete coded_input; + delete input; + } + } + + delete [] temp_buffer; + delete [] buffer; +} + #if HAVE_ZLIB TEST_F(IoTest, GzipIo) { const int kBufferSize = 2*1024; @@ -296,8 +348,12 @@ TEST_F(IoTest, GzipIo) { int size; { ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]); - GzipOutputStream gzout( - &output, GzipOutputStream::GZIP, gzip_buffer_size); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + GzipOutputStream gzout(&output, options); WriteStuff(&gzout); gzout.Close(); size = output.ByteCount(); @@ -324,8 +380,12 @@ TEST_F(IoTest, ZlibIo) { int size; { ArrayOutputStream output(buffer, kBufferSize, kBlockSizes[i]); - GzipOutputStream gzout( - &output, GzipOutputStream::ZLIB, gzip_buffer_size); + GzipOutputStream::Options options; + options.format = GzipOutputStream::ZLIB; + if (gzip_buffer_size != -1) { + options.buffer_size = gzip_buffer_size; + } + GzipOutputStream gzout(&output, options); WriteStuff(&gzout); gzout.Close(); size = output.ByteCount(); @@ -348,7 +408,9 @@ TEST_F(IoTest, ZlibIoInputAutodetect) { int size; { ArrayOutputStream output(buffer, kBufferSize); - GzipOutputStream gzout(&output, GzipOutputStream::ZLIB); + GzipOutputStream::Options options; + options.format = GzipOutputStream::ZLIB; + GzipOutputStream gzout(&output, options); WriteStuff(&gzout); gzout.Close(); size = output.ByteCount(); @@ -360,7 +422,9 @@ TEST_F(IoTest, ZlibIoInputAutodetect) { } { ArrayOutputStream output(buffer, kBufferSize); - GzipOutputStream gzout(&output, GzipOutputStream::GZIP); + GzipOutputStream::Options options; + options.format = GzipOutputStream::GZIP; + GzipOutputStream gzout(&output, options); WriteStuff(&gzout); gzout.Close(); size = output.ByteCount(); @@ -432,6 +496,71 @@ TEST_F(IoTest, CompressionOptions) { EXPECT_TRUE(Uncompress(gzip_compressed) == golden); EXPECT_TRUE(Uncompress(zlib_compressed) == golden); } + +TEST_F(IoTest, TwoSessionWriteGzip) { + // Test that two concatenated gzip streams can be read correctly + + static const char* strA = "0123456789"; + static const char* strB = "QuickBrownFox"; + const int kBufferSize = 2*1024; + uint8* buffer = new uint8[kBufferSize]; + char* temp_buffer = new char[40]; + + for (int i = 0; i < kBlockSizeCount; i++) { + for (int j = 0; j < kBlockSizeCount; j++) { + ArrayOutputStream* output = + new ArrayOutputStream(buffer, kBufferSize, kBlockSizes[i]); + GzipOutputStream* gzout = new GzipOutputStream(output); + CodedOutputStream* coded_output = new CodedOutputStream(gzout); + int32 outlen = strlen(strA) + 1; + coded_output->WriteVarint32(outlen); + coded_output->WriteRaw(strA, outlen); + delete coded_output; // flush + delete gzout; // flush + int64 pos = output->ByteCount(); + delete output; + output = new ArrayOutputStream( + buffer + pos, kBufferSize - pos, kBlockSizes[i]); + gzout = new GzipOutputStream(output); + coded_output = new CodedOutputStream(gzout); + outlen = strlen(strB) + 1; + coded_output->WriteVarint32(outlen); + coded_output->WriteRaw(strB, outlen); + delete coded_output; // flush + delete gzout; // flush + int64 size = pos + output->ByteCount(); + delete output; + + ArrayInputStream* input = + new ArrayInputStream(buffer, size, kBlockSizes[j]); + GzipInputStream* gzin = new GzipInputStream(input); + CodedInputStream* coded_input = new CodedInputStream(gzin); + uint32 insize; + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strA) + 1, insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strA, insize)) + << "strA=" << strA << " in=" << temp_buffer; + + EXPECT_TRUE(coded_input->ReadVarint32(&insize)); + EXPECT_EQ(strlen(strB) + 1, insize); + EXPECT_TRUE(coded_input->ReadRaw(temp_buffer, insize)); + EXPECT_EQ(0, memcmp(temp_buffer, strB, insize)) + << " out_block_size=" << kBlockSizes[i] + << " in_block_size=" << kBlockSizes[j] + << " pos=" << pos + << " size=" << size + << " strB=" << strB << " in=" << temp_buffer; + + delete coded_input; + delete gzin; + delete input; + } + } + + delete [] temp_buffer; + delete [] buffer; +} #endif // There is no string input, only string output. Also, it doesn't support diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index d117fe25..4bbc6418 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -123,6 +123,7 @@ #include + namespace google { namespace protobuf { diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc index f7beb110..09377742 100644 --- a/src/google/protobuf/repeated_field.cc +++ b/src/google/protobuf/repeated_field.cc @@ -32,11 +32,14 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include #include namespace google { namespace protobuf { + namespace internal { void RepeatedPtrFieldBase::Reserve(int new_size) { @@ -88,8 +91,8 @@ void StringTypeHandlerBase::Delete(string* value) { delete value; } +} // namespace internal -} // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index cc07fdb8..ae96107a 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -72,8 +72,11 @@ template class RepeatedField { public: RepeatedField(); + RepeatedField(const RepeatedField& other); ~RepeatedField(); + RepeatedField& operator=(const RepeatedField& other); + int size() const; const Element& Get(int index) const; @@ -90,6 +93,7 @@ class RepeatedField { void RemoveLast(); void Clear(); void MergeFrom(const RepeatedField& other); + void CopyFrom(const RepeatedField& other); // Reserve space to expand the field to at least the given size. If the // array is grown, it will always be at least doubled in size. @@ -116,6 +120,7 @@ class RepeatedField { // STL-like iterator support typedef Element* iterator; typedef const Element* const_iterator; + typedef Element value_type; iterator begin(); const_iterator begin() const; @@ -127,8 +132,6 @@ class RepeatedField { int SpaceUsedExcludingSelf() const; private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedField); - static const int kInitialSize = 4; Element* elements_; @@ -203,6 +206,8 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { void Clear(); template void MergeFrom(const RepeatedPtrFieldBase& other); + template + void CopyFrom(const RepeatedPtrFieldBase& other); void Reserve(int new_size); @@ -300,7 +305,7 @@ class LIBPROTOBUF_EXPORT StringTypeHandlerBase { static void Merge(const string& from, string* to) { *to = from; } }; -class StringTypeHandler : public StringTypeHandlerBase { +class LIBPROTOBUF_EXPORT StringTypeHandler : public StringTypeHandlerBase { public: static int SpaceUsed(const string& value) { return sizeof(value) + StringSpaceUsedExcludingSelf(value); @@ -316,9 +321,11 @@ template class RepeatedPtrField : public internal::RepeatedPtrFieldBase { public: RepeatedPtrField(); - + RepeatedPtrField(const RepeatedPtrField& other); ~RepeatedPtrField(); + RepeatedPtrField& operator=(const RepeatedPtrField& other); + int size() const; const Element& Get(int index) const; @@ -327,6 +334,7 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase { void RemoveLast(); // Remove the last element in the array. void Clear(); void MergeFrom(const RepeatedPtrField& other); + void CopyFrom(const RepeatedPtrField& other); // Reserve space to expand the field to at least the given size. This only // resizes the pointer array; it doesn't allocate any objects. If the @@ -349,6 +357,7 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase { // STL-like iterator support typedef internal::RepeatedPtrIterator iterator; typedef internal::RepeatedPtrIterator const_iterator; + typedef Element value_type; iterator begin(); const_iterator begin() const; @@ -365,11 +374,6 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase { // excluding sizeof(*this). int SpaceUsedExcludingSelf() const; - // The spaced used just by the pointer array, not counting the objects pointed - // at. Returns zero if the array is inlined (i.e. initial_space_ is being - // used). - int SpaceUsedByArray() const; - // Advanced memory management -------------------------------------- // When hardcore memory management becomes necessary -- as it often // does here at Google -- the following methods may be useful. @@ -410,9 +414,6 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase { // methods on RepeatedPtrFieldBase. class TypeHandler; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrField); }; // implementation ==================================================== @@ -424,6 +425,14 @@ inline RepeatedField::RepeatedField() total_size_(kInitialSize) { } +template +inline RepeatedField::RepeatedField(const RepeatedField& other) + : elements_(initial_space_), + current_size_(0), + total_size_(kInitialSize) { + CopyFrom(other); +} + template RepeatedField::~RepeatedField() { if (elements_ != initial_space_) { @@ -431,6 +440,13 @@ RepeatedField::~RepeatedField() { } } +template +inline RepeatedField& +RepeatedField::operator=(const RepeatedField& other) { + CopyFrom(other); + return *this; +} + template inline int RepeatedField::size() const { return current_size_; @@ -501,6 +517,12 @@ inline void RepeatedField::MergeFrom(const RepeatedField& other) { current_size_ += other.current_size_; } +template +inline void RepeatedField::CopyFrom(const RepeatedField& other) { + Clear(); + MergeFrom(other); +} + template inline Element* RepeatedField::mutable_data() { return elements_; @@ -679,6 +701,12 @@ inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { } } +template +inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) { + RepeatedPtrFieldBase::Clear(); + RepeatedPtrFieldBase::MergeFrom(other); +} + inline int RepeatedPtrFieldBase::Capacity() const { return total_size_; } @@ -804,11 +832,24 @@ class RepeatedPtrField::TypeHandler template inline RepeatedPtrField::RepeatedPtrField() {} +template +inline RepeatedPtrField::RepeatedPtrField( + const RepeatedPtrField& other) { + CopyFrom(other); +} + template RepeatedPtrField::~RepeatedPtrField() { Destroy(); } +template +inline RepeatedPtrField& RepeatedPtrField::operator=( + const RepeatedPtrField& other) { + CopyFrom(other); + return *this; +} + template inline int RepeatedPtrField::size() const { return RepeatedPtrFieldBase::size(); @@ -845,6 +886,12 @@ inline void RepeatedPtrField::MergeFrom( RepeatedPtrFieldBase::MergeFrom(other); } +template +inline void RepeatedPtrField::CopyFrom( + const RepeatedPtrField& other) { + RepeatedPtrFieldBase::CopyFrom(other); +} + template inline Element** RepeatedPtrField::mutable_data() { return RepeatedPtrFieldBase::mutable_data(); @@ -944,7 +991,7 @@ class RepeatedPtrIterator template RepeatedPtrIterator(const RepeatedPtrIterator& other) : it_(other.it_) { - // Force a compiler error if the other type is not convertable to ours. + // Force a compiler error if the other type is not convertible to ours. if (false) { implicit_cast(0); } diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 7c35f604..e7e1e99b 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -232,6 +232,54 @@ TEST(RepeatedField, MergeFrom) { EXPECT_EQ(5, destination.Get(4)); } +TEST(RepeatedField, CopyFrom) { + RepeatedField source, destination; + + source.Add(4); + source.Add(5); + + destination.Add(1); + destination.Add(2); + destination.Add(3); + + destination.CopyFrom(source); + + ASSERT_EQ(2, destination.size()); + + EXPECT_EQ(4, destination.Get(0)); + EXPECT_EQ(5, destination.Get(1)); +} + +TEST(RepeatedField, CopyConstruct) { + RepeatedField source; + source.Add(1); + source.Add(2); + + RepeatedField destination(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ(1, destination.Get(0)); + EXPECT_EQ(2, destination.Get(1)); +} + +TEST(RepeatedField, CopyAssign) { + RepeatedField source, destination; + + source.Add(4); + source.Add(5); + + destination.Add(1); + destination.Add(2); + destination.Add(3); + + destination = source; + + ASSERT_EQ(2, destination.size()); + + EXPECT_EQ(4, destination.Get(0)); + EXPECT_EQ(5, destination.Get(1)); +} + TEST(RepeatedField, MutableDataIsMutable) { RepeatedField field; field.Add(1); @@ -536,6 +584,55 @@ TEST(RepeatedPtrField, MergeFrom) { EXPECT_EQ("5", destination.Get(4)); } +TEST(RepeatedPtrField, CopyFrom) { + RepeatedPtrField source, destination; + + source.Add()->assign("4"); + source.Add()->assign("5"); + + destination.Add()->assign("1"); + destination.Add()->assign("2"); + destination.Add()->assign("3"); + + destination.CopyFrom(source); + + ASSERT_EQ(2, destination.size()); + + EXPECT_EQ("4", destination.Get(0)); + EXPECT_EQ("5", destination.Get(1)); +} + +TEST(RepeatedPtrField, CopyConstruct) { + RepeatedPtrField source; + + source.Add()->assign("1"); + source.Add()->assign("2"); + + RepeatedPtrField destination(source); + + ASSERT_EQ(2, destination.size()); + EXPECT_EQ("1", destination.Get(0)); + EXPECT_EQ("2", destination.Get(1)); +} + +TEST(RepeatedPtrField, CopyAssign) { + RepeatedPtrField source, destination; + + source.Add()->assign("4"); + source.Add()->assign("5"); + + destination.Add()->assign("1"); + destination.Add()->assign("2"); + destination.Add()->assign("3"); + + destination = source; + + ASSERT_EQ(2, destination.size()); + + EXPECT_EQ("4", destination.Get(0)); + EXPECT_EQ("5", destination.Get(1)); +} + TEST(RepeatedPtrField, MutableDataIsMutable) { RepeatedPtrField field; *field.Add() = "1"; @@ -564,7 +661,8 @@ class RepeatedFieldIteratorTest : public testing::Test { TEST_F(RepeatedFieldIteratorTest, Convertible) { RepeatedField::iterator iter = proto_array_.begin(); RepeatedField::const_iterator c_iter = iter; - EXPECT_EQ(0, *c_iter); + RepeatedField::value_type value = *c_iter; + EXPECT_EQ(0, value); } TEST_F(RepeatedFieldIteratorTest, MutableIteration) { @@ -613,6 +711,8 @@ class RepeatedPtrFieldIteratorTest : public testing::Test { TEST_F(RepeatedPtrFieldIteratorTest, Convertible) { RepeatedPtrField::iterator iter = proto_array_.begin(); RepeatedPtrField::const_iterator c_iter = iter; + RepeatedPtrField::value_type value = *c_iter; + EXPECT_EQ("foo", value); } TEST_F(RepeatedPtrFieldIteratorTest, MutableIteration) { diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 137cbcee..1494ebd7 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -118,8 +119,10 @@ class TextFormat::Parser::ParserImpl { ParserImpl(const Descriptor* root_message_type, io::ZeroCopyInputStream* input_stream, io::ErrorCollector* error_collector, + TextFormat::Finder* finder, SingularOverwritePolicy singular_overwrite_policy) : error_collector_(error_collector), + finder_(finder), tokenizer_error_collector_(this), tokenizer_(input_stream, &tokenizer_error_collector_), root_message_type_(root_message_type), @@ -249,7 +252,9 @@ class TextFormat::Parser::ParserImpl { } DO(Consume("]")); - field = reflection->FindKnownExtensionByName(field_name); + field = (finder_ != NULL + ? finder_->FindExtension(message, field_name) + : reflection->FindKnownExtensionByName(field_name)); if (field == NULL) { ReportError("Extension \"" + field_name + "\" is not defined or " @@ -301,9 +306,24 @@ class TextFormat::Parser::ParserImpl { DO(ConsumeFieldMessage(message, reflection, field)); } else { DO(Consume(":")); - DO(ConsumeFieldValue(message, reflection, field)); + if (field->is_repeated() && TryConsume("[")) { + // Short repeated format, e.g. "foo: [1, 2, 3]" + while (true) { + DO(ConsumeFieldValue(message, reflection, field)); + if (TryConsume("]")) { + break; + } + DO(Consume(",")); + } + } else { + DO(ConsumeFieldValue(message, reflection, field)); + } } + // For historical reasons, fields may optionally be separated by commas or + // semicolons. + TryConsume(";") || TryConsume(","); + if (field->options().deprecated()) { ReportWarning("text format contains deprecated field \"" + field_name + "\""); @@ -397,29 +417,46 @@ class TextFormat::Parser::ParserImpl { } case FieldDescriptor::CPPTYPE_BOOL: { - string value; - DO(ConsumeIdentifier(&value)); - - if (value == "true") { - SET_FIELD(Bool, true); - } else if (value == "false") { - SET_FIELD(Bool, false); + if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + uint64 value; + DO(ConsumeUnsignedInteger(&value, 1)); + SET_FIELD(Bool, value); } else { - ReportError("Invalid value for boolean field \"" + field->name() - + "\". Value: \"" + value + "\"."); - return false; + string value; + DO(ConsumeIdentifier(&value)); + if (value == "true" || value == "t") { + SET_FIELD(Bool, true); + } else if (value == "false" || value == "f") { + SET_FIELD(Bool, false); + } else { + ReportError("Invalid value for boolean field \"" + field->name() + + "\". Value: \"" + value + "\"."); + return false; + } } break; } case FieldDescriptor::CPPTYPE_ENUM: { string value; - DO(ConsumeIdentifier(&value)); - - // Find the enumeration value. const EnumDescriptor* enum_type = field->enum_type(); - const EnumValueDescriptor* enum_value - = enum_type->FindValueByName(value); + const EnumValueDescriptor* enum_value = NULL; + + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + DO(ConsumeIdentifier(&value)); + // Find the enumeration value. + enum_value = enum_type->FindValueByName(value); + + } else if (LookingAt("-") || + LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + int64 int_value; + DO(ConsumeSignedInteger(&int_value, kint32max)); + value = SimpleItoa(int_value); // for error reporting + enum_value = enum_type->FindValueByNumber(int_value); + } else { + ReportError("Expected integer or identifier."); + return false; + } if (enum_value == NULL) { ReportError("Unknown enumeration value of \"" + value + "\" for " @@ -632,6 +669,7 @@ class TextFormat::Parser::ParserImpl { }; io::ErrorCollector* error_collector_; + TextFormat::Finder* finder_; ParserErrorCollector tokenizer_error_collector_; io::Tokenizer tokenizer_; const Descriptor* root_message_type_; @@ -765,9 +803,14 @@ class TextFormat::Printer::TextGenerator { // =========================================================================== +TextFormat::Finder::~Finder() { +} + TextFormat::Parser::Parser() : error_collector_(NULL), - allow_partial_(false) {} + finder_(NULL), + allow_partial_(false) { +} TextFormat::Parser::~Parser() {} @@ -775,7 +818,7 @@ bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, Message* output) { output->Clear(); ParserImpl parser(output->GetDescriptor(), input, error_collector_, - ParserImpl::FORBID_SINGULAR_OVERWRITES); + finder_, ParserImpl::FORBID_SINGULAR_OVERWRITES); return MergeUsingImpl(input, output, &parser); } @@ -788,7 +831,7 @@ bool TextFormat::Parser::ParseFromString(const string& input, bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, Message* output) { ParserImpl parser(output->GetDescriptor(), input, error_collector_, - ParserImpl::ALLOW_SINGULAR_OVERWRITES); + finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES); return MergeUsingImpl(input, output, &parser); } @@ -818,7 +861,7 @@ bool TextFormat::Parser::ParseFieldValueFromString( Message* output) { io::ArrayInputStream input_stream(input.data(), input.size()); ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_, - ParserImpl::ALLOW_SINGULAR_OVERWRITES); + finder_, ParserImpl::ALLOW_SINGULAR_OVERWRITES); return parser.ParseField(field, output); } @@ -853,7 +896,7 @@ TextFormat::Printer::Printer() TextFormat::Printer::~Printer() {} bool TextFormat::Printer::PrintToString(const Message& message, - string* output) { + string* output) const { GOOGLE_DCHECK(output) << "output specified is NULL"; output->clear(); @@ -866,7 +909,7 @@ bool TextFormat::Printer::PrintToString(const Message& message, bool TextFormat::Printer::PrintUnknownFieldsToString( const UnknownFieldSet& unknown_fields, - string* output) { + string* output) const { GOOGLE_DCHECK(output) << "output specified is NULL"; output->clear(); @@ -875,7 +918,7 @@ bool TextFormat::Printer::PrintUnknownFieldsToString( } bool TextFormat::Printer::Print(const Message& message, - io::ZeroCopyOutputStream* output) { + io::ZeroCopyOutputStream* output) const { TextGenerator generator(output, initial_indent_level_); Print(message, generator); @@ -886,7 +929,7 @@ bool TextFormat::Printer::Print(const Message& message, bool TextFormat::Printer::PrintUnknownFields( const UnknownFieldSet& unknown_fields, - io::ZeroCopyOutputStream* output) { + io::ZeroCopyOutputStream* output) const { TextGenerator generator(output, initial_indent_level_); PrintUnknownFields(unknown_fields, generator); @@ -896,7 +939,7 @@ bool TextFormat::Printer::PrintUnknownFields( } void TextFormat::Printer::Print(const Message& message, - TextGenerator& generator) { + TextGenerator& generator) const { const Reflection* reflection = message.GetReflection(); vector fields; reflection->ListFields(message, &fields); @@ -910,7 +953,7 @@ void TextFormat::Printer::PrintFieldValueToString( const Message& message, const FieldDescriptor* field, int index, - string* output) { + string* output) const { GOOGLE_DCHECK(output) << "output specified is NULL"; @@ -924,7 +967,7 @@ void TextFormat::Printer::PrintFieldValueToString( void TextFormat::Printer::PrintField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator) { + TextGenerator& generator) const { if (use_short_repeated_primitives_ && field->is_repeated() && field->cpp_type() != FieldDescriptor::CPPTYPE_STRING && @@ -980,10 +1023,11 @@ void TextFormat::Printer::PrintField(const Message& message, } } -void TextFormat::Printer::PrintShortRepeatedField(const Message& message, - const Reflection* reflection, - const FieldDescriptor* field, - TextGenerator& generator) { +void TextFormat::Printer::PrintShortRepeatedField( + const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + TextGenerator& generator) const { // Print primitive repeated field in short form. PrintFieldName(message, reflection, field, generator); @@ -1003,7 +1047,7 @@ void TextFormat::Printer::PrintShortRepeatedField(const Message& message, void TextFormat::Printer::PrintFieldName(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator) { + TextGenerator& generator) const { if (field->is_extension()) { generator.Print("["); // We special-case MessageSet elements for compatibility with proto1. @@ -1031,7 +1075,7 @@ void TextFormat::Printer::PrintFieldValue( const Reflection* reflection, const FieldDescriptor* field, int index, - TextGenerator& generator) { + TextGenerator& generator) const { GOOGLE_DCHECK(field->is_repeated() || (index == -1)) << "Index must be -1 for non-repeated fields"; @@ -1143,7 +1187,7 @@ static string PaddedHex(IntType value) { } void TextFormat::Printer::PrintUnknownFields( - const UnknownFieldSet& unknown_fields, TextGenerator& generator) { + const UnknownFieldSet& unknown_fields, TextGenerator& generator) const { for (int i = 0; i < unknown_fields.field_count(); i++) { const UnknownField& field = unknown_fields.field(i); string field_number = SimpleItoa(field.number()); diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index e78e1042..03c04910 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -90,20 +90,20 @@ class LIBPROTOBUF_EXPORT TextFormat { ~Printer(); // Like TextFormat::Print - bool Print(const Message& message, io::ZeroCopyOutputStream* output); + bool Print(const Message& message, io::ZeroCopyOutputStream* output) const; // Like TextFormat::PrintUnknownFields bool PrintUnknownFields(const UnknownFieldSet& unknown_fields, - io::ZeroCopyOutputStream* output); + io::ZeroCopyOutputStream* output) const; // Like TextFormat::PrintToString - bool PrintToString(const Message& message, string* output); + bool PrintToString(const Message& message, string* output) const; // Like TextFormat::PrintUnknownFieldsToString bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields, - string* output); + string* output) const; // Like TextFormat::PrintFieldValueToString void PrintFieldValueToString(const Message& message, const FieldDescriptor* field, int index, - string* output); + string* output) const; // Adjust the initial indent level of all output. Each indent level is // equal to two spaces. @@ -121,8 +121,7 @@ class LIBPROTOBUF_EXPORT TextFormat { // field_name: [1, 2, 3, 4] // instead of printing each value on its own line. Short format applies // only to primitive values -- i.e. everything except strings and - // sub-messages/groups. Note that at present this format is not recognized - // by the parser. + // sub-messages/groups. void SetUseShortRepeatedPrimitives(bool use_short_repeated_primitives) { use_short_repeated_primitives_ = use_short_repeated_primitives; } @@ -143,26 +142,26 @@ class LIBPROTOBUF_EXPORT TextFormat { // Internal Print method, used for writing to the OutputStream via // the TextGenerator class. void Print(const Message& message, - TextGenerator& generator); + TextGenerator& generator) const; // Print a single field. void PrintField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator); + TextGenerator& generator) const; // Print a repeated primitive field in short form. void PrintShortRepeatedField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator); + TextGenerator& generator) const; // Print the name of a field -- i.e. everything that comes before the // ':' for a single name/value pair. void PrintFieldName(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator); + TextGenerator& generator) const; // Outputs a textual representation of the value of the field supplied on // the message supplied or the default value if not set. @@ -170,13 +169,13 @@ class LIBPROTOBUF_EXPORT TextFormat { const Reflection* reflection, const FieldDescriptor* field, int index, - TextGenerator& generator); + TextGenerator& generator) const; // Print the fields in an UnknownFieldSet. They are printed by tag number // only. Embedded messages are heuristically identified by attempting to // parse them. void PrintUnknownFields(const UnknownFieldSet& unknown_fields, - TextGenerator& generator); + TextGenerator& generator) const; int initial_indent_level_; @@ -207,6 +206,20 @@ class LIBPROTOBUF_EXPORT TextFormat { const FieldDescriptor* field, Message* message); + // Interface that TextFormat::Parser can use to find extensions. + // This class may be extended in the future to find more information + // like fields, etc. + class LIBPROTOBUF_EXPORT Finder { + public: + virtual ~Finder(); + + // Try to find an extension of *message by fully-qualified field + // name. Returns NULL if no extension is known for this name or number. + virtual const FieldDescriptor* FindExtension( + Message* message, + const string& name) const = 0; + }; + // For more control over parsing, use this class. class LIBPROTOBUF_EXPORT Parser { public: @@ -228,6 +241,13 @@ class LIBPROTOBUF_EXPORT TextFormat { error_collector_ = error_collector; } + // Set how parser finds extensions. If NULL (the default), the + // parser will use the standard Reflection object associated with + // the message being parsed. + void SetFinder(Finder* finder) { + finder_ = finder; + } + // Normally parsing fails if, after parsing, output->IsInitialized() // returns false. Call AllowPartialMessage(true) to skip this check. void AllowPartialMessage(bool allow) { @@ -251,6 +271,7 @@ class LIBPROTOBUF_EXPORT TextFormat { ParserImpl* parser_impl); io::ErrorCollector* error_collector_; + Finder* finder_; bool allow_partial_; }; diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index ddf8ff7f..00ea8c3c 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -353,6 +353,25 @@ TEST_F(TextFormatExtensionsTest, ParseExtensions) { TestUtil::ExpectAllExtensionsSet(proto_); } +TEST_F(TextFormatTest, ParseEnumFieldFromNumber) { + // Create a parse string with a numerical value for an enum field. + string parse_string = strings::Substitute("optional_nested_enum: $0", + unittest::TestAllTypes::BAZ); + EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto_)); + EXPECT_TRUE(proto_.has_optional_nested_enum()); + EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.optional_nested_enum()); +} + +TEST_F(TextFormatTest, ParseEnumFieldFromNegativeNumber) { + ASSERT_LT(unittest::SPARSE_E, 0); + string parse_string = strings::Substitute("sparse_enum: $0", + unittest::SPARSE_E); + unittest::SparseEnumMessage proto; + EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto)); + EXPECT_TRUE(proto.has_sparse_enum()); + EXPECT_EQ(unittest::SPARSE_E, proto.sparse_enum()); +} + TEST_F(TextFormatTest, ParseStringEscape) { // Create a parse string with escpaed characters in it. string parse_string = "optional_string: " @@ -406,6 +425,34 @@ TEST_F(TextFormatTest, ParseFloatWithSuffix) { EXPECT_EQ(1.0, proto_.optional_float()); } +TEST_F(TextFormatTest, ParseShortRepeatedForm) { + string parse_string = + // Mixed short-form and long-form are simply concatenated. + "repeated_int32: 1\n" + "repeated_int32: [456, 789]\n" + "repeated_nested_enum: [ FOO ,BAR, # comment\n" + " 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"; + + ASSERT_TRUE(TextFormat::ParseFromString(parse_string, &proto_)); + + ASSERT_EQ(3, proto_.repeated_int32_size()); + EXPECT_EQ(1, proto_.repeated_int32(0)); + EXPECT_EQ(456, proto_.repeated_int32(1)); + EXPECT_EQ(789, proto_.repeated_int32(2)); + + ASSERT_EQ(3, proto_.repeated_nested_enum_size()); + EXPECT_EQ(unittest::TestAllTypes::FOO, proto_.repeated_nested_enum(0)); + EXPECT_EQ(unittest::TestAllTypes::BAR, proto_.repeated_nested_enum(1)); + EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.repeated_nested_enum(2)); + + ASSERT_EQ(2, proto_.repeated_string_size()); + EXPECT_EQ("foo", proto_.repeated_string(0)); + EXPECT_EQ("bar", proto_.repeated_string(1)); +} + TEST_F(TextFormatTest, Comments) { // Test that comments are ignored. @@ -771,7 +818,12 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { // bool EXPECT_FIELD(bool, true, "true"); EXPECT_FIELD(bool, false, "false"); - EXPECT_INVALID(bool, "1"); + EXPECT_FIELD(bool, true, "1"); + EXPECT_FIELD(bool, true, "t"); + EXPECT_FIELD(bool, false, "0"); + EXPECT_FIELD(bool, false, "f"); + EXPECT_INVALID(bool, "2"); + EXPECT_INVALID(bool, "-0"); EXPECT_INVALID(bool, "on"); EXPECT_INVALID(bool, "a"); EXPECT_INVALID(bool, "True"); @@ -799,7 +851,8 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { // enum EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR"); - EXPECT_INVALID(nested_enum, "1"); // number not supported + EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAZ, + SimpleItoa(unittest::TestAllTypes::BAZ)); EXPECT_INVALID(nested_enum, "FOOBAR"); // message @@ -820,7 +873,7 @@ TEST_F(TextFormatParserTest, InvalidToken) { ExpectFailure("optional_bool: true\n-5\n", "Expected identifier.", 2, 1); - ExpectFailure("optional_bool: true;\n", "Expected identifier.", 1, 20); + ExpectFailure("optional_bool: true!\n", "Expected identifier.", 1, 20); ExpectFailure("\"some string\"", "Expected identifier.", 1, 1); } @@ -890,7 +943,7 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { // Invalid values for a boolean field. ExpectFailure("optional_bool: \"hello\"\n", "Expected identifier.", 1, 16); - ExpectFailure("optional_bool: 5\n", "Expected identifier.", 1, 16); + ExpectFailure("optional_bool: 5\n", "Integer out of range.", 1, 16); ExpectFailure("optional_bool: -7.5\n", "Expected identifier.", 1, 16); ExpectFailure("optional_bool: !\n", "Expected identifier.", 1, 16); @@ -911,12 +964,18 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { 1, 17); // Invalid values for an enumeration field. - ExpectFailure("optional_nested_enum: \"hello\"\n", "Expected identifier.", - 1, 23); - - ExpectFailure("optional_nested_enum: 5\n", "Expected identifier.", 1, 23); - ExpectFailure("optional_nested_enum: -7.5\n", "Expected identifier.", 1, 23); - ExpectFailure("optional_nested_enum: !\n", "Expected identifier.", 1, 23); + ExpectFailure("optional_nested_enum: \"hello\"\n", + "Expected integer or identifier.", 1, 23); + + // Valid token, but enum value is not defined. + ExpectFailure("optional_nested_enum: 5\n", + "Unknown enumeration value of \"5\" for field " + "\"optional_nested_enum\".", 2, 1); + // We consume the negative sign, so the error position starts one character + // later. + ExpectFailure("optional_nested_enum: -7.5\n", "Expected integer.", 1, 24); + ExpectFailure("optional_nested_enum: !\n", + "Expected integer or identifier.", 1, 23); ExpectFailure( "optional_nested_enum: grah\n", @@ -986,6 +1045,14 @@ TEST_F(TextFormatParserTest, MergeDuplicateOptional) { EXPECT_EQ(2, message.c()); } +TEST_F(TextFormatParserTest, ExplicitDelimiters) { + unittest::TestRequired message; + EXPECT_TRUE(TextFormat::ParseFromString("a:1,b:2;c:3", &message)); + EXPECT_EQ(1, message.a()); + EXPECT_EQ(2, message.b()); + EXPECT_EQ(3, message.c()); +} + TEST_F(TextFormatParserTest, PrintErrorsToStderr) { vector errors; diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto index d51fa1e7..de4425be 100644 --- a/src/google/protobuf/unittest.proto +++ b/src/google/protobuf/unittest.proto @@ -35,6 +35,12 @@ // A proto file we will use for unit testing. +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; // auto-added + import "google/protobuf/unittest_import.proto"; // We don't put this in a package within proto2 because we need to make sure @@ -489,6 +495,10 @@ message TestExtremeDefaultValues { optional float nan_float = 19 [default = nan]; } +message SparseEnumMessage { + optional TestSparseEnum sparse_enum = 1; +} + // Test String and Bytes: string is for valid UTF-8 strings message OneString { optional string data = 1; @@ -598,6 +608,7 @@ message TestRepeatedScalarDifferentTagSizes { repeated uint64 repeated_uint64 = 262143; } + // Test that RPC services work. message FooRequest {} message FooResponse {} diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto index b6ee03da..a610785f 100644 --- a/src/google/protobuf/unittest_custom_options.proto +++ b/src/google/protobuf/unittest_custom_options.proto @@ -35,6 +35,12 @@ // A proto file used to test the "custom options" feature of proto2. +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; + // A custom file option (defined below). option (file_opt1) = 9876543210; @@ -273,3 +279,88 @@ message VariousComplexOptions { option (complex_opt3).complexoptiontype5.plugh = 22; option (complexopt6).xyzzy = 24; } + +// ------------------------------------------------------ +// Definitions for testing aggregate option parsing. +// See descriptor_unittest.cc. + +message AggregateMessageSet { + option message_set_wire_format = true; + extensions 4 to max; +} + +message AggregateMessageSetElement { + extend AggregateMessageSet { + optional AggregateMessageSetElement message_set_extension = 15447542; + } + optional string s = 1; +} + +// A helper type used to test aggregate option parsing +message Aggregate { + optional int32 i = 1; + optional string s = 2; + + // A nested object + optional Aggregate sub = 3; + + // To test the parsing of extensions inside aggregate values + optional google.protobuf.FileOptions file = 4; + extend google.protobuf.FileOptions { + optional Aggregate nested = 15476903; + } + + // An embedded message set + optional AggregateMessageSet mset = 5; +} + +// Allow Aggregate to be used as an option at all possible locations +// in the .proto grammer. +extend google.protobuf.FileOptions { optional Aggregate fileopt = 15478479; } +extend google.protobuf.MessageOptions { optional Aggregate msgopt = 15480088; } +extend google.protobuf.FieldOptions { optional Aggregate fieldopt = 15481374; } +extend google.protobuf.EnumOptions { optional Aggregate enumopt = 15483218; } +extend google.protobuf.EnumValueOptions { optional Aggregate enumvalopt = 15486921; } +extend google.protobuf.ServiceOptions { optional Aggregate serviceopt = 15497145; } +extend google.protobuf.MethodOptions { optional Aggregate methodopt = 15512713; } + +// Try using AggregateOption at different points in the proto grammar +option (fileopt) = { + s: 'FileAnnotation' + // Also test the handling of comments + /* of both types */ i: 100 + + sub { s: 'NestedFileAnnotation' } + + // Include a google.protobuf.FileOptions and recursively extend it with + // another fileopt. + file { + [protobuf_unittest.fileopt] { + s:'FileExtensionAnnotation' + } + } + + // A message set inside an option value + mset { + [protobuf_unittest.AggregateMessageSetElement.message_set_extension] { + s: 'EmbeddedMessageSetElement' + } + } +}; + +message AggregateMessage { + option (msgopt) = { i:101 s:'MessageAnnotation' }; + optional int32 fieldname = 1 [(fieldopt) = { s:'FieldAnnotation' }]; +} + +service AggregateService { + option (serviceopt) = { s:'ServiceAnnotation' }; + rpc Method (AggregateMessage) returns (AggregateMessage) { + option (methodopt) = { s:'MethodAnnotation' }; + } +} + +enum AggregateEnum { + option (enumopt) = { s:'EnumAnnotation' }; + VALUE = 1 [(enumvalopt) = { s:'EnumValueAnnotation' }]; +} diff --git a/src/google/protobuf/unittest_no_generic_services.proto b/src/google/protobuf/unittest_no_generic_services.proto index fcae4214..cffb4122 100644 --- a/src/google/protobuf/unittest_no_generic_services.proto +++ b/src/google/protobuf/unittest_no_generic_services.proto @@ -32,9 +32,7 @@ package google.protobuf.no_generic_services_test; -option cc_generic_services = false; -option java_generic_services = false; -option py_generic_services = false; +// *_generic_services are false by default. message TestMessage { optional int32 a = 1; diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h index d7b2c302..a461a6ca 100644 --- a/src/google/protobuf/wire_format_lite_inl.h +++ b/src/google/protobuf/wire_format_lite_inl.h @@ -368,12 +368,24 @@ inline bool WireFormatLite::ReadMessage(io::CodedInputStream* input, return true; } -template -inline bool WireFormatLite::ReadGroupNoVirtual(int field_number, - io::CodedInputStream* input, - MessageType* value) { +// We name the template parameter something long and extremely unlikely to occur +// elsewhere because a *qualified* member access expression designed to avoid +// virtual dispatch, C++03 [basic.lookup.classref] 3.4.5/4 requires that the +// name of the qualifying class to be looked up both in the context of the full +// expression (finding the template parameter) and in the context of the object +// whose member we are accessing. This could potentially find a nested type +// within that object. The standard goes on to require these names to refer to +// the same entity, which this collision would violate. The lack of a safe way +// to avoid this collision appears to be a defect in the standard, but until it +// is corrected, we choose the name to avoid accidental collisions. +template +inline bool WireFormatLite::ReadGroupNoVirtual( + int field_number, io::CodedInputStream* input, + MessageType_WorkAroundCppLookupDefect* value) { if (!input->IncrementRecursionDepth()) return false; - if (!value->MessageType::MergePartialFromCodedStream(input)) return false; + if (!value-> + MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) + return false; input->DecrementRecursionDepth(); // Make sure the last thing read was an end tag for this group. if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { @@ -381,14 +393,16 @@ inline bool WireFormatLite::ReadGroupNoVirtual(int field_number, } return true; } -template -inline bool WireFormatLite::ReadMessageNoVirtual(io::CodedInputStream* input, - MessageType* value) { +template +inline bool WireFormatLite::ReadMessageNoVirtual( + io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) { uint32 length; if (!input->ReadVarint32(&length)) return false; if (!input->IncrementRecursionDepth()) return false; io::CodedInputStream::Limit limit = input->PushLimit(length); - if (!value->MessageType::MergePartialFromCodedStream(input)) return false; + if (!value-> + MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) + return false; // Make sure that parsing stopped when the limit was hit, not at an endgroup // tag. if (!input->ConsumedEntireMessage()) return false; @@ -461,21 +475,24 @@ inline void WireFormatLite::WriteEnumNoTag(int value, output->WriteVarint32SignExtended(value); } -template -inline void WireFormatLite::WriteGroupNoVirtual(int field_number, - const MessageType& value, - io::CodedOutputStream* output) { +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template +inline void WireFormatLite::WriteGroupNoVirtual( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + io::CodedOutputStream* output) { WriteTag(field_number, WIRETYPE_START_GROUP, output); - value.MessageType::SerializeWithCachedSizes(output); + value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); WriteTag(field_number, WIRETYPE_END_GROUP, output); } -template -inline void WireFormatLite::WriteMessageNoVirtual(int field_number, - const MessageType& value, - io::CodedOutputStream* output) { +template +inline void WireFormatLite::WriteMessageNoVirtual( + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + io::CodedOutputStream* output) { WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); - output->WriteVarint32(value.MessageType::GetCachedSize()); - value.MessageType::SerializeWithCachedSizes(output); + output->WriteVarint32( + value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()); + value.MessageType_WorkAroundCppLookupDefect::SerializeWithCachedSizes(output); } // =================================================================== @@ -672,20 +689,26 @@ inline uint8* WireFormatLite::WriteMessageToArray(int field_number, return value.SerializeWithCachedSizesToArray(target); } -template +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template inline uint8* WireFormatLite::WriteGroupNoVirtualToArray( - int field_number, const MessageType& value, uint8* target) { + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + uint8* target) { target = WriteTagToArray(field_number, WIRETYPE_START_GROUP, target); - target = value.MessageType::SerializeWithCachedSizesToArray(target); + target = value.MessageType_WorkAroundCppLookupDefect + ::SerializeWithCachedSizesToArray(target); return WriteTagToArray(field_number, WIRETYPE_END_GROUP, target); } -template +template inline uint8* WireFormatLite::WriteMessageNoVirtualToArray( - int field_number, const MessageType& value, uint8* target) { + int field_number, const MessageType_WorkAroundCppLookupDefect& value, + uint8* target) { target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); target = io::CodedOutputStream::WriteVarint32ToArray( - value.MessageType::GetCachedSize(), target); - return value.MessageType::SerializeWithCachedSizesToArray(target); + value.MessageType_WorkAroundCppLookupDefect::GetCachedSize(), target); + return value.MessageType_WorkAroundCppLookupDefect + ::SerializeWithCachedSizesToArray(target); } // =================================================================== @@ -730,13 +753,17 @@ inline int WireFormatLite::MessageSize(const MessageLite& value) { return io::CodedOutputStream::VarintSize32(size) + size; } -template -inline int WireFormatLite::GroupSizeNoVirtual(const MessageType& value) { - return value.MessageType::ByteSize(); +// See comment on ReadGroupNoVirtual to understand the need for this template +// parameter name. +template +inline int WireFormatLite::GroupSizeNoVirtual( + const MessageType_WorkAroundCppLookupDefect& value) { + return value.MessageType_WorkAroundCppLookupDefect::ByteSize(); } -template -inline int WireFormatLite::MessageSizeNoVirtual(const MessageType& value) { - int size = value.MessageType::ByteSize(); +template +inline int WireFormatLite::MessageSizeNoVirtual( + const MessageType_WorkAroundCppLookupDefect& value) { + int size = value.MessageType_WorkAroundCppLookupDefect::ByteSize(); return io::CodedOutputStream::VarintSize32(size) + size; } -- cgit v1.2.3