diff options
Diffstat (limited to 'src/google/protobuf/compiler')
159 files changed, 9740 insertions, 9495 deletions
diff --git a/src/google/protobuf/compiler/annotation_test_util.h b/src/google/protobuf/compiler/annotation_test_util.h index 90bd88b3..fbd3dec5 100644 --- a/src/google/protobuf/compiler/annotation_test_util.h +++ b/src/google/protobuf/compiler/annotation_test_util.h @@ -49,15 +49,15 @@ namespace annotation_test_util { // file_content = content of Foo.java // file_info = parsed content of Foo.java.pb.meta struct ExpectedOutput { - string file_path; - string file_content; + std::string file_path; + std::string file_content; GeneratedCodeInfo file_info; - explicit ExpectedOutput(const string& file_path) : file_path(file_path) {} + explicit ExpectedOutput(const std::string& file_path) : file_path(file_path) {} }; // Creates a file with name `filename` and content `data` in temp test // directory. -void AddFile(const string& filename, const string& data); +void AddFile(const std::string& filename, const std::string& data); // Runs proto compiler. Captures proto file structrue in FileDescriptorProto. // Files will be generated in TestTempDir() folder. Callers of this @@ -70,45 +70,45 @@ void AddFile(const string& filename, const string& data); // annotation_unittest.cc for an example of how to initialize it. // file: output parameter, will be set to the descriptor of the proto file // specified in filename. -bool RunProtoCompiler(const string& filename, - const string& plugin_specific_args, +bool RunProtoCompiler(const std::string& filename, + const std::string& plugin_specific_args, CommandLineInterface* cli, FileDescriptorProto* file); -bool DecodeMetadata(const string& path, GeneratedCodeInfo* info); +bool DecodeMetadata(const std::string& path, GeneratedCodeInfo* info); // Finds all of the Annotations for a given source file and path. -// See Location.path in http://google/protobuf/descriptor.proto for +// See Location.path in http://google3/net/proto2/proto/descriptor.proto for // explanation of what path vector is. void FindAnnotationsOnPath( - const GeneratedCodeInfo& info, const string& source_file, + const GeneratedCodeInfo& info, const std::string& source_file, const std::vector<int>& path, std::vector<const GeneratedCodeInfo::Annotation*>* annotations); // Finds the Annotation for a given source file and path (or returns null if it // couldn't). If there are several annotations for given path, returns the first // one. See Location.path in -// http://google/protobuf/descriptor.proto for explanation of what path +// http://google3/net/proto2/proto/descriptor.proto for explanation of what path // vector is. const GeneratedCodeInfo::Annotation* FindAnnotationOnPath( - const GeneratedCodeInfo& info, const string& source_file, + const GeneratedCodeInfo& info, const std::string& source_file, const std::vector<int>& path); // Returns true if at least one of the provided annotations covers a given // substring in file_content. bool AtLeastOneAnnotationMatchesSubstring( - const string& file_content, + const std::string& file_content, const std::vector<const GeneratedCodeInfo::Annotation*>& annotations, - const string& expected_text); + const std::string& expected_text); // Returns true if the provided annotation covers a given substring in // file_content. -bool AnnotationMatchesSubstring(const string& file_content, +bool AnnotationMatchesSubstring(const std::string& file_content, const GeneratedCodeInfo::Annotation* annotation, - const string& expected_text); + const std::string& expected_text); } // namespace annotation_test_util } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__ diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index 4c2b3ee1..b1eb61ac 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -43,6 +43,8 @@ #include <vector> #include <utility> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { @@ -61,7 +63,7 @@ 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 // be registered with CommandLineInterface to support various languages. -class LIBPROTOC_EXPORT CodeGenerator { +class PROTOC_EXPORT CodeGenerator { public: inline CodeGenerator() {} virtual ~CodeGenerator(); @@ -78,9 +80,9 @@ class LIBPROTOC_EXPORT CodeGenerator { // Returns true if successful. Otherwise, sets *error to a description of // the problem (e.g. "invalid parameter") and returns false. virtual bool Generate(const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* generator_context, - string* error) const = 0; + std::string* error) const = 0; // Generates code for all given proto files. // @@ -94,9 +96,9 @@ class LIBPROTOC_EXPORT CodeGenerator { // Returns true if successful. Otherwise, sets *error to a description of // the problem (e.g. "invalid parameter") and returns false. virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files, - const string& parameter, + const std::string& parameter, GeneratorContext* generator_context, - string* error) const; + std::string* error) const; // This is no longer used, but this class is part of the opensource protobuf // library, so it has to remain to keep vtables the same for the current @@ -112,7 +114,7 @@ class LIBPROTOC_EXPORT CodeGenerator { // abstract interface represents the directory to which the CodeGenerator is // to write and other information about the context in which the Generator // runs. -class LIBPROTOC_EXPORT GeneratorContext { +class PROTOC_EXPORT GeneratorContext { public: inline GeneratorContext() { } @@ -128,10 +130,10 @@ class LIBPROTOC_EXPORT GeneratorContext { // generate the files "foo/bar.pb.h" and "foo/bar.pb.cc"; note that // "foo/" is included in these filenames. The filename is not allowed to // contain "." or ".." components. - virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0; + virtual io::ZeroCopyOutputStream* Open(const std::string& filename) = 0; // Similar to Open() but the output will be appended to the file if exists - virtual io::ZeroCopyOutputStream* OpenForAppend(const string& filename); + virtual io::ZeroCopyOutputStream* OpenForAppend(const std::string& filename); // Creates a ZeroCopyOutputStream which will insert code into the given file // at the given insertion point. See plugin.proto (plugin.pb.h) for more @@ -140,7 +142,7 @@ class LIBPROTOC_EXPORT GeneratorContext { // // WARNING: This feature is currently EXPERIMENTAL and is subject to change. virtual io::ZeroCopyOutputStream* OpenForInsert( - const string& filename, const string& insertion_point); + const std::string& filename, const std::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 @@ -166,11 +168,13 @@ typedef GeneratorContext OutputDirectory; // "foo=bar,baz,qux=corge" // parses to the pairs: // ("foo", "bar"), ("baz", ""), ("qux", "corge") -LIBPROTOC_EXPORT void ParseGeneratorParameter( - const string&, std::vector<std::pair<string, string> >*); +PROTOC_EXPORT void ParseGeneratorParameter( + const std::string&, std::vector<std::pair<std::string, std::string> >*); } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 8380367f..4d1ef09b 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -84,6 +84,8 @@ #include <google/protobuf/stubs/io_win32.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { @@ -168,7 +170,9 @@ bool VerifyDirectoryExists(const string& path) { // directories listed in |filename|. bool TryCreateParentDirectory(const string& prefix, const string& filename) { // Recursively create parent directories to the output file. - std::vector<string> parts = Split(filename, "/", true); + // On Windows, both '/' and '\' are valid path separators. + std::vector<string> parts = + Split(filename, "/\\", true); string path_so_far = prefix; for (int i = 0; i < parts.size() - 1; i++) { path_so_far += parts[i]; @@ -395,7 +399,7 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { private: friend class MemoryOutputStream; - // map instead of hash_map so that files are written in order (good when + // map instead of unordered_map so that files are written in order (good when // writing zips). std::map<string, string*> files_; const std::vector<const FileDescriptor*>& parsed_files_; @@ -749,7 +753,7 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { // Now copy in the data. string::size_type data_pos = 0; - char* target_ptr = string_as_array(target) + pos; + char* target_ptr = ::google::protobuf::string_as_array(target) + pos; while (data_pos < data_.size()) { // Copy indent. memcpy(target_ptr, indent_.data(), indent_.size()); @@ -766,7 +770,7 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { } GOOGLE_CHECK_EQ(target_ptr, - string_as_array(target) + pos + data_.size() + indent_size); + ::google::protobuf::string_as_array(target) + pos + data_.size() + indent_size); } } } @@ -988,6 +992,7 @@ bool CommandLineInterface::InitializeDiskSourceTree( if (!MakeInputsBeProtoPathRelative(source_tree)) { return false; } + return true; } @@ -1039,15 +1044,15 @@ bool CommandLineInterface::ParseInputFiles( std::vector<const FileDescriptor*>* parsed_files) { // Parse each file. - for (int i = 0; i < input_files_.size(); i++) { + for (const auto& input_file : input_files_) { // Import the file. - descriptor_pool->AddUnusedImportTrackFile(input_files_[i]); + descriptor_pool->AddUnusedImportTrackFile(input_file); const FileDescriptor* parsed_file = - descriptor_pool->FindFileByName(input_files_[i]); + descriptor_pool->FindFileByName(input_file); descriptor_pool->ClearUnusedImportTrackFiles(); if (parsed_file == NULL) { if (!descriptor_set_in_names_.empty()) { - std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl; + std::cerr << input_file << ": " << strerror(ENOENT) << std::endl; } return false; } @@ -1096,6 +1101,7 @@ void CommandLineInterface::Clear() { descriptor_set_out_name_.clear(); dependency_out_name_.clear(); + mode_ = MODE_COMPILE; print_mode_ = PRINT_NONE; imports_in_descriptor_set_ = false; @@ -1104,64 +1110,73 @@ void CommandLineInterface::Clear() { direct_dependencies_explicitly_set_ = false; } -bool CommandLineInterface::MakeInputsBeProtoPathRelative( - DiskSourceTree* source_tree) { - for (int i = 0; i < input_files_.size(); i++) { - // If the input file path is not a physical file path, it must be a virtual - // path. - if (access(input_files_[i].c_str(), F_OK) < 0) { +bool CommandLineInterface::MakeProtoProtoPathRelative( + DiskSourceTree* source_tree, string* proto) { + // If the input file path is not a physical file path, it must be a virtual + // path. + if (access(proto->c_str(), F_OK) < 0) { + string disk_file; + if (source_tree->VirtualFileToDiskFile(*proto, &disk_file)) { + return true; + } else { + std::cerr << *proto << ": " << strerror(ENOENT) << std::endl; + return false; + } + } + string virtual_file, shadowing_disk_file; + switch (source_tree->DiskFileToVirtualFile( + *proto, &virtual_file, &shadowing_disk_file)) { + case DiskSourceTree::SUCCESS: + *proto = virtual_file; + break; + case DiskSourceTree::SHADOWED: + std::cerr << *proto + << ": Input is shadowed in the --proto_path by \"" + << shadowing_disk_file + << "\". Either use the latter file as your input or reorder " + "the --proto_path so that the former file's location " + "comes first." << std::endl; + return false; + case DiskSourceTree::CANNOT_OPEN: + std::cerr << *proto << ": " << strerror(errno) << std::endl; + return false; + case DiskSourceTree::NO_MAPPING: { + // Try to interpret the path as a virtual path. string disk_file; - if (source_tree->VirtualFileToDiskFile(input_files_[i], &disk_file)) { - return true; + if (source_tree->VirtualFileToDiskFile(*proto, &disk_file)) { + return true; } else { - std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl; + // The input file path can't be mapped to any --proto_path and it also + // can't be interpreted as a virtual path. + std::cerr + << *proto + << ": File does not reside within any path " + "specified using --proto_path (or -I). You must specify a " + "--proto_path which encompasses this file. Note that the " + "proto_path must be an exact prefix of the .proto file " + "names -- protoc is too dumb to figure out when two paths " + "(e.g. absolute and relative) are equivalent (it's harder " + "than you think)." + << std::endl; return false; } } - string virtual_file, shadowing_disk_file; - switch (source_tree->DiskFileToVirtualFile( - input_files_[i], &virtual_file, &shadowing_disk_file)) { - case DiskSourceTree::SUCCESS: - input_files_[i] = virtual_file; - break; - case DiskSourceTree::SHADOWED: - std::cerr << input_files_[i] - << ": Input is shadowed in the --proto_path by \"" - << shadowing_disk_file - << "\". Either use the latter file as your input or reorder " - "the --proto_path so that the former file's location " - "comes first." << std::endl; - return false; - case DiskSourceTree::CANNOT_OPEN: - std::cerr << input_files_[i] << ": " << strerror(errno) << std::endl; - return false; - case DiskSourceTree::NO_MAPPING: { - // Try to interpret the path as a virtual path. - string disk_file; - if (source_tree->VirtualFileToDiskFile(input_files_[i], &disk_file)) { - return true; - } else { - // The input file path can't be mapped to any --proto_path and it also - // can't be interpreted as a virtual path. - std::cerr - << input_files_[i] - << ": File does not reside within any path " - "specified using --proto_path (or -I). You must specify a " - "--proto_path which encompasses this file. Note that the " - "proto_path must be an exact prefix of the .proto file " - "names -- protoc is too dumb to figure out when two paths " - "(e.g. absolute and relative) are equivalent (it's harder " - "than you think)." - << std::endl; - return false; - } - } + } + return true; +} + +bool CommandLineInterface::MakeInputsBeProtoPathRelative( + DiskSourceTree* source_tree) { + for (auto& input_file : input_files_) { + if (!MakeProtoProtoPathRelative(source_tree, &input_file)) { + return false; } } return true; } + bool CommandLineInterface::ExpandArgumentFile(const string& file, std::vector<string>* arguments) { // The argument file is searched in the working directory only. We don't @@ -1534,7 +1549,7 @@ CommandLineInterface::InterpretArgument(const string& name, std::cout << version_info_ << std::endl; } std::cout << "libprotoc " - << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION) + << protobuf::internal::VersionString(PROTOBUF_VERSION) << std::endl; return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. @@ -1920,10 +1935,10 @@ bool CommandLineInterface::GeneratePluginOutput( google::protobuf::compiler::Version* version = request.mutable_compiler_version(); - version->set_major(GOOGLE_PROTOBUF_VERSION / 1000000); - version->set_minor(GOOGLE_PROTOBUF_VERSION / 1000 % 1000); - version->set_patch(GOOGLE_PROTOBUF_VERSION % 1000); - version->set_suffix(GOOGLE_PROTOBUF_VERSION_SUFFIX); + version->set_major(PROTOBUF_VERSION / 1000000); + version->set_minor(PROTOBUF_VERSION / 1000 % 1000); + version->set_patch(PROTOBUF_VERSION % 1000); + version->set_suffix(PROTOBUF_VERSION_SUFFIX); // Invoke the plugin. Subprocess subprocess; diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 7d3037a9..cef29ffe 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -38,13 +38,16 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/hash.h> -#include <string> -#include <vector> #include <map> #include <set> +#include <string> +#include <unordered_map> #include <utility> +#include <vector> + +#include <google/protobuf/stubs/common.h> + +#include <google/protobuf/port_def.inc> namespace google { namespace protobuf { @@ -101,7 +104,7 @@ class DiskSourceTree; // importer.h // relative virtual path, the physical file path takes precendence. // // For a full description of the command-line syntax, invoke it with --help. -class LIBPROTOC_EXPORT CommandLineInterface { +class PROTOC_EXPORT CommandLineInterface { public: static const char* const kPathSeparator; @@ -124,9 +127,9 @@ class LIBPROTOC_EXPORT CommandLineInterface { // protoc --foo_out=enable_bar:outdir // The text before the colon is passed to CodeGenerator::Generate() as the // "parameter". - void RegisterGenerator(const string& flag_name, + void RegisterGenerator(const std::string& flag_name, CodeGenerator* generator, - const string& help_text); + const std::string& help_text); // Register a code generator for a language. // Besides flag_name you can specify another option_flag_name that could be @@ -136,10 +139,10 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Then you could invoke the compiler with a command like: // protoc --foo_out=enable_bar:outdir --foo_opt=enable_baz // This will pass "enable_bar,enable_baz" as the parameter to the generator. - void RegisterGenerator(const string& flag_name, - const string& option_flag_name, + void RegisterGenerator(const std::string& flag_name, + const std::string& option_flag_name, CodeGenerator* generator, - const string& help_text); + const std::string& help_text); // Enables "plugins". In this mode, if a command-line flag ends with "_out" // but does not match any registered generator, the compiler will attempt to @@ -177,7 +180,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // protoc --plug_out=enable_bar:outdir --plug_opt=enable_baz // This will pass "enable_bar,enable_baz" as the parameter to the plugin. // - void AllowPlugins(const string& exe_name_prefix); + void AllowPlugins(const std::string& exe_name_prefix); // Run the Protocol Compiler with the given command-line parameters. // Returns the error code which should be returned by main(). @@ -195,7 +198,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Provides some text which will be printed when the --version flag is // used. The version of libprotoc will also be printed on the next line // after this text. - void SetVersionInfo(const string& text) { + void SetVersionInfo(const std::string& text) { version_info_ = text; } @@ -206,17 +209,21 @@ class LIBPROTOC_EXPORT CommandLineInterface { class ErrorPrinter; class GeneratorContextImpl; class MemoryOutputStream; - typedef hash_map<string, GeneratorContextImpl*> GeneratorContextMap; + typedef std::unordered_map<std::string, GeneratorContextImpl*> GeneratorContextMap; // Clear state from previous Run(). void Clear(); + // Remaps the proto file so that it is relative to one of the ddirectories + // in proto_path_. Returns false if an error occurred. + bool MakeProtoProtoPathRelative(DiskSourceTree* source_tree, std::string* proto); + // Remaps each file in input_files_ so that it is relative to one of the - // directories in proto_path_. Returns false if an error occurred. This - // is only used if inputs_are_proto_path_relative_ is false. + // directories in proto_path_. Returns false if an error occurred. bool MakeInputsBeProtoPathRelative( DiskSourceTree* source_tree); + // Return status for ParseArguments() and InterpretArgument(). enum ParseArgumentStatus { PARSE_ARGUMENT_DONE_AND_CONTINUE, @@ -229,7 +236,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Read an argument file and append the file's content to the list of // arguments. Return false if the file cannot be read. - bool ExpandArgumentFile(const string& file, std::vector<string>* arguments); + bool ExpandArgumentFile(const std::string& file, std::vector<std::string>* arguments); // Parses a command-line argument into a name/value pair. Returns // true if the next argument in the argv should be used as the value, @@ -242,11 +249,11 @@ class LIBPROTOC_EXPORT CommandLineInterface { // name = "--cpp_out", value = "src/foo.pb2.cc" // "foo.proto" -> // name = "", value = "foo.proto" - bool ParseArgument(const char* arg, string* name, string* value); + bool ParseArgument(const char* arg, std::string* name, std::string* value); // Interprets arguments parsed with ParseArgument. - ParseArgumentStatus InterpretArgument(const string& name, - const string& value); + ParseArgumentStatus InterpretArgument(const std::string& name, + const std::string& value); // Print the --help text to stderr. void PrintHelpText(); @@ -268,8 +275,8 @@ class LIBPROTOC_EXPORT CommandLineInterface { GeneratorContext* generator_context); bool GeneratePluginOutput( const std::vector<const FileDescriptor*>& parsed_files, - const string& plugin_name, const string& parameter, - GeneratorContext* generator_context, string* error); + const std::string& plugin_name, const std::string& parameter, + GeneratorContext* generator_context, std::string* error); // Implements --encode and --decode. bool EncodeOrDecode(const DescriptorPool* pool); @@ -319,36 +326,36 @@ class LIBPROTOC_EXPORT CommandLineInterface { // ----------------------------------------------------------------- // The name of the executable as invoked (i.e. argv[0]). - string executable_name_; + std::string executable_name_; // Version info set with SetVersionInfo(). - string version_info_; + std::string version_info_; // Registered generators. struct GeneratorInfo { - string flag_name; - string option_flag_name; + std::string flag_name; + std::string option_flag_name; CodeGenerator* generator; - string help_text; + std::string help_text; }; - typedef std::map<string, GeneratorInfo> GeneratorMap; + typedef std::map<std::string, GeneratorInfo> GeneratorMap; GeneratorMap generators_by_flag_name_; GeneratorMap generators_by_option_name_; // A map from generator names to the parameters specified using the option // flag. For example, if the user invokes the compiler with: // protoc --foo_out=outputdir --foo_opt=enable_bar ... // Then there will be an entry ("--foo_out", "enable_bar") in this map. - std::map<string, string> generator_parameters_; + std::map<std::string, std::string> generator_parameters_; // Similar to generator_parameters_, but stores the parameters for plugins. - std::map<string, string> plugin_parameters_; + std::map<std::string, std::string> plugin_parameters_; // See AllowPlugins(). If this is empty, plugins aren't allowed. - string plugin_prefix_; + std::string plugin_prefix_; // Maps specific plugin names to files. When executing a plugin, this map // is searched first to find the plugin executable. If not found here, the // PATH (or other OS-specific search strategy) is searched. - std::map<string, string> plugins_; + std::map<std::string, std::string> plugins_; // Stuff parsed from command line. enum Mode { @@ -374,44 +381,44 @@ class LIBPROTOC_EXPORT CommandLineInterface { ErrorFormat error_format_; - std::vector<std::pair<string, string> > + std::vector<std::pair<std::string, std::string> > proto_path_; // Search path for proto files. - std::vector<string> input_files_; // Names of the input proto files. + std::vector<std::string> input_files_; // Names of the input proto files. // Names of proto files which are allowed to be imported. Used by build // systems to enforce depend-on-what-you-import. - std::set<string> direct_dependencies_; + std::set<std::string> direct_dependencies_; bool direct_dependencies_explicitly_set_; // If there's a violation of depend-on-what-you-import, this string will be // presented to the user. "%s" will be replaced with the violating import. - string direct_dependencies_violation_msg_; + std::string direct_dependencies_violation_msg_; // output_directives_ lists all the files we are supposed to output and what // generator to use for each. struct OutputDirective { - string name; // E.g. "--foo_out" + std::string name; // E.g. "--foo_out" CodeGenerator* generator; // NULL for plugins - string parameter; - string output_location; + std::string parameter; + std::string output_location; }; std::vector<OutputDirective> output_directives_; // When using --encode or --decode, this names the type we are encoding or // decoding. (Empty string indicates --decode_raw.) - string codec_type_; + std::string codec_type_; // If --descriptor_set_in was given, these are filenames containing // parsed FileDescriptorSets to be used for loading protos. Otherwise, empty. - std::vector<string> descriptor_set_in_names_; + std::vector<std::string> descriptor_set_in_names_; // If --descriptor_set_out was given, this is the filename to which the // FileDescriptorSet should be written. Otherwise, empty. - string descriptor_set_out_name_; + std::string descriptor_set_out_name_; // If --dependency_out was given, this is the path to the file where the // dependency file will be written. Otherwise, empty. - string dependency_out_name_; + std::string dependency_out_name_; // True if --include_imports was given, meaning that we should // write all transitive dependencies to the DescriptorSet. Otherwise, only @@ -430,6 +437,8 @@ class LIBPROTOC_EXPORT CommandLineInterface { } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 41eb244a..4e6f4af5 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -49,6 +49,7 @@ #include <google/protobuf/compiler/subprocess.h> #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/compiler/command_line_interface.h> +#include <google/protobuf/test_util2.h> #include <google/protobuf/unittest.pb.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> @@ -2284,12 +2285,11 @@ class EncodeDecodeTest : public testing::TestWithParam<EncodeDecodeTestMode> { SplitStringUsing(command, " ", &args); switch (GetParam()) { case PROTO_PATH: - args.push_back("--proto_path=" + TestSourceDir()); + args.push_back("--proto_path=" + TestUtil::TestSourceDir()); break; case DESCRIPTOR_SET_IN: - args.push_back(StrCat( - "--descriptor_set_in=", - unittest_proto_descriptor_set_filename_)); + args.push_back(StrCat("--descriptor_set_in=", + unittest_proto_descriptor_set_filename_)); break; default: ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam(); @@ -2369,30 +2369,34 @@ class EncodeDecodeTest : public testing::TestWithParam<EncodeDecodeTestMode> { }; TEST_P(EncodeDecodeTest, Encode) { - RedirectStdinFromFile(TestSourceDir() + "/google/protobuf/" - "testdata/text_format_unittest_data_oneof_implemented.txt"); - EXPECT_TRUE(Run("google/protobuf/unittest.proto " - "--encode=protobuf_unittest.TestAllTypes")); - ExpectStdoutMatchesBinaryFile(TestSourceDir() + - "/google/protobuf/testdata/golden_message_oneof_implemented"); + RedirectStdinFromFile(TestUtil::GetTestDataPath( + "net/proto2/internal/" + "testdata/text_format_unittest_data_oneof_implemented.txt")); + EXPECT_TRUE( + Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") + + " --encode=protobuf_unittest.TestAllTypes")); + ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath( + "net/proto2/internal/testdata/golden_message_oneof_implemented")); ExpectStderrMatchesText(""); } TEST_P(EncodeDecodeTest, Decode) { - RedirectStdinFromFile(TestSourceDir() + - "/google/protobuf/testdata/golden_message_oneof_implemented"); - EXPECT_TRUE(Run("google/protobuf/unittest.proto " - "--decode=protobuf_unittest.TestAllTypes")); - ExpectStdoutMatchesTextFile(TestSourceDir() + - "/google/protobuf/" - "testdata/text_format_unittest_data_oneof_implemented.txt"); + RedirectStdinFromFile(TestUtil::GetTestDataPath( + "net/proto2/internal/testdata/golden_message_oneof_implemented")); + EXPECT_TRUE( + Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") + + " --decode=protobuf_unittest.TestAllTypes")); + ExpectStdoutMatchesTextFile(TestUtil::GetTestDataPath( + "net/proto2/internal/" + "testdata/text_format_unittest_data_oneof_implemented.txt")); ExpectStderrMatchesText(""); } TEST_P(EncodeDecodeTest, Partial) { RedirectStdinFromText(""); - EXPECT_TRUE(Run("google/protobuf/unittest.proto " - "--encode=protobuf_unittest.TestRequired")); + EXPECT_TRUE( + Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") + + " --encode=protobuf_unittest.TestRequired")); ExpectStdoutMatchesText(""); ExpectStderrMatchesText( "warning: Input message is missing required fields: a, b, c\n"); @@ -2413,18 +2417,20 @@ TEST_P(EncodeDecodeTest, DecodeRaw) { } TEST_P(EncodeDecodeTest, UnknownType) { - EXPECT_FALSE(Run("google/protobuf/unittest.proto " - "--encode=NoSuchType")); + EXPECT_FALSE( + Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") + + " --encode=NoSuchType")); ExpectStdoutMatchesText(""); ExpectStderrMatchesText("Type not defined: NoSuchType\n"); } TEST_P(EncodeDecodeTest, ProtoParseError) { - EXPECT_FALSE(Run("google/protobuf/no_such_file.proto " - "--encode=NoSuchType")); + EXPECT_FALSE( + Run("net/proto2/internal/no_such_file.proto " + "--encode=NoSuchType")); ExpectStdoutMatchesText(""); ExpectStderrMatchesText( - "google/protobuf/no_such_file.proto: No such file or directory\n"); + "net/proto2/internal/no_such_file.proto: No such file or directory\n"); } INSTANTIATE_TEST_CASE_P(FileDescriptorSetSource, diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc index 4e150fe3..a19ad595 100644 --- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -32,7 +32,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // -// This test insures that google/protobuf/descriptor.pb.{h,cc} match exactly +// This test insures that net/proto2/proto/descriptor.pb.{h,cc} match exactly // what would be generated by the protocol compiler. These files are not // generated automatically at build time because they are compiled into the // protocol compiler itself. So, if they were auto-generated, you'd have a @@ -47,8 +47,10 @@ #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/compiler/cpp/cpp_generator.h> #include <google/protobuf/compiler/importer.h> +#include <google/protobuf/test_util2.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/descriptor.h> +#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> #include <google/protobuf/stubs/map_util.h> #include <google/protobuf/stubs/stl_util.h> @@ -83,9 +85,7 @@ class MockErrorCollector : public MultiFileErrorCollector { class MockGeneratorContext : public GeneratorContext { public: MockGeneratorContext() {} - ~MockGeneratorContext() { - STLDeleteValues(&files_); - } + ~MockGeneratorContext() { STLDeleteValues(&files_); } void ExpectFileMatches(const string& virtual_filename, const string& physical_filename) { @@ -95,9 +95,18 @@ class MockGeneratorContext : public GeneratorContext { string actual_contents; GOOGLE_CHECK_OK( - File::GetContents(TestSourceDir() + "/" + physical_filename, - &actual_contents, true)); - EXPECT_TRUE(actual_contents == *expected_contents) + File::GetContents(TestUtil::TestSourceDir() + "/" + physical_filename, + &actual_contents, true)) + << physical_filename; + CleanStringLineEndings(&actual_contents, false); + +#ifdef WRITE_FILES // Define to debug mismatched files. + GOOGLE_CHECK_OK( + File::SetContents("/tmp/1.cc", *expected_contents, true)); + GOOGLE_CHECK_OK(File::SetContents("/tmp/2.cc", actual_contents, true)); +#endif + + EXPECT_EQ(*expected_contents, actual_contents) << physical_filename << " needs to be regenerated. Please run " "generate_descriptor_proto.sh. " @@ -118,8 +127,8 @@ class MockGeneratorContext : public GeneratorContext { std::map<string, string*> files_; }; -const char kDescriptorParameter[] = "dllexport_decl=LIBPROTOBUF_EXPORT"; -const char kPluginParameter[] = "dllexport_decl=LIBPROTOC_EXPORT"; +const char kDescriptorParameter[] = "dllexport_decl=PROTOBUF_EXPORT"; +const char kPluginParameter[] = "dllexport_decl=PROTOC_EXPORT"; const char kNormalParameter[] = ""; const char* test_protos[][2] = { @@ -136,11 +145,11 @@ TEST(BootstrapTest, GeneratedFilesMatch) { "net/proto2/z_generated_example/test_messages_proto2"; rpath_map["third_party/protobuf/src/google/protobuf/test_messages_proto3"] = "net/proto2/z_generated_example/test_messages_proto3"; - rpath_map["google/protobuf/proto2_weak"] = + rpath_map["net/proto2/internal/proto2_weak"] = "net/proto2/z_generated_example/proto2_weak"; DiskSourceTree source_tree; - source_tree.MapPath("", TestSourceDir()); + source_tree.MapPath("", TestUtil::TestSourceDir()); for (auto file_parameter : test_protos) { MockErrorCollector error_collector; diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 0d6a9e24..39fe9e68 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -46,7 +46,7 @@ namespace cpp { namespace { // The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value -// is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the +// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the // generation of the GOOGLE_ARRAYSIZE constant. bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { int32 max_value = descriptor->value(0)->number(); @@ -55,61 +55,53 @@ bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { max_value = descriptor->value(i)->number(); } } - return max_value != ::google::protobuf::kint32max; + return max_value != kint32max; } } // namespace EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, + const std::map<string, string>& vars, const Options& options) - : descriptor_(descriptor), - classname_(ClassName(descriptor, false)), - options_(options), - generate_array_size_(ShouldGenerateArraySize(descriptor)) { + : descriptor_(descriptor), + classname_(ClassName(descriptor, false)), + options_(options), + generate_array_size_(ShouldGenerateArraySize(descriptor)), + variables_(vars) { + variables_["classname"] = classname_; + variables_["classtype"] = QualifiedClassName(descriptor_); + variables_["short_name"] = descriptor_->name(); + variables_["enumbase"] = options_.proto_h ? " : int" : ""; + variables_["nested_name"] = descriptor_->name(); + variables_["constexpr"] = options_.proto_h ? "constexpr" : ""; + variables_["prefix"] = + (descriptor_->containing_type() == NULL) ? "" : classname_ + "_"; } EnumGenerator::~EnumGenerator() {} -void EnumGenerator::FillForwardDeclaration( - std::map<string, const EnumDescriptor*>* enum_names) { - if (!options_.proto_h) { - return; - } - (*enum_names)[classname_] = descriptor_; -} - void EnumGenerator::GenerateDefinition(io::Printer* printer) { - std::map<string, string> vars; - vars["classname"] = classname_; - vars["short_name"] = descriptor_->name(); - vars["enumbase"] = options_.proto_h ? " : int" : ""; - // These variables are placeholders to pick out the beginning and ends of - // identifiers for annotations (when doing so with existing variables would - // be ambiguous or impossible). They should never be set to anything but the - // empty string. - vars["{"] = ""; - vars["}"] = ""; - - printer->Print(vars, "enum $classname$$enumbase$ {\n"); - printer->Annotate("classname", descriptor_); - printer->Indent(); + Formatter format(printer, variables_); + format("enum ${1$$classname$$}$$enumbase$ {\n", descriptor_); + format.Indent(); const EnumValueDescriptor* min_value = descriptor_->value(0); const EnumValueDescriptor* max_value = descriptor_->value(0); for (int i = 0; i < descriptor_->value_count(); i++) { - vars["name"] = EnumValueName(descriptor_->value(i)); + auto format_value = format; + format_value.Set("name", EnumValueName(descriptor_->value(i))); // In C++, an value of -2147483648 gets interpreted as the negative of // 2147483648, and since 2147483648 can't fit in an integer, this produces a // compiler warning. This works around that issue. - vars["number"] = Int32ToString(descriptor_->value(i)->number()); - vars["prefix"] = (descriptor_->containing_type() == NULL) ? - "" : classname_ + "_"; - vars["deprecation"] = descriptor_->value(i)->options().deprecated() ? - " PROTOBUF_DEPRECATED" : ""; + format_value.Set("number", Int32ToString(descriptor_->value(i)->number())); + format_value.Set( + "deprecation", + DeprecatedAttribute(options_, + descriptor_->value(i)->options().deprecated())); - if (i > 0) printer->Print(",\n"); - printer->Print(vars, "${$$prefix$$name$$}$$deprecation$ = $number$"); - printer->Annotate("{", "}", descriptor_->value(i)); + if (i > 0) format_value(",\n"); + format_value("${1$$prefix$$name$$}$ $deprecation$= $number$", + descriptor_->value(i)); if (descriptor_->value(i)->number() < min_value->number()) { min_value = descriptor_->value(i); @@ -122,153 +114,163 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { // For new enum semantics: generate min and max sentinel values equal to // INT32_MIN and INT32_MAX - if (descriptor_->value_count() > 0) printer->Print(",\n"); - printer->Print(vars, - "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min,\n" - "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max"); + if (descriptor_->value_count() > 0) format(",\n"); + format( + "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = " + "std::numeric_limits<$int32$>::min(),\n" + "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = " + "std::numeric_limits<$int32$>::max()"); } - printer->Outdent(); - printer->Print("\n};\n"); + format.Outdent(); + format("\n};\n"); - vars["min_name"] = EnumValueName(min_value); - vars["max_name"] = EnumValueName(max_value); - - if (options_.dllexport_decl.empty()) { - vars["dllexport"] = ""; - } else { - vars["dllexport"] = options_.dllexport_decl + " "; - } - - printer->Print(vars, - "$dllexport$bool $classname$_IsValid(int value);\n" - "const $classname$ ${$$prefix$$short_name$_MIN$}$ = " - "$prefix$$min_name$;\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(vars, - "const $classname$ ${$$prefix$$short_name$_MAX$}$ = " - "$prefix$$max_name$;\n"); - printer->Annotate("{", "}", descriptor_); + format( + "$dllexport_decl $bool $classname$_IsValid(int value);\n" + "const $classname$ ${1$$prefix$$short_name$_MIN$}$ = " + "$prefix$$2$;\n" + "const $classname$ ${1$$prefix$$short_name$_MAX$}$ = " + "$prefix$$3$;\n", + descriptor_, EnumValueName(min_value), EnumValueName(max_value)); if (generate_array_size_) { - printer->Print(vars, - "const int ${$$prefix$$short_name$_ARRAYSIZE$}$ = " - "$prefix$$short_name$_MAX + 1;\n\n"); - printer->Annotate("{", "}", descriptor_); + format( + "const int ${1$$prefix$$short_name$_ARRAYSIZE$}$ = " + "$prefix$$short_name$_MAX + 1;\n\n", + descriptor_); } if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print(vars, - "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n"); + format( + "$dllexport_decl $const ::$proto_ns$::EnumDescriptor* " + "$classname$_descriptor();\n"); // The _Name and _Parse methods - printer->Print( - vars, - "inline const ::std::string& $classname$_Name($classname$ value) {\n" - " return ::google::protobuf::internal::NameOfEnum(\n" - " $classname$_descriptor(), value);\n" + if (options_.opensource_runtime) { + // TODO(haberman): consider removing this in favor of the stricter + // version below. Would this break our compatibility guarantees? + format( + "inline const $string$& $classname$_Name($classname$ value) {\n" + " return ::$proto_ns$::internal::NameOfEnum(\n" + " $classname$_descriptor(), value);\n" + "}\n"); + } else { + // Support a stricter, type-checked enum-to-string method that + // statically checks whether the parameter is the exact enum type or is + // an integral type. + format( + "template<typename T>\n" + "inline const $string$& $classname$_Name(T enum_t_value) {\n" + " static_assert(::std::is_same<T, $classname$>::value ||\n" + " ::std::is_integral<T>::value,\n" + " \"Incorrect type passed to function $classname$_Name.\");\n" + " return ::$proto_ns$::internal::NameOfEnum(\n" + " $classname$_descriptor(), enum_t_value);\n" + "}\n"); + } + format( + "inline bool $classname$_Parse(\n" + " const $string$& name, $classname$* value) {\n" + " return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n" + " $classname$_descriptor(), name, value);\n" "}\n"); - printer->Print(vars, - "inline bool $classname$_Parse(\n" - " const ::std::string& name, $classname$* value) {\n" - " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n" - " $classname$_descriptor(), name, value);\n" - "}\n"); } } -void EnumGenerator:: -GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { - printer->Print( - "template <> struct is_proto_enum< $classname$> : ::std::true_type " - "{};\n", - "classname", ClassName(descriptor_, true)); +void EnumGenerator::GenerateGetEnumDescriptorSpecializations( + io::Printer* printer) { + Formatter format(printer, variables_); + format( + "template <> struct is_proto_enum< $classtype$> : ::std::true_type " + "{};\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - "template <>\n" - "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" - " return $classname$_descriptor();\n" - "}\n", - "classname", ClassName(descriptor_, true)); + format( + "template <>\n" + "inline const EnumDescriptor* GetEnumDescriptor< $classtype$>() {\n" + " return $classtype$_descriptor();\n" + "}\n"); } } -void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { - std::map<string, string> vars; - vars["nested_name"] = descriptor_->name(); - vars["classname"] = classname_; - vars["constexpr"] = options_.proto_h ? "constexpr " : ""; - vars["{"] = ""; - vars["}"] = ""; - printer->Print(vars, "typedef $classname$ $nested_name$;\n"); +void EnumGenerator::GenerateSymbolImports(io::Printer* printer) const { + Formatter format(printer, variables_); + format("typedef $classname$ $nested_name$;\n"); for (int j = 0; j < descriptor_->value_count(); j++) { - vars["tag"] = EnumValueName(descriptor_->value(j)); - vars["deprecated_attr"] = descriptor_->value(j)->options().deprecated() ? - "GOOGLE_PROTOBUF_DEPRECATED_ATTR " : ""; - printer->Print(vars, - "$deprecated_attr$static $constexpr$const $nested_name$ ${$$tag$$}$ =\n" - " $classname$_$tag$;\n"); - printer->Annotate("{", "}", descriptor_->value(j)); + string deprecated_attr = DeprecatedAttribute( + options_, descriptor_->value(j)->options().deprecated()); + format( + "$1$static $constexpr $const $nested_name$ ${2$$3$$}$ =\n" + " $classname$_$3$;\n", + deprecated_attr, descriptor_->value(j), + EnumValueName(descriptor_->value(j))); } - printer->Print(vars, - "static inline bool $nested_name$_IsValid(int value) {\n" - " return $classname$_IsValid(value);\n" - "}\n" - "static const $nested_name$ ${$$nested_name$_MIN$}$ =\n" - " $classname$_$nested_name$_MIN;\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(vars, - "static const $nested_name$ ${$$nested_name$_MAX$}$ =\n" - " $classname$_$nested_name$_MAX;\n"); - printer->Annotate("{", "}", descriptor_); + format( + "static inline bool $nested_name$_IsValid(int value) {\n" + " return $classname$_IsValid(value);\n" + "}\n" + "static const $nested_name$ ${1$$nested_name$_MIN$}$ =\n" + " $classname$_$nested_name$_MIN;\n" + "static const $nested_name$ ${1$$nested_name$_MAX$}$ =\n" + " $classname$_$nested_name$_MAX;\n", + descriptor_); if (generate_array_size_) { - printer->Print(vars, - "static const int ${$$nested_name$_ARRAYSIZE$}$ =\n" - " $classname$_$nested_name$_ARRAYSIZE;\n"); - printer->Annotate("{", "}", descriptor_); + format( + "static const int ${1$$nested_name$_ARRAYSIZE$}$ =\n" + " $classname$_$nested_name$_ARRAYSIZE;\n", + descriptor_); } if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print(vars, - "static inline const ::google::protobuf::EnumDescriptor*\n" - "$nested_name$_descriptor() {\n" - " return $classname$_descriptor();\n" - "}\n"); - printer->Print(vars, - "static inline const ::std::string& " - "$nested_name$_Name($nested_name$ value) {" - "\n" - " return $classname$_Name(value);\n" - "}\n"); - printer->Print(vars, - "static inline bool $nested_name$_Parse(const ::std::string& name,\n" - " $nested_name$* value) {\n" - " return $classname$_Parse(name, value);\n" - "}\n"); + format( + "static inline const ::$proto_ns$::EnumDescriptor*\n" + "$nested_name$_descriptor() {\n" + " return $classname$_descriptor();\n" + "}\n"); + if (options_.opensource_runtime) { + // TODO(haberman): consider removing this in favor of the stricter + // version below. Would this break our compatibility guarantees? + format( + "static inline const $string$& " + "$nested_name$_Name($nested_name$ value) {" + "\n" + " return $classname$_Name(value);\n" + "}\n"); + } else { + // Support a stricter, type-checked enum-to-string method that + // statically checks whether the parameter is the exact enum type or is + // an integral type. + format( + "template<typename T>\n" + "static inline const $string$& $nested_name$_Name(T enum_t_value) {\n" + " static_assert(::std::is_same<T, $nested_name$>::value ||\n" + " ::std::is_integral<T>::value,\n" + " \"Incorrect type passed to function $nested_name$_Name.\");\n" + " return $classname$_Name(enum_t_value);\n" + "}\n"); + } + format( + "static inline bool $nested_name$_Parse(const $string$& name,\n" + " $nested_name$* value) {\n" + " return $classname$_Parse(name, value);\n" + "}\n"); } } void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) { - std::map<string, string> vars; - vars["classname"] = classname_; - vars["index_in_metadata"] = SimpleItoa(idx); - vars["constexpr"] = options_.proto_h ? "constexpr " : ""; - vars["file_namespace"] = FileLevelNamespace(descriptor_->file()->name()); - + Formatter format(printer, variables_); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - vars, - "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n" - " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" - " return " - "$file_namespace$::file_level_enum_descriptors[$index_in_metadata$];\n" - "}\n"); + format( + "const ::$proto_ns$::EnumDescriptor* $classname$_descriptor() {\n" + " ::$proto_ns$::internal::AssignDescriptors(&$assign_desc_table$);\n" + " return $file_level_enum_descriptors$[$1$];\n" + "}\n", + idx); } - printer->Print(vars, - "bool $classname$_IsValid(int value) {\n" - " switch (value) {\n"); + format( + "bool $classname$_IsValid(int value) {\n" + " switch (value) {\n"); // Multiple values may have the same number. Make sure we only cover // each number once by first constructing a set containing all valid @@ -280,44 +282,40 @@ void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) { numbers.insert(value->number()); } - for (std::set<int>::iterator iter = numbers.begin(); - iter != numbers.end(); ++iter) { - printer->Print( - " case $number$:\n", - "number", Int32ToString(*iter)); + for (std::set<int>::iterator iter = numbers.begin(); iter != numbers.end(); + ++iter) { + format(" case $1$:\n", Int32ToString(*iter)); } - printer->Print(vars, - " return true;\n" - " default:\n" - " return false;\n" - " }\n" - "}\n" - "\n"); + format( + " return true;\n" + " default:\n" + " return false;\n" + " }\n" + "}\n" + "\n"); if (descriptor_->containing_type() != NULL) { + string parent = ClassName(descriptor_->containing_type(), false); // We need to "define" the static constants which were declared in the // header, to give the linker a place to put them. Or at least the C++ // standard says we have to. MSVC actually insists that we do _not_ define // them again in the .cc file, prior to VC++ 2015. - printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); + format("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); - vars["parent"] = ClassName(descriptor_->containing_type(), false); - vars["nested_name"] = descriptor_->name(); for (int i = 0; i < descriptor_->value_count(); i++) { - vars["value"] = EnumValueName(descriptor_->value(i)); - printer->Print(vars, - "$constexpr$const $classname$ $parent$::$value$;\n"); + format("$constexpr $const $classname$ $1$::$2$;\n", parent, + EnumValueName(descriptor_->value(i))); } - printer->Print(vars, - "const $classname$ $parent$::$nested_name$_MIN;\n" - "const $classname$ $parent$::$nested_name$_MAX;\n"); + format( + "const $classname$ $1$::$nested_name$_MIN;\n" + "const $classname$ $1$::$nested_name$_MAX;\n", + parent); if (generate_array_size_) { - printer->Print(vars, - "const int $parent$::$nested_name$_ARRAYSIZE;\n"); + format("const int $1$::$nested_name$_ARRAYSIZE;\n", parent); } - printer->Print("#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n"); + format("#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n"); } } diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h index 0d2488a9..6b9700ae 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -46,8 +46,10 @@ namespace protobuf { namespace io { class Printer; // printer.h } -} +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { @@ -55,20 +57,10 @@ namespace cpp { class EnumGenerator { public: // See generator.cc for the meaning of dllexport_decl. - EnumGenerator(const EnumDescriptor* descriptor, const Options& options); + EnumGenerator(const EnumDescriptor* descriptor, + const std::map<std::string, std::string>& vars, const Options& options); ~EnumGenerator(); - // Header stuff. - - // Fills the name to use when declaring the enum. This is for use when - // generating other .proto.h files. This code should be placed within the - // enum's package namespace, but NOT within any class, even for nested - // enums. A given key in enum_names will map from an enum class name to the - // EnumDescriptor that was responsible for its inclusion in the map. This can - // be used to associate the descriptor with the code generated for it. - void FillForwardDeclaration( - std::map<string, const EnumDescriptor*>* enum_names); - // Generate header code defining the enum. This code should be placed // within the enum's package namespace, but NOT within any class, even for // nested enums. @@ -82,7 +74,7 @@ class EnumGenerator { // symbols (e.g. the enum type name, all its values, etc.) into the class's // namespace. This should be placed inside the class definition in the // header. - void GenerateSymbolImports(io::Printer* printer); + void GenerateSymbolImports(io::Printer* printer) const; // Source file stuff. @@ -93,11 +85,13 @@ class EnumGenerator { private: const EnumDescriptor* descriptor_; - const string classname_; + const std::string classname_; const Options& options_; // whether to generate the *_ARRAYSIZE constant. const bool generate_array_size_; + std::map<std::string, std::string> variables_; + friend class FileGenerator; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); }; @@ -105,6 +99,6 @@ class EnumGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 828d0be5..a406f2ee 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -61,457 +61,452 @@ void SetEnumVariables(const FieldDescriptor* descriptor, EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetEnumVariables(descriptor, &variables_, options); } EnumFieldGenerator::~EnumFieldGenerator() {} -void EnumFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, "int $name$_;\n"); +void EnumFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { + Formatter format(printer, variables_); + format("int $name$_;\n"); } -void EnumFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_$name$$}$($type$ value);\n"); - printer->Annotate("{", "}", descriptor_); +void EnumFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "$deprecated_attr$$type$ ${1$$name$$}$() const;\n" + "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n", + descriptor_); } -void EnumFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return static_cast< $type$ >($name$_);\n" - "}\n" - "inline void $classname$::set_$name$($type$ value) {\n"); +void EnumFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return static_cast< $type$ >($name$_);\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - " assert($type$_IsValid(value));\n"); + format(" assert($type$_IsValid(value));\n"); } - printer->Print(variables_, - " $set_hasbit$\n" - " $name$_ = value;\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); + format( + " $set_hasbit$\n" + " $name$_ = value;\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n"); } -void EnumFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); +void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_ = $default$;\n"); } -void EnumFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "set_$name$(from.$name$());\n"); +void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("set_$name$(from.$name$());\n"); } -void EnumFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "swap($name$_, other->$name$_);\n"); +void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("swap($name$_, other->$name$_);\n"); } -void EnumFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); +void EnumFieldGenerator::GenerateConstructorCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_ = $default$;\n"); } -void EnumFieldGenerator:: -GenerateCopyConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = from.$name$_;\n"); +void EnumFieldGenerator::GenerateCopyConstructorCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_ = from.$name$_;\n"); } -void EnumFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "int value = 0;\n" - "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n" - " input, &value)));\n"); +void EnumFieldGenerator::GenerateMergeFromCodedStream( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "int value = 0;\n" + "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n" + " int, ::$proto_ns$::internal::WireFormatLite::TYPE_ENUM>(\n" + " input, &value)));\n"); if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - "set_$name$(static_cast< $type$ >(value));\n"); + format("set_$name$(static_cast< $type$ >(value));\n"); } else { - printer->Print(variables_, - "if ($type$_IsValid(value)) {\n" - " set_$name$(static_cast< $type$ >(value));\n"); + format( + "if ($type$_IsValid(value)) {\n" + " set_$name$(static_cast< $type$ >(value));\n"); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(variables_, - "} else {\n" - " mutable_unknown_fields()->AddVarint(\n" - " $number$, static_cast< ::google::protobuf::uint64>(value));\n"); + format( + "} else {\n" + " mutable_unknown_fields()->AddVarint(\n" + " $number$, static_cast<$uint64$>(value));\n"); } else { - printer->Print( - "} else {\n" - " unknown_fields_stream.WriteVarint32($tag$u);\n" - " unknown_fields_stream.WriteVarint32(\n" - " static_cast< ::google::protobuf::uint32>(value));\n", - "tag", SimpleItoa(internal::WireFormat::MakeTag(descriptor_))); + format( + "} else {\n" + " unknown_fields_stream.WriteVarint32($1$u);\n" + " unknown_fields_stream.WriteVarint32(\n" + " static_cast<$uint32$>(value));\n", + internal::WireFormat::MakeTag(descriptor_)); } - printer->Print(variables_, - "}\n"); + format("}\n"); } } -void EnumFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::WriteEnum(\n" - " $number$, this->$name$(), output);\n"); +void EnumFieldGenerator::GenerateSerializeWithCachedSizes( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "::$proto_ns$::internal::WireFormatLite::WriteEnum(\n" + " $number$, this->$name$(), output);\n"); } -void EnumFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n" - " $number$, this->$name$(), target);\n"); +void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n" + " $number$, this->$name$(), target);\n"); } -void EnumFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n"); +void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::EnumSize(this->$name$());\n"); } // =================================================================== -EnumOneofFieldGenerator:: -EnumOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : EnumFieldGenerator(descriptor, options) { +EnumOneofFieldGenerator::EnumOneofFieldGenerator( + const FieldDescriptor* descriptor, const Options& options) + : EnumFieldGenerator(descriptor, options) { SetCommonOneofFieldVariables(descriptor, &variables_); } EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {} -void EnumOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " if (has_$name$()) {\n" - " return static_cast< $type$ >($field_member$);\n" - " }\n" - " return static_cast< $type$ >($default$);\n" - "}\n" - "inline void $classname$::set_$name$($type$ value) {\n"); +void EnumOneofFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " if (has_$name$()) {\n" + " return static_cast< $type$ >($field_member$);\n" + " }\n" + " return static_cast< $type$ >($default$);\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - " assert($type$_IsValid(value));\n"); + format(" assert($type$_IsValid(value));\n"); } - printer->Print(variables_, - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " }\n" - " $field_member$ = value;\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); + format( + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " }\n" + " $field_member$ = value;\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n"); } -void EnumOneofFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$field_member$ = $default$;\n"); +void EnumOneofFieldGenerator::GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); + format("$field_member$ = $default$;\n"); } -void EnumOneofFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { +void EnumOneofFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { // Don't print any swapping code. Swapping the union will swap this field. } -void EnumOneofFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { - printer->Print(variables_, - "$ns$::_$classname$_default_instance_.$name$_ = $default$;\n"); +void EnumOneofFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n"); } // =================================================================== RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetEnumVariables(descriptor, &variables_, options); } RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} -void RepeatedEnumFieldGenerator:: -GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::RepeatedField<int> $name$_;\n"); +void RepeatedEnumFieldGenerator::GeneratePrivateMembers( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("::$proto_ns$::RepeatedField<int> $name$_;\n"); if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file(), options_)) { - printer->Print(variables_, - "mutable int _$name$_cached_byte_size_;\n"); + format("mutable std::atomic<int> _$name$_cached_byte_size_;\n"); } } -void RepeatedEnumFieldGenerator:: -GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, - "$deprecated_attr$$type$ $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$add_$name$$}$($type$ value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedField<int>& $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::RepeatedField<int>* " - "${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); -} - -void RepeatedEnumFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return static_cast< $type$ >($name$_.Get(index));\n" - "}\n" - "inline void $classname$::set_$name$(int index, $type$ value) {\n"); +void RepeatedEnumFieldGenerator::GenerateAccessorDeclarations( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n" + "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n" + "$deprecated_attr$const ::$proto_ns$::RepeatedField<int>& " + "${1$$name$$}$() const;\n" + "$deprecated_attr$::$proto_ns$::RepeatedField<int>* " + "${1$mutable_$name$$}$();\n", + descriptor_); +} + +void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions( + io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return static_cast< $type$ >($name$_.Get(index));\n" + "}\n" + "inline void $classname$::set_$name$(int index, $type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - " assert($type$_IsValid(value));\n"); + format(" assert($type$_IsValid(value));\n"); } - printer->Print(variables_, - " $name$_.Set(index, value);\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "inline void $classname$::add_$name$($type$ value) {\n"); + format( + " $name$_.Set(index, value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n" + "inline void $classname$::add_$name$($type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - " assert($type$_IsValid(value));\n"); + format(" assert($type$_IsValid(value));\n"); } - printer->Print(variables_, - " $name$_.Add(value);\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "inline const ::google::protobuf::RepeatedField<int>&\n" - "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $name$_;\n" - "}\n" - "inline ::google::protobuf::RepeatedField<int>*\n" - "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$name$_;\n" - "}\n"); + format( + " $name$_.Add(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" + "}\n" + "inline const ::$proto_ns$::RepeatedField<int>&\n" + "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" + " return $name$_;\n" + "}\n" + "inline ::$proto_ns$::RepeatedField<int>*\n" + "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" + " return &$name$_;\n" + "}\n"); } -void RepeatedEnumFieldGenerator:: -GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); +void RepeatedEnumFieldGenerator::GenerateClearingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.Clear();\n"); } -void RepeatedEnumFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); +void RepeatedEnumFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.MergeFrom(from.$name$_);\n"); } -void RepeatedEnumFieldGenerator:: -GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n"); +void RepeatedEnumFieldGenerator::GenerateSwappingCode( + io::Printer* printer) const { + Formatter format(printer, variables_); + format("$name$_.InternalSwap(&other->$name$_);\n"); } -void RepeatedEnumFieldGenerator:: -GenerateConstructorCode(io::Printer* printer) const { +void RepeatedEnumFieldGenerator::GenerateConstructorCode( + io::Printer* printer) const { // Not needed for repeated fields. } -void RepeatedEnumFieldGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) const { +void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStream( + io::Printer* printer) const { + Formatter format(printer, variables_); // Don't use ReadRepeatedPrimitive here so that the enum can be validated. - printer->Print(variables_, - "int value = 0;\n" - "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n" - " input, &value)));\n"); + format( + "int value = 0;\n" + "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n" + " int, ::$proto_ns$::internal::WireFormatLite::TYPE_ENUM>(\n" + " input, &value)));\n"); if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - "add_$name$(static_cast< $type$ >(value));\n"); + format("add_$name$(static_cast< $type$ >(value));\n"); } else { - printer->Print(variables_, - "if ($type$_IsValid(value)) {\n" - " add_$name$(static_cast< $type$ >(value));\n"); + format( + "if ($type$_IsValid(value)) {\n" + " add_$name$(static_cast< $type$ >(value));\n"); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(variables_, - "} else {\n" - " mutable_unknown_fields()->AddVarint(\n" - " $number$, static_cast< ::google::protobuf::uint64>(value));\n"); + format( + "} else {\n" + " mutable_unknown_fields()->AddVarint(\n" + " $number$, static_cast<$uint64$>(value));\n"); } else { - printer->Print( - "} else {\n" - " unknown_fields_stream.WriteVarint32(tag);\n" - " unknown_fields_stream.WriteVarint32(\n" - " static_cast< ::google::protobuf::uint32>(value));\n"); + format( + "} else {\n" + " unknown_fields_stream.WriteVarint32(tag);\n" + " unknown_fields_stream.WriteVarint32(\n" + " static_cast<$uint32$>(value));\n"); } - printer->Print("}\n"); + format("}\n"); } } -void RepeatedEnumFieldGenerator:: -GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { +void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStreamWithPacking( + io::Printer* printer) const { + Formatter format(printer, variables_); if (!descriptor_->is_packed()) { - // This path is rarely executed, so we use a non-inlined implementation. + // This path is rarely executed, so we use a non-inlined implementation. if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - "DO_((::google::protobuf::internal::" - "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" - " input,\n" - " $number$,\n" - " NULL,\n" - " NULL,\n" - " this->mutable_$name$())));\n"); + format( + "DO_((::$proto_ns$::internal::" + "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " NULL,\n" + " NULL,\n" + " this->mutable_$name$())));\n"); } else if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(variables_, - "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n" - " input,\n" - " $number$,\n" - " $type$_IsValid,\n" - " mutable_unknown_fields(),\n" - " this->mutable_$name$())));\n"); + format( + "DO_((::$proto_ns$::internal::WireFormat::" + "ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " $type$_IsValid,\n" + " mutable_unknown_fields(),\n" + " this->mutable_$name$())));\n"); } else { - printer->Print(variables_, - "DO_((::google::protobuf::internal::" - "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" - " input,\n" - " $number$,\n" - " $type$_IsValid,\n" - " &unknown_fields_stream,\n" - " this->mutable_$name$())));\n"); + format( + "DO_((::$proto_ns$::internal::" + "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " $type$_IsValid,\n" + " &unknown_fields_stream,\n" + " this->mutable_$name$())));\n"); } } else { - printer->Print(variables_, - "::google::protobuf::uint32 length;\n" - "DO_(input->ReadVarint32(&length));\n" - "::google::protobuf::io::CodedInputStream::Limit limit = " - "input->PushLimit(static_cast<int>(length));\n" - "while (input->BytesUntilLimit() > 0) {\n" - " int value = 0;\n" - " DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n" - " input, &value)));\n"); + format( + "$uint32$ length;\n" + "DO_(input->ReadVarint32(&length));\n" + "::$proto_ns$::io::CodedInputStream::Limit limit = " + "input->PushLimit(static_cast<int>(length));\n" + "while (input->BytesUntilLimit() > 0) {\n" + " int value = 0;\n" + " DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n" + " int, ::$proto_ns$::internal::WireFormatLite::TYPE_ENUM>(\n" + " input, &value)));\n"); if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, - " add_$name$(static_cast< $type$ >(value));\n"); + format(" add_$name$(static_cast< $type$ >(value));\n"); } else { - printer->Print(variables_, - " if ($type$_IsValid(value)) {\n" - " add_$name$(static_cast< $type$ >(value));\n" - " } else {\n"); + format( + " if ($type$_IsValid(value)) {\n" + " add_$name$(static_cast< $type$ >(value));\n" + " } else {\n"); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(variables_, - " mutable_unknown_fields()->AddVarint(\n" - " $number$, static_cast< ::google::protobuf::uint64>(value));\n"); + format( + " mutable_unknown_fields()->AddVarint(\n" + " $number$, static_cast<$uint64$>(value));\n"); } else { - printer->Print(variables_, - " unknown_fields_stream.WriteVarint32(tag);\n" - " unknown_fields_stream.WriteVarint32(\n" - " static_cast< ::google::protobuf::uint32>(value));\n"); + format( + " unknown_fields_stream.WriteVarint32(tag);\n" + " unknown_fields_stream.WriteVarint32(\n" + " static_cast<$uint32$>(value));\n"); } - printer->Print( - " }\n"); + format(" }\n"); } - printer->Print(variables_, - "}\n" - "input->PopLimit(limit);\n"); + format( + "}\n" + "input->PopLimit(limit);\n"); } } -void RepeatedEnumFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { +void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizes( + io::Printer* printer) const { + Formatter format(printer, variables_); if (descriptor_->is_packed()) { // Write the tag and the size. - printer->Print(variables_, - "if (this->$name$_size() > 0) {\n" - " ::google::protobuf::internal::WireFormatLite::WriteTag(\n" - " $number$,\n" - " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" - " output);\n" - " output->WriteVarint32(\n" - " static_cast< ::google::protobuf::uint32>(_$name$_cached_byte_size_));\n" - "}\n"); + format( + "if (this->$name$_size() > 0) {\n" + " ::$proto_ns$::internal::WireFormatLite::WriteTag(\n" + " $number$,\n" + " " + "::$proto_ns$::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " output);\n" + " output->WriteVarint32(_$name$_cached_byte_size_.load(\n" + " std::memory_order_relaxed));\n" + "}\n"); } - printer->Print(variables_, - "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); + format("for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); if (descriptor_->is_packed()) { - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n" - " this->$name$(i), output);\n"); + format( + " ::$proto_ns$::internal::WireFormatLite::WriteEnumNoTag(\n" + " this->$name$(i), output);\n"); } else { - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::WriteEnum(\n" - " $number$, this->$name$(i), output);\n"); + format( + " ::$proto_ns$::internal::WireFormatLite::WriteEnum(\n" + " $number$, this->$name$(i), output);\n"); } - printer->Print("}\n"); + format("}\n"); } -void RepeatedEnumFieldGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { +void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const { + Formatter format(printer, variables_); if (descriptor_->is_packed()) { // Write the tag and the size. - printer->Print(variables_, - "if (this->$name$_size() > 0) {\n" - " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" - " $number$,\n" - " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" - " target);\n" - " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(" - " static_cast< ::google::protobuf::uint32>(\n" - " _$name$_cached_byte_size_), target);\n" - " target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n" - " this->$name$_, target);\n" - "}\n"); + format( + "if (this->$name$_size() > 0) {\n" + " target = ::$proto_ns$::internal::WireFormatLite::WriteTagToArray(\n" + " $number$,\n" + " " + "::$proto_ns$::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " target);\n" + " target = ::$proto_ns$::io::CodedOutputStream::WriteVarint32ToArray(" + " _$name$_cached_byte_size_.load(std::memory_order_relaxed),\n" + " target);\n" + " target = " + "::$proto_ns$::internal::WireFormatLite::WriteEnumNoTagToArray(\n" + " this->$name$_, target);\n" + "}\n"); } else { - printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n" - " $number$, this->$name$_, target);\n"); + format( + "target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n" + " $number$, this->$name$_, target);\n"); } } -void RepeatedEnumFieldGenerator:: -GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "{\n" - " size_t data_size = 0;\n" - " unsigned int count = static_cast<unsigned int>(this->$name$_size());"); - printer->Indent(); - printer->Print(variables_, +void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const { + Formatter format(printer, variables_); + format( + "{\n" + " size_t data_size = 0;\n" + " unsigned int count = static_cast<unsigned int>(this->$name$_size());"); + format.Indent(); + format( "for (unsigned int i = 0; i < count; i++) {\n" - " data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n" + " data_size += ::$proto_ns$::internal::WireFormatLite::EnumSize(\n" " this->$name$(static_cast<int>(i)));\n" "}\n"); if (descriptor_->is_packed()) { - printer->Print(variables_, - "if (data_size > 0) {\n" - " total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::Int32Size(\n" - " static_cast< ::google::protobuf::int32>(data_size));\n" - "}\n" - "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" - "_$name$_cached_byte_size_ = cached_size;\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" - "total_size += data_size;\n"); + format( + "if (data_size > 0) {\n" + " total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::Int32Size(\n" + " static_cast<$int32$>(data_size));\n" + "}\n" + "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n" + "_$name$_cached_byte_size_.store(cached_size,\n" + " std::memory_order_relaxed);\n" + "total_size += data_size;\n"); } else { - printer->Print(variables_, - "total_size += ($tag_size$UL * count) + data_size;\n"); + format("total_size += ($tag_size$UL * count) + data_size;\n"); } - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h index d0e87b79..b43d402b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h @@ -63,10 +63,6 @@ class EnumFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - protected: - const FieldDescriptor* descriptor_; - std::map<string, string> variables_; - private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); }; @@ -109,15 +105,12 @@ class RepeatedEnumFieldGenerator : public FieldGenerator { void GenerateByteSize(io::Printer* printer) const; private: - const FieldDescriptor* descriptor_; - std::map<string, string> variables_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc index c416ba10..f866eb6e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.cc +++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc @@ -84,86 +84,98 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, break; default: type_traits_.append("PrimitiveTypeTraits< "); - type_traits_.append(PrimitiveTypeName(descriptor_->cpp_type())); + type_traits_.append(PrimitiveTypeName(options_, descriptor_->cpp_type())); type_traits_.append(" >"); break; } + SetCommonVars(options, &variables_); + variables_["extendee"] = ExtendeeClassName(descriptor_); + variables_["type_traits"] = type_traits_; + string name = descriptor_->name(); + variables_["name"] = name; + variables_["constant_name"] = FieldConstantName(descriptor_); + variables_["field_type"] = + SimpleItoa(static_cast<int>(descriptor_->type())); + variables_["packed"] = descriptor_->options().packed() ? "true" : "false"; + + string scope = + IsScoped() ? ClassName(descriptor_->extension_scope(), false) + "::" : ""; + variables_["scope"] = scope; + string scoped_name = scope + name; + variables_["scoped_name"] = scoped_name; + variables_["number"] = SimpleItoa(descriptor_->number()); } ExtensionGenerator::~ExtensionGenerator() {} -void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) { - std::map<string, string> vars; - vars["extendee" ] = ExtendeeClassName(descriptor_); - vars["number" ] = SimpleItoa(descriptor_->number()); - vars["type_traits" ] = type_traits_; - vars["name" ] = descriptor_->name(); - vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type())); - vars["packed" ] = descriptor_->options().packed() ? "true" : "false"; - vars["constant_name"] = FieldConstantName(descriptor_); +bool ExtensionGenerator::IsScoped() const { + return descriptor_->extension_scope() != nullptr; +} + +void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) const { + Formatter format(printer, variables_); // If this is a class member, it needs to be declared "static". Otherwise, // it needs to be "extern". In the latter case, it also needs the DLL // export/import specifier. - if (descriptor_->extension_scope() == NULL) { - vars["qualifier"] = "extern"; + string qualifier; + if (!IsScoped()) { + qualifier = "extern"; if (!options_.dllexport_decl.empty()) { - vars["qualifier"] = options_.dllexport_decl + " " + vars["qualifier"]; + qualifier = options_.dllexport_decl + " " + qualifier; } } else { - vars["qualifier"] = "static"; + qualifier = "static"; } - printer->Print(vars, - "static const int $constant_name$ = $number$;\n" - "$qualifier$ ::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n" - " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n" - " $name$;\n" - ); + format( + "static const int $constant_name$ = $number$;\n" + "$1$ ::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n" + " ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n" + " $name$;\n", + qualifier); } void ExtensionGenerator::GenerateDefinition(io::Printer* printer) { - // If this is a class member, it needs to be declared in its class scope. - string scope = (descriptor_->extension_scope() == NULL) ? "" : - ClassName(descriptor_->extension_scope(), false) + "::"; - string name = scope + descriptor_->name(); - - std::map<string, string> vars; - vars["extendee" ] = ExtendeeClassName(descriptor_); - vars["type_traits" ] = type_traits_; - vars["name" ] = name; - vars["constant_name"] = FieldConstantName(descriptor_); - vars["default" ] = DefaultValue(descriptor_); - vars["field_type" ] = SimpleItoa(static_cast<int>(descriptor_->type())); - vars["packed" ] = descriptor_->options().packed() ? "true" : "false"; - vars["scope" ] = scope; + // If we are building for lite with implicit weak fields, we want to skip over + // any custom options (i.e. extensions of messages from descriptor.proto). + // This prevents the creation of any unnecessary linker references to the + // descriptor messages. + if (options_.lite_implicit_weak_fields && + descriptor_->containing_type()->file()->name() == + "net/proto2/proto/descriptor.proto") { + return; + } + Formatter format(printer, variables_); + string default_str; + // If this is a class member, it needs to be declared in its class scope. if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { // We need to declare a global string which will contain the default value. // We cannot declare it at class scope because that would require exposing // it in the header which would be annoying for other reasons. So we // replace :: with _ in the name and declare it as a global. - string global_name = StringReplace(name, "::", "_", true); - vars["global_name"] = global_name; - printer->Print(vars, - "const ::std::string $global_name$_default($default$);\n"); - - // Update the default to refer to the string global. - vars["default"] = global_name + "_default"; + default_str = + StringReplace(variables_["scoped_name"], "::", "_", true) + "_default"; + format("const ::std::string $1$($2$);\n", default_str, + DefaultValue(options_, descriptor_)); + } else { + default_str = DefaultValue(options_, descriptor_); } // Likewise, class members need to declare the field constant variable. - if (descriptor_->extension_scope() != NULL) { - printer->Print(vars, - "#if !defined(_MSC_VER) || _MSC_VER >= 1900\n" - "const int $scope$$constant_name$;\n" - "#endif\n"); + if (IsScoped()) { + format( + "#if !defined(_MSC_VER) || _MSC_VER >= 1900\n" + "const int $scope$$constant_name$;\n" + "#endif\n"); } - printer->Print(vars, - "::google::protobuf::internal::ExtensionIdentifier< $extendee$,\n" - " ::google::protobuf::internal::$type_traits$, $field_type$, $packed$ >\n" - " $name$($constant_name$, $default$);\n"); + format( + "::$proto_ns$::internal::ExtensionIdentifier< $extendee$,\n" + " ::$proto_ns$::internal::$type_traits$, $field_type$, $packed$ >\n" + " $scoped_name$($constant_name$, $1$);\n", + default_str); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h index 30236d71..72413f6b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.h +++ b/src/google/protobuf/compiler/cpp/cpp_extension.h @@ -35,18 +35,22 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__ +#include <map> #include <string> + #include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/cpp/cpp_options.h> namespace google { namespace protobuf { - class FieldDescriptor; // descriptor.h - namespace io { - class Printer; // printer.h - } +class FieldDescriptor; // descriptor.h +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { @@ -62,22 +66,26 @@ class ExtensionGenerator { ~ExtensionGenerator(); // Header stuff. - void GenerateDeclaration(io::Printer* printer); + void GenerateDeclaration(io::Printer* printer) const; // Source file stuff. void GenerateDefinition(io::Printer* printer); + bool IsScoped() const; + private: const FieldDescriptor* descriptor_; - string type_traits_; + std::string type_traits_; Options options_; + std::map<std::string, std::string> variables_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc index 0de20f84..582da4ae 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -38,6 +38,7 @@ #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/compiler/cpp/cpp_primitive_field.h> #include <google/protobuf/compiler/cpp/cpp_string_field.h> + #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/cpp/cpp_enum_field.h> @@ -58,6 +59,7 @@ using internal::WireFormat; void SetCommonFieldVariables(const FieldDescriptor* descriptor, std::map<string, string>* variables, const Options& options) { + SetCommonVars(options, variables); (*variables)["ns"] = Namespace(descriptor); (*variables)["name"] = FieldName(descriptor); (*variables)["index"] = SimpleItoa(descriptor->index()); @@ -67,20 +69,17 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["field_member"] = FieldName(descriptor) + "_"; (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); - (*variables)["deprecation"] = descriptor->options().deprecated() - ? " PROTOBUF_DEPRECATED" : ""; - (*variables)["deprecated_attr"] = descriptor->options().deprecated() - ? "GOOGLE_PROTOBUF_DEPRECATED_ATTR " : ""; + WireFormat::TagSize(descriptor->number(), descriptor->type())); + (*variables)["deprecated_attr"] = + DeprecatedAttribute(options, descriptor->options().deprecated()); + (*variables)["set_hasbit"] = ""; + (*variables)["clear_hasbit"] = ""; if (HasFieldPresence(descriptor->file())) { - (*variables)["set_hasbit"] = - "set_has_" + FieldName(descriptor) + "();"; - (*variables)["clear_hasbit"] = - "clear_has_" + FieldName(descriptor) + "();"; + (*variables)["set_hasbit_io"] = + "HasBitSetters::set_has_" + FieldName(descriptor) + "(this);"; } else { - (*variables)["set_hasbit"] = ""; - (*variables)["clear_hasbit"] = ""; + (*variables)["set_hasbit_io"] = ""; } // These variables are placeholders to pick out the beginning and ends of @@ -91,11 +90,24 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["}"] = ""; } +void FieldGenerator::SetHasBitIndex(int32 has_bit_index) { + if (!HasFieldPresence(descriptor_->file()) || has_bit_index == -1) { + return; + } + variables_["set_hasbit"] = StrCat( + "_has_bits_[", has_bit_index / 32, "] |= 0x", + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;"); + variables_["clear_hasbit"] = StrCat( + "_has_bits_[", has_bit_index / 32, "] &= ~0x", + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;"); +} + void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, std::map<string, string>* variables) { const string prefix = descriptor->containing_oneof()->name() + "_."; (*variables)["oneof_name"] = descriptor->containing_oneof()->name(); - (*variables)["field_member"] = StrCat(prefix, (*variables)["name"], "_"); + (*variables)["field_member"] = + StrCat(prefix, (*variables)["name"], "_"); } FieldGenerator::~FieldGenerator() {} @@ -114,7 +126,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Options& options, - SCCAnalyzer* scc_analyzer) + MessageSCCAnalyzer* scc_analyzer) : descriptor_(descriptor), options_(options), field_generators_(descriptor->field_count()) { @@ -125,9 +137,22 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, } } -FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, - const Options& options, - SCCAnalyzer* scc_analyzer) { +FieldGenerator* FieldGeneratorMap::MakeGoogleInternalGenerator( + const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer) { + + return nullptr; +} + +FieldGenerator* FieldGeneratorMap::MakeGenerator( + const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer) { + FieldGenerator* generator = + MakeGoogleInternalGenerator(field, options, scc_analyzer); + if (generator) { + return generator; + } + if (field->is_repeated()) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: @@ -138,11 +163,7 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, scc_analyzer); } case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // RepeatedStringFieldGenerator handles unknown ctypes. - case FieldOptions::STRING: - return new RepeatedStringFieldGenerator(field, options); - } + return new RepeatedStringFieldGenerator(field, options); case FieldDescriptor::CPPTYPE_ENUM: return new RepeatedEnumFieldGenerator(field, options); default: @@ -153,11 +174,7 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, case FieldDescriptor::CPPTYPE_MESSAGE: return new MessageOneofFieldGenerator(field, options, scc_analyzer); case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // StringOneofFieldGenerator handles unknown ctypes. - case FieldOptions::STRING: - return new StringOneofFieldGenerator(field, options); - } + return new StringOneofFieldGenerator(field, options); case FieldDescriptor::CPPTYPE_ENUM: return new EnumOneofFieldGenerator(field, options); default: @@ -168,11 +185,7 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, case FieldDescriptor::CPPTYPE_MESSAGE: return new MessageFieldGenerator(field, options, scc_analyzer); case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // StringFieldGenerator handles unknown ctypes. - case FieldOptions::STRING: - return new StringFieldGenerator(field, options); - } + return new StringFieldGenerator(field, options); case FieldDescriptor::CPPTYPE_ENUM: return new EnumFieldGenerator(field, options); default: diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index 8cdbe886..43a3e367 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -45,11 +45,13 @@ namespace google { namespace protobuf { - namespace io { - class Printer; // printer.h - } +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { @@ -59,15 +61,17 @@ namespace cpp { // ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size', // 'deprecation']. void SetCommonFieldVariables(const FieldDescriptor* descriptor, - std::map<string, string>* variables, + std::map<std::string, std::string>* variables, const Options& options); void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, - std::map<string, string>* variables); + std::map<std::string, std::string>* variables); class FieldGenerator { public: - explicit FieldGenerator(const Options& options) : options_(options) {} + explicit FieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : descriptor_(descriptor), options_(options) {} virtual ~FieldGenerator(); // Generate lines of code declaring members fields of the message class @@ -95,17 +99,27 @@ class FieldGenerator { virtual void GenerateNonInlineAccessorDefinitions( io::Printer* /*printer*/) const {} + // Generate declarations of accessors that are for internal purposes only. + // Most field types don't need this, so the default implementation is empty. + virtual void GenerateInternalAccessorDefinitions( + io::Printer* /*printer*/) const {} + + // Generate definitions of accessors that are for internal purposes only. + // Most field types don't need this, so the default implementation is empty. + virtual void GenerateInternalAccessorDeclarations( + io::Printer* /*printer*/) const {} + // Generate lines of code (statements, not declarations) which clear the // field. This is used to define the clear_$name$() method virtual void GenerateClearingCode(io::Printer* printer) const = 0; - // Generate lines of code (statements, not declarations) which clear the field - // as part of the Clear() method for the whole message. For message types - // which have field presence bits, MessageGenerator::GenerateClear will have - // already checked the presence bits. + // Generate lines of code (statements, not declarations) which clear the + // field as part of the Clear() method for the whole message. For message + // types which have field presence bits, MessageGenerator::GenerateClear + // will have already checked the presence bits. // - // Since most field types can re-use GenerateClearingCode, this method is not - // pure virtual. + // Since most field types can re-use GenerateClearingCode, this method is + // not pure virtual. virtual void GenerateMessageClearingCode(io::Printer* printer) const { GenerateClearingCode(printer); } @@ -140,17 +154,17 @@ class FieldGenerator { // Generate a manual destructor invocation for use when the message is on an // arena. The code that this method generates will be executed inside a - // shared-for-the-whole-message-class method registered with OwnDestructor(). - // The method should return |true| if it generated any code that requires a - // call; this allows the message generator to eliminate the OwnDestructor() - // registration if no fields require it. + // shared-for-the-whole-message-class method registered with + // OwnDestructor(). The method should return |true| if it generated any code + // that requires a call; this allows the message generator to eliminate the + // OwnDestructor() registration if no fields require it. virtual bool GenerateArenaDestructorCode(io::Printer* printer) const { return false; } // Generate code that allocates the fields's default instance. - virtual void GenerateDefaultInstanceAllocator(io::Printer* /*printer*/) - const {} + virtual void GenerateDefaultInstanceAllocator( + io::Printer* /*printer*/) const {} // Generate lines to decode this field, which will be placed inside the // message's MergeFromCodedStream() method. @@ -162,8 +176,8 @@ class FieldGenerator { // Generate lines to decode this field from a packed value, which will be // placed inside the message's MergeFromCodedStream() method. - virtual void GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) - const; + virtual void GenerateMergeFromCodedStreamWithPacking( + io::Printer* printer) const; // Generate lines to serialize this field, which are placed within the // message's SerializeWithCachedSizes() method. @@ -184,8 +198,12 @@ class FieldGenerator { virtual uint32 CalculateFieldTag() const { return 0; } virtual bool IsInlined() const { return false; } + void SetHasBitIndex(int32 has_bit_index); + protected: + const FieldDescriptor* descriptor_; const Options& options_; + std::map<std::string, std::string> variables_; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); @@ -195,19 +213,28 @@ class FieldGenerator { class FieldGeneratorMap { public: FieldGeneratorMap(const Descriptor* descriptor, const Options& options, - SCCAnalyzer* scc_analyzer); + MessageSCCAnalyzer* scc_analyzer); ~FieldGeneratorMap(); const FieldGenerator& get(const FieldDescriptor* field) const; + void SetHasBitIndices(const std::vector<int>& has_bit_indices_) { + for (int i = 0; i < descriptor_->field_count(); ++i) { + field_generators_[i]->SetHasBitIndex(has_bit_indices_[i]); + } + } + private: const Descriptor* descriptor_; const Options& options_; std::vector<std::unique_ptr<FieldGenerator>> field_generators_; + static FieldGenerator* MakeGoogleInternalGenerator( + const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer); static FieldGenerator* MakeGenerator(const FieldDescriptor* field, const Options& options, - SCCAnalyzer* scc_analyzer); + MessageSCCAnalyzer* scc_analyzer); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; @@ -215,6 +242,6 @@ class FieldGeneratorMap { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index 02f360bb..1e80715d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -44,72 +44,79 @@ #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/compiler/cpp/cpp_message.h> #include <google/protobuf/compiler/cpp/cpp_service.h> +#include <google/protobuf/compiler/scc.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/stubs/strutil.h> + +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { namespace cpp { FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) - : file_(file), - options_(options), - scc_analyzer_(options), - enum_generators_owner_( - new std::unique_ptr<EnumGenerator>[file->enum_type_count()]), - service_generators_owner_( - new std::unique_ptr<ServiceGenerator>[file->service_count()]), - extension_generators_owner_( - new std::unique_ptr<ExtensionGenerator>[file->extension_count()]) { + : file_(file), options_(options), scc_analyzer_(options) { + // These variables are the same on a file level + SetCommonVars(options, &variables_); + variables_["dllexport_decl"] = options.dllexport_decl; + variables_["tablename"] = UniqueName("TableStruct", file_, options_); + variables_["assign_desc_table"] = + UniqueName("assign_descriptors_table", file_, options_); + variables_["file_level_metadata"] = + UniqueName("file_level_metadata", file_, options_); + variables_["file_level_enum_descriptors"] = + UniqueName("file_level_enum_descriptors", file_, options_); + variables_["file_level_service_descriptors"] = + UniqueName("file_level_service_descriptors", file_, options_); + variables_["add_descriptors"] = UniqueName("AddDescriptors", file_, options_); + variables_["filename"] = file_->name(); + variables_["package_ns"] = Namespace(file_); + variables_["init_defaults"] = UniqueName("InitDefaults", file_, options_); + std::vector<const Descriptor*> msgs = FlattenMessagesInFile(file); for (int i = 0; i < msgs.size(); i++) { // Deleted in destructor MessageGenerator* msg_gen = - new MessageGenerator(msgs[i], i, options, &scc_analyzer_); - message_generators_.push_back(msg_gen); + new MessageGenerator(msgs[i], variables_, i, options, &scc_analyzer_); + message_generators_.emplace_back(msg_gen); msg_gen->AddGenerators(&enum_generators_, &extension_generators_); } for (int i = 0; i < file->enum_type_count(); i++) { - enum_generators_owner_[i].reset( - new EnumGenerator(file->enum_type(i), options)); - enum_generators_.push_back(enum_generators_owner_[i].get()); + enum_generators_.emplace_back( + new EnumGenerator(file->enum_type(i), variables_, options)); } for (int i = 0; i < file->service_count(); i++) { - service_generators_owner_[i].reset( - new ServiceGenerator(file->service(i), options)); - service_generators_.push_back(service_generators_owner_[i].get()); + service_generators_.emplace_back( + new ServiceGenerator(file->service(i), variables_, options)); } if (HasGenericServices(file_, options_)) { for (int i = 0; i < service_generators_.size(); i++) { service_generators_[i]->index_in_metadata_ = i; } } - for (int i = 0; i < file->extension_count(); i++) { - extension_generators_owner_[i].reset( + extension_generators_.emplace_back( new ExtensionGenerator(file->extension(i), options)); - extension_generators_.push_back(extension_generators_owner_[i].get()); } - - - package_parts_ = Split(file_->package(), ".", true); -} - -FileGenerator::~FileGenerator() { - for (int i = 0; i < message_generators_.size(); i++) { - delete message_generators_[i]; + for (int i = 0; i < file->weak_dependency_count(); ++i) { + weak_deps_.insert(file->weak_dependency(i)); } } +FileGenerator::~FileGenerator() = default; + void FileGenerator::GenerateMacroUndefs(io::Printer* printer) { + Formatter format(printer, variables_); // Only do this for protobuf's own types. There are some google3 protos using // macros as field names and the generated code compiles after the macro // expansion. Undefing these macros actually breaks such code. - if (file_->name() != "google/protobuf/compiler/plugin.proto") { + if (file_->name() != "net/proto2/compiler/proto/plugin.proto" && + file_->name() != "google/protobuf/compiler/plugin.proto") { return; } std::vector<string> names_to_undef; @@ -126,70 +133,89 @@ void FileGenerator::GenerateMacroUndefs(io::Printer* printer) { } } for (int i = 0; i < names_to_undef.size(); ++i) { - printer->Print( - "#ifdef $name$\n" - "#undef $name$\n" + format( + "#ifdef $1$\n" + "#undef $1$\n" "#endif\n", - "name", names_to_undef[i]); + names_to_undef[i]); } } void FileGenerator::GenerateHeader(io::Printer* printer) { - printer->Print( - "// @@protoc_insertion_point(includes)\n"); + Formatter format(printer, variables_); - printer->Print("#define PROTOBUF_INTERNAL_EXPORT_$filename$ $export$\n", - "filename", FileLevelNamespace(file_), - "export", options_.dllexport_decl); + // port_def.inc must be included after all other includes. + IncludeFile("net/proto2/public/port_def.inc", printer); + format("#define $1$$ dllexport_decl$\n", + UniqueName("PROTOBUF_INTERNAL_EXPORT", file_, options_)); GenerateMacroUndefs(printer); + if (IsProto2MessageSetFile(file_, options_)) { + // Proto2 MessageSet overrides GetMapper() so we forward declare TagMapper + // to avoid inclusion of "tagmapper.h". + format("class TagMapper;\n"); + } + + if (!options_.opensource_runtime) { + // EmbeddedMessageHolder is a proxy class to provide access into arena + // constructors for proto1 message objects. + // See net/proto/proto_arena_internal.h + format( + "namespace proto {\n" + "namespace internal {\n" + "template <typename T> struct EmbeddedMessageHolder;\n" + "} // namespace internal\n" + "} // namespace proto\n"); + } GenerateGlobalStateFunctionDeclarations(printer); GenerateForwardDeclarations(printer); { - NamespaceOpener ns(Namespace(file_), printer); + NamespaceOpener ns(Namespace(file_), format); - printer->Print("\n"); + format("\n"); GenerateEnumDefinitions(printer); - printer->Print(kThickSeparator); - printer->Print("\n"); + format(kThickSeparator); + format("\n"); GenerateMessageDefinitions(printer); - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + format("\n"); + format(kThickSeparator); + format("\n"); GenerateServiceDefinitions(printer); GenerateExtensionIdentifiers(printer); - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + format("\n"); + format(kThickSeparator); + format("\n"); GenerateInlineFunctionDefinitions(printer); - printer->Print( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n" - "\n"); + format( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n" + "\n"); } // We need to specialize some templates in the ::google::protobuf namespace: GenerateProto2NamespaceEnumSpecializations(printer); - printer->Print( - "\n" - "// @@protoc_insertion_point(global_scope)\n" - "\n"); + format( + "\n" + "// @@protoc_insertion_point(global_scope)\n" + "\n"); + IncludeFile("net/proto2/public/port_undef.inc", printer); } void FileGenerator::GenerateProtoHeader(io::Printer* printer, const string& info_path) { + Formatter format(printer, variables_); if (!options_.proto_h) { return; } @@ -197,99 +223,187 @@ void FileGenerator::GenerateProtoHeader(io::Printer* printer, string filename_identifier = FilenameIdentifier(file_->name()); GenerateTopHeaderGuard(printer, filename_identifier); + if (!options_.opensource_runtime) { + format( + "#ifdef SWIG\n" + "#error \"Do not SWIG-wrap protobufs.\"\n" + "#endif // SWIG\n" + "\n"); + } + + if (IsBootstrapProto(options_, file_)) { + format("// IWYU pragma: private, include \"$1$.proto.h\"\n\n", + StripProto(file_->name())); + } GenerateLibraryIncludes(printer); for (int i = 0; i < file_->public_dependency_count(); i++) { const FileDescriptor* dep = file_->public_dependency(i); const char* extension = ".proto.h"; + // The proto1 compiler only generates .pb.h files, so even if we are + // running in proto-h mode, we can only use the .pb.h. + if (IsProto1(dep, options_)) { + extension = ".pb.h"; + } string dependency = StripProto(dep->name()) + extension; - printer->Print( - "#include \"$dependency$\" // IWYU pragma: export\n", - "dependency", dependency); + format("#include \"$1$\"\n", dependency); } + format("// @@protoc_insertion_point(includes)\n"); + GenerateMetadataPragma(printer, info_path); GenerateHeader(printer); + IncludeFile("net/proto2/public/port_undef.inc", printer); + GenerateBottomHeaderGuard(printer, filename_identifier); } void FileGenerator::GeneratePBHeader(io::Printer* printer, const string& info_path) { + Formatter format(printer, variables_); string filename_identifier = FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : "")); GenerateTopHeaderGuard(printer, filename_identifier); if (options_.proto_h) { string target_basename = StripProto(file_->name()); - printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n", - "basename", target_basename); + if (!options_.opensource_runtime) { + GetBootstrapBasename(options_, target_basename, &target_basename); + } + format("#include \"$1$.proto.h\" // IWYU pragma: export\n", + target_basename); } else { GenerateLibraryIncludes(printer); } - GenerateDependencyIncludes(printer); + if (options_.transitive_pb_h) { + GenerateDependencyIncludes(printer); + } + + // This is unfortunately necessary for some plugins. I don't see why we + // need two of the same insertion points. + // TODO(gerbens) remove this. + format("// @@protoc_insertion_point(includes)\n"); + GenerateMetadataPragma(printer, info_path); if (!options_.proto_h) { GenerateHeader(printer); } else { - // This is unfortunately necessary for some plugins. I don't see why we - // need two of the same insertion points. - // TODO(gerbens) remove this. - printer->Print( - "// @@protoc_insertion_point(includes)\n"); { - NamespaceOpener ns(Namespace(file_), printer); - printer->Print( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n"); + NamespaceOpener ns(Namespace(file_), format); + format( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n"); } - printer->Print( - "\n" - "// @@protoc_insertion_point(global_scope)\n" - "\n"); + format( + "\n" + "// @@protoc_insertion_point(global_scope)\n" + "\n"); } GenerateBottomHeaderGuard(printer, filename_identifier); } +void FileGenerator::DoIncludeFile(const string& google3_name, bool do_export, + io::Printer* printer) { + Formatter format(printer, variables_); + const string prefix = "net/proto2/"; + GOOGLE_CHECK(google3_name.find(prefix) == 0) << google3_name; + + if (options_.opensource_runtime) { + string path = google3_name.substr(prefix.size()); + + path = StringReplace(path, "internal/", "", false); + path = StringReplace(path, "proto/", "", false); + path = StringReplace(path, "public/", "", false); + if (options_.opensource_include_paths) { + format("#include <google/protobuf/$1$>", path); + } else { + format( + "#include " + "\"third_party/protobuf/testing/extracted/src/google/protobuf/$1$\"", + path); + } + } else { + format("#include \"$1$\"", google3_name); + } + + if (do_export) { + format(" // IWYU pragma: export"); + } + + format("\n"); +} + +string FileGenerator::CreateHeaderInclude(const string& basename, + const FileDescriptor* file) { + bool use_system_include = false; + string name = basename; + + if (options_.opensource_runtime) { + if (IsWellKnownMessage(file)) { + if (options_.opensource_include_paths) { + use_system_include = true; + } else { + name = "third_party/protobuf/testing/extracted/src/" + basename; + } + } + } + + string left = "\""; + string right = "\""; + if (use_system_include) { + left = "<"; + right = ">"; + } + return left + name + right; +} + void FileGenerator::GenerateSourceIncludes(io::Printer* printer) { + Formatter format(printer, variables_); string target_basename = StripProto(file_->name()); - const bool use_system_include = IsWellKnownMessage(file_); - - string header = target_basename + (options_.proto_h ? ".proto.h" : ".pb.h"); - printer->Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $filename$\n" - "\n" - "#include $left$$header$$right$\n" - "\n" - "#include <algorithm>\n" // for swap() - "\n" - "#include <google/protobuf/stubs/common.h>\n" - "#include <google/protobuf/stubs/port.h>\n" - "#include <google/protobuf/io/coded_stream.h>\n" - "#include <google/protobuf/wire_format_lite_inl.h>\n", - "filename", file_->name(), - "header", header, - "left", use_system_include ? "<" : "\"", - "right", use_system_include ? ">" : "\""); + if (!options_.opensource_runtime) { + GetBootstrapBasename(options_, target_basename, &target_basename); + } + target_basename += options_.proto_h ? ".proto.h" : ".pb.h"; + format( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n" + "#include $1$\n" + "\n" + "#include <algorithm>\n" // for swap() + "\n", + CreateHeaderInclude(target_basename, file_)); + + if (options_.opensource_runtime) { + DoIncludeFile("net/proto2/public/stubs/common.h", false, printer); + } + + IncludeFile("net/proto2/io/public/coded_stream.h", printer); + // TODO(gerbens) This is to include parse_context.h, we need a better way + IncludeFile("net/proto2/public/extension_set.h", printer); + IncludeFile("net/proto2/public/wire_format_lite_inl.h", printer); // Unknown fields implementation in lite mode uses StringOutputStream if (!UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) { - printer->Print( - "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n"); + IncludeFile("net/proto2/io/public/zero_copy_stream_impl_lite.h", printer); } if (HasDescriptorMethods(file_, options_)) { - printer->Print( - "#include <google/protobuf/descriptor.h>\n" - "#include <google/protobuf/generated_message_reflection.h>\n" - "#include <google/protobuf/reflection_ops.h>\n" - "#include <google/protobuf/wire_format.h>\n"); + IncludeFile("net/proto2/public/descriptor.h", printer); + IncludeFile("net/proto2/public/generated_message_reflection.h", printer); + IncludeFile("net/proto2/public/reflection_ops.h", printer); + IncludeFile("net/proto2/public/wire_format.h", printer); + } + if (IsProto2MessageSetFile(file_, options_)) { + format( + // Implementation of proto1 MessageSet API methods. + "#include \"net/proto2/bridge/internal/message_set_util.h\"\n"); } if (options_.proto_h) { @@ -298,104 +412,100 @@ void FileGenerator::GenerateSourceIncludes(io::Printer* printer) { const FileDescriptor* dep = file_->dependency(i); const char* extension = ".proto.h"; string basename = StripProto(dep->name()); + // Do not import weak deps. + if (!options_.opensource_runtime && IsDepWeak(dep)) continue; + // The proto1 compiler only generates .pb.h files, so even if we are + // running in proto-h mode, we can only use the .pb.h. + if (IsProto1(dep, options_)) { + extension = ".pb.h"; + } + if (IsBootstrapProto(options_, file_)) { + GetBootstrapBasename(options_, basename, &basename); + } string dependency = basename + extension; - printer->Print( - "#include \"$dependency$\"\n", - "dependency", dependency); + format("#include \"$1$\"\n", dependency); } } - // TODO(gerbens) Remove this when all code in google is using the same - // proto library. This is a temporary hack to force build errors if - // the proto library is compiled with GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS - // and is also linking internal proto2. This is to prevent regressions while - // we work cleaning up the code base. After this is completed and we have - // one proto lib all code uses this should be removed. - printer->Print( - "// This is a temporary google only hack\n" - "#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS\n" - "#include \"third_party/protobuf/version.h\"\n" - "#endif\n"); - - printer->Print( - "// @@protoc_insertion_point(includes)\n"); + format("// @@protoc_insertion_point(includes)\n"); + IncludeFile("net/proto2/public/port_def.inc", printer); } void FileGenerator::GenerateSourceDefaultInstance(int idx, io::Printer* printer) { - printer->Print( - "class $classname$DefaultTypeInternal {\n" + Formatter format(printer, variables_); + format( + "class $1$DefaultTypeInternal {\n" " public:\n" - " ::google::protobuf::internal::ExplicitlyConstructed<$classname$>\n" - " _instance;\n", - "classname", message_generators_[idx]->classname_); - printer->Indent(); + " ::$proto_ns$::internal::ExplicitlyConstructed<$1$> _instance;\n", + message_generators_[idx]->classname_); + format.Indent(); message_generators_[idx]->GenerateExtraDefaultFields(printer); - printer->Outdent(); - printer->Print("} _$classname$_default_instance_;\n", "classname", - message_generators_[idx]->classname_); + format.Outdent(); + format("} _$1$_default_instance_;\n", message_generators_[idx]->classname_); } -namespace { - // Generates weak symbol declarations for types that are to be considered weakly // referenced. -void GenerateInternalForwardDeclarations( +void FileGenerator::GenerateInternalForwardDeclarations( const std::vector<const FieldDescriptor*>& fields, const Options& options, - SCCAnalyzer* scc_analyzer, io::Printer* printer) { + MessageSCCAnalyzer* scc_analyzer, io::Printer* printer) { + Formatter format(printer); // To ensure determinism and minimize the number of namespace statements, // we output the forward declarations sorted on namespace and type / function // name. + std::set<string> global_namespace_decls; + // weak defaults std::set<std::pair<string, string> > messages; - std::set<std::pair<string, string> > sccs; - std::set<std::pair<string, string> > inits; for (int i = 0; i < fields.size(); ++i) { const FieldDescriptor* field = fields[i]; const Descriptor* msg = field->message_type(); if (msg == nullptr) continue; bool is_weak = IsImplicitWeakField(field, options, scc_analyzer); - string flns = FileLevelNamespace(msg); - auto scc = scc_analyzer->GetSCC(msg); - string repr = ClassName(scc->GetRepresentative()); + if (field->options().weak()) { + GOOGLE_CHECK(!options_.opensource_runtime); + is_weak = true; + } string weak_attr; if (is_weak) { - inits.insert(std::make_pair(flns, "AddDescriptors")); + global_namespace_decls.insert( + "void " + UniqueName("AddDescriptors", msg, options_) + + "() __attribute__((weak))"); messages.insert(std::make_pair(Namespace(msg), ClassName(msg))); weak_attr = " __attribute__((weak))"; } - string dllexport = "PROTOBUF_INTERNAL_EXPORT_" + FileLevelNamespace(msg); - sccs.insert(std::make_pair(flns, "extern " + dllexport + weak_attr + - " ::google::protobuf::internal::SCCInfo<" + - SimpleItoa(scc->children.size()) + - "> scc_info_" + repr + ";\n")); - } - - printer->Print("\n"); - NamespaceOpener ns(printer); - for (std::set<std::pair<string, string> >::const_iterator it = - messages.begin(); - it != messages.end(); ++it) { - ns.ChangeTo(it->first); - printer->Print( - "extern __attribute__((weak)) $classname$DefaultTypeInternal " - "_$classname$_default_instance_;\n", - "classname", it->second); - } - for (std::set<std::pair<string, string> >::const_iterator it = inits.begin(); - it != inits.end(); ++it) { - ns.ChangeTo(it->first); - printer->Print("void $name$() __attribute__((weak));\n", - "name", it->second); - } - for (const auto& p : sccs) { - ns.ChangeTo(p.first); - printer->Print(p.second.c_str()); + string dllexport = UniqueName("PROTOBUF_INTERNAL_EXPORT", msg, options_); + if (IsProto1(msg->file(), options_) || IsWeak(field, options_)) { + dllexport = ""; + } + auto scc = scc_analyzer->GetSCC(msg); + string repr = + UniqueName(ClassName(scc->GetRepresentative()), msg, options_); + global_namespace_decls.insert( + "extern " + dllexport + weak_attr + " ::" + ProtobufNamespace(options) + + "::internal::SCCInfo<" + SimpleItoa(scc->children.size()) + + "> scc_info_" + repr); + } + + format("\n"); + + for (const string& decl : global_namespace_decls) { + format("$1$;\n", decl); } -} -} // namespace + // Weak external fields + NamespaceOpener ns(format); + for (const auto& pair : messages) { + ns.ChangeTo(pair.first); + format( + "extern __attribute__((weak)) $1$DefaultTypeInternal " + "_$1$_default_instance_;\n", + pair.second); + } +} void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) { + Formatter format(printer, variables_); GenerateSourceIncludes(printer); // Generate weak declarations. We do this for the whole strongly-connected @@ -411,45 +521,43 @@ void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) { printer); if (IsSCCRepresentative(message_generators_[idx]->descriptor_)) { - NamespaceOpener ns(FileLevelNamespace(file_), printer); GenerateInitForSCC(GetSCC(message_generators_[idx]->descriptor_), printer); } { // package namespace - NamespaceOpener ns(Namespace(file_), printer); + NamespaceOpener ns(Namespace(file_), format); // Define default instances GenerateSourceDefaultInstance(idx, printer); if (options_.lite_implicit_weak_fields) { - printer->Print("void $classname$_ReferenceStrong() {}\n", "classname", - message_generators_[idx]->classname_); + format("void $1$_ReferenceStrong() {}\n", + message_generators_[idx]->classname_); } // Generate classes. - printer->Print("\n"); + format("\n"); message_generators_[idx]->GenerateClassMethods(printer); - printer->Print( + format( "\n" "// @@protoc_insertion_point(namespace_scope)\n"); } // end package namespace - printer->Print( - "namespace google {\nnamespace protobuf {\n"); - message_generators_[idx]->GenerateSourceInProto2Namespace(printer); - printer->Print( - "} // namespace protobuf\n} // namespace google\n"); + { + NamespaceOpener proto_ns(ProtobufNamespace(options_), format); + message_generators_[idx]->GenerateSourceInProto2Namespace(printer); + } - printer->Print( + format( "\n" "// @@protoc_insertion_point(global_scope)\n"); } void FileGenerator::GenerateGlobalSource(io::Printer* printer) { + Formatter format(printer, variables_); GenerateSourceIncludes(printer); { - NamespaceOpener ns(FileLevelNamespace(file_), printer); GenerateTables(printer); // Define the code to initialize reflection. This code uses a global @@ -459,7 +567,7 @@ void FileGenerator::GenerateGlobalSource(io::Printer* printer) { } } - NamespaceOpener ns(Namespace(file_), printer); + NamespaceOpener ns(Namespace(file_), format); // Generate enums. for (int i = 0; i < enum_generators_.size(); i++) { @@ -474,15 +582,16 @@ void FileGenerator::GenerateGlobalSource(io::Printer* printer) { if (HasGenericServices(file_, options_)) { // Generate services. for (int i = 0; i < service_generators_.size(); i++) { - if (i == 0) printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + if (i == 0) format("\n"); + format(kThickSeparator); + format("\n"); service_generators_[i]->GenerateImplementation(printer); } } } void FileGenerator::GenerateSource(io::Printer* printer) { + Formatter format(printer, variables_); GenerateSourceIncludes(printer); std::vector<const FieldDescriptor*> fields; ListAllFields(file_, &fields); @@ -490,20 +599,19 @@ void FileGenerator::GenerateSource(io::Printer* printer) { printer); { - NamespaceOpener ns(Namespace(file_), printer); + NamespaceOpener ns(Namespace(file_), format); // Define default instances for (int i = 0; i < message_generators_.size(); i++) { GenerateSourceDefaultInstance(i, printer); if (options_.lite_implicit_weak_fields) { - printer->Print("void $classname$_ReferenceStrong() {}\n", "classname", - message_generators_[i]->classname_); + format("void $1$_ReferenceStrong() {}\n", + message_generators_[i]->classname_); } } } { - NamespaceOpener ns(FileLevelNamespace(file_), printer); GenerateTables(printer); // Now generate the InitDefaults for each SCC. @@ -514,26 +622,28 @@ void FileGenerator::GenerateSource(io::Printer* printer) { } } - printer->Print("void InitDefaults() {\n"); - for (int i = 0; i < message_generators_.size(); i++) { - if (!IsSCCRepresentative(message_generators_[i]->descriptor_)) continue; - string scc_name = ClassName(message_generators_[i]->descriptor_); - printer->Print( - " ::google::protobuf::internal::InitSCC(&scc_info_$scc_name$.base);\n", - "scc_name", scc_name); - } - printer->Print("}\n\n"); - - // Define the code to initialize reflection. This code uses a global - // constructor to register reflection data with the runtime pre-main. if (HasDescriptorMethods(file_, options_)) { + // TODO(gerbens) This is for proto1 interoperability. Remove when proto1 + // is gone. + format("void $init_defaults$() {\n"); + for (int i = 0; i < message_generators_.size(); i++) { + if (!IsSCCRepresentative(message_generators_[i]->descriptor_)) continue; + string scc_name = + UniqueName(ClassName(message_generators_[i]->descriptor_), + message_generators_[i]->descriptor_, options_); + format(" ::$proto_ns$::internal::InitSCC(&scc_info_$1$.base);\n", + scc_name); + } + format("}\n\n"); + + // Define the code to initialize reflection. This code uses a global + // constructor to register reflection data with the runtime pre-main. GenerateReflectionInitializationCode(printer); } } - { - NamespaceOpener ns(Namespace(file_), printer); + NamespaceOpener ns(Namespace(file_), format); // Actually implement the protos @@ -544,18 +654,18 @@ void FileGenerator::GenerateSource(io::Printer* printer) { // Generate classes. for (int i = 0; i < message_generators_.size(); i++) { - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + format("\n"); + format(kThickSeparator); + format("\n"); message_generators_[i]->GenerateClassMethods(printer); } if (HasGenericServices(file_, options_)) { // Generate services. for (int i = 0; i < service_generators_.size(); i++) { - if (i == 0) printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + if (i == 0) format("\n"); + format(kThickSeparator); + format("\n"); service_generators_[i]->GenerateImplementation(printer); } } @@ -565,144 +675,28 @@ void FileGenerator::GenerateSource(io::Printer* printer) { extension_generators_[i]->GenerateDefinition(printer); } - printer->Print( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n"); - } - - printer->Print( - "namespace google {\nnamespace protobuf {\n"); - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->GenerateSourceInProto2Namespace(printer); - } - printer->Print( - "} // namespace protobuf\n} // namespace google\n"); - - printer->Print( - "\n" - "// @@protoc_insertion_point(global_scope)\n"); -} - -class FileGenerator::ForwardDeclarations { - public: - ~ForwardDeclarations() { - for (std::map<string, ForwardDeclarations*>::iterator - it = namespaces_.begin(), - end = namespaces_.end(); - it != end; ++it) { - delete it->second; - } - namespaces_.clear(); - } - - ForwardDeclarations* AddOrGetNamespace(const string& ns_name) { - ForwardDeclarations*& ns = namespaces_[ns_name]; - if (ns == nullptr) { - ns = new ForwardDeclarations; - } - return ns; - } - - std::map<string, const Descriptor*>& classes() { return classes_; } - std::map<string, const EnumDescriptor*>& enums() { return enums_; } - - void PrintForwardDeclarations(io::Printer* printer, - const Options& options) const { - PrintNestedDeclarations(printer, options); - PrintTopLevelDeclarations(printer, options); - } - - - private: - void PrintNestedDeclarations(io::Printer* printer, - const Options& options) const { - PrintDeclarationsInsideNamespace(printer, options); - for (std::map<string, ForwardDeclarations *>::const_iterator - it = namespaces_.begin(), - end = namespaces_.end(); - it != end; ++it) { - printer->Print("namespace $nsname$ {\n", - "nsname", it->first); - it->second->PrintNestedDeclarations(printer, options); - printer->Print("} // namespace $nsname$\n", - "nsname", it->first); - } - } - - void PrintTopLevelDeclarations(io::Printer* printer, - const Options& options) const { - PrintDeclarationsOutsideNamespace(printer, options); - for (std::map<string, ForwardDeclarations *>::const_iterator - it = namespaces_.begin(), - end = namespaces_.end(); - it != end; ++it) { - it->second->PrintTopLevelDeclarations(printer, options); - } + format( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n"); } - void PrintDeclarationsInsideNamespace(io::Printer* printer, - const Options& options) const { - for (std::map<string, const EnumDescriptor *>::const_iterator - it = enums_.begin(), - end = enums_.end(); - it != end; ++it) { - printer->Print("enum $enumname$ : int;\n", "enumname", it->first); - printer->Annotate("enumname", it->second); - printer->Print("bool $enumname$_IsValid(int value);\n", "enumname", - it->first); - } - for (std::map<string, const Descriptor*>::const_iterator - it = classes_.begin(), - end = classes_.end(); - it != end; ++it) { - printer->Print("class $classname$;\n", "classname", it->first); - printer->Annotate("classname", it->second); - - printer->Print( - "class $classname$DefaultTypeInternal;\n" - "$dllexport_decl$" - "extern $classname$DefaultTypeInternal " - "_$classname$_default_instance_;\n", // NOLINT - "dllexport_decl", - options.dllexport_decl.empty() ? "" : options.dllexport_decl + " ", - "classname", - it->first); - if (options.lite_implicit_weak_fields) { - printer->Print("void $classname$_ReferenceStrong();\n", - "classname", it->first); - } + { + NamespaceOpener proto_ns(ProtobufNamespace(options_), format); + for (int i = 0; i < message_generators_.size(); i++) { + message_generators_[i]->GenerateSourceInProto2Namespace(printer); } } - void PrintDeclarationsOutsideNamespace(io::Printer* printer, - const Options& options) const { - if (classes_.size() == 0) return; - - printer->Print( - "namespace google {\nnamespace protobuf {\n"); - for (std::map<string, const Descriptor*>::const_iterator - it = classes_.begin(), - end = classes_.end(); - it != end; ++it) { - const Descriptor* d = it->second; - printer->Print( - "template<> " - "$dllexport_decl$" - "$classname$* Arena::CreateMaybeMessage<$classname$>" - "(Arena*);\n", - "classname", QualifiedClassName(d), "dllexport_decl", - options.dllexport_decl.empty() ? "" : options.dllexport_decl + " "); - } - printer->Print( - "} // namespace protobuf\n} // namespace google\n"); - } + format( + "\n" + "// @@protoc_insertion_point(global_scope)\n"); - std::map<string, ForwardDeclarations*> namespaces_; - std::map<string, const Descriptor*> classes_; - std::map<string, const EnumDescriptor*> enums_; -}; + IncludeFile("net/proto2/public/port_undef.inc", printer); +} void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { + Formatter format(printer, variables_); + // AddDescriptors() is a file-level procedure which adds the encoded // FileDescriptorProto for this .proto file to the global DescriptorPool for // generated files (DescriptorPool::generated_pool()). It ordinarily runs at @@ -716,39 +710,50 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { // in the file. if (!message_generators_.empty()) { - printer->Print("::google::protobuf::Metadata file_level_metadata[$size$];\n", "size", - SimpleItoa(message_generators_.size())); + format("::$proto_ns$::Metadata $file_level_metadata$[$1$];\n", + message_generators_.size()); + } else { + format( + "constexpr ::$proto_ns$::Metadata* $file_level_metadata$ = nullptr;\n"); } if (!enum_generators_.empty()) { - printer->Print( - "const ::google::protobuf::EnumDescriptor* " - "file_level_enum_descriptors[$size$];\n", - "size", SimpleItoa(enum_generators_.size())); + format( + "const ::$proto_ns$::EnumDescriptor* " + "$file_level_enum_descriptors$[$1$];\n", + enum_generators_.size()); + } else { + format( + "constexpr ::$proto_ns$::EnumDescriptor const** " + "$file_level_enum_descriptors$ = nullptr;\n"); } if (HasGenericServices(file_, options_) && file_->service_count() > 0) { - printer->Print( - "const ::google::protobuf::ServiceDescriptor* " - "file_level_service_descriptors[$size$];\n", - "size", SimpleItoa(file_->service_count())); + format( + "const ::$proto_ns$::ServiceDescriptor* " + "$file_level_service_descriptors$[$1$];\n", + file_->service_count()); + } else { + format( + "constexpr ::$proto_ns$::ServiceDescriptor const** " + "$file_level_service_descriptors$ = nullptr;\n"); } if (!message_generators_.empty()) { - printer->Print( + format( "\n" - "const ::google::protobuf::uint32 TableStruct::offsets[] " - "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); + "const $uint32$ $tablename$::offsets[] " + "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); + format.Indent(); std::vector<std::pair<size_t, size_t> > pairs; pairs.reserve(message_generators_.size()); for (int i = 0; i < message_generators_.size(); i++) { pairs.push_back(message_generators_[i]->GenerateOffsets(printer)); } - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "};\n" - "static const ::google::protobuf::internal::MigrationSchema schemas[] " - "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); + "static const ::$proto_ns$::internal::MigrationSchema schemas[] " + "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); + format.Indent(); { int offset = 0; for (int i = 0; i < message_generators_.size(); i++) { @@ -757,30 +762,33 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { offset += pairs[i].first; } } - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "};\n" "\nstatic " - "::google::protobuf::Message const * const file_default_instances[] = {\n"); - printer->Indent(); + "::$proto_ns$::Message const * const file_default_instances[] = {\n"); + format.Indent(); for (int i = 0; i < message_generators_.size(); i++) { const Descriptor* descriptor = message_generators_[i]->descriptor_; - printer->Print( + format( "reinterpret_cast<const " - "::google::protobuf::Message*>(&$ns$::_$classname$_default_instance_),\n", - "classname", ClassName(descriptor), "ns", Namespace(descriptor)); + "::$proto_ns$::Message*>(&$1$::_$2$_default_instance_),\n", + Namespace(descriptor), // 1 + ClassName(descriptor)); // 2 } - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "};\n" "\n"); } else { // we still need these symbols to exist - printer->Print( + format( // MSVC doesn't like empty arrays, so we add a dummy. - "const ::google::protobuf::uint32 TableStruct::offsets[1] = {};\n" - "static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;\n" - "static const ::google::protobuf::Message* const* " + "const $uint32$ $tablename$::offsets[1] = {};\n" + "static constexpr ::$proto_ns$::internal::MigrationSchema* schemas = " + "NULL;" + "\n" + "static constexpr ::$proto_ns$::Message* const* " "file_default_instances = NULL;\n" "\n"); } @@ -790,161 +798,90 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { // protobuf_AssignDescriptorsOnce(): The first time it is called, calls // AssignDescriptors(). All later times, waits for the first call to // complete and then returns. - printer->Print( - "static void protobuf_AssignDescriptors() {\n" - // Make sure the file has found its way into the pool. If a descriptor - // is requested *during* static init then AddDescriptors() may not have - // been called yet, so we call it manually. Note that it's fine if - // AddDescriptors() is called multiple times. - " AddDescriptors();\n" - " AssignDescriptors(\n" - " \"$filename$\", schemas, file_default_instances, " - "TableStruct::offsets,\n" - " $metadata$, $enum_descriptors$, $service_descriptors$);\n", - "filename", file_->name(), "metadata", - !message_generators_.empty() ? "file_level_metadata" : "NULL", - "enum_descriptors", - !enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL", - "service_descriptors", - HasGenericServices(file_, options_) && file_->service_count() > 0 - ? "file_level_service_descriptors" - : "NULL"); - printer->Print( - "}\n" - "\n" - "static void protobuf_AssignDescriptorsOnce() {\n" - " static ::google::protobuf::internal::once_flag once;\n" - " ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors);\n" - "}\n" - "\n", - "filename", file_->name(), "metadata", - !message_generators_.empty() ? "file_level_metadata" : "NULL", - "enum_descriptors", - !enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL", - "service_descriptors", - HasGenericServices(file_, options_) && file_->service_count() > 0 - ? "file_level_service_descriptors" - : "NULL"); - - // Only here because of useless string reference that we don't want in - // protobuf_AssignDescriptorsOnce, because that is called from all the - // GetMetadata member methods. - printer->Print( - "void protobuf_RegisterTypes(const ::std::string&) " - "GOOGLE_PROTOBUF_ATTRIBUTE_COLD;\n" - "void protobuf_RegisterTypes(const ::std::string&) {\n" - " protobuf_AssignDescriptorsOnce();\n"); - printer->Indent(); - - // All normal messages can be done generically - if (!message_generators_.empty()) { - printer->Print( - "::google::protobuf::internal::RegisterAllTypes(file_level_metadata, $size$);\n", - "size", SimpleItoa(message_generators_.size())); - } + format( + "::$proto_ns$::internal::AssignDescriptorsTable $assign_desc_table$ = " + "{\n" + " {}, $add_descriptors$, \"$filename$\", schemas,\n" + " file_default_instances, $tablename$::offsets,\n" + " $file_level_metadata$, $1$, $file_level_enum_descriptors$, " + "$file_level_service_descriptors$,\n" + "};\n" + "\n", + message_generators_.size()); + + // Now generate the AddDescriptors() function. + format( + "::$proto_ns$::internal::DescriptorTable $1$ = {\n" + " false, $init_defaults$, \n", + UniqueName("descriptor_table", file_, options_)); + format.Indent(); + + // Embed the descriptor. We simply serialize the entire + // FileDescriptorProto + // and embed it as a string literal, which is parsed and built into real + // descriptors at initialization time. + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + string file_data; + file_proto.SerializeToString(&file_data); - printer->Outdent(); - printer->Print( - "}\n" - "\n"); - - // Now generate the AddDescriptors() function. - printer->Print( - "static void AddDescriptorsImpl() {\n" - " InitDefaults();\n"); - printer->Indent(); - - // Embed the descriptor. We simply serialize the entire - // FileDescriptorProto - // and embed it as a string literal, which is parsed and built into real - // descriptors at initialization time. - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); - string file_data; - file_proto.SerializeToString(&file_data); - - printer->Print("static const char descriptor[] " - "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) " - "= {\n"); - printer->Indent(); - - if (file_data.size() > 65535) { - // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535 - // bytes in length". Declare a static array of characters rather than use - // a string literal. Only write 25 bytes per line. - static const int kBytesPerLine = 25; - for (int i = 0; i < file_data.size();) { - for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { - printer->Print("'$char$', ", "char", - CEscape(file_data.substr(i, 1))); - } - printer->Print("\n"); - } - } else { - // Only write 40 bytes per line. - static const int kBytesPerLine = 40; - for (int i = 0; i < file_data.size(); i += kBytesPerLine) { - printer->Print(" \"$data$\"\n", "data", - EscapeTrigraphs(CEscape( - file_data.substr(i, kBytesPerLine)))); - } + { + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + format( + "\"$1$\"\n", + EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine)))); } - - printer->Outdent(); - printer->Print("};\n"); - printer->Print( - "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(\n" - " descriptor, $size$);\n", - "size", SimpleItoa(file_data.size())); - - // Call MessageFactory::InternalRegisterGeneratedFile(). - printer->Print( - "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n" - " \"$filename$\", &protobuf_RegisterTypes);\n", - "filename", file_->name()); - - // Call the AddDescriptors() methods for all of our dependencies, to make - // sure they get added first. - for (int i = 0; i < file_->dependency_count(); i++) { - const FileDescriptor* dependency = file_->dependency(i); - // Print the namespace prefix for the dependency. - string file_namespace = FileLevelNamespace(dependency); - // Call its AddDescriptors function. - printer->Print("::$file_namespace$::AddDescriptors();\n", "file_namespace", - file_namespace); } - printer->Outdent(); - printer->Print( - "}\n" - "\n" - "void AddDescriptors() {\n" - " static ::google::protobuf::internal::once_flag once;\n" - " ::google::protobuf::internal::call_once(once, AddDescriptorsImpl);\n" - "}\n"); - - printer->Print( - "// Force AddDescriptors() to be called at dynamic initialization " - "time.\n" - "struct StaticDescriptorInitializer {\n" - " StaticDescriptorInitializer() {\n" - " AddDescriptors();\n" - " }\n" - "} static_descriptor_initializer;\n"); + format.Outdent(); + const int num_deps = file_->dependency_count(); + format( + ",\n \"$filename$\", &$assign_desc_table$, $1$,\n" + "};\n\n" + "void $add_descriptors$() {\n" + " static constexpr ::$proto_ns$::internal::InitFunc deps[$2$] =\n" + " {\n", + file_data.size(), std::max(num_deps, 1)); + for (int i = 0; i < num_deps; i++) { + const FileDescriptor* dependency = file_->dependency(i); + format(" ::$1$,\n", UniqueName("AddDescriptors", dependency, options_)); + } + format( + " };\n" + " ::$proto_ns$::internal::AddDescriptors(&$1$, deps, $2$);\n" + "}\n\n", + UniqueName("descriptor_table", file_, options_), // 1 + num_deps); // 2 + format( + "// Force running AddDescriptors() at dynamic initialization time.\n" + "static bool $1$ = []() { $add_descriptors$(); return true; }();\n", + UniqueName("dynamic_init_dummy", file_, options_)); } void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) { + Formatter format(printer, variables_); const string scc_name = ClassName(scc->GetRepresentative()); // We use static and not anonymous namespace because symbol names are // substantially shorter. - printer->Print( - "static void InitDefaults$scc_name$() {\n" - " GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n" - , // awkward comma due to macro - "scc_name", scc_name); + format("static void InitDefaults$1$() {\n", + UniqueName(scc_name, scc->GetRepresentative(), options_)); - printer->Indent(); + if (options_.opensource_runtime) { + format(" GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n"); + } + format.Indent(); + + if (!options_.opensource_runtime) { + for (int i = 0; i < scc->children.size(); i++) { + const SCC* child_scc = scc->children[i]; + const FileDescriptor* dependency = child_scc->GetRepresentative()->file(); + if (!IsProto1(dependency, options_)) continue; + format("$1$();\n", UniqueName("InitDefaults", dependency, options_)); + } + } // First construct all the necessary default instances. for (int i = 0; i < message_generators_.size(); i++) { @@ -954,17 +891,18 @@ void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) { // TODO(gerbens) This requires this function to be friend. Remove // the need for this. message_generators_[i]->GenerateFieldDefaultInstances(printer); - printer->Print( + format( "{\n" - " void* ptr = &$ns$::_$classname$_default_instance_;\n" - " new (ptr) $ns$::$classname$();\n", - "ns", Namespace(message_generators_[i]->descriptor_), - "classname", ClassName(message_generators_[i]->descriptor_)); - if (!IsMapEntryMessage(message_generators_[i]->descriptor_)) { - printer->Print( + " void* ptr = &$1$::_$2$_default_instance_;\n" + " new (ptr) $1$::$2$();\n", + Namespace(message_generators_[i]->descriptor_), // 1 + ClassName(message_generators_[i]->descriptor_)); // 2 + if (options_.opensource_runtime && + !IsMapEntryMessage(message_generators_[i]->descriptor_)) { + format( " ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);\n"); } - printer->Print("}\n"); + format("}\n"); } // TODO(gerbens) make default instances be the same as normal instances. @@ -974,37 +912,44 @@ void FileGenerator::GenerateInitForSCC(const SCC* scc, io::Printer* printer) { if (scc_analyzer_.GetSCC(message_generators_[i]->descriptor_) != scc) { continue; } - printer->Print("$classname$::InitAsDefaultInstance();\n", "classname", - QualifiedClassName(message_generators_[i]->descriptor_)); - } - printer->Outdent(); - printer->Print("}\n\n"); - - printer->Print( - "$dllexport_decl$::google::protobuf::internal::SCCInfo<$size$> " - "scc_info_$scc_name$ =\n" - " {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), " - "$size$, InitDefaults$scc_name$}, {", - "size", SimpleItoa(scc->children.size()), "scc_name", - ClassName(scc->GetRepresentative()), "dllexport_decl", - options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " "); + format("$1$::InitAsDefaultInstance();\n", + QualifiedClassName(message_generators_[i]->descriptor_)); + } + format.Outdent(); + format("}\n\n"); + + format( + "$dllexport_decl $::$proto_ns$::internal::SCCInfo<$1$> " + "scc_info_$2$ =\n" + " " + "{{ATOMIC_VAR_INIT(::$proto_ns$::internal::SCCInfoBase::kUninitialized), " + "$1$, InitDefaults$2$}, {", + scc->children.size(), // 1 + UniqueName(ClassName(scc->GetRepresentative()), scc->GetRepresentative(), + options_)); for (const SCC* child : scc->children) { auto repr = child->GetRepresentative(); - printer->Print("\n &$ns$::scc_info_$child$.base,", "ns", - FileLevelNamespace(repr), "child", ClassName(repr)); + if (IsProto1(repr->file(), options_)) { + GOOGLE_CHECK(!options_.opensource_runtime); + format("\n nullptr,"); + continue; + } + format("\n &scc_info_$1$.base,", + UniqueName(ClassName(repr), repr, options_)); } - printer->Print("}};\n\n"); + format("}};\n\n"); } void FileGenerator::GenerateTables(io::Printer* printer) { + Formatter format(printer, variables_); if (options_.table_driven_parsing) { // TODO(ckennelly): Gate this with the same options flag to enable // table-driven parsing. - printer->Print( - "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField\n" - " const TableStruct::entries[] " - "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); + format( + "PROTOBUF_CONSTEXPR_VAR ::$proto_ns$::internal::ParseTableField\n" + " const $tablename$::entries[] " + "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); + format.Indent(); std::vector<size_t> entries; size_t count = 0; @@ -1016,17 +961,18 @@ void FileGenerator::GenerateTables(io::Printer* printer) { // We need these arrays to exist, and MSVC does not like empty arrays. if (count == 0) { - printer->Print("{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},\n"); + format("{0, 0, 0, ::$proto_ns$::internal::kInvalidMask, 0, 0},\n"); } - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "};\n" "\n" - "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField\n" - " const TableStruct::aux[] " - "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); + "PROTOBUF_CONSTEXPR_VAR " + "::$proto_ns$::internal::AuxillaryParseTableField\n" + " const $tablename$::aux[] " + "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); + format.Indent(); std::vector<size_t> aux_entries; count = 0; @@ -1037,16 +983,16 @@ void FileGenerator::GenerateTables(io::Printer* printer) { } if (count == 0) { - printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n"); + format("::$proto_ns$::internal::AuxillaryParseTableField(),\n"); } - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "};\n" - "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const\n" - " TableStruct::schema[] " - "GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n"); - printer->Indent(); + "PROTOBUF_CONSTEXPR_VAR ::$proto_ns$::internal::ParseTable const\n" + " $tablename$::schema[] " + "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); + format.Indent(); size_t offset = 0; size_t aux_offset = 0; @@ -1057,20 +1003,21 @@ void FileGenerator::GenerateTables(io::Printer* printer) { } if (message_generators_.empty()) { - printer->Print("{ NULL, NULL, 0, -1, -1, false },\n"); + format("{ NULL, NULL, 0, -1, -1, false },\n"); } - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "};\n" "\n"); } if (!message_generators_.empty() && options_.table_driven_serialization) { - printer->Print( - "const ::google::protobuf::internal::FieldMetadata TableStruct::field_metadata[] " + format( + "const ::$proto_ns$::internal::FieldMetadata " + "$tablename$::field_metadata[] " "= {\n"); - printer->Indent(); + format.Indent(); std::vector<int> field_metadata_offsets; int idx = 0; for (int i = 0; i < message_generators_.size(); i++) { @@ -1078,12 +1025,12 @@ void FileGenerator::GenerateTables(io::Printer* printer) { idx += message_generators_[i]->GenerateFieldMetadata(printer); } field_metadata_offsets.push_back(idx); - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "};\n" - "const ::google::protobuf::internal::SerializationTable " - "TableStruct::serialization_table[] = {\n"); - printer->Indent(); + "const ::$proto_ns$::internal::SerializationTable " + "$tablename$::serialization_table[] = {\n"); + format.Indent(); // We rely on the order we layout the tables to match the order we // calculate them with FlattenMessagesInFile, so we check here that // these match exactly. @@ -1092,235 +1039,327 @@ void FileGenerator::GenerateTables(io::Printer* printer) { GOOGLE_CHECK_EQ(calculated_order.size(), message_generators_.size()); for (int i = 0; i < message_generators_.size(); i++) { GOOGLE_CHECK_EQ(calculated_order[i], message_generators_[i]->descriptor_); - printer->Print( - "{$num_fields$, TableStruct::field_metadata + $index$},\n", - "classname", message_generators_[i]->classname_, "num_fields", - SimpleItoa(field_metadata_offsets[i + 1] - field_metadata_offsets[i]), - "index", SimpleItoa(field_metadata_offsets[i])); + format("{$1$, $tablename$::field_metadata + $2$},\n", + field_metadata_offsets[i + 1] - field_metadata_offsets[i], // 1 + field_metadata_offsets[i]); // 2 } - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "};\n" "\n"); } } -void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { - ForwardDeclarations decls; - FillForwardDeclarations(&decls); - decls.PrintForwardDeclarations(printer, options_); +class FileGenerator::ForwardDeclarations { + public: + void AddMessage(const Descriptor* d) { classes_[ClassName(d)] = d; } + void AddEnum(const EnumDescriptor* d) { enums_[ClassName(d)] = d; } + + void Print(const Formatter& format, const Options& options) const { + for (const auto& p : enums_) { + const string& enumname = p.first; + const EnumDescriptor* enum_desc = p.second; + format( + "enum ${1$$2$$}$ : int;\n" + "bool $2$_IsValid(int value);\n", + enum_desc, enumname); + } + for (const auto& p : classes_) { + const string& classname = p.first; + const Descriptor* class_desc = p.second; + format( + "class ${1$$2$$}$;\n" + "class $2$DefaultTypeInternal;\n" + "$dllexport_decl $extern " + "$2$DefaultTypeInternal _$2$_default_instance_;\n", + class_desc, classname); + if (options.lite_implicit_weak_fields) { + format("void $1$_ReferenceStrong();\n", classname); + } + } + } + + void PrintTopLevelDecl(const Formatter& format) const { + for (const auto& pair : classes_) { + format( + "template<> $dllexport_decl $" + "$1$* Arena::CreateMaybeMessage<$1$>(Arena*);\n", + QualifiedClassName(pair.second)); + } + } + + private: + std::map<string, const Descriptor*> classes_; + std::map<string, const EnumDescriptor*> enums_; +}; + +static void PublicImportDFS(const FileDescriptor* fd, + std::unordered_set<const FileDescriptor*>* fd_set) { + for (int i = 0; i < fd->public_dependency_count(); i++) { + const FileDescriptor* dep = fd->public_dependency(i); + if (fd_set->insert(dep).second) PublicImportDFS(dep, fd_set); + } } -void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) { - for (int i = 0; i < package_parts_.size(); i++) { - decls = decls->AddOrGetNamespace(package_parts_[i]); +void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { + Formatter format(printer, variables_); + std::vector<const Descriptor*> classes; + std::vector<const EnumDescriptor*> enums; + + FlattenMessagesInFile(file_, &classes); // All messages need forward decls. + + if (options_.proto_h) { // proto.h needs extra forward declarations. + // All classes / enums refered to as field members + std::vector<const FieldDescriptor*> fields; + ListAllFields(file_, &fields); + for (int i = 0; i < fields.size(); i++) { + classes.push_back(fields[i]->containing_type()); + classes.push_back(fields[i]->message_type()); + enums.push_back(fields[i]->enum_type()); + } + ListAllTypesForServices(file_, &classes); } - // Generate enum definitions. - for (int i = 0; i < enum_generators_.size(); i++) { - enum_generators_[i]->FillForwardDeclaration(&decls->enums()); + + // Calculate the set of files whose definitions we get through include. + // No need to forward declare types that are defined in these. + std::unordered_set<const FileDescriptor*> public_set; + PublicImportDFS(file_, &public_set); + + std::map<string, ForwardDeclarations> decls; + for (int i = 0; i < classes.size(); i++) { + const Descriptor* d = classes[i]; + if (d && !public_set.count(d->file())) decls[Namespace(d)].AddMessage(d); } - // Generate forward declarations of classes. - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->FillMessageForwardDeclarations( - &decls->classes()); + for (int i = 0; i < enums.size(); i++) { + const EnumDescriptor* d = enums[i]; + if (d && !public_set.count(d->file())) decls[Namespace(d)].AddEnum(d); + } + + + NamespaceOpener ns(format); + for (const auto& pair : decls) { + ns.ChangeTo(pair.first); + pair.second.Print(format, options_); + } + ns.ChangeTo(variables_["proto_ns"]); + for (const auto& pair : decls) { + pair.second.PrintTopLevelDecl(format); } } void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer, const string& filename_identifier) { + Formatter format(printer, variables_); // Generate top of header. - printer->Print( + format( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "// source: $filename$\n" "\n" - "#ifndef PROTOBUF_INCLUDED_$filename_identifier$\n" - "#define PROTOBUF_INCLUDED_$filename_identifier$\n" + "#ifndef PROTOBUF_INCLUDED_$1$\n" + "#define PROTOBUF_INCLUDED_$1$\n" "\n" + "#include <limits>\n" "#include <string>\n", - "filename", file_->name(), "filename_identifier", filename_identifier); - printer->Print("\n"); + filename_identifier); + if (!options_.opensource_runtime && !enum_generators_.empty()) { + // Add header to provide std::is_integral for safe Enum_Name() function. + format("#include <type_traits>\n"); + } + format("\n"); } void FileGenerator::GenerateBottomHeaderGuard( io::Printer* printer, const string& filename_identifier) { - printer->Print( - "#endif // PROTOBUF_INCLUDED_$filename_identifier$\n", - "filename_identifier", filename_identifier); + Formatter format(printer, variables_); + format("#endif // PROTOBUF_INCLUDED_$1$\n", filename_identifier); } void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { + Formatter format(printer, variables_); if (UsingImplicitWeakFields(file_, options_)) { - printer->Print("#include <google/protobuf/implicit_weak_message.h>\n"); - } - - printer->Print( - "#include <google/protobuf/stubs/common.h>\n" - "\n"); - - // Verify the protobuf library header version is compatible with the protoc - // version before going any further. - printer->Print( - "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n" - "#error This file was generated by a newer version of protoc which is\n" - "#error incompatible with your Protocol Buffer headers. Please update\n" - "#error your headers.\n" - "#endif\n" - "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n" - "#error This file was generated by an older version of protoc which is\n" - "#error incompatible with your Protocol Buffer headers. Please\n" - "#error regenerate this file with a newer version of protoc.\n" - "#endif\n" - "\n", - "min_header_version", - SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc), - "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION)); + IncludeFile("net/proto2/public/implicit_weak_message.h", printer); + } + if (HasWeakFields(file_, options_)) { + GOOGLE_CHECK(!options_.opensource_runtime); + IncludeFile("net/proto2/public/weak_field_map.h", printer); + } + if (HasLazyFields(file_, options_)) { + GOOGLE_CHECK(!options_.opensource_runtime); + IncludeFile("net/proto2/public/lazy_field.h", printer); + } + + if (options_.opensource_runtime) { + // Verify the protobuf library header version is compatible with the protoc + // version before going any further. + IncludeFile("net/proto2/public/port_def.inc", printer); + format( + "#if PROTOBUF_VERSION < $1$\n" + "#error This file was generated by a newer version of protoc which is\n" + "#error incompatible with your Protocol Buffer headers. Please update\n" + "#error your headers.\n" + "#endif\n" + "#if $2$ < PROTOBUF_MIN_PROTOC_VERSION\n" + "#error This file was generated by an older version of protoc which " + "is\n" + "#error incompatible with your Protocol Buffer headers. Please\n" + "#error regenerate this file with a newer version of protoc.\n" + "#endif\n" + "\n", + PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC, // 1 + PROTOBUF_VERSION); // 2 + IncludeFile("net/proto2/public/port_undef.inc", printer); + } // OK, it's now safe to #include other files. - printer->Print( - "#include <google/protobuf/io/coded_stream.h>\n" - "#include <google/protobuf/arena.h>\n" - "#include <google/protobuf/arenastring.h>\n" - "#include <google/protobuf/generated_message_table_driven.h>\n" - "#include <google/protobuf/generated_message_util.h>\n" - "#include <google/protobuf/inlined_string_field.h>\n"); - + IncludeFile("net/proto2/io/public/coded_stream.h", printer); + IncludeFile("net/proto2/public/arena.h", printer); + IncludeFile("net/proto2/public/arenastring.h", printer); + IncludeFile("net/proto2/public/generated_message_table_driven.h", printer); + IncludeFile("net/proto2/public/generated_message_util.h", printer); + IncludeFile("net/proto2/public/inlined_string_field.h", printer); if (HasDescriptorMethods(file_, options_)) { - printer->Print( - "#include <google/protobuf/metadata.h>\n"); + IncludeFile("net/proto2/public/metadata.h", printer); } else { - printer->Print( - "#include <google/protobuf/metadata_lite.h>\n"); + IncludeFile("net/proto2/public/metadata_lite.h", printer); } if (!message_generators_.empty()) { if (HasDescriptorMethods(file_, options_)) { - printer->Print( - "#include <google/protobuf/message.h>\n"); + IncludeFile("net/proto2/public/message.h", printer); } else { - printer->Print( - "#include <google/protobuf/message_lite.h>\n"); + IncludeFile("net/proto2/public/message_lite.h", printer); + } + } + if (options_.opensource_runtime) { + // Open-source relies on unconditional includes of these. + IncludeFileAndExport("net/proto2/public/repeated_field.h", printer); + IncludeFileAndExport("net/proto2/public/extension_set.h", printer); + } else { + // Google3 includes these files only when they are necessary. + if (HasExtensionsOrExtendableMessage(file_)) { + IncludeFileAndExport("net/proto2/public/extension_set.h", printer); + } + if (HasRepeatedFields(file_)) { + IncludeFileAndExport("net/proto2/public/repeated_field.h", printer); + } + if (HasStringPieceFields(file_, options_)) { + IncludeFile("net/proto2/public/string_piece_field_support.h", printer); + } + if (HasCordFields(file_, options_)) { + format("#include \"third_party/absl/strings/cord.h\"\n"); } } - printer->Print( - "#include <google/protobuf/repeated_field.h>" - " // IWYU pragma: export\n" - "#include <google/protobuf/extension_set.h>" - " // IWYU pragma: export\n"); if (HasMapFields(file_)) { - printer->Print( - "#include <google/protobuf/map.h>" - " // IWYU pragma: export\n"); + IncludeFileAndExport("net/proto2/public/map.h", printer); if (HasDescriptorMethods(file_, options_)) { - printer->Print("#include <google/protobuf/map_entry.h>\n"); - printer->Print("#include <google/protobuf/map_field_inl.h>\n"); + IncludeFile("net/proto2/public/map_entry.h", printer); + IncludeFile("net/proto2/public/map_field_inl.h", printer); } else { - printer->Print("#include <google/protobuf/map_entry_lite.h>\n"); - printer->Print("#include <google/protobuf/map_field_lite.h>\n"); + IncludeFile("net/proto2/public/map_entry_lite.h", printer); + IncludeFile("net/proto2/public/map_field_lite.h", printer); } } if (HasEnumDefinitions(file_)) { if (HasDescriptorMethods(file_, options_)) { - printer->Print( - "#include <google/protobuf/generated_enum_reflection.h>\n"); + IncludeFile("net/proto2/public/generated_enum_reflection.h", printer); } else { - printer->Print( - "#include <google/protobuf/generated_enum_util.h>\n"); + IncludeFile("net/proto2/public/generated_enum_util.h", printer); } } if (HasGenericServices(file_, options_)) { - printer->Print( - "#include <google/protobuf/service.h>\n"); + IncludeFile("net/proto2/public/service.h", printer); } if (UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) { - printer->Print( - "#include <google/protobuf/unknown_field_set.h>\n"); + IncludeFile("net/proto2/public/unknown_field_set.h", printer); } - if (IsAnyMessage(file_)) { - printer->Print( - "#include <google/protobuf/any.h>\n"); + IncludeFile("net/proto2/internal/any.h", printer); } } void FileGenerator::GenerateMetadataPragma(io::Printer* printer, const string& info_path) { + Formatter format(printer, variables_); if (!info_path.empty() && !options_.annotation_pragma_name.empty() && !options_.annotation_guard_name.empty()) { - printer->Print( + format.Set("guard", options_.annotation_guard_name); + format.Set("pragma", options_.annotation_pragma_name); + format.Set("info_path", info_path); + format( "#ifdef $guard$\n" "#pragma $pragma$ \"$info_path$\"\n" - "#endif // $guard$\n", - "guard", options_.annotation_guard_name, "pragma", - options_.annotation_pragma_name, "info_path", info_path); + "#endif // $guard$\n"); } } void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) { - std::set<string> public_import_names; - for (int i = 0; i < file_->public_dependency_count(); i++) { - public_import_names.insert(file_->public_dependency(i)->name()); - } - + Formatter format(printer, variables_); for (int i = 0; i < file_->dependency_count(); i++) { - const bool use_system_include = IsWellKnownMessage(file_->dependency(i)); - const string& name = file_->dependency(i)->name(); - bool public_import = (public_import_names.count(name) != 0); - string basename = StripProto(name); + string basename = StripProto(file_->dependency(i)->name()); + + // Do not import weak deps. + if (IsDepWeak(file_->dependency(i))) continue; + if (IsBootstrapProto(options_, file_)) { + GetBootstrapBasename(options_, basename, &basename); + } - printer->Print( - "#include $left$$dependency$.pb.h$right$$iwyu$\n", - "dependency", basename, - "iwyu", (public_import) ? " // IWYU pragma: export" : "", - "left", use_system_include ? "<" : "\"", - "right", use_system_include ? ">" : "\""); + format("#include $1$\n", + CreateHeaderInclude(basename + ".pb.h", file_->dependency(i))); } } void FileGenerator::GenerateGlobalStateFunctionDeclarations( io::Printer* printer) { -// Forward-declare the AddDescriptors, InitDefaults because these are called -// by .pb.cc files depending on this file. - printer->Print( + Formatter format(printer, variables_); + // Forward-declare the AddDescriptors, InitDefaults because these are called + // by .pb.cc files depending on this file. + // + // The TableStruct is also outputted in weak_message_field.cc, because the + // weak fields must refer to table struct but cannot include the header. + // Also it annotates extra weak attributes. + // TODO(gerbens) make sure this situation is handled better. + format( "\n" - "namespace $file_namespace$ {\n" "// Internal implementation detail -- do not use these members.\n" - "struct $dllexport_decl$TableStruct {\n" + "struct $dllexport_decl $$tablename$ {\n" // These tables describe how to serialize and parse messages. Used // for table driven code. - " static const ::google::protobuf::internal::ParseTableField entries[];\n" - " static const ::google::protobuf::internal::AuxillaryParseTableField aux[];\n" - " static const ::google::protobuf::internal::ParseTable schema[$num$];\n" - " static const ::google::protobuf::internal::FieldMetadata field_metadata[];\n" - " static const ::google::protobuf::internal::SerializationTable " + " static const ::$proto_ns$::internal::ParseTableField entries[]\n" + " PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n" + " static const ::$proto_ns$::internal::AuxillaryParseTableField aux[]\n" + " PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n" + " static const ::$proto_ns$::internal::ParseTable schema[$1$]\n" + " PROTOBUF_SECTION_VARIABLE(protodesc_cold);\n" + " static const ::$proto_ns$::internal::FieldMetadata field_metadata[];\n" + " static const ::$proto_ns$::internal::SerializationTable " "serialization_table[];\n" - " static const ::google::protobuf::uint32 offsets[];\n" + " static const $uint32$ offsets[];\n" "};\n", - "file_namespace", FileLevelNamespace(file_), "dllexport_decl", - options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ", - "num", SimpleItoa(std::max(size_t(1), message_generators_.size()))); + std::max(size_t(1), message_generators_.size())); if (HasDescriptorMethods(file_, options_)) { - printer->Print( - "void $dllexport_decl$AddDescriptors();\n", "dllexport_decl", - options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " "); + format("void $dllexport_decl $$add_descriptors$();\n"); + if (!options_.opensource_runtime) { + // TODO(gerbens) This is for proto1 interoperability. Remove when proto1 + // is gone. + format("void $dllexport_decl $$init_defaults$();\n"); + } } - printer->Print( - "} // namespace $file_namespace$\n", - "file_namespace", FileLevelNamespace(file_)); } void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) { + Formatter format(printer, variables_); // Generate class definitions. for (int i = 0; i < message_generators_.size(); i++) { if (i > 0) { - printer->Print("\n"); - printer->Print(kThinSeparator); - printer->Print("\n"); + format("\n"); + format(kThinSeparator); + format("\n"); } message_generators_[i]->GenerateClassDefinition(printer); } @@ -1334,74 +1373,77 @@ void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) { } void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) { + Formatter format(printer, variables_); if (HasGenericServices(file_, options_)) { // Generate service definitions. for (int i = 0; i < service_generators_.size(); i++) { if (i > 0) { - printer->Print("\n"); - printer->Print(kThinSeparator); - printer->Print("\n"); + format("\n"); + format(kThinSeparator); + format("\n"); } service_generators_[i]->GenerateDeclarations(printer); } - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + format("\n"); + format(kThickSeparator); + format("\n"); } } void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) { // Declare extension identifiers. These are in global scope and so only // the global scope extensions. - for (int i = 0; i < file_->extension_count(); i++) { - extension_generators_owner_[i]->GenerateDeclaration(printer); + for (auto& extension_generator : extension_generators_) { + if (extension_generator->IsScoped()) continue; + extension_generator->GenerateDeclaration(printer); } } void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) { + Formatter format(printer, variables_); // TODO(gerbens) remove pragmas when gcc is no longer used. Current version // of gcc fires a bogus error when compiled with strict-aliasing. - printer->Print( - "#ifdef __GNUC__\n" - " #pragma GCC diagnostic push\n" - " #pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n" - "#endif // __GNUC__\n"); + format( + "#ifdef __GNUC__\n" + " #pragma GCC diagnostic push\n" + " #pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n" + "#endif // __GNUC__\n"); // Generate class inline methods. for (int i = 0; i < message_generators_.size(); i++) { if (i > 0) { - printer->Print(kThinSeparator); - printer->Print("\n"); + format(kThinSeparator); + format("\n"); } message_generators_[i]->GenerateInlineMethods(printer); } - printer->Print( - "#ifdef __GNUC__\n" - " #pragma GCC diagnostic pop\n" - "#endif // __GNUC__\n"); + format( + "#ifdef __GNUC__\n" + " #pragma GCC diagnostic pop\n" + "#endif // __GNUC__\n"); for (int i = 0; i < message_generators_.size(); i++) { if (i > 0) { - printer->Print(kThinSeparator); - printer->Print("\n"); + format(kThinSeparator); + format("\n"); } } } void FileGenerator::GenerateProto2NamespaceEnumSpecializations( io::Printer* printer) { + Formatter format(printer, variables_); // Emit GetEnumDescriptor specializations into google::protobuf namespace: if (HasEnumDefinitions(file_)) { - printer->Print( - "\n" - "namespace google {\nnamespace protobuf {\n" - "\n"); - for (int i = 0; i < enum_generators_.size(); i++) { - enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + format("\n"); + { + NamespaceOpener proto_ns(ProtobufNamespace(options_), format); + format("\n"); + for (int i = 0; i < enum_generators_.size(); i++) { + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + format("\n"); } - printer->Print( - "\n" - "} // namespace protobuf\n} // namespace google\n"); } } diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h index 94da9a14..315cf139 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.h +++ b/src/google/protobuf/compiler/cpp/cpp_file.h @@ -44,23 +44,26 @@ #include <google/protobuf/compiler/cpp/cpp_field.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/compiler/cpp/cpp_options.h> +#include <google/protobuf/compiler/scc.h> namespace google { namespace protobuf { - class FileDescriptor; // descriptor.h - namespace io { - class Printer; // printer.h - } +class FileDescriptor; // descriptor.h +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { -class EnumGenerator; // enum.h -class MessageGenerator; // message.h -class ServiceGenerator; // service.h -class ExtensionGenerator; // extension.h +class EnumGenerator; // enum.h +class MessageGenerator; // message.h +class ServiceGenerator; // service.h +class ExtensionGenerator; // extension.h class FileGenerator { public: @@ -71,14 +74,12 @@ class FileGenerator { // Shared code between the two header generators below. void GenerateHeader(io::Printer* printer); - // info_path, if non-empty, should be the path (relative to printer's output) - // to the metadata file describing this proto header. - void GenerateProtoHeader(io::Printer* printer, - const string& info_path); - // info_path, if non-empty, should be the path (relative to printer's output) - // to the metadata file describing this PB header. - void GeneratePBHeader(io::Printer* printer, - const string& info_path); + // info_path, if non-empty, should be the path (relative to printer's + // output) to the metadata file describing this proto header. + void GenerateProtoHeader(io::Printer* printer, const std::string& info_path); + // info_path, if non-empty, should be the path (relative to printer's + // output) to the metadata file describing this PB header. + void GeneratePBHeader(io::Printer* printer, const std::string& info_path); void GenerateSource(io::Printer* printer); int NumMessages() const { return message_generators_.size(); } @@ -90,6 +91,20 @@ class FileGenerator { // Internal type used by GenerateForwardDeclarations (defined in file.cc). class ForwardDeclarations; + void IncludeFile(const std::string& google3_name, io::Printer* printer) { + DoIncludeFile(google3_name, false, printer); + } + void IncludeFileAndExport(const std::string& google3_name, io::Printer* printer) { + DoIncludeFile(google3_name, true, printer); + } + void DoIncludeFile(const std::string& google3_name, bool do_export, + io::Printer* printer); + + std::string CreateHeaderInclude(const std::string& basename, + const FileDescriptor* file); + void GenerateInternalForwardDeclarations( + const std::vector<const FieldDescriptor*>& fields, const Options& options, + MessageSCCAnalyzer* scc_analyzer, io::Printer* printer); void GenerateSourceIncludes(io::Printer* printer); void GenerateSourceDefaultInstance(int idx, io::Printer* printer); @@ -100,16 +115,11 @@ class FileGenerator { // For other imports, generates their forward-declarations. void GenerateForwardDeclarations(io::Printer* printer); - // Internal helper used by GenerateForwardDeclarations: fills 'decls' - // with all necessary forward-declarations for this file and its - // transient depednencies. - void FillForwardDeclarations(ForwardDeclarations* decls); - // Generates top or bottom of a header file. void GenerateTopHeaderGuard(io::Printer* printer, - const string& filename_identifier); + const std::string& filename_identifier); void GenerateBottomHeaderGuard(io::Printer* printer, - const string& filename_identifier); + const std::string& filename_identifier); // Generates #include directives. void GenerateLibraryIncludes(io::Printer* printer); @@ -117,7 +127,7 @@ class FileGenerator { // Generate a pragma to pull in metadata using the given info_path (if // non-empty). info_path should be relative to printer's output. - void GenerateMetadataPragma(io::Printer* printer, const string& info_path); + void GenerateMetadataPragma(io::Printer* printer, const std::string& info_path); // Generates a couple of different pieces before definitions: void GenerateGlobalStateFunctionDeclarations(io::Printer* printer); @@ -138,13 +148,13 @@ class FileGenerator { void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer); - // Sometimes the names we use in a .proto file happen to be defined as macros - // on some platforms (e.g., macro/minor used in plugin.proto are defined as - // macros in sys/types.h on FreeBSD and a few other platforms). To make the - // generated code compile on these platforms, we either have to undef the - // macro for these few platforms, or rename the field name for all platforms. - // Since these names are part of protobuf public API, renaming is generally - // a breaking change so we prefer the #undef approach. + // Sometimes the names we use in a .proto file happen to be defined as + // macros on some platforms (e.g., macro/minor used in plugin.proto are + // defined as macros in sys/types.h on FreeBSD and a few other platforms). + // To make the generated code compile on these platforms, we either have to + // undef the macro for these few platforms, or rename the field name for all + // platforms. Since these names are part of protobuf public API, renaming is + // generally a breaking change so we prefer the #undef approach. void GenerateMacroUndefs(io::Printer* printer); bool IsSCCRepresentative(const Descriptor* d) { @@ -157,30 +167,29 @@ class FileGenerator { return scc_analyzer_.GetSCC(d); } + bool IsDepWeak(const FileDescriptor* dep) const { + if (weak_deps_.count(dep) != 0) { + GOOGLE_CHECK(!options_.opensource_runtime); + return true; + } + return false; + } + + std::set<const FileDescriptor*> weak_deps_; const FileDescriptor* file_; const Options options_; - SCCAnalyzer scc_analyzer_; + MessageSCCAnalyzer scc_analyzer_; + std::map<std::string, std::string> variables_; // Contains the post-order walk of all the messages (and child messages) in // this file. If you need a pre-order walk just reverse iterate. - std::vector<MessageGenerator*> message_generators_; - std::vector<EnumGenerator*> enum_generators_; - std::vector<ServiceGenerator*> service_generators_; - std::vector<ExtensionGenerator*> extension_generators_; - - // These members are just for owning (and thus proper deleting). - // Nested (enum/extension)_generators are owned by child messages. - std::unique_ptr<std::unique_ptr<EnumGenerator> []> enum_generators_owner_; - std::unique_ptr<std::unique_ptr<ServiceGenerator> []> - service_generators_owner_; - std::unique_ptr<std::unique_ptr<ExtensionGenerator> []> - extension_generators_owner_; - - // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}. - std::vector<string> package_parts_; + std::vector<std::unique_ptr<MessageGenerator>> message_generators_; + std::vector<std::unique_ptr<EnumGenerator>> enum_generators_; + std::vector<std::unique_ptr<ServiceGenerator>> service_generators_; + std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; @@ -188,6 +197,6 @@ class FileGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index 20bb8a1a..0e7e4dfd 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -77,6 +77,21 @@ bool CppGenerator::Generate(const FileDescriptor* file, // __declspec(dllimport) depending on what is being compiled. // Options file_options; + + switch (runtime_) { + case Runtime::kGoogle3: + file_options.opensource_runtime = false; + break; + case Runtime::kOpensource: + file_options.opensource_runtime = true; + file_options.opensource_include_paths = true; + break; + case Runtime::kOpensourceGoogle3: + file_options.opensource_runtime = true; + file_options.opensource_include_paths = false; + break; + } + for (int i = 0; i < options.size(); i++) { if (options[i].first == "dllexport_decl") { file_options.dllexport_decl = options[i].second; @@ -108,7 +123,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, // The safe_boundary_check option controls behavior for Google-internal // protobuf APIs. - if (file_options.safe_boundary_check) { + if (file_options.safe_boundary_check && file_options.opensource_runtime) { *error = "The safe_boundary_check option is not supported outside of Google."; return false; @@ -119,6 +134,10 @@ bool CppGenerator::Generate(const FileDescriptor* file, string basename = StripProto(file->name()); + if (MaybeBootstrap(file_options, generator_context, file_options.bootstrap, + &basename)) { + return true; + } FileGenerator file_generator(file, file_options); @@ -163,32 +182,41 @@ bool CppGenerator::Generate(const FileDescriptor* file, // Generate cc file(s). if (UsingImplicitWeakFields(file, file_options)) { - { - // This is the global .cc file, containing enum/services/tables/reflection + if (file->name() == "net/proto2/proto/descriptor.proto") { + // If we are building with implicit weak fields then we do not want to + // produce any symbols for descriptor.proto, so we just create an empty + // pb.cc file. std::unique_ptr<io::ZeroCopyOutputStream> output( generator_context->Open(basename + ".pb.cc")); - io::Printer printer(output.get(), '$'); - file_generator.GenerateGlobalSource(&printer); - } + } else { + { + // This is the global .cc file, containing + // enum/services/tables/reflection + std::unique_ptr<io::ZeroCopyOutputStream> output( + generator_context->Open(basename + ".pb.cc")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateGlobalSource(&printer); + } - int num_cc_files = file_generator.NumMessages(); + int num_cc_files = file_generator.NumMessages(); - // If we're using implicit weak fields then we allow the user to optionally - // specify how many files to generate, not counting the global pb.cc file. - // If we have more files than messages, then some files will be generated as - // empty placeholders. - if (file_options.num_cc_files > 0) { - GOOGLE_CHECK_LE(file_generator.NumMessages(), file_options.num_cc_files) - << "There must be at least as many numbered .cc files as messages."; - num_cc_files = file_options.num_cc_files; - } - for (int i = 0; i < num_cc_files; i++) { - // TODO(gerbens) Agree on naming scheme. - std::unique_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(basename + "." + SimpleItoa(i) + ".cc")); - io::Printer printer(output.get(), '$'); - if (i < file_generator.NumMessages()) { - file_generator.GenerateSourceForMessage(i, &printer); + // If we're using implicit weak fields then we allow the user to + // optionally specify how many files to generate, not counting the global + // pb.cc file. If we have more files than messages, then some files will + // be generated as empty placeholders. + if (file_options.num_cc_files > 0) { + GOOGLE_CHECK_LE(file_generator.NumMessages(), file_options.num_cc_files) + << "There must be at least as many numbered .cc files as messages."; + num_cc_files = file_options.num_cc_files; + } + for (int i = 0; i < num_cc_files; i++) { + std::unique_ptr<io::ZeroCopyOutputStream> output( + generator_context->Open(basename + ".out/" + + SimpleItoa(i) + ".cc")); + io::Printer printer(output.get(), '$'); + if (i < file_generator.NumMessages()) { + file_generator.GenerateSourceForMessage(i, &printer); + } } } } else { diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.h b/src/google/protobuf/compiler/cpp/cpp_generator.h index 3d517cf4..30363e73 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.h +++ b/src/google/protobuf/compiler/cpp/cpp_generator.h @@ -40,6 +40,8 @@ #include <string> #include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { @@ -49,24 +51,41 @@ namespace cpp { // header. If you create your own protocol compiler binary and you want // it to support C++ output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT CppGenerator : public CodeGenerator { +class PROTOC_EXPORT CppGenerator : public CodeGenerator { public: CppGenerator(); ~CppGenerator(); + enum class Runtime { + kGoogle3, // Use the internal google3 runtime. + kOpensource, // Use the open-source runtime. + + // Use the open-source runtime with google3 #include paths. We make these + // absolute to avoid ambiguity, so the runtime will be #included like: + // #include "third_party/protobuf/<...>/google/protobuf/message.h" + kOpensourceGoogle3 + }; + + void set_runtime(Runtime runtime) { + runtime_ = runtime; + } + // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* generator_context, - string* error) const; + std::string* error) const; private: + Runtime runtime_ = Runtime::kOpensource; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 163dac0a..472c55f4 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -32,22 +32,28 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/stubs/hash.h> #include <limits> #include <map> #include <queue> +#include <unordered_set> #include <vector> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> +#include <google/protobuf/compiler/scc.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/wire_format_lite.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> +#include <google/protobuf/stubs/hash.h> + +#include <google/protobuf/port_def.inc> namespace google { namespace protobuf { @@ -83,15 +89,15 @@ const char* const kKeywordList[] = { "while", "xor", "xor_eq" }; -hash_set<string> MakeKeywordsMap() { - hash_set<string> result; +std::unordered_set<string> MakeKeywordsMap() { + std::unordered_set<string> result; for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); i++) { result.insert(kKeywordList[i]); } return result; } -hash_set<string> kKeywords = MakeKeywordsMap(); +std::unordered_set<string> kKeywords = MakeKeywordsMap(); // Returns whether the provided descriptor has an extension. This includes its // nested types. @@ -131,8 +137,55 @@ string Base63(I n, int k) { return res; } +string IntTypeName(const Options& options, const string& type) { + if (options.opensource_runtime) { + return "::google::protobuf::" + type; + } else { + return "::" + type; + } +} + +string StringTypeName(const Options& options) { + return options.opensource_runtime ? "::std::string" : "::std::string"; +} + +void SetIntVar(const Options& options, const string& type, + std::map<string, string>* variables) { + (*variables)[type] = IntTypeName(options, type); +} + } // namespace +void SetCommonVars(const Options& options, + std::map<string, string>* variables) { + (*variables)["proto_ns"] = ProtobufNamespace(options); + + // Warning: there is some clever naming/splitting here to avoid extract script + // rewrites. The names of these variables must not be things that the extract + // script will rewrite. That's why we use "CHK" (for example) instead of + // "GOOGLE_CHECK". + if (options.opensource_runtime) { + (*variables)["GOOGLE_PROTOBUF"] = "GOOGLE_PROTOBUF"; + (*variables)["CHK"] = "GOOGLE_CHECK"; + (*variables)["DCHK"] = "GOOGLE_DCHECK"; + } else { + // These values are things the extract script would rewrite if we did not + // split them. It might not strictly matter since we don't generate google3 + // code in open-source. But it's good to prevent surprising things from + // happening. + (*variables)["GOOGLE_PROTOBUF"] = "GOOGLE3" "_PROTOBUF"; + (*variables)["CHK"] = "CH" "ECK"; + (*variables)["DCHK"] = "DCH" "ECK"; + } + + SetIntVar(options, "uint8", variables); + SetIntVar(options, "uint32", variables); + SetIntVar(options, "uint64", variables); + SetIntVar(options, "int32", variables); + SetIntVar(options, "int64", variables); + (*variables)["string"] = StringTypeName(options); +} + string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { string result; // Note: I distrust ctype.h due to locales. @@ -205,11 +258,25 @@ string ClassName(const EnumDescriptor* enum_descriptor) { } } +string QualifiedClassName(const Descriptor* d) { + return Namespace(d) + "::" + ClassName(d); +} + +string QualifiedClassName(const EnumDescriptor* d) { + return Namespace(d) + "::" + ClassName(d); +} + string Namespace(const string& package) { if (package.empty()) return ""; return "::" + DotsToColons(package); } +string Namespace(const Descriptor* d) { return Namespace(d->file()); } + +string Namespace(const FieldDescriptor* d) { return Namespace(d->file()); } + +string Namespace(const EnumDescriptor* d) { return Namespace(d->file()); } + string DefaultInstanceName(const Descriptor* descriptor) { string prefix = descriptor->file()->package().empty() ? "" : "::"; return prefix + DotsToColons(descriptor->file()->package()) + "::_" + @@ -221,9 +288,9 @@ string ReferenceFunctionName(const Descriptor* descriptor) { } string SuperClassName(const Descriptor* descriptor, const Options& options) { - return HasDescriptorMethods(descriptor->file(), options) - ? "::google::protobuf::Message" - : "::google::protobuf::MessageLite"; + return "::" + ProtobufNamespace(options) + + (HasDescriptorMethods(descriptor->file(), options) ? "::Message" + : "::MessageLite"); } string FieldName(const FieldDescriptor* field) { @@ -318,6 +385,38 @@ const char* PrimitiveTypeName(FieldDescriptor::CppType type) { return NULL; } +string PrimitiveTypeName(const Options& options, + FieldDescriptor::CppType type) { + switch (type) { + case FieldDescriptor::CPPTYPE_INT32: + return IntTypeName(options, "int32"); + case FieldDescriptor::CPPTYPE_INT64: + return IntTypeName(options, "int64"); + case FieldDescriptor::CPPTYPE_UINT32: + return IntTypeName(options, "uint32"); + case FieldDescriptor::CPPTYPE_UINT64: + return IntTypeName(options, "uint64"); + case FieldDescriptor::CPPTYPE_DOUBLE: + return "double"; + case FieldDescriptor::CPPTYPE_FLOAT: + return "float"; + case FieldDescriptor::CPPTYPE_BOOL: + return "bool"; + case FieldDescriptor::CPPTYPE_ENUM: + return "int"; + case FieldDescriptor::CPPTYPE_STRING: + return StringTypeName(options); + case FieldDescriptor::CPPTYPE_MESSAGE: + return ""; + + // No default because we want the compiler to complain if any new + // CppTypes are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return ""; +} + const char* DeclaredTypeMethodName(FieldDescriptor::Type type) { switch (type) { case FieldDescriptor::TYPE_INT32 : return "Int32"; @@ -349,44 +448,58 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) { } string Int32ToString(int number) { - // gcc rejects the decimal form of kint32min. if (number == kint32min) { - GOOGLE_COMPILE_ASSERT(kint32min == (~0x7fffffff), kint32min_value_error); - return "(~0x7fffffff)"; + // This needs to be special-cased, see explanation here: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661 + return SimpleItoa(number + 1) + " - 1"; } else { return SimpleItoa(number); } } -string Int64ToString(int64 number) { - // gcc rejects the decimal form of kint64min +string Int64ToString(const string& macro_prefix, int64 number) { if (number == kint64min) { - // Make sure we are in a 2's complement system. - GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(~0x7fffffffffffffff), - kint64min_value_error); - return "GOOGLE_LONGLONG(~0x7fffffffffffffff)"; + // This needs to be special-cased, see explanation here: + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661 + return macro_prefix + "_LONGLONG(" + SimpleItoa(number + 1) + + ") - 1"; } - return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")"; + return macro_prefix + "_LONGLONG(" + SimpleItoa(number) + ")"; +} + +string UInt64ToString(const string& macro_prefix, uint64 number) { + return macro_prefix + "_ULONGLONG(" + SimpleItoa(number) + ")"; } string DefaultValue(const FieldDescriptor* field) { switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT64: + return Int64ToString("GG", field->default_value_int64()); + case FieldDescriptor::CPPTYPE_UINT64: + return UInt64ToString("GG", field->default_value_uint64()); + default: + return DefaultValue(Options(), field); + } +} + +string DefaultValue(const Options& options, const FieldDescriptor* field) { + switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: return Int32ToString(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: return SimpleItoa(field->default_value_uint32()) + "u"; case FieldDescriptor::CPPTYPE_INT64: - return Int64ToString(field->default_value_int64()); + return Int64ToString("PROTOBUF", field->default_value_int64()); case FieldDescriptor::CPPTYPE_UINT64: - return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")"; + return UInt64ToString("PROTOBUF", field->default_value_uint64()); case FieldDescriptor::CPPTYPE_DOUBLE: { double value = field->default_value_double(); if (value == std::numeric_limits<double>::infinity()) { - return "::google::protobuf::internal::Infinity()"; + return "std::numeric_limits<double>::infinity()"; } else if (value == -std::numeric_limits<double>::infinity()) { - return "-::google::protobuf::internal::Infinity()"; + return "-std::numeric_limits<double>::infinity()"; } else if (value != value) { - return "::google::protobuf::internal::NaN()"; + return "std::numeric_limits<double>::quiet_NaN()"; } else { return SimpleDtoa(value); } @@ -395,11 +508,11 @@ string DefaultValue(const FieldDescriptor* field) { { float value = field->default_value_float(); if (value == std::numeric_limits<float>::infinity()) { - return "static_cast<float>(::google::protobuf::internal::Infinity())"; + return "std::numeric_limits<float>::infinity()"; } else if (value == -std::numeric_limits<float>::infinity()) { - return "static_cast<float>(-::google::protobuf::internal::Infinity())"; + return "-std::numeric_limits<float>::infinity()"; } else if (value != value) { - return "static_cast<float>(::google::protobuf::internal::NaN())"; + return "std::numeric_limits<float>::quiet_NaN()"; } else { string float_value = SimpleFtoa(value); // If floating point value contains a period (.) or an exponent @@ -450,8 +563,9 @@ string FilenameIdentifier(const string& filename) { return result; } -string FileLevelNamespace(const string& filename) { - return "protobuf_" + FilenameIdentifier(filename); +string UniqueName(const string& name, const string& filename, + const Options& options) { + return name + "_" + FilenameIdentifier(filename); } // Return the qualified C++ name for a file level symbol. @@ -487,6 +601,126 @@ string SafeFunctionName(const Descriptor* descriptor, return function_name; } +static bool HasLazyFields(const Descriptor* descriptor, + const Options& options) { + for (int field_idx = 0; field_idx < descriptor->field_count(); field_idx++) { + if (IsLazy(descriptor->field(field_idx), options)) { + return true; + } + } + for (int idx = 0; idx < descriptor->extension_count(); idx++) { + if (IsLazy(descriptor->extension(idx), options)) { + return true; + } + } + for (int idx = 0; idx < descriptor->nested_type_count(); idx++) { + if (HasLazyFields(descriptor->nested_type(idx), options)) { + return true; + } + } + return false; +} + +// Does the given FileDescriptor use lazy fields? +bool HasLazyFields(const FileDescriptor* file, const Options& options) { + for (int i = 0; i < file->message_type_count(); i++) { + const Descriptor* descriptor(file->message_type(i)); + if (HasLazyFields(descriptor, options)) { + return true; + } + } + for (int field_idx = 0; field_idx < file->extension_count(); field_idx++) { + if (IsLazy(file->extension(field_idx), options)) { + return true; + } + } + return false; +} + +static bool HasRepeatedFields(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->field_count(); ++i) { + if (descriptor->field(i)->label() == FieldDescriptor::LABEL_REPEATED) { + return true; + } + } + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasRepeatedFields(descriptor->nested_type(i))) return true; + } + return false; +} + +bool HasRepeatedFields(const FileDescriptor* file) { + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasRepeatedFields(file->message_type(i))) return true; + } + return false; +} + +static bool IsStringPieceField(const FieldDescriptor* field, + const Options& options) { + return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE; +} + +static bool HasStringPieceFields(const Descriptor* descriptor, + const Options& options) { + for (int i = 0; i < descriptor->field_count(); ++i) { + if (IsStringPieceField(descriptor->field(i), options)) return true; + } + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasStringPieceFields(descriptor->nested_type(i), options)) return true; + } + return false; +} + +bool HasStringPieceFields(const FileDescriptor* file, const Options& options) { + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasStringPieceFields(file->message_type(i), options)) return true; + } + return false; +} + +static bool IsCordField(const FieldDescriptor* field, const Options& options) { + return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field, options) == FieldOptions::CORD; +} + +static bool HasCordFields(const Descriptor* descriptor, + const Options& options) { + for (int i = 0; i < descriptor->field_count(); ++i) { + if (IsCordField(descriptor->field(i), options)) return true; + } + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasCordFields(descriptor->nested_type(i), options)) return true; + } + return false; +} + +bool HasCordFields(const FileDescriptor* file, const Options& options) { + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasCordFields(file->message_type(i), options)) return true; + } + return false; +} + +static bool HasExtensionsOrExtendableMessage(const Descriptor* descriptor) { + if (descriptor->extension_range_count() > 0) return true; + if (descriptor->extension_count() > 0) return true; + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasExtensionsOrExtendableMessage(descriptor->nested_type(i))) { + return true; + } + } + return false; +} + +bool HasExtensionsOrExtendableMessage(const FileDescriptor* file) { + if (file->extension_count() > 0) return true; + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasExtensionsOrExtendableMessage(file->message_type(i))) return true; + } + return false; +} static bool HasMapFields(const Descriptor* descriptor) { for (int i = 0; i < descriptor->field_count(); ++i) { @@ -543,11 +777,16 @@ bool IsStringOrMessage(const FieldDescriptor* field) { return false; } -FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) { +FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field, + const Options& options) { GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); - // Open-source protobuf release only supports STRING ctype. - return FieldOptions::STRING; - + if (options.opensource_runtime) { + // Open-source protobuf release only supports STRING ctype. + return FieldOptions::STRING; + } else { + // Google-internal supports all ctypes. + return field->options().ctype(); + } } bool IsAnyMessage(const FileDescriptor* descriptor) { @@ -569,62 +808,81 @@ enum Utf8CheckMode { NONE = 2, // No UTF-8 check. }; +static bool FieldEnforceUtf8(const FieldDescriptor* field, + const Options& options) { + return true; +} + +static bool FileUtf8Verification(const FileDescriptor* file, + const Options& options) { + return true; +} + // Which level of UTF-8 enforcemant is placed on this file. static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, const Options& options) { - if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && + FieldEnforceUtf8(field, options)) { return STRICT; } else if (GetOptimizeFor(field->file(), options) != - FileOptions::LITE_RUNTIME) { + FileOptions::LITE_RUNTIME && + FileUtf8Verification(field->file(), options)) { return VERIFY; } else { return NONE; } } +string GetUtf8Suffix(const FieldDescriptor* field, const Options& options) { + switch (GetUtf8CheckMode(field, options)) { + case STRICT: + return "UTF8"; + case VERIFY: + return "UTF8Verify"; + case NONE: + default: // Some build configs warn on missing return without default. + return ""; + } +} + static void GenerateUtf8CheckCode(const FieldDescriptor* field, const Options& options, bool for_parse, - const std::map<string, string>& variables, const char* parameters, const char* strict_function, const char* verify_function, - io::Printer* printer) { + const Formatter& format) { switch (GetUtf8CheckMode(field, options)) { case STRICT: { if (for_parse) { - printer->Print("DO_("); + format("DO_("); } - printer->Print( - "::google::protobuf::internal::WireFormatLite::$function$(\n", - "function", strict_function); - printer->Indent(); - printer->Print(variables, parameters); + format("::$proto_ns$::internal::WireFormatLite::$1$(\n", strict_function); + format.Indent(); + format(parameters); if (for_parse) { - printer->Print("::google::protobuf::internal::WireFormatLite::PARSE,\n"); + format("::$proto_ns$::internal::WireFormatLite::PARSE,\n"); } else { - printer->Print("::google::protobuf::internal::WireFormatLite::SERIALIZE,\n"); + format("::$proto_ns$::internal::WireFormatLite::SERIALIZE,\n"); } - printer->Print("\"$full_name$\")", "full_name", field->full_name()); + format("\"$1$\")", field->full_name()); if (for_parse) { - printer->Print(")"); + format(")"); } - printer->Print(";\n"); - printer->Outdent(); + format(";\n"); + format.Outdent(); break; } case VERIFY: { - printer->Print( - "::google::protobuf::internal::WireFormat::$function$(\n", - "function", verify_function); - printer->Indent(); - printer->Print(variables, parameters); + format("::$proto_ns$::internal::WireFormat::$1$(\n", verify_function); + format.Indent(); + format(parameters); if (for_parse) { - printer->Print("::google::protobuf::internal::WireFormat::PARSE,\n"); + format("::$proto_ns$::internal::WireFormat::PARSE,\n"); } else { - printer->Print("::google::protobuf::internal::WireFormat::SERIALIZE,\n"); + format("::$proto_ns$::internal::WireFormat::SERIALIZE,\n"); } - printer->Print("\"$full_name$\");\n", "full_name", field->full_name()); - printer->Outdent(); + format("\"$1$\");\n", field->full_name()); + format.Outdent(); break; } case NONE: @@ -634,21 +892,19 @@ static void GenerateUtf8CheckCode(const FieldDescriptor* field, void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, const Options& options, bool for_parse, - const std::map<string, string>& variables, const char* parameters, - io::Printer* printer) { - GenerateUtf8CheckCode(field, options, for_parse, variables, parameters, + const Formatter& format) { + GenerateUtf8CheckCode(field, options, for_parse, parameters, "VerifyUtf8String", "VerifyUTF8StringNamedField", - printer); + format); } void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, const Options& options, bool for_parse, - const std::map<string, string>& variables, const char* parameters, - io::Printer* printer) { - GenerateUtf8CheckCode(field, options, for_parse, variables, parameters, - "VerifyUtf8Cord", "VerifyUTF8CordNamedField", printer); + const Formatter& format) { + GenerateUtf8CheckCode(field, options, for_parse, parameters, "VerifyUtf8Cord", + "VerifyUTF8CordNamedField", format); } namespace { @@ -669,11 +925,17 @@ void FlattenMessagesInFile(const FileDescriptor* file, } } -bool HasWeakFields(const Descriptor* descriptor) { +bool HasWeakFields(const Descriptor* descriptor, const Options& options) { + for (int i = 0; i < descriptor->field_count(); i++) { + if (IsWeak(descriptor->field(i), options)) return true; + } return false; } -bool HasWeakFields(const FileDescriptor* file) { +bool HasWeakFields(const FileDescriptor* file, const Options& options) { + for (int i = 0; i < file->message_type_count(); ++i) { + if (HasWeakFields(file->message_type(i), options)) return true; + } return false; } @@ -684,7 +946,7 @@ bool UsingImplicitWeakFields(const FileDescriptor* file, } bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options, - SCCAnalyzer* scc_analyzer) { + MessageSCCAnalyzer* scc_analyzer) { return UsingImplicitWeakFields(field->file(), options) && field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_required() && !field->is_map() && @@ -696,85 +958,18 @@ bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options, scc_analyzer->GetSCC(field->message_type()); } -struct CompareDescriptors { - bool operator()(const Descriptor* a, const Descriptor* b) { - return a->full_name() < b->full_name(); - } -}; - -SCCAnalyzer::NodeData SCCAnalyzer::DFS(const Descriptor* descriptor) { - // Must not have visited already. - GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0); - - // Mark visited by inserting in map. - NodeData& result = cache_[descriptor]; - // Initialize data structures. - result.index = result.lowlink = index_++; - stack_.push_back(descriptor); - - // Recurse the fields / nodes in graph - for (int i = 0; i < descriptor->field_count(); i++) { - const Descriptor* child = descriptor->field(i)->message_type(); - if (child) { - if (cache_.count(child) == 0) { - // unexplored node - NodeData child_data = DFS(child); - result.lowlink = std::min(result.lowlink, child_data.lowlink); - } else { - NodeData child_data = cache_[child]; - if (child_data.scc == NULL) { - // Still in the stack_ so we found a back edge - result.lowlink = std::min(result.lowlink, child_data.index); - } - } - } - } - if (result.index == result.lowlink) { - // This is the root of a strongly connected component - SCC* scc = CreateSCC(); - while (true) { - const Descriptor* scc_desc = stack_.back(); - scc->descriptors.push_back(scc_desc); - // Remove from stack - stack_.pop_back(); - cache_[scc_desc].scc = scc; - - if (scc_desc == descriptor) break; - } - - // The order of descriptors is random and depends how this SCC was - // discovered. In-order to ensure maximum stability we sort it by name. - std::sort(scc->descriptors.begin(), scc->descriptors.end(), - CompareDescriptors()); - AddChildren(scc); - } - return result; -} - -void SCCAnalyzer::AddChildren(SCC* scc) { - std::set<const SCC*> seen; - for (int i = 0; i < scc->descriptors.size(); i++) { - const Descriptor* descriptor = scc->descriptors[i]; - for (int j = 0; j < descriptor->field_count(); j++) { - const Descriptor* child_msg = descriptor->field(j)->message_type(); - if (child_msg) { - const SCC* child = GetSCC(child_msg); - if (child == scc) continue; - if (seen.insert(child).second) { - scc->children.push_back(child); - } - } - } - } -} - -MessageAnalysis SCCAnalyzer::GetSCCAnalysis(const SCC* scc) { +MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) { if (analysis_cache_.count(scc)) return analysis_cache_[scc]; - MessageAnalysis result = MessageAnalysis(); + MessageAnalysis result{}; for (int i = 0; i < scc->descriptors.size(); i++) { const Descriptor* descriptor = scc->descriptors[i]; if (descriptor->extension_range_count() > 0) { result.contains_extension = true; + // Extensions are found by looking up default_instance and extension + // number in a map. So you'd maybe expect here + // result.constructor_requires_initialization = true; + // However the extension registration mechanism already makes sure + // the default will be initialized. } for (int i = 0; i < descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); @@ -784,6 +979,7 @@ MessageAnalysis SCCAnalyzer::GetSCCAnalysis(const SCC* scc) { switch (field->type()) { case FieldDescriptor::TYPE_STRING: case FieldDescriptor::TYPE_BYTES: { + result.constructor_requires_initialization = true; if (field->options().ctype() == FieldOptions::CORD) { result.contains_cord = true; } @@ -791,7 +987,8 @@ MessageAnalysis SCCAnalyzer::GetSCCAnalysis(const SCC* scc) { } case FieldDescriptor::TYPE_GROUP: case FieldDescriptor::TYPE_MESSAGE: { - const SCC* child = GetSCC(field->message_type()); + result.constructor_requires_initialization = true; + const SCC* child = analyzer_.GetSCC(field->message_type()); if (child != scc) { MessageAnalysis analysis = GetSCCAnalysis(child); result.contains_cord |= analysis.contains_cord; @@ -860,6 +1057,597 @@ void ListAllTypesForServices(const FileDescriptor* fd, } } +bool GetBootstrapBasename(const Options& options, const string& basename, + string* bootstrap_basename) { + if (options.opensource_runtime || options.lite_implicit_weak_fields) { + return false; + } + + std::unordered_map<string, string> bootstrap_mapping{ + {"net/proto2/proto/descriptor", + "net/proto2/internal/descriptor"}, + {"net/proto2/compiler/proto/plugin", + "net/proto2/compiler/proto/plugin"}, + {"net/proto2/compiler/proto/profile", + "net/proto2/compiler/proto/profile_bootstrap"}, + }; + auto iter = bootstrap_mapping.find(basename); + if (iter == bootstrap_mapping.end()) { + *bootstrap_basename = basename; + return false; + } else { + *bootstrap_basename = iter->second; + return true; + } +} + +bool IsBootstrapProto(const Options& options, const FileDescriptor* file) { + string my_name = StripProto(file->name()); + return GetBootstrapBasename(options, my_name, &my_name); +} + +bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context, + bool bootstrap_flag, string* basename) { + string bootstrap_basename; + if (!GetBootstrapBasename(options, *basename, &bootstrap_basename)) { + return false; + } + + if (bootstrap_flag) { + // Adjust basename, but don't abort code generation. + *basename = bootstrap_basename; + return false; + } else { + string forward_to_basename = bootstrap_basename; + + // Generate forwarding headers and empty .pb.cc. + { + std::unique_ptr<io::ZeroCopyOutputStream> output( + generator_context->Open(*basename + ".pb.h")); + io::Printer printer(output.get(), '$', nullptr); + printer.Print( + "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n" + "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n" + "#include \"$forward_to_basename$.pb.h\" // IWYU pragma: export\n" + "#endif // PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n", + "forward_to_basename", forward_to_basename, + "filename_identifier", FilenameIdentifier(*basename)); + + if (!options.opensource_runtime) { + // HACK HACK HACK, tech debt from the deeps of proto1 and SWIG + // protocoltype is SWIG'ed and we need to forward + if (*basename == "net/proto/protocoltype") { + printer.Print( + "#ifdef SWIG\n" + "%include \"$forward_to_basename$.pb.h\"\n" + "#endif // SWIG\n", + "forward_to_basename", forward_to_basename); + } + } + } + + { + std::unique_ptr<io::ZeroCopyOutputStream> output( + generator_context->Open(*basename + ".proto.h")); + io::Printer printer(output.get(), '$', nullptr); + printer.Print( + "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n" + "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n" + "#include \"$forward_to_basename$.proto.h\" // IWYU pragma: " + "export\n" + "#endif // " + "PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n", + "forward_to_basename", forward_to_basename, + "filename_identifier", FilenameIdentifier(*basename)); + } + + { + std::unique_ptr<io::ZeroCopyOutputStream> output( + generator_context->Open(*basename + ".pb.cc")); + io::Printer printer(output.get(), '$', nullptr); + printer.Print("\n"); + } + + { + std::unique_ptr<io::ZeroCopyOutputStream> output( + generator_context->Open(*basename + ".pb.h.meta")); + } + + { + std::unique_ptr<io::ZeroCopyOutputStream> output( + generator_context->Open(*basename + ".proto.h.meta")); + } + + // Abort code generation. + return true; + } +} + +bool ShouldRepeat(const FieldDescriptor* descriptor, + internal::WireFormatLite::WireType wiretype) { + return descriptor->is_repeated() && + (!descriptor->is_packable() || + wiretype != internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED); +} + +void GenerateLengthDelim( + const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer, + const Formatter& format) { + format( + "ptr = Varint::Parse32Inline(ptr, &size);\n" + "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n"); + if (!IsProto1(field->file(), options) && field->is_packable()) { + if (!HasPreservingUnknownEnumSemantics(field->file()) && + field->type() == FieldDescriptor::TYPE_ENUM) { + format( + "ctx->extra_parse_data().SetEnumValidator($1$_IsValid, " + "msg->mutable_unknown_fields(), $2$);\n" + "parser_till_end = " + "::$proto_ns$::internal::PackedValidEnumParser$3$;\n" + "object = msg->mutable_$4$();\n", + QualifiedClassName(field->enum_type()), field->number(), + UseUnknownFieldSet(field->file(), options) ? "" : "Lite", + FieldName(field)); + } else { + format( + "parser_till_end = ::$proto_ns$::internal::Packed$1$Parser;\n" + "object = msg->mutable_$2$();\n", + DeclaredTypeMethodName(field->type()), FieldName(field)); + } + format( + "if (size > end - ptr) goto len_delim_till_end;\n" + "auto newend = ptr + size;\n" + "if (size) ptr = parser_till_end(ptr, newend, object, ctx);\n" + "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr == newend);\n"); + } else { + auto field_type = field->type(); + if (IsProto1(field->file(), options)) { + if (field->is_packable()) { + // Sigh ... packed fields endup as a string in proto1 + field_type = FieldDescriptor::TYPE_BYTES; + } + if (field_type == FieldDescriptor::TYPE_STRING) { + // In proto1 strings are treated as bytes + field_type = FieldDescriptor::TYPE_BYTES; + } + } + string utf8 = ""; + switch (field_type) { + case FieldDescriptor::TYPE_STRING: + utf8 = GetUtf8Suffix(field, options); + if (!utf8.empty()) { + string name = "nullptr"; + if (HasDescriptorMethods(field->file(), options)) { + name = "\"" + field->full_name() + "\""; + } + format("ctx->extra_parse_data().SetFieldName($1$);\n", name); + } + PROTOBUF_FALLTHROUGH_INTENDED; + case FieldDescriptor::TYPE_BYTES: { + if (field->options().ctype() == FieldOptions::STRING || + (IsProto1(field->file(), options) && + field->options().ctype() == FieldOptions::STRING_PIECE)) { + format( + "parser_till_end = ::$proto_ns$::internal::StringParser$1$;\n" + "$string$* str = msg->$2$_$3$();\n" + "str->clear();\n", + utf8, + field->is_repeated() && !field->is_map() && + !field->is_packable() + ? "add" + : "mutable", + FieldName(field)); + if (utf8.empty()) { + // special case if there is no utf8 verification. + format( + "object = str;\n" + "if (size > end - ptr) goto len_delim_till_end;\n" + "str->append(ptr, size);\n" + "ptr += size;\n"); + return; + } + } else if (field->options().ctype() == FieldOptions::CORD) { + string cord_parser = "CordParser" + utf8; + format( + "parser_till_end = ::$proto_ns$::internal::$1$;\n" + "auto* str = msg->$2$_$3$();\n" + "str->Clear();\n", + cord_parser, + field->is_repeated() && !field->is_map() ? "add" : "mutable", + FieldName(field)); + } else if (field->options().ctype() == FieldOptions::STRING_PIECE) { + format( + "parser_till_end = " + "::$proto_ns$::internal::StringPieceParser$1$;\n" + "::$proto_ns$::internal::StringPieceField* str = " + "msg->$2$_$3$();\n" + "str->Clear();\n", + utf8, + field->is_repeated() && !field->is_map() ? "add" : "mutable", + FieldName(field)); + } + format( + "object = str;\n" + "if (size > end - ptr) goto len_delim_till_end;\n" + "auto newend = ptr + size;\n" + "if (size) ptr = parser_till_end(ptr, newend, object, ctx);\n"); + if (!utf8.empty()) { + // If utf8 verification is on this can fail. + format("$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr == newend);\n"); + } + break; + } + case FieldDescriptor::TYPE_MESSAGE: { + GOOGLE_CHECK(field->message_type()); + if (!IsProto1(field->file(), options) && field->is_map()) { + const FieldDescriptor* val = + field->message_type()->FindFieldByName("value"); + GOOGLE_CHECK(val); + if (HasFieldPresence(field->file()) && + val->type() == FieldDescriptor::TYPE_ENUM) { + format( + "ctx->extra_parse_data().field_number = $1$;\n" + "ctx->extra_parse_data().unknown_fields = " + "&msg->_internal_metadata_;\n", + field->number()); + } + format( + "parser_till_end = ::$proto_ns$::internal::SlowMapEntryParser;\n" + "auto parse_map = $1$::_ParseMap;\n" + "ctx->extra_parse_data().payload.clear();\n" + "ctx->extra_parse_data().parse_map = parse_map;\n" + "object = &msg->$2$_;\n" + "if (size > end - ptr) goto len_delim_till_end;\n" + "auto newend = ptr + size;\n" + "GOOGLE_PROTOBUF_PARSER_ASSERT(parse_map(ptr, newend, " + "object, ctx));\n" + "ptr = newend;\n", + QualifiedClassName(field->message_type()), FieldName(field)); + break; + } + if (IsImplicitWeakField(field, options, scc_analyzer)) { + if (!field->is_repeated()) { + format("object = HasBitSetters::mutable_$1$(msg);\n", + FieldName(field)); + } else { + format( + "object = " + "CastToBase(&msg->$1$_)->AddWeak(reinterpret_cast<const " + "::google::protobuf::MessageLite*>(&$2$::_$3$_default_instance_));\n", + FieldName(field), Namespace(field->message_type()), + ClassName(field->message_type())); + } + format( + "parser_till_end = static_cast<::$proto_ns$::MessageLite*>(" + "object)->_ParseFunc();\n"); + } else if (IsWeak(field, options)) { + if (IsProto1(field->file(), options)) { + format("object = msg->internal_mutable_$1$();\n", + FieldName(field)); + } else { + format( + "object = msg->_weak_field_map_.MutableMessage($1$, " + "_$classname$_default_instance_.$2$_);\n", + field->number(), FieldName(field)); + } + format( + "parser_till_end = static_cast<::$proto_ns$::MessageLite*>(" + "object)->_ParseFunc();\n"); + } else { + format( + "parser_till_end = $1$::_InternalParse;\n" + "object = msg->$2$_$3$();\n", + QualifiedClassName(field->message_type()), + field->is_repeated() ? "add" : "mutable", FieldName(field)); + } + format( + "if (size > end - ptr) goto len_delim_till_end;\n" + "auto newend = ptr + size;\n" + "bool ok = ctx->ParseExactRange({parser_till_end, object},\n" + " ptr, newend);\n" + "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ok);\n" + "ptr = newend;\n"); + break; + } + default: + GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype " + << " filed type is " << field->type(); + } + } +} + +void GenerateCaseBody(internal::WireFormatLite::WireType wiretype, + const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer, + const Formatter& format) { + using internal::WireFormat; + using internal::WireFormatLite; + + if (ShouldRepeat(field, wiretype)) { + format("do {\n"); + format.Indent(); + } + switch (wiretype) { + case WireFormatLite::WIRETYPE_VARINT: { + format( + "$uint64$ val;\n" + "ptr = Varint::Parse64(ptr, &val);\n" + "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n"); + string type = PrimitiveTypeName(options, field->cpp_type()); + if ((field->type() == FieldDescriptor::TYPE_SINT32 || + field->type() == FieldDescriptor::TYPE_SINT64) && + !IsProto1(field->file(), options)) { + int size = EstimateAlignmentSize(field) * 8; + format( + "$1$ value = " + "::$proto_ns$::internal::WireFormatLite::ZigZagDecode$2$(val);\n", + type, size); + } else if (field->type() == FieldDescriptor::TYPE_ENUM && + !IsProto1(field->file(), options)) { + if (!HasPreservingUnknownEnumSemantics(field->file())) { + format( + "if (!$1$_IsValid(val)) {\n" + " ::$proto_ns$::internal::WriteVarint($2$, val, " + "msg->mutable_unknown_fields());\n" + " break;\n" + "}\n", + QualifiedClassName(field->enum_type()), field->number()); + } + format("$1$ value = static_cast<$1$>(val);\n", + QualifiedClassName(field->enum_type())); + } else { + format("$1$ value = val;\n", type); + } + if (field->is_repeated()) { + format("msg->add_$1$(value);\n", FieldName(field)); + } else { + format("msg->set_$1$(value);\n", FieldName(field)); + } + break; + } + case WireFormatLite::WIRETYPE_FIXED64: { + string type = PrimitiveTypeName(options, field->cpp_type()); + format( + "$1$ val;\n" + "::std::memcpy(&val, ptr, 8);\n" + "ptr += 8;\n", + type); + if (field->is_repeated()) { + format("msg->add_$1$(val);\n", FieldName(field)); + } else { + format("msg->set_$1$(val);\n", FieldName(field)); + } + break; + } + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { + GenerateLengthDelim(field, options, scc_analyzer, format); + break; + } + case WireFormatLite::WIRETYPE_START_GROUP: { + format( + "parser_till_end = $1$::_InternalParse;\n" + "object = msg->$2$_$3$();\n" + "bool ok = ctx->PrepareGroup(tag, &depth);\n" + "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ok);\n" + "ptr = parser_till_end(ptr, end, object, ctx);\n" + "$GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n" + "if (ctx->GroupContinues(depth)) goto group_continues;\n", + QualifiedClassName(field->message_type()), + field->is_repeated() ? "add" : "mutable", FieldName(field)); + break; + } + case WireFormatLite::WIRETYPE_END_GROUP: { + GOOGLE_LOG(FATAL) << "Can't have end group field\n"; + break; + } + case WireFormatLite::WIRETYPE_FIXED32: { + string type = PrimitiveTypeName(options, field->cpp_type()); + format( + "$1$ val;\n" + "std::memcpy(&val, ptr, 4);\n" + "ptr += 4;\n", + type); + if (field->is_repeated()) { + format("msg->add_$1$(val);\n", FieldName(field)); + } else { + format("msg->set_$1$(val);\n", FieldName(field)); + } + break; + } + } // switch (wire_type) + + if (ShouldRepeat(field, wiretype)) { + format("if (ptr >= end) break;\n"); + uint32 x = field->number() * 8 + wiretype; + uint64 y = 0; + int cnt = 0; + do { + y += static_cast<uint64>((x & 0x7F) + (x >= 128 ? 128 : 0)) + << (cnt++ * 8); + x >>= 7; + } while (x); + uint64 mask = (1ull << (cnt * 8)) - 1; + format.Outdent(); + format( + "} while ((::$proto_ns$::io::UnalignedLoad<$uint64$>(ptr) & $1$) == " + "$2$ && (ptr += $3$));\n", + mask, y, cnt); + } + format("break;\n"); +} + +void GenerateCaseBody(const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer, + const Formatter& format) { + using internal::WireFormat; + using internal::WireFormatLite; + + if (!IsProto1(field->file(), options) && field->is_packable()) { + auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type()); + GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + uint32 expected_tag = + WireFormatLite::MakeTag(field->number(), expected_wiretype); + auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED; + uint32 fallback_tag = + WireFormatLite::MakeTag(field->number(), fallback_wiretype); + + if (field->is_packed()) { + std::swap(expected_tag, fallback_tag); + std::swap(expected_wiretype, fallback_wiretype); + } + + format("if (static_cast<$uint8$>(tag) == $1$) {\n", expected_tag & 0xFF); + format.Indent(); + GenerateCaseBody(expected_wiretype, field, options, scc_analyzer, format); + format.Outdent(); + format( + "} else if (static_cast<$uint8$>(tag) != $1$) goto handle_unusual;\n", + fallback_tag & 0xFF); + GenerateCaseBody(fallback_wiretype, field, options, scc_analyzer, format); + } else { + auto wiretype = WireFormat::WireTypeForField(field); + format("if (static_cast<$uint8$>(tag) != $1$) goto handle_unusual;\n", + WireFormat::MakeTag(field) & 0xFF); + GenerateCaseBody(wiretype, field, options, scc_analyzer, format); + } +} + +void GenerateParserLoop(const Descriptor* descriptor, const Options& options, + MessageSCCAnalyzer* scc_analyzer, + io::Printer* printer) { + using internal::WireFormat; + using internal::WireFormatLite; + + Formatter format(printer); + format.Set("classname", ClassName(descriptor)); + format.Set("proto_ns", ProtobufNamespace(options)); + std::map<string, string> vars; + SetCommonVars(options, &vars); + format.AddMap(vars); + + std::vector<const FieldDescriptor*> ordered_fields; + for (auto field : FieldRange(descriptor)) { + ordered_fields.push_back(field); + } + std::sort(ordered_fields.begin(), ordered_fields.end(), + [](const FieldDescriptor* a, const FieldDescriptor* b) { + return a->number() < b->number(); + }); + + format( + "const char* $classname$::_InternalParse(const char* begin, const char* " + "end, void* object,\n" + " ::$proto_ns$::internal::ParseContext* ctx) {\n" + " auto msg = static_cast<$classname$*>(object);\n" + " $uint32$ size; (void)size;\n" + " int depth; (void)depth;\n" + " ::$proto_ns$::internal::ParseFunc parser_till_end; " + "(void)parser_till_end;\n" + " auto ptr = begin;\n" + " while (ptr < end) {\n" + " $uint32$ tag;\n" + " ptr = Varint::Parse32Inline(ptr, &tag);\n" + " $GOOGLE_PROTOBUF$_PARSER_ASSERT(ptr);\n" + " switch (tag >> 3) {\n"); + + format.Indent(); + format.Indent(); + format.Indent(); + + for (const auto* field : ordered_fields) { + if (IsProto1(descriptor->file(), options)) { + if (field->number() >= (1 << 14)) continue; + } + // Print the field's (or oneof's) proto-syntax definition as a comment. + // We don't want to print group bodies so we cut off after the first + // line. + string def; + { + DebugStringOptions options; + options.elide_group_body = true; + options.elide_oneof_body = true; + def = field->DebugStringWithOptions(options); + def = def.substr(0, def.find_first_of('\n')); + } + format( + "// $1$\n" + "case $2$: {\n", + def, field->number()); + format.Indent(); + GenerateCaseBody(field, options, scc_analyzer, format); + format.Outdent(); + format("}\n"); // case + } // for fields + format( + "default: {\n" + "handle_unusual: (void)&&handle_unusual;\n" + " if ((tag & 7) == 4 || tag == 0) {\n" + " bool ok = ctx->ValidEndGroup(tag);\n" + " $GOOGLE_PROTOBUF$_PARSER_ASSERT(ok);\n" + " return ptr;\n" + " }\n"); + if (IsMapEntryMessage(descriptor)) { + format( + " break;\n" + "}\n"); + } else { + if (descriptor->extension_range_count() > 0) { + format("if ("); + for (int i = 0; i < descriptor->extension_range_count(); i++) { + const Descriptor::ExtensionRange* range = + descriptor->extension_range(i); + if (i > 0) format(" ||\n "); + + uint32 start_tag = WireFormatLite::MakeTag( + range->start, static_cast<WireFormatLite::WireType>(0)); + uint32 end_tag = WireFormatLite::MakeTag( + range->end, static_cast<WireFormatLite::WireType>(0)); + + if (range->end > FieldDescriptor::kMaxNumber) { + format("($1$u <= tag)", start_tag); + } else { + format("($1$u <= tag && tag < $2$u)", start_tag, end_tag); + } + } + format(") {\n"); + format( + " auto res = msg->_extensions_.ParseField(tag, {_InternalParse, " + "msg}, ptr, end,\n" + " internal_default_instance(), &msg->_internal_metadata_, " + "ctx);\n" + " ptr = res.first;\n" + " if (res.second) return ptr;\n" + " continue;\n" + "}\n"); + } + format( + " auto res = UnknownFieldParse(tag, {_InternalParse, msg},\n" + " ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), " + "ctx);\n" + " ptr = res.first;\n" + " if (res.second) return ptr;\n" + "}\n"); // default case + } + format.Outdent(); + format.Outdent(); + format.Outdent(); + format( + " } // switch\n" + " } // while\n" + " return ptr;\n" + "len_delim_till_end: (void)&&len_delim_till_end;\n" + " return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},\n" + " {parser_till_end, object}, size);\n" + "group_continues: (void)&&group_continues;\n" + " $DCHK$(ptr >= end);\n" + // Group crossed end and must be continued. Either this a parse failure + // or we need to resume on the next chunk and thus save the state. + " ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, " + "depth);\n" + " return ptr;\n" + "}\n"); +} } // namespace cpp } // namespace compiler diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index eac65124..b8431aed 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -35,48 +35,76 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ +#include <iterator> #include <map> #include <string> + #include <google/protobuf/compiler/cpp/cpp_options.h> +#include <google/protobuf/compiler/scc.h> #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/descriptor.h> +#include <google/protobuf/port.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { namespace cpp { +inline std::string ProtobufNamespace(const Options& options) { + return options.opensource_runtime ? "google::protobuf" : "proto2"; +} + +inline std::string MacroPrefix(const Options& options) { + return options.opensource_runtime ? "GOOGLE_PROTOBUF" : "GOOGLE_PROTOBUF"; +} + +inline std::string DeprecatedAttribute(const Options& options, bool deprecated) { + return deprecated ? "PROTOBUF_DEPRECATED " : ""; +} + // Commonly-used separator comments. Thick is a line of '=', thin is a line // of '-'. extern const char kThickSeparator[]; extern const char kThinSeparator[]; +inline bool IsProto1(const FileDescriptor* file, const Options& options) { + return false; +} + +void SetCommonVars(const Options& options, std::map<std::string, std::string>* variables); + +bool GetBootstrapBasename(const Options& options, const std::string& basename, + std::string* bootstrap_basename); +bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context, + bool bootstrap_flag, std::string* basename); +bool IsBootstrapProto(const Options& options, const FileDescriptor* file); // Name space of the proto file. This namespace is such that the string // "<namespace>::some_name" is the correct fully qualified namespace. // This means if the package is empty the namespace is "", and otherwise // the namespace is "::foo::bar::...::baz" without trailing semi-colons. -string Namespace(const string& package); -inline string Namespace(const FileDescriptor* d) { +std::string Namespace(const std::string& package); +inline std::string Namespace(const FileDescriptor* d) { return Namespace(d->package()); } -template <typename Desc> -string Namespace(const Desc* d) { - return Namespace(d->file()); -} + +std::string Namespace(const Descriptor* d); +std::string Namespace(const FieldDescriptor* d); +std::string Namespace(const EnumDescriptor* d); // Returns true if it's safe to reset "field" to zero. bool CanInitializeByZeroing(const FieldDescriptor* field); -string ClassName(const Descriptor* descriptor); -string ClassName(const EnumDescriptor* enum_descriptor); -template <typename Desc> -string QualifiedClassName(const Desc* d) { - return Namespace(d) + "::" + ClassName(d); -} +std::string ClassName(const Descriptor* descriptor); +std::string ClassName(const EnumDescriptor* enum_descriptor); + +std::string QualifiedClassName(const Descriptor* d); +std::string QualifiedClassName(const EnumDescriptor* d); // DEPRECATED just use ClassName or QualifiedClassName, a boolean is very // unreadable at the callsite. @@ -88,33 +116,33 @@ string QualifiedClassName(const Desc* d) { // ::foo::bar::Baz_Qux // While the non-qualified version would be: // Baz_Qux -inline string ClassName(const Descriptor* descriptor, bool qualified) { +inline std::string ClassName(const Descriptor* descriptor, bool qualified) { return qualified ? QualifiedClassName(descriptor) : ClassName(descriptor); } -inline string ClassName(const EnumDescriptor* descriptor, bool qualified) { +inline std::string ClassName(const EnumDescriptor* descriptor, bool qualified) { return qualified ? QualifiedClassName(descriptor) : ClassName(descriptor); } // Fully qualified name of the default_instance of this message. -string DefaultInstanceName(const Descriptor* descriptor); +std::string DefaultInstanceName(const Descriptor* descriptor); // Returns the name of a no-op function that we can call to introduce a linker // dependency on the given message type. This is used to implement implicit weak // fields. -string ReferenceFunctionName(const Descriptor* descriptor); +std::string ReferenceFunctionName(const Descriptor* descriptor); // Name of the base class: google::protobuf::Message or google::protobuf::MessageLite. -string SuperClassName(const Descriptor* descriptor, const Options& options); +std::string SuperClassName(const Descriptor* descriptor, const Options& options); // Get the (unqualified) name that should be used for this field in C++ code. // The name is coerced to lower-case to emulate proto1 behavior. People // should be using lowercase-with-underscores style for proto field names // anyway, so normally this just returns field->name(). -string FieldName(const FieldDescriptor* field); +std::string FieldName(const FieldDescriptor* field); // Get the sanitized name that should be used for the given enum in C++ code. -string EnumValueName(const EnumValueDescriptor* enum_value); +std::string EnumValueName(const EnumValueDescriptor* enum_value); // 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 @@ -124,7 +152,7 @@ int EstimateAlignmentSize(const FieldDescriptor* field); // Get the unqualified name that should be used for a field's field // number constant. -string FieldConstantName(const FieldDescriptor *field); +std::string FieldConstantName(const FieldDescriptor *field); // Returns the scope where the field was defined (for extensions, this is // different from the message type to which the field applies). @@ -135,64 +163,88 @@ inline const Descriptor* FieldScope(const FieldDescriptor* field) { // Returns the fully-qualified type name field->message_type(). Usually this // is just ClassName(field->message_type(), true); -string FieldMessageTypeName(const FieldDescriptor* field); +std::string FieldMessageTypeName(const FieldDescriptor* field); // Strips ".proto" or ".protodevel" from the end of a filename. -LIBPROTOC_EXPORT string StripProto(const string& filename); +PROTOC_EXPORT std::string StripProto(const std::string& filename); // Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.). -// Note: non-built-in type names will be qualified, meaning they will start -// with a ::. If you are using the type as a template parameter, you will -// need to insure there is a space between the < and the ::, because the -// ridiculous C++ standard defines "<:" to be a synonym for "[". const char* PrimitiveTypeName(FieldDescriptor::CppType type); +std::string PrimitiveTypeName(const Options& options, FieldDescriptor::CppType type); // Get the declared type name in CamelCase format, as is used e.g. for the // methods of WireFormat. For example, TYPE_INT32 becomes "Int32". const char* DeclaredTypeMethodName(FieldDescriptor::Type type); // Return the code that evaluates to the number when compiled. -string Int32ToString(int number); +std::string Int32ToString(int number); // Return the code that evaluates to the number when compiled. -string Int64ToString(int64 number); +std::string Int64ToString(const Options& options, int64 number); // Get code that evaluates to the field's default value. -string DefaultValue(const FieldDescriptor* field); +std::string DefaultValue(const Options& options, const FieldDescriptor* field); + +// Compatibility function for callers outside proto2. +std::string DefaultValue(const FieldDescriptor* field); // Convert a file name into a valid identifier. -string FilenameIdentifier(const string& filename); +std::string FilenameIdentifier(const std::string& filename); + +// For each .proto file generates a unique name. To prevent collisions of +// symbols in the global namespace +std::string UniqueName(const std::string& name, const std::string& filename, + const Options& options); +inline std::string UniqueName(const std::string& name, const FileDescriptor* d, + const Options& options) { + return UniqueName(name, d->name(), options); +} +inline std::string UniqueName(const std::string& name, const Descriptor* d, + const Options& options) { + return UniqueName(name, d->file(), options); +} +inline std::string UniqueName(const std::string& name, const EnumDescriptor* d, + const Options& options) { + return UniqueName(name, d->file(), options); +} +inline std::string UniqueName(const std::string& name, const ServiceDescriptor* d, + const Options& options) { + return UniqueName(name, d->file(), options); +} -// For each .proto file generates a unique namespace. In this namespace global -// definitions are put to prevent collisions. -string FileLevelNamespace(const string& filename); -inline string FileLevelNamespace(const FileDescriptor* file) { - return FileLevelNamespace(file->name()); +// Versions for call sites that only support the internal runtime (like proto1 +// support). +inline Options InternalRuntimeOptions() { + Options options; + options.opensource_runtime = false; + return options; +} +inline std::string UniqueName(const std::string& name, const std::string& filename) { + return UniqueName(name, filename, InternalRuntimeOptions()); +} +inline std::string UniqueName(const std::string& name, const FileDescriptor* d) { + return UniqueName(name, d->name(), InternalRuntimeOptions()); +} +inline std::string UniqueName(const std::string& name, const Descriptor* d) { + return UniqueName(name, d->file(), InternalRuntimeOptions()); } -inline string FileLevelNamespace(const Descriptor* d) { - return FileLevelNamespace(d->file()); +inline std::string UniqueName(const std::string& name, const EnumDescriptor* d) { + return UniqueName(name, d->file(), InternalRuntimeOptions()); +} +inline std::string UniqueName(const std::string& name, const ServiceDescriptor* d) { + return UniqueName(name, d->file(), InternalRuntimeOptions()); } // Return the qualified C++ name for a file level symbol. -string QualifiedFileLevelSymbol(const string& package, const string& name); +std::string QualifiedFileLevelSymbol(const std::string& package, const std::string& name); // Escape C++ trigraphs by escaping question marks to \? -string EscapeTrigraphs(const string& to_escape); +std::string EscapeTrigraphs(const std::string& to_escape); // Escaped function name to eliminate naming conflict. -string SafeFunctionName(const Descriptor* descriptor, +std::string SafeFunctionName(const Descriptor* descriptor, const FieldDescriptor* field, - const string& prefix); - -// Returns true if unknown fields are always preserved after parsing. -inline bool AlwaysPreserveUnknownFields(const FileDescriptor* file) { - return file->syntax() != FileDescriptor::SYNTAX_PROTO3; -} - -// Returns true if unknown fields are preserved after parsing. -inline bool AlwaysPreserveUnknownFields(const Descriptor* message) { - return AlwaysPreserveUnknownFields(message->file()); -} + const std::string& prefix); // Returns true if generated messages have public unknown fields accessors inline bool PublicUnknownFieldsAccessors(const Descriptor* message) { @@ -200,8 +252,8 @@ inline bool PublicUnknownFieldsAccessors(const Descriptor* message) { } // Returns the optimize mode for <file>, respecting <options.enforce_lite>. -::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor( - const FileDescriptor* file, const Options& options); +FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, + const Options& options); // Determines whether unknown fields will be stored in an UnknownFieldSet or // a string. @@ -210,6 +262,56 @@ inline bool UseUnknownFieldSet(const FileDescriptor* file, return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME; } +inline bool IsWeak(const FieldDescriptor* field, const Options& options) { + if (field->options().weak()) { + GOOGLE_CHECK(!options.opensource_runtime); + return true; + } + return false; +} + +// For a string field, returns the effective ctype. If the actual ctype is +// not supported, returns the default of STRING. +FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field, + const Options& options); + +inline bool IsCord(const FieldDescriptor* field, const Options& options) { + return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field, options) == FieldOptions::CORD; +} + +inline bool IsStringPiece(const FieldDescriptor* field, + const Options& options) { + return field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE; +} + +// Does the given FileDescriptor use lazy fields? +bool HasLazyFields(const FileDescriptor* file, const Options& options); + +// Is the given field a supported lazy field? +inline bool IsLazy(const FieldDescriptor* field, const Options& options) { + return field->options().lazy() && !field->is_repeated() && + field->type() == FieldDescriptor::TYPE_MESSAGE && + GetOptimizeFor(field->file(), options) != FileOptions::LITE_RUNTIME && + !options.opensource_runtime; +} + +// Does the file contain any definitions that need extension_set.h? +bool HasExtensionsOrExtendableMessage(const FileDescriptor* file); + +// Does the file have any repeated fields, necessitating the file to include +// repeated_field.h? This does not include repeated extensions, since those are +// all stored internally in an ExtensionSet, not a separate RepeatedField*. +bool HasRepeatedFields(const FileDescriptor* file); + +// Does the file have any string/bytes fields with ctype=STRING_PIECE? This +// does not include extensions, since ctype is ignored for extensions. +bool HasStringPieceFields(const FileDescriptor* file, const Options& options); + +// Does the file have any string/bytes fields with ctype=CORD? This does not +// include extensions, since ctype is ignored for extensions. +bool HasCordFields(const FileDescriptor* file, const Options& options); // Does the file have any map fields, necessitating the file to include // map_field_inl.h and map.h. @@ -247,6 +349,22 @@ inline bool HasFastArraySerialization(const FileDescriptor* file, return GetOptimizeFor(file, options) == FileOptions::SPEED; } +inline bool IsProto2MessageSet(const Descriptor* descriptor, + const Options& options) { + return !options.opensource_runtime && + !options.enforce_lite && + !options.lite_implicit_weak_fields && + descriptor->options().message_set_wire_format() && + descriptor->full_name() == "google.protobuf.bridge.MessageSet"; +} + +inline bool IsProto2MessageSetFile(const FileDescriptor* file, + const Options& options) { + return !options.opensource_runtime && + !options.enforce_lite && + !options.lite_implicit_weak_fields && + file->name() == "net/proto2/bridge/proto/message_set.proto"; +} inline bool IsMapEntryMessage(const Descriptor* descriptor) { return descriptor->options().map_entry(); @@ -255,11 +373,7 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) { // Returns true if the field's CPPTYPE is string or message. bool IsStringOrMessage(const FieldDescriptor* field); -// For a string field, returns the effective ctype. If the actual ctype is -// not supported, returns the default of STRING. -FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field); - -string UnderscoresToCamelCase(const string& input, bool cap_next_letter); +std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter); inline bool HasFieldPresence(const FileDescriptor* file) { return file->syntax() != FileDescriptor::SYNTAX_PROTO3; @@ -288,11 +402,11 @@ inline bool IsCrossFileMessage(const FieldDescriptor* field) { field->message_type()->file() != field->file(); } -inline string MessageCreateFunction(const Descriptor* d) { +inline std::string MessageCreateFunction(const Descriptor* d) { return SupportsArenas(d) ? "CreateMessage" : "Create"; } -inline string MakeDefaultName(const FieldDescriptor* field) { +inline std::string MakeDefaultName(const FieldDescriptor* field) { return "_i_give_permission_to_break_this_code_default_" + FieldName(field) + "_"; } @@ -302,19 +416,8 @@ bool IsAnyMessage(const Descriptor* descriptor); bool IsWellKnownMessage(const FileDescriptor* descriptor); -void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, - const Options& options, bool for_parse, - const std::map<string, string>& variables, - const char* parameters, - io::Printer* printer); - -void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, - const Options& options, bool for_parse, - const std::map<string, string>& variables, - const char* parameters, io::Printer* printer); - -inline ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor( - const FileDescriptor* file, const Options& options) { +inline FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, + const Options& options) { return options.enforce_lite ? FileOptions::LITE_RUNTIME : file->options().optimize_for(); @@ -330,27 +433,179 @@ inline std::vector<const Descriptor*> FlattenMessagesInFile( return result; } -bool HasWeakFields(const Descriptor* desc); -bool HasWeakFields(const FileDescriptor* desc); +bool HasWeakFields(const Descriptor* desc, const Options& options); +bool HasWeakFields(const FileDescriptor* desc, const Options& options); // Returns true if the "required" restriction check should be ignored for the // given field. inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field, const Options& options) { - return false; + // Do not check "required" for lazy fields. + return IsLazy(field, options); } -class LIBPROTOC_EXPORT NamespaceOpener { +struct MessageAnalysis { + bool is_recursive; + bool contains_cord; + bool contains_extension; + bool contains_required; + bool constructor_requires_initialization; +}; + +// This class is used in FileGenerator, to ensure linear instead of +// quadratic performance, if we do this per message we would get O(V*(V+E)). +// Logically this is just only used in message.cc, but in the header for +// FileGenerator to help share it. +class PROTOC_EXPORT MessageSCCAnalyzer { + public: + explicit MessageSCCAnalyzer(const Options& options) : options_(options) {} + + MessageAnalysis GetSCCAnalysis(const SCC* scc); + + bool HasRequiredFields(const Descriptor* descriptor) { + MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor)); + return result.contains_required || result.contains_extension; + } + const SCC* GetSCC(const Descriptor* descriptor) { + return analyzer_.GetSCC(descriptor); + } + + private: + SCCAnalyzer analyzer_; + Options options_; + std::map<const SCC*, MessageAnalysis> analysis_cache_; +}; + +void ListAllFields(const Descriptor* d, + std::vector<const FieldDescriptor*>* fields); +void ListAllFields(const FileDescriptor* d, + std::vector<const FieldDescriptor*>* fields); +void ListAllTypesForServices(const FileDescriptor* fd, + std::vector<const Descriptor*>* types); + +// Indicates whether we should use implicit weak fields for this file. +bool UsingImplicitWeakFields(const FileDescriptor* file, + const Options& options); + +// Indicates whether to treat this field as implicitly weak. +bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer); + +// Formatter is a functor class which acts as a closure around printer and +// the variable map. It's much like printer->Print except it supports both named +// variables that are substituted using a key value map and direct arguments. In +// the format string $1$, $2$, etc... are substituted for the first, second, ... +// direct argument respectively in the format call, it accepts both strings and +// integers. The implementation verifies all arguments are used and are "first" +// used in order of appearance in the argument list. For example, +// +// Format("return array[$1$];", 3) -> "return array[3];" +// Format("array[$2$] = $1$;", "Bla", 3) -> FATAL error (wrong order) +// Format("array[$1$] = $2$;", 3, "Bla") -> "array[3] = Bla;" +// +// The arguments can be used more than once like +// +// Format("array[$1$] = $2$; // Index = $1$", 3, "Bla") -> +// "array[3] = Bla; // Index = 3" +// +// If you use more arguments use the following style to help the reader, +// +// Format("int $1$() {\n" +// " array[$2$] = $3$;\n" +// " return $4$;" +// "}\n", +// funname, // 1 +// idx, // 2 +// varname, // 3 +// retval); // 4 +// +// but consider using named variables. Named variables like $foo$, with some +// identifier foo, are looked up in the map. One additional feature is that +// spaces are accepted between the '$' delimiters, $ foo$ will +// substiture to " bar" if foo stands for "bar", but in case it's empty +// will substitute to "". Hence, for example, +// +// Format(vars, "$dllexport $void fun();") -> "void fun();" +// "__declspec(export) void fun();" +// +// which is convenient to prevent double, leading or trailing spaces. +class PROTOC_EXPORT Formatter { public: - explicit NamespaceOpener(io::Printer* printer) : printer_(printer) {} - NamespaceOpener(const string& name, io::Printer* printer) - : printer_(printer) { + explicit Formatter(io::Printer* printer) : printer_(printer) {} + Formatter(io::Printer* printer, const std::map<std::string, std::string>& vars) + : printer_(printer), vars_(vars) {} + + template <typename T> + void Set(const std::string& key, const T& value) { + vars_[key] = ToString(value); + } + + void AddMap(const std::map<std::string, std::string>& vars) { + for (const auto& keyval : vars) vars_[keyval.first] = keyval.second; + } + + template <typename... Args> + void operator()(const char* format, const Args&... args) const { + printer_->FormatInternal({ToString(args)...}, vars_, format); + } + + void Indent() const { printer_->Indent(); } + void Outdent() const { printer_->Outdent(); } + io::Printer* printer() const { return printer_; } + + class PROTOC_EXPORT SaveState { + public: + explicit SaveState(Formatter* format) + : format_(format), vars_(format->vars_) {} + ~SaveState() { format_->vars_.swap(vars_); } + + private: + Formatter* format_; + std::map<std::string, std::string> vars_; + }; + + private: + io::Printer* printer_; + std::map<std::string, std::string> vars_; + + // Convenience overloads to accept different types as arguments. + static std::string ToString(const std::string& s) { return s; } + template <typename I, typename = typename std::enable_if< + std::is_integral<I>::value>::type> + static std::string ToString(I x) { + return SimpleItoa(x); + } + static std::string ToString(strings::Hex x) { return StrCat(x); } + static std::string ToString(const FieldDescriptor* d) { return Payload(d); } + static std::string ToString(const Descriptor* d) { return Payload(d); } + static std::string ToString(const EnumDescriptor* d) { return Payload(d); } + static std::string ToString(const EnumValueDescriptor* d) { return Payload(d); } + + template <typename Descriptor> + static std::string Payload(const Descriptor* descriptor) { + std::vector<int> path; + descriptor->GetLocationPath(&path); + GeneratedCodeInfo::Annotation annotation; + for (int i = 0; i < path.size(); ++i) { + annotation.add_path(path[i]); + } + annotation.set_source_file(descriptor->file()->name()); + return annotation.SerializeAsString(); + } +}; + +class PROTOC_EXPORT NamespaceOpener { + public: + explicit NamespaceOpener(const Formatter& format) + : printer_(format.printer()) {} + NamespaceOpener(const std::string& name, const Formatter& format) + : NamespaceOpener(format) { ChangeTo(name); } ~NamespaceOpener() { ChangeTo(""); } - void ChangeTo(const string& name) { - std::vector<string> new_stack_ = + void ChangeTo(const std::string& name) { + std::vector<std::string> new_stack_ = Split(name, "::", true); int len = std::min(name_stack_.size(), new_stack_.size()); int common_idx = 0; @@ -369,93 +624,100 @@ class LIBPROTOC_EXPORT NamespaceOpener { private: io::Printer* printer_; - std::vector<string> name_stack_; + std::vector<std::string> name_stack_; }; -// Description of each strongly connected component. Note that the order -// of both the descriptors in this SCC and the order of children is -// deterministic. -struct SCC { - std::vector<const Descriptor*> descriptors; - std::vector<const SCC*> children; +std::string GetUtf8Suffix(const FieldDescriptor* field, const Options& options); +void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, + const Options& options, bool for_parse, + const char* parameters, + const Formatter& format); - const Descriptor* GetRepresentative() const { return descriptors[0]; } -}; +void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, + const Options& options, bool for_parse, + const char* parameters, + const Formatter& format); -struct MessageAnalysis { - bool is_recursive; - bool contains_cord; - bool contains_extension; - bool contains_required; +template <typename T> +struct FieldRangeImpl { + struct Iterator { + using iterator_category = std::forward_iterator_tag; + using value_type = const FieldDescriptor*; + using difference_type = int; + + value_type operator*() { return descriptor->field(idx); } + + friend bool operator==(const Iterator& a, const Iterator& b) { + GOOGLE_DCHECK(a.descriptor == b.descriptor); + return a.idx == b.idx; + } + friend bool operator!=(const Iterator& a, const Iterator& b) { + return !(a == b); + } + + Iterator& operator++() { + idx++; + return *this; + } + + int idx; + const T* descriptor; + }; + + Iterator begin() const { return {0, descriptor}; } + Iterator end() const { return {descriptor->field_count(), descriptor}; } + + const T* descriptor; }; -// This class is used in FileGenerator, to ensure linear instead of -// quadratic performance, if we do this per message we would get O(V*(V+E)). -// Logically this is just only used in message.cc, but in the header for -// FileGenerator to help share it. -class LIBPROTOC_EXPORT SCCAnalyzer { - public: - explicit SCCAnalyzer(const Options& options) : options_(options), index_(0) {} - ~SCCAnalyzer() { - for (int i = 0; i < garbage_bin_.size(); i++) delete garbage_bin_[i]; - } +template <typename T> +FieldRangeImpl<T> FieldRange(const T* desc) { + return {desc}; +} - const SCC* GetSCC(const Descriptor* descriptor) { - if (cache_.count(descriptor)) return cache_[descriptor].scc; - return DFS(descriptor).scc; - } +struct OneOfRangeImpl { + struct Iterator { + using iterator_category = std::forward_iterator_tag; + using value_type = const OneofDescriptor*; + using difference_type = int; - MessageAnalysis GetSCCAnalysis(const SCC* scc); + value_type operator*() { return descriptor->oneof_decl(idx); } - bool HasRequiredFields(const Descriptor* descriptor) { - MessageAnalysis result = GetSCCAnalysis(GetSCC(descriptor)); - return result.contains_required || result.contains_extension; - } + friend bool operator==(const Iterator& a, const Iterator& b) { + GOOGLE_DCHECK(a.descriptor == b.descriptor); + return a.idx == b.idx; + } + friend bool operator!=(const Iterator& a, const Iterator& b) { + return !(a == b); + } - private: - struct NodeData { - const SCC* scc; // if null it means its still on the stack - int index; - int lowlink; - }; + Iterator& operator++() { + idx++; + return *this; + } - Options options_; - std::map<const Descriptor*, NodeData> cache_; - std::map<const SCC*, MessageAnalysis> analysis_cache_; - std::vector<const Descriptor*> stack_; - int index_; - std::vector<SCC*> garbage_bin_; + int idx; + const Descriptor* descriptor; + }; - SCC* CreateSCC() { - garbage_bin_.push_back(new SCC()); - return garbage_bin_.back(); + Iterator begin() const { return {0, descriptor}; } + Iterator end() const { + return {descriptor->oneof_decl_count(), descriptor}; } - // Tarjan's Strongly Connected Components algo - NodeData DFS(const Descriptor* descriptor); - - // Add the SCC's that are children of this SCC to its children. - void AddChildren(SCC* scc); + const Descriptor* descriptor; }; -void ListAllFields(const Descriptor* d, - std::vector<const FieldDescriptor*>* fields); -void ListAllFields(const FileDescriptor* d, - std::vector<const FieldDescriptor*>* fields); -void ListAllTypesForServices(const FileDescriptor* fd, - std::vector<const Descriptor*>* types); +inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; } -// Indicates whether we should use implicit weak fields for this file. -bool UsingImplicitWeakFields(const FileDescriptor* file, - const Options& options); - -// Indicates whether to treat this field as implicitly weak. -bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options, - SCCAnalyzer* scc_analyzer); +void GenerateParserLoop(const Descriptor* descriptor, const Options& options, + MessageSCCAnalyzer* scc_analyzer, io::Printer* printer); } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index 0e485cac..3114bbf7 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -32,9 +32,9 @@ #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/wire_format.h> - #include <google/protobuf/stubs/strutil.h> + namespace google { namespace protobuf { namespace compiler { @@ -50,8 +50,6 @@ void SetMessageVariables(const FieldDescriptor* descriptor, const Options& options) { SetCommonFieldVariables(descriptor, variables, options); (*variables)["type"] = ClassName(descriptor->message_type(), false); - (*variables)["file_namespace"] = - FileLevelNamespace(descriptor->file()->name()); (*variables)["stream_writer"] = (*variables)["declared_type"] + (HasFastArraySerialization(descriptor->message_type()->file(), options) @@ -63,7 +61,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, descriptor->message_type()->FindFieldByName("key"); const FieldDescriptor* val = descriptor->message_type()->FindFieldByName("value"); - (*variables)["key_cpp"] = PrimitiveTypeName(key->cpp_type()); + (*variables)["key_cpp"] = PrimitiveTypeName(options, key->cpp_type()); switch (val->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: (*variables)["val_cpp"] = FieldMessageTypeName(val); @@ -74,18 +72,17 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["wrapper"] = "EnumEntryWrapper"; break; default: - (*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type()); + (*variables)["val_cpp"] = PrimitiveTypeName(options, val->cpp_type()); (*variables)["wrapper"] = "EntryWrapper"; } (*variables)["key_wire_type"] = - "::google::protobuf::internal::WireFormatLite::TYPE_" + - ToUpper(DeclaredTypeMethodName(key->type())); + "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); (*variables)["val_wire_type"] = - "::google::protobuf::internal::WireFormatLite::TYPE_" + - ToUpper(DeclaredTypeMethodName(val->type())); + "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); (*variables)["map_classname"] = ClassName(descriptor->message_type(), false); (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + (*variables)["tag"] = + SimpleItoa(internal::WireFormat::MakeTag(descriptor)); if (HasDescriptorMethods(descriptor->file(), options)) { (*variables)["lite"] = ""; @@ -104,7 +101,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetMessageVariables(descriptor, &variables_, options); } @@ -112,37 +109,37 @@ MapFieldGenerator::~MapFieldGenerator() {} void MapFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::internal::MapField$lite$<\n" - " $map_classname$,\n" - " $key_cpp$, $val_cpp$,\n" - " $key_wire_type$,\n" - " $val_wire_type$,\n" - " $default_enum_value$ > $name$_;\n"); + Formatter format(printer, variables_); + format( + "::$proto_ns$::internal::MapField$lite$<\n" + " $map_classname$,\n" + " $key_cpp$, $val_cpp$,\n" + " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n" + " $default_enum_value$ > $name$_;\n"); } void MapFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print( - variables_, - "$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" - " $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" - " ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); + Formatter format(printer, variables_); + format( + "$deprecated_attr$const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n" + " ${1$$name$$}$() const;\n" + "$deprecated_attr$::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n" + " ${1$mutable_$name$$}$();\n", + descriptor_); } void MapFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" + Formatter format(printer, variables_); + format( + "inline const ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_map:$full_name$)\n" " return $name$_.GetMap();\n" "}\n" - "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" + "inline ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_map:$full_name$)\n" " return $name$_.MutableMap();\n" @@ -151,17 +148,20 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { void MapFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); + Formatter format(printer, variables_); + format("$name$_.Clear();\n"); } void MapFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); + Formatter format(printer, variables_); + format("$name$_.MergeFrom(from.$name$_);\n"); } void MapFieldGenerator:: GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n"); + Formatter format(printer, variables_); + format("$name$_.Swap(&other->$name$_);\n"); } void MapFieldGenerator:: @@ -172,147 +172,138 @@ GenerateCopyConstructorCode(io::Printer* printer) const { void MapFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { - const FieldDescriptor* key_field = - descriptor_->message_type()->FindFieldByName("key"); + Formatter format(printer, variables_); + const FieldDescriptor* key_field = + descriptor_->message_type()->FindFieldByName("key"); const FieldDescriptor* value_field = descriptor_->message_type()->FindFieldByName("value"); - bool using_entry = false; string key; string value; + format( + "$map_classname$::Parser< ::$proto_ns$::internal::MapField$lite$<\n" + " $map_classname$,\n" + " $key_cpp$, $val_cpp$,\n" + " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n" + " $default_enum_value$ >,\n" + " ::$proto_ns$::Map< $key_cpp$, $val_cpp$ > >" + " parser(&$name$_);\n"); if (IsProto3Field(descriptor_) || value_field->type() != FieldDescriptor::TYPE_ENUM) { - printer->Print( - variables_, - "$map_classname$::Parser< ::google::protobuf::internal::MapField$lite$<\n" - " $map_classname$,\n" - " $key_cpp$, $val_cpp$,\n" - " $key_wire_type$,\n" - " $val_wire_type$,\n" - " $default_enum_value$ >,\n" - " ::google::protobuf::Map< $key_cpp$, $val_cpp$ > >" - " parser(&$name$_);\n" - "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" + format( + "DO_(::$proto_ns$::internal::WireFormatLite::ReadMessageNoVirtual(\n" " input, &parser));\n"); key = "parser.key()"; value = "parser.value()"; } else { - using_entry = true; key = "entry->key()"; value = "entry->value()"; - printer->Print(variables_, - "::std::unique_ptr<$map_classname$> entry($name$_.NewEntry());\n"); - printer->Print(variables_, - "{\n" - " ::std::string data;\n" - " DO_(::google::protobuf::internal::WireFormatLite::ReadString(input, &data));\n" - " DO_(entry->ParseFromString(data));\n" - " if ($val_cpp$_IsValid(*entry->mutable_value())) {\n" - " (*mutable_$name$())[entry->key()] =\n" - " static_cast< $val_cpp$ >(*entry->mutable_value());\n" - " } else {\n"); + format("auto entry = parser.NewEntry();\n"); + format( + "::std::string data;\n" + "DO_(::$proto_ns$::internal::WireFormatLite::ReadString(input, " + "&data));\n" + "DO_(entry->ParseFromString(data));\n" + "if ($val_cpp$_IsValid(*entry->mutable_value())) {\n" + " (*mutable_$name$())[entry->key()] =\n" + " static_cast< $val_cpp$ >(*entry->mutable_value());\n" + "} else {\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print(variables_, - " mutable_unknown_fields()" + format( + " mutable_unknown_fields()" "->AddLengthDelimited($number$, data);\n"); } else { - printer->Print(variables_, - " unknown_fields_stream.WriteVarint32($tag$u);\n" - " unknown_fields_stream.WriteVarint32(\n" - " static_cast< ::google::protobuf::uint32>(data.size()));\n" - " unknown_fields_stream.WriteString(data);\n"); + format( + " unknown_fields_stream.WriteVarint32($tag$u);\n" + " unknown_fields_stream.WriteVarint32(\n" + " static_cast< ::google::protobuf::uint32>(data.size()));\n" + " unknown_fields_stream.WriteString(data);\n"); } - - printer->Print(variables_, - " }\n" - "}\n"); + format("}\n"); } if (key_field->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - key_field, options_, true, variables_, - StrCat(key, ".data(), static_cast<int>(", key, ".length()),\n").data(), - printer); + key_field, options_, true, + StrCat(key, ".data(), static_cast<int>(", key, ".length()),\n") + .data(), + format); } if (value_field->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - value_field, options_, true, variables_, - StrCat(value, ".data(), static_cast<int>(", value, ".length()),\n") + value_field, options_, true, + StrCat(value, ".data(), static_cast<int>(", value, + ".length()),\n") .data(), - printer); - } - - // If entry is allocated by arena, its desctructor should be avoided. - if (using_entry && SupportsArenas(descriptor_)) { - printer->Print(variables_, - "if (entry->GetArena() != NULL) entry.release();\n"); + format); } } -static void GenerateSerializationLoop(io::Printer* printer, - const std::map<string, string>& variables, - bool supports_arenas, - const string& utf8_check, - const string& loop_header, - const string& ptr, - bool loop_via_iterators) { - printer->Print(variables, - StrCat("::std::unique_ptr<$map_classname$> entry;\n", - loop_header, " {\n").c_str()); - printer->Indent(); - - printer->Print(variables, StrCat( - "entry.reset($name$_.New$wrapper$(\n" - " ", ptr, "->first, ", ptr, "->second));\n" - "$write_entry$;\n").c_str()); +static void GenerateSerializationLoop(const Formatter& format, + bool supports_arenas, bool string_key, + bool string_value, bool to_array, + bool is_deterministic) { + format("::std::unique_ptr<$map_classname$> entry;\n"); + string ptr; + if (is_deterministic) { + format("for (size_type i = 0; i < n; i++) {\n"); + ptr = string_key ? "items[static_cast<ptrdiff_t>(i)]" + : "items[static_cast<ptrdiff_t>(i)].second"; + } else { + format( + "for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" + " it = this->$name$().begin();\n" + " it != this->$name$().end(); ++it) {\n"); + ptr = "it"; + } + format.Indent(); + + format("entry.reset($name$_.New$wrapper$($1$->first, $1$->second));\n", ptr); + if (to_array) { + format( + "target = ::$proto_ns$::internal::WireFormatLite::InternalWrite" + "$declared_type$NoVirtualToArray($number$, *entry, deterministic, " + "target);\n"); + } else { + format( + "::$proto_ns$::internal::WireFormatLite::Write$stream_writer$($number$," + " " + "*entry, output);\n"); + } // If entry is allocated by arena, its desctructor should be avoided. if (supports_arenas) { - printer->Print( + format( "if (entry->GetArena() != NULL) {\n" " entry.release();\n" "}\n"); } - if (!utf8_check.empty()) { - // If loop_via_iterators is true then ptr is actually an iterator, and we - // create a pointer by prefixing it with "&*". - printer->Print( - StrCat(utf8_check, "(", (loop_via_iterators ? "&*" : ""), ptr, ");\n") - .c_str()); + if (string_key || string_value) { + // ptr is either an actual pointer or an iterator, either way we can + // create a pointer by taking the address after de-referencing it. + format("Utf8Check::Check(&(*$1$));\n", ptr); } - printer->Outdent(); - printer->Print( - "}\n"); + format.Outdent(); + format("}\n"); } void MapFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { - std::map<string, string> variables(variables_); - variables["write_entry"] = "::google::protobuf::internal::WireFormatLite::Write" + - variables["stream_writer"] + "(\n " + - variables["number"] + ", *entry, output)"; - variables["deterministic"] = "output->IsSerializationDeterministic()"; - GenerateSerializeWithCachedSizes(printer, variables); + GenerateSerializeWithCachedSizes(printer, false); } void MapFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - std::map<string, string> variables(variables_); - variables["write_entry"] = - "target = ::google::protobuf::internal::WireFormatLite::\n" - " InternalWrite" + variables["declared_type"] + - "NoVirtualToArray(\n " + variables["number"] + - ", *entry, deterministic, target);\n"; - variables["deterministic"] = "deterministic"; - GenerateSerializeWithCachedSizes(printer, variables); + GenerateSerializeWithCachedSizes(printer, true); } -void MapFieldGenerator::GenerateSerializeWithCachedSizes( - io::Printer* printer, const std::map<string, string>& variables) const { - printer->Print(variables, - "if (!this->$name$().empty()) {\n"); - printer->Indent(); +void MapFieldGenerator::GenerateSerializeWithCachedSizes(io::Printer* printer, + bool to_array) const { + Formatter format(printer, variables_); + format("if (!this->$name$().empty()) {\n"); + format.Indent(); const FieldDescriptor* key_field = descriptor_->message_type()->FindFieldByName("key"); const FieldDescriptor* value_field = @@ -320,114 +311,110 @@ void MapFieldGenerator::GenerateSerializeWithCachedSizes( const bool string_key = key_field->type() == FieldDescriptor::TYPE_STRING; const bool string_value = value_field->type() == FieldDescriptor::TYPE_STRING; - printer->Print(variables, - "typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_pointer\n" + format( + "typedef ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_pointer\n" " ConstPtr;\n"); if (string_key) { - printer->Print(variables, + format( "typedef ConstPtr SortItem;\n" - "typedef ::google::protobuf::internal::" + "typedef ::$proto_ns$::internal::" "CompareByDerefFirst<SortItem> Less;\n"); } else { - printer->Print(variables, - "typedef ::google::protobuf::internal::SortItem< $key_cpp$, ConstPtr > " + format( + "typedef ::$proto_ns$::internal::SortItem< $key_cpp$, ConstPtr > " "SortItem;\n" - "typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;\n"); + "typedef ::$proto_ns$::internal::CompareByFirstField<SortItem> " + "Less;\n"); } - string utf8_check; - if (string_key || string_value) { - printer->Print( + bool utf8_check = string_key || string_value; + if (utf8_check) { + format( "struct Utf8Check {\n" " static void Check(ConstPtr p) {\n"); - printer->Indent(); - printer->Indent(); + format.Indent(); + format.Indent(); if (string_key) { GenerateUtf8CheckCodeForString( - key_field, options_, false, variables, - "p->first.data(), static_cast<int>(p->first.length()),\n", printer); + key_field, options_, false, + "p->first.data(), static_cast<int>(p->first.length()),\n", format); } if (string_value) { GenerateUtf8CheckCodeForString( - value_field, options_, false, variables, - "p->second.data(), static_cast<int>(p->second.length()),\n", printer); + value_field, options_, false, + "p->second.data(), static_cast<int>(p->second.length()),\n", format); } - printer->Outdent(); - printer->Outdent(); - printer->Print( + format.Outdent(); + format.Outdent(); + format( " }\n" "};\n"); - utf8_check = "Utf8Check::Check"; } - printer->Print(variables, + format( "\n" - "if ($deterministic$ &&\n" + "if ($1$ &&\n" " this->$name$().size() > 1) {\n" " ::std::unique_ptr<SortItem[]> items(\n" " new SortItem[this->$name$().size()]);\n" - " typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n" + " typedef ::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::size_type " + "size_type;\n" " size_type n = 0;\n" - " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" + " for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" " it = this->$name$().begin();\n" " it != this->$name$().end(); ++it, ++n) {\n" " items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);\n" " }\n" - " ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n"); - printer->Indent(); - GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_), - utf8_check, "for (size_type i = 0; i < n; i++)", - string_key ? "items[static_cast<ptrdiff_t>(i)]" : - "items[static_cast<ptrdiff_t>(i)].second", false); - printer->Outdent(); - printer->Print( - "} else {\n"); - printer->Indent(); - GenerateSerializationLoop( - printer, variables, SupportsArenas(descriptor_), utf8_check, - "for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = this->$name$().begin();\n" - " it != this->$name$().end(); ++it)", - "it", true); - printer->Outdent(); - printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); + " ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n", + to_array ? "deterministic" : "output->IsSerializationDeterministic()"); + format.Indent(); + GenerateSerializationLoop(format, SupportsArenas(descriptor_), string_key, + string_value, to_array, true); + format.Outdent(); + format("} else {\n"); + format.Indent(); + GenerateSerializationLoop(format, SupportsArenas(descriptor_), string_key, + string_value, to_array, false); + format.Outdent(); + format("}\n"); + format.Outdent(); + format("}\n"); } void MapFieldGenerator:: GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, + Formatter format(printer, variables_); + format( "total_size += $tag_size$ *\n" - " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n" + " ::$proto_ns$::internal::FromIntSize(this->$name$_size());\n" "{\n" " ::std::unique_ptr<$map_classname$> entry;\n" - " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" + " for (::$proto_ns$::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" " it = this->$name$().begin();\n" " it != this->$name$().end(); ++it) {\n"); // If entry is allocated by arena, its desctructor should be avoided. if (SupportsArenas(descriptor_)) { - printer->Print(variables_, + format( " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" " entry.release();\n" " }\n"); } - printer->Print(variables_, + format( " entry.reset($name$_.New$wrapper$(it->first, it->second));\n" - " total_size += ::google::protobuf::internal::WireFormatLite::\n" + " total_size += ::$proto_ns$::internal::WireFormatLite::\n" " $declared_type$SizeNoVirtual(*entry);\n" " }\n"); // If entry is allocated by arena, its desctructor should be avoided. if (SupportsArenas(descriptor_)) { - printer->Print(variables_, + format( " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" " entry.release();\n" " }\n"); } - printer->Print("}\n"); + format("}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h index 0d54f0ea..95eecc07 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h @@ -62,11 +62,8 @@ class MapFieldGenerator : public FieldGenerator { private: // A helper for GenerateSerializeWithCachedSizes{,ToArray}. - void GenerateSerializeWithCachedSizes( - io::Printer* printer, const std::map<string, string>& variables) const; - - const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + void GenerateSerializeWithCachedSizes(io::Printer* printer, + bool to_array) const; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); }; @@ -74,6 +71,6 @@ class MapFieldGenerator : public FieldGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 778fc406..4af54032 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -35,9 +35,9 @@ #include <google/protobuf/compiler/cpp/cpp_message.h> #include <algorithm> -#include <google/protobuf/stubs/hash.h> #include <map> #include <memory> +#include <unordered_map> #include <utility> #include <vector> @@ -57,6 +57,8 @@ #include <google/protobuf/stubs/substitute.h> +#include <google/protobuf/stubs/hash.h> + namespace google { namespace protobuf { @@ -69,7 +71,7 @@ using internal::WireFormatLite; namespace { template <class T> -void PrintFieldComment(io::Printer* printer, const T* field) { +void PrintFieldComment(const Formatter& format, const T* field) { // Print the field's (or oneof's) proto-syntax definition as a comment. // We don't want to print group bodies so we cut off after the first // line. @@ -77,8 +79,25 @@ void PrintFieldComment(io::Printer* printer, const T* field) { options.elide_group_body = true; options.elide_oneof_body = true; string def = field->DebugStringWithOptions(options); - printer->Print("// $def$\n", - "def", def.substr(0, def.find_first_of('\n'))); + format("// $1$\n", def.substr(0, def.find_first_of('\n'))); +} + +void PrintPresenceCheck(const Formatter& format, const FieldDescriptor* field, + const std::vector<int>& has_bit_indices, + io::Printer* printer, int* cached_has_bit_index) { + if (!field->options().weak()) { + int has_bit_index = has_bit_indices[field->index()]; + if (*cached_has_bit_index != (has_bit_index / 32)) { + *cached_has_bit_index = (has_bit_index / 32); + format("cached_has_bits = _has_bits_[$1$];\n", *cached_has_bit_index); + } + const string mask = + StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + format("if (cached_has_bits & 0x$1$u) {\n", mask); + } else { + format("if (has_$1$()) {\n", FieldName(field)); + } + format.Indent(); } struct FieldOrderingByNumber { @@ -135,9 +154,9 @@ bool CanConstructByZeroing(const FieldDescriptor* field, // Non-repeated, non-lazy message fields are simply raw pointers, so we can // use memset to initialize these in SharedCtor. We cannot use this in // Clear, as we need to potentially delete the existing value. - ret = ret || - (!field->is_repeated() && - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); + ret = ret || (!field->is_repeated() && + !IsLazy(field, options) && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); return ret; } @@ -145,36 +164,27 @@ bool CanConstructByZeroing(const FieldDescriptor* field, // considered non-default (will be sent over the wire), for message types // without true field presence. Should only be called if // !HasFieldPresence(message_descriptor). -bool EmitFieldNonDefaultCondition(io::Printer* printer, - const string& prefix, +bool EmitFieldNonDefaultCondition(io::Printer* printer, const string& prefix, const FieldDescriptor* field) { + Formatter format(printer); + format.Set("prefix", prefix); + format.Set("name", FieldName(field)); // Merge and serialize semantics: primitive fields are merged/serialized only // if non-zero (numeric) or non-empty (string). if (!field->is_repeated() && !field->containing_oneof()) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { - printer->Print( - "if ($prefix$$name$().size() > 0) {\n", - "prefix", prefix, - "name", FieldName(field)); + format("if ($prefix$$name$().size() > 0) {\n"); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // Message fields still have has_$name$() methods. - printer->Print( - "if ($prefix$has_$name$()) {\n", - "prefix", prefix, - "name", FieldName(field)); + format("if ($prefix$has_$name$()) {\n"); } else { - printer->Print( - "if ($prefix$$name$() != 0) {\n", - "prefix", prefix, - "name", FieldName(field)); + format("if ($prefix$$name$() != 0) {\n"); } - printer->Indent(); + format.Indent(); return true; } else if (field->containing_oneof()) { - printer->Print( - "if (has_$name$()) {\n", - "name", FieldName(field)); - printer->Indent(); + format("if (has_$name$()) {\n"); + format.Indent(); return true; } return false; @@ -192,13 +202,13 @@ bool HasHasMethod(const FieldDescriptor* field) { } // Collects map entry message type information. -void CollectMapInfo(const Descriptor* descriptor, +void CollectMapInfo(const Options& options, const Descriptor* descriptor, std::map<string, string>* variables) { GOOGLE_CHECK(IsMapEntryMessage(descriptor)); std::map<string, string>& vars = *variables; const FieldDescriptor* key = descriptor->FindFieldByName("key"); const FieldDescriptor* val = descriptor->FindFieldByName("value"); - vars["key_cpp"] = PrimitiveTypeName(key->cpp_type()); + vars["key_cpp"] = PrimitiveTypeName(options, key->cpp_type()); switch (val->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: vars["val_cpp"] = FieldMessageTypeName(val); @@ -207,12 +217,12 @@ void CollectMapInfo(const Descriptor* descriptor, vars["val_cpp"] = ClassName(val->enum_type(), true); break; default: - vars["val_cpp"] = PrimitiveTypeName(val->cpp_type()); + vars["val_cpp"] = PrimitiveTypeName(options, val->cpp_type()); } - vars["key_wire_type"] = "::google::protobuf::internal::WireFormatLite::TYPE_" + - ToUpper(DeclaredTypeMethodName(key->type())); - vars["val_wire_type"] = "::google::protobuf::internal::WireFormatLite::TYPE_" + - ToUpper(DeclaredTypeMethodName(val->type())); + vars["key_wire_type"] = + "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); + vars["val_wire_type"] = + "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); if (descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 && val->type() == FieldDescriptor::TYPE_ENUM) { const EnumValueDescriptor* default_value = val->default_value_enum(); @@ -231,9 +241,51 @@ bool HasPrivateHasMethod(const FieldDescriptor* field) { field->containing_oneof() != NULL); } +// TODO(ckennelly): Cull these exclusions if/when these protos do not have +// their methods overriden by subclasses. + +bool ShouldMarkClearAsFinal(const Descriptor* descriptor, + const Options& options) { + static std::set<string> exclusions{ + }; + + const string name = ClassName(descriptor, true); + return exclusions.find(name) == exclusions.end() || + options.opensource_runtime; +} -bool TableDrivenParsingEnabled( - const Descriptor* descriptor, const Options& options) { +bool ShouldMarkIsInitializedAsFinal(const Descriptor* descriptor, + const Options& options) { + static std::set<string> exclusions{ + }; + + const string name = ClassName(descriptor, true); + return exclusions.find(name) == exclusions.end() || + options.opensource_runtime; +} + +bool ShouldMarkMergePartialAsFinal(const Descriptor* descriptor, + const Options& options) { + static std::set<string> exclusions{ + }; + + const string name = ClassName(descriptor, true); + return exclusions.find(name) == exclusions.end() || + options.opensource_runtime; +} + +bool ShouldMarkNewAsFinal(const Descriptor* descriptor, + const Options& options) { + static std::set<string> exclusions{ + }; + + const string name = ClassName(descriptor, true); + return exclusions.find(name) == exclusions.end() || + options.opensource_runtime; +} + +bool TableDrivenParsingEnabled(const Descriptor* descriptor, + const Options& options) { if (!options.table_driven_parsing) { return false; } @@ -247,14 +299,18 @@ bool TableDrivenParsingEnabled( const double table_sparseness = 0.5; int max_field_number = 0; - for (int i = 0; i < descriptor->field_count(); i++) { - const FieldDescriptor* field = descriptor->field(i); + for (auto field : FieldRange(descriptor)) { if (max_field_number < field->number()) { max_field_number = field->number(); } // - There are no weak fields. - if (field->options().weak()) { + if (IsWeak(field, options)) { + return false; + } + + // - There are no lazy fields (they require the non-lite library). + if (IsLazy(field, options)) { return false; } } @@ -282,24 +338,16 @@ bool TableDrivenParsingEnabled( void SetUnknkownFieldsVariable(const Descriptor* descriptor, const Options& options, std::map<string, string>* variables) { + string proto_ns = ProtobufNamespace(options); if (UseUnknownFieldSet(descriptor->file(), options)) { - (*variables)["unknown_fields_type"] = "::google::protobuf::UnknownFieldSet"; - } else { - (*variables)["unknown_fields_type"] = "::std::string"; - } - if (AlwaysPreserveUnknownFields(descriptor)) { - (*variables)["have_unknown_fields"] = - "_internal_metadata_.have_unknown_fields()"; - (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields()"; + (*variables)["unknown_fields_type"] = "::" + proto_ns + "::UnknownFieldSet"; } else { - (*variables)["have_unknown_fields"] = - "(_internal_metadata_.have_unknown_fields() && " - " ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())"; - (*variables)["unknown_fields"] = - "(::google::protobuf::internal::GetProto3PreserveUnknownsDefault()" - " ? _internal_metadata_.unknown_fields()" - " : _internal_metadata_.default_instance())"; + (*variables)["unknown_fields_type"] = + PrimitiveTypeName(options, FieldDescriptor::CPPTYPE_STRING); } + (*variables)["have_unknown_fields"] = + "_internal_metadata_.have_unknown_fields()"; + (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields()"; (*variables)["mutable_unknown_fields"] = "_internal_metadata_.mutable_unknown_fields()"; } @@ -393,13 +441,13 @@ std::vector<std::vector<const FieldDescriptor*> > CollectFields( const FieldDescriptor* last_field = fields.front(); std::vector<const FieldDescriptor*> chunk; - for (int i = 0; i < fields.size(); i++) { - if (!equivalent(last_field, fields[i]) && !chunk.empty()) { + for (auto field : fields) { + if (!equivalent(last_field, field) && !chunk.empty()) { chunks.push_back(chunk); chunk.clear(); } - chunk.push_back(fields[i]); - last_field = fields[i]; + chunk.push_back(field); + last_field = field; } if (!chunk.empty()) { chunks.push_back(chunk); @@ -415,8 +463,7 @@ uint32 GenChunkMask(const std::vector<const FieldDescriptor*>& fields, GOOGLE_CHECK(!fields.empty()); int first_index_offset = has_bit_indices[fields.front()->index()] / 32; uint32 chunk_mask = 0; - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; + for (auto field : fields) { // "index" defines where in the _has_bits_ the field appears. int index = has_bit_indices[field->index()]; GOOGLE_CHECK_EQ(first_index_offset, index / 32); @@ -426,32 +473,161 @@ uint32 GenChunkMask(const std::vector<const FieldDescriptor*>& fields, return chunk_mask; } +// Return the number of bits set in n, a non-negative integer. +static int popcnt(uint32 n) { + int result = 0; + while (n != 0) { + result += (n & 1); + n = n / 2; + } + return result; +} + +// For a run of cold chunks, opens and closes an external if statement that +// checks multiple has_bits words to skip bulk of cold fields. +class ColdChunkSkipper { + public: + ColdChunkSkipper( + const Options& options, + const std::vector<std::vector<const FieldDescriptor*>>& chunks, + const std::vector<int>& has_bit_indices, const double cold_threshold, + bool has_field_presence) + : chunks_(chunks), + has_bit_indices_(has_bit_indices), + access_info_map_(options.access_info_map), + cold_threshold_(cold_threshold), + has_field_presence_(has_field_presence) { + SetCommonVars(options, &variables_); + } + + // May open an external if check for a batch of cold fields. "from" is the + // prefix to _has_bits_ to allow MergeFrom to use "from._has_bits_". + // Otherwise, it should be "". + void OnStartChunk(int chunk, int cached_has_bit_index, const string& from, + io::Printer* printer); + bool OnEndChunk(int chunk, io::Printer* printer); + + private: + bool IsColdChunk(int chunk); + + int HasbitWord(int chunk, int offset) { + return has_bit_indices_[chunks_[chunk][offset]->index()] / 32; + } + + const std::vector<std::vector<const FieldDescriptor*> >& chunks_; + const std::vector<int>& has_bit_indices_; + const AccessInfoMap* access_info_map_; + const double cold_threshold_; + std::map<string, string> variables_; + int limit_chunk_ = -1; + bool has_field_presence_; +}; + +// Tuning parameters for ColdChunkSkipper. +const double kColdRatio = 0.005; + +bool ColdChunkSkipper::IsColdChunk(int chunk) { return false; } + +void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_bit_index, + const string& from, io::Printer* printer) { + Formatter format(printer, variables_); + if (!access_info_map_ || !has_field_presence_) { + return; + } else if (chunk < limit_chunk_) { + // We are already inside a run of cold chunks. + return; + } else if (!IsColdChunk(chunk)) { + // We can't start a run of cold chunks. + return; + } + + // Find the end of consecutive cold chunks. + limit_chunk_ = chunk; + while (limit_chunk_ < chunks_.size() && IsColdChunk(limit_chunk_)) { + limit_chunk_++; + } + + if (limit_chunk_ <= chunk + 1) { + // Require at least two chunks to emit external has_bit checks. + limit_chunk_ = -1; + return; + } + + // Emit has_bit check for each has_bit_dword index. + format("if (PROTOBUF_PREDICT_FALSE("); + int first_word = HasbitWord(chunk, 0); + while (chunk < limit_chunk_) { + uint32 mask = 0; + int this_word = HasbitWord(chunk, 0); + // Generate mask for chunks on the same word. + for (; chunk < limit_chunk_ && HasbitWord(chunk, 0) == this_word; chunk++) { + for (auto field : chunks_[chunk]) { + int hasbit_index = has_bit_indices_[field->index()]; + // Fields on a chunk must be in the same word. + GOOGLE_CHECK_EQ(this_word, hasbit_index / 32); + mask |= 1 << (hasbit_index % 32); + } + } + + if (this_word != first_word) { + format(" ||\n "); + } + format.Set("mask", strings::Hex(mask, strings::ZERO_PAD_8)); + if (this_word == cached_has_bit_index) { + format("(cached_has_bits & 0x$mask$u) != 0"); + } else { + format("($1$_has_bits_[$2$] & 0x$mask$u) != 0", from, this_word); + } + } + format(")) {\n"); + format.Indent(); +} + +bool ColdChunkSkipper::OnEndChunk(int chunk, io::Printer* printer) { + Formatter format(printer, variables_); + if (chunk != limit_chunk_ - 1) { + return false; + } + format.Outdent(); + format("}\n"); + return true; +} + } // anonymous namespace // =================================================================== MessageGenerator::MessageGenerator(const Descriptor* descriptor, + const std::map<string, string>& vars, int index_in_file_messages, const Options& options, - SCCAnalyzer* scc_analyzer) + MessageSCCAnalyzer* scc_analyzer) : descriptor_(descriptor), index_in_file_messages_(index_in_file_messages), classname_(ClassName(descriptor, false)), options_(options), field_generators_(descriptor, options, scc_analyzer), max_has_bit_index_(0), - enum_generators_( - new std::unique_ptr<EnumGenerator>[descriptor->enum_type_count()]), - extension_generators_(new std::unique_ptr< - ExtensionGenerator>[descriptor->extension_count()]), num_weak_fields_(0), - message_layout_helper_(new PaddingOptimizer()), - scc_analyzer_(scc_analyzer) { + scc_analyzer_(scc_analyzer), + variables_(vars) { + if (!message_layout_helper_) { + message_layout_helper_.reset(new PaddingOptimizer()); + } + + // Variables that apply to this class + variables_["classname"] = classname_; + variables_["classtype"] = QualifiedClassName(descriptor_); + string scc_name = + ClassName(scc_analyzer_->GetSCC(descriptor_)->GetRepresentative()); + variables_["scc_name"] = UniqueName(scc_name, descriptor_, options_); + variables_["full_name"] = descriptor_->full_name(); + variables_["superclass"] = SuperClassName(descriptor_, options_); + // Compute optimized field order to be used for layout and initialization // purposes. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->options().weak()) { + for (auto field : FieldRange(descriptor_)) { + if (IsWeak(field, options_)) { num_weak_fields_++; } else if (!field->containing_oneof()) { optimized_order_.push_back(field); @@ -463,8 +639,7 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, if (HasFieldPresence(descriptor_->file())) { // We use -1 as a sentinel. has_bit_indices_.resize(descriptor_->field_count(), -1); - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { // Skip fields that do not have has bits. if (field->is_repeated()) { continue; @@ -472,16 +647,7 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, has_bit_indices_[field->index()] = max_has_bit_index_++; } - } - - for (int i = 0; i < descriptor->enum_type_count(); i++) { - enum_generators_[i].reset( - new EnumGenerator(descriptor->enum_type(i), options)); - } - - for (int i = 0; i < descriptor->extension_count(); i++) { - extension_generators_[i].reset( - new ExtensionGenerator(descriptor->extension(i), options)); + field_generators_.SetHasBitIndices(has_bit_indices_); } num_required_fields_ = 0; @@ -492,12 +658,9 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, } table_driven_ = TableDrivenParsingEnabled(descriptor_, options_); - - scc_name_ = - ClassName(scc_analyzer_->GetSCC(descriptor_)->GetRepresentative(), false); } -MessageGenerator::~MessageGenerator() {} +MessageGenerator::~MessageGenerator() = default; size_t MessageGenerator::HasBitsSize() const { size_t sizeof_has_bits = (max_has_bit_index_ + 31) / 32 * 4; @@ -513,23 +676,22 @@ size_t MessageGenerator::HasBitsSize() const { } void MessageGenerator::AddGenerators( - std::vector<EnumGenerator*>* enum_generators, - std::vector<ExtensionGenerator*>* extension_generators) { + std::vector<std::unique_ptr<EnumGenerator>>* enum_generators, + std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators) { for (int i = 0; i < descriptor_->enum_type_count(); i++) { - enum_generators->push_back(enum_generators_[i].get()); + enum_generators->emplace_back( + new EnumGenerator(descriptor_->enum_type(i), variables_, options_)); + enum_generators_.push_back(enum_generators->back().get()); } for (int i = 0; i < descriptor_->extension_count(); i++) { - extension_generators->push_back(extension_generators_[i].get()); + extension_generators->emplace_back( + new ExtensionGenerator(descriptor_->extension(i), options_)); + extension_generators_.push_back(extension_generators->back().get()); } } -void MessageGenerator::FillMessageForwardDeclarations( - std::map<string, const Descriptor*>* class_names) { - (*class_names)[classname_] = descriptor_; -} - -void MessageGenerator:: -GenerateFieldAccessorDeclarations(io::Printer* printer) { +void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { + Formatter format(printer, variables_); // optimized_fields_ does not contain fields where // field->containing_oneof() != NULL // so we need to iterate over those as well. @@ -540,77 +702,75 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { std::vector<const FieldDescriptor*> ordered_fields; ordered_fields.reserve(descriptor_->field_count()); - ordered_fields.insert( - ordered_fields.begin(), optimized_order_.begin(), optimized_order_.end()); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); + ordered_fields.insert(ordered_fields.begin(), optimized_order_.begin(), + optimized_order_.end()); + for (auto field : FieldRange(descriptor_)) { if (field->containing_oneof() == NULL && !field->options().weak()) { continue; } ordered_fields.push_back(field); } - for (int i = 0; i < ordered_fields.size(); i++) { - const FieldDescriptor* field = ordered_fields[i]; + for (auto field : ordered_fields) { + PrintFieldComment(format, field); - PrintFieldComment(printer, field); + Formatter::SaveState save(&format); std::map<string, string> vars; SetCommonFieldVariables(field, &vars, options_); - vars["constant_name"] = FieldConstantName(field); + format.AddMap(vars); if (field->is_repeated()) { - printer->Print(vars, "$deprecated_attr$int ${$$name$_size$}$() const;\n"); - printer->Annotate("{", "}", field); + format("$deprecated_attr$int ${1$$name$_size$}$() const;\n", field); } else if (HasHasMethod(field)) { - printer->Print(vars, "$deprecated_attr$bool ${$has_$name$$}$() const;\n"); - printer->Annotate("{", "}", field); + format("$deprecated_attr$bool ${1$has_$name$$}$() const;\n", field); } else if (HasPrivateHasMethod(field)) { - printer->Print(vars, - "private:\n" - "bool ${$has_$name$$}$() const;\n" - "public:\n"); - printer->Annotate("{", "}", field); + format( + "private:\n" + "bool ${1$has_$name$$}$() const;\n" + "public:\n", + field); } - printer->Print(vars, "$deprecated_attr$void ${$clear_$name$$}$();\n"); - printer->Annotate("{", "}", field); - printer->Print(vars, - "$deprecated_attr$static const int $constant_name$ = " - "$number$;\n"); - printer->Annotate("constant_name", field); + format( + "$deprecated_attr$void ${1$clear_$name$$}$();\n" + "$deprecated_attr$static const int ${1$$2$$}$ = $number$;\n", + field, FieldConstantName(field)); // Generate type-specific accessor declarations. field_generators_.get(field).GenerateAccessorDeclarations(printer); - printer->Print("\n"); + format("\n"); } if (descriptor_->extension_range_count() > 0) { // Generate accessors for extensions. We just call a macro located in // extension_set.h since the accessors about 80 lines of static code. - printer->Print( - "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n", - "classname", classname_); + format("$GOOGLE_PROTOBUF$_EXTENSION_ACCESSORS($classname$)\n"); + // Generate MessageSet specific APIs for proto2 MessageSet. + // For testing purposes we don't check for bridge.MessageSet, so + // we don't use IsProto2MessageSet + if (descriptor_->options().message_set_wire_format() && + !options_.opensource_runtime && !options_.lite_implicit_weak_fields) { + // Special-case MessageSet + format("GOOGLE_PROTOBUF_EXTENSION_MESSAGE_SET_ACCESSORS($classname$)\n"); + } } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( + for (auto oneof : OneOfRange(descriptor_)) { + Formatter::SaveState saver(&format); + format.Set("oneof_name", oneof->name()); + format.Set("camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true)); + format( "void clear_$oneof_name$();\n" - "$camel_oneof_name$Case $oneof_name$_case() const;\n", - "camel_oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true), - "oneof_name", descriptor_->oneof_decl(i)->name()); + "$camel_oneof_name$Case $oneof_name$_case() const;\n"); } } -void MessageGenerator:: -GenerateSingularFieldHasBits(const FieldDescriptor* field, - std::map<string, string> vars, - io::Printer* printer) { +void MessageGenerator::GenerateSingularFieldHasBits( + const FieldDescriptor* field, Formatter format) { if (field->options().weak()) { - printer->Print( - vars, + format( "inline bool $classname$::has_$name$() const {\n" " return _weak_field_map_.Has($number$);\n" "}\n"); @@ -622,31 +782,23 @@ GenerateSingularFieldHasBits(const FieldDescriptor* field, int has_bit_index = has_bit_indices_[field->index()]; GOOGLE_CHECK_GE(has_bit_index, 0); - vars["has_array_index"] = SimpleItoa(has_bit_index / 32); - vars["has_mask"] = StrCat(strings::Hex(1u << (has_bit_index % 32), - strings::ZERO_PAD_8)); - printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" - " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" - "}\n" - "inline void $classname$::set_has_$name$() {\n" - " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" - "}\n" - "inline void $classname$::clear_has_$name$() {\n" - " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" - "}\n"); + format.Set("has_array_index", has_bit_index / 32); + format.Set("has_mask", + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + format( + "inline bool $classname$::has_$name$() const {\n" + " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" + "}\n"); } else { // Message fields have a has_$name$() method. if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - bool is_lazy = false; - if (is_lazy) { - printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" - " return !$name$_.IsCleared();\n" - "}\n"); + if (IsLazy(field, options_)) { + format( + "inline bool $classname$::has_$name$() const {\n" + " return !$name$_.IsCleared();\n" + "}\n"); } else { - printer->Print( - vars, + format( "inline bool $classname$::has_$name$() const {\n" " return this != internal_default_instance() && $name$_ != NULL;\n" "}\n"); @@ -655,17 +807,13 @@ GenerateSingularFieldHasBits(const FieldDescriptor* field, } } -void MessageGenerator:: -GenerateOneofHasBits(io::Printer* printer) { - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - std::map<string, string> vars; - vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); - vars["cap_oneof_name"] = - ToUpper(descriptor_->oneof_decl(i)->name()); - vars["classname"] = classname_; - printer->Print( - vars, +void MessageGenerator::GenerateOneofHasBits(io::Printer* printer) { + Formatter format(printer, variables_); + for (auto oneof : OneOfRange(descriptor_)) { + format.Set("oneof_name", oneof->name()); + format.Set("oneof_index", oneof->index()); + format.Set("cap_oneof_name", ToUpper(oneof->name())); + format( "inline bool $classname$::has_$oneof_name$() const {\n" " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" "}\n" @@ -675,168 +823,157 @@ GenerateOneofHasBits(io::Printer* printer) { } } -void MessageGenerator:: -GenerateOneofMemberHasBits(const FieldDescriptor* field, - const std::map<string, string>& vars, - io::Printer* printer) { +void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field, + const Formatter& format) { // Singular field in a oneof // N.B.: Without field presence, we do not use has-bits or generate // has_$name$() methods, but oneofs still have set_has_$name$(). // Oneofs also have has_$name$() but only as a private helper // method, so that generated code is slightly cleaner (vs. comparing // _oneof_case_[index] against a constant everywhere). - printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" - " return $oneof_name$_case() == k$field_name$;\n" - "}\n"); - printer->Print(vars, - "inline void $classname$::set_has_$name$() {\n" - " _oneof_case_[$oneof_index$] = k$field_name$;\n" - "}\n"); + format( + "inline bool $classname$::has_$name$() const {\n" + " return $oneof_name$_case() == k$field_name$;\n" + "}\n" + "inline void $classname$::set_has_$name$() {\n" + " _oneof_case_[$oneof_index$] = k$field_name$;\n" + "}\n"); } -void MessageGenerator:: -GenerateFieldClear(const FieldDescriptor* field, - const std::map<string, string>& vars, - bool is_inline, - io::Printer* printer) { +void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field, + bool is_inline, + Formatter format) { // Generate clear_$name$(). if (is_inline) { - printer->Print("inline "); + format("inline "); } - printer->Print(vars, - "void $classname$::clear_$name$() {\n"); + format("void $classname$::clear_$name$() {\n"); - printer->Indent(); + format.Indent(); if (field->containing_oneof()) { // Clear this field only if it is the active field in this oneof, // otherwise ignore - printer->Print(vars, - "if (has_$name$()) {\n"); - printer->Indent(); - field_generators_.get(field) - .GenerateClearingCode(printer); - printer->Print(vars, - "clear_has_$oneof_name$();\n"); - printer->Outdent(); - printer->Print("}\n"); + format("if (has_$name$()) {\n"); + format.Indent(); + field_generators_.get(field).GenerateClearingCode(format.printer()); + format("clear_has_$oneof_name$();\n"); + format.Outdent(); + format("}\n"); } else { - field_generators_.get(field) - .GenerateClearingCode(printer); + field_generators_.get(field).GenerateClearingCode(format.printer()); if (HasFieldPresence(descriptor_->file())) { if (!field->is_repeated() && !field->options().weak()) { - printer->Print(vars, "clear_has_$name$();\n"); + int has_bit_index = has_bit_indices_[field->index()]; + GOOGLE_CHECK_GE(has_bit_index, 0); + + format.Set("has_array_index", has_bit_index / 32); + format.Set("has_mask", + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + format("_has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"); } } } - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateFieldAccessorDefinitions(io::Printer* printer) { - printer->Print("// $classname$\n\n", "classname", classname_); +void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) { + Formatter format(printer, variables_); + format("// $classname$\n\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - - PrintFieldComment(printer, field); + for (auto field : FieldRange(descriptor_)) { + PrintFieldComment(format, field); std::map<string, string> vars; SetCommonFieldVariables(field, &vars, options_); + Formatter::SaveState saver(&format); + format.AddMap(vars); + // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { - printer->Print(vars, - "inline int $classname$::$name$_size() const {\n" - " return $name$_.size();\n" - "}\n"); + format( + "inline int $classname$::$name$_size() const {\n" + " return $name$_.size();\n" + "}\n"); } else if (field->containing_oneof()) { - vars["field_name"] = UnderscoresToCamelCase(field->name(), true); - vars["oneof_name"] = field->containing_oneof()->name(); - vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); - GenerateOneofMemberHasBits(field, vars, printer); + format.Set("field_name", UnderscoresToCamelCase(field->name(), true)); + format.Set("oneof_name", field->containing_oneof()->name()); + format.Set("oneof_index", + SimpleItoa(field->containing_oneof()->index())); + GenerateOneofMemberHasBits(field, format); } else { // Singular field. - GenerateSingularFieldHasBits(field, vars, printer); + GenerateSingularFieldHasBits(field, format); } if (!IsCrossFileMaybeMap(field)) { - GenerateFieldClear(field, vars, true, printer); + GenerateFieldClear(field, true, format); } // Generate type-specific accessors. field_generators_.get(field).GenerateInlineAccessorDefinitions(printer); - printer->Print("\n"); + format("\n"); } // Generate has_$name$() and clear_has_$name$() functions for oneofs. GenerateOneofHasBits(printer); } -void MessageGenerator:: -GenerateClassDefinition(io::Printer* printer) { +void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { + Formatter format(printer, variables_); if (IsMapEntryMessage(descriptor_)) { std::map<string, string> vars; - vars["classname"] = classname_; - CollectMapInfo(descriptor_, &vars); + CollectMapInfo(options_, descriptor_, &vars); vars["lite"] = HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite"; - printer->Print( - vars, + format.AddMap(vars); + format( "class $classname$ : public " - "::google::protobuf::internal::MapEntry$lite$<$classname$, \n" + "::$proto_ns$::internal::MapEntry$lite$<$classname$, \n" " $key_cpp$, $val_cpp$,\n" - " $key_wire_type$,\n" - " $val_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n" " $default_enum_value$ > {\n" "public:\n" - " typedef ::google::protobuf::internal::MapEntry$lite$<$classname$, \n" + "#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n" + "static bool _ParseMap(const char* begin, const " + "char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);\n" + "#endif // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n" + " typedef ::$proto_ns$::internal::MapEntry$lite$<$classname$, \n" " $key_cpp$, $val_cpp$,\n" - " $key_wire_type$,\n" - " $val_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n" + " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$,\n" " $default_enum_value$ > SuperType;\n" " $classname$();\n" - " $classname$(::google::protobuf::Arena* arena);\n" + " $classname$(::$proto_ns$::Arena* arena);\n" " void MergeFrom(const $classname$& other);\n" " static const $classname$* internal_default_instance() { return " "reinterpret_cast<const " "$classname$*>(&_$classname$_default_instance_); }\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - " void MergeFrom(const ::google::protobuf::Message& other) final;\n" - " ::google::protobuf::Metadata GetMetadata() const;\n" + format( + " void MergeFrom(const ::$proto_ns$::Message& other) final;\n" + " ::$proto_ns$::Metadata GetMetadata() const;\n" "};\n"); } else { - printer->Print("};\n"); + format("};\n"); } return; } - std::map<string, string> vars; - vars["classname"] = classname_; - vars["full_name"] = descriptor_->full_name(); - vars["field_count"] = SimpleItoa(descriptor_->field_count()); - vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count()); - if (options_.dllexport_decl.empty()) { - vars["dllexport"] = ""; - } else { - vars["dllexport"] = options_.dllexport_decl + " "; - } - vars["superclass"] = SuperClassName(descriptor_, options_); - printer->Print(vars, - "class $dllexport$$classname$ : public $superclass$ " - "/* @@protoc_insertion_point(class_definition:$full_name$) */ " - "{\n"); - printer->Annotate("classname", descriptor_); - printer->Print(" public:\n"); - printer->Indent(); - - printer->Print( - vars, + format( + "class $dllexport_decl $${1$$classname$$}$ : public $superclass$ " + "/* @@protoc_insertion_point(class_definition:$full_name$) */ " + "{\n", + descriptor_); + format(" public:\n"); + format.Indent(); + + format( "$classname$();\n" "virtual ~$classname$();\n" "\n" @@ -848,34 +985,36 @@ GenerateClassDefinition(io::Printer* printer) { "}\n"); if (options_.table_driven_serialization) { - printer->Print( - "private:\n" - "const void* InternalGetTable() const;\n" - "public:\n" - "\n"); + format( + "private:\n" + "const void* InternalGetTable() const;\n" + "public:\n" + "\n"); } // Generate move constructor and move assignment operator. - printer->Print(vars, - "#if LANG_CXX11\n" - "$classname$($classname$&& from) noexcept\n" - " : $classname$() {\n" - " *this = ::std::move(from);\n" - "}\n" - "\n" - "inline $classname$& operator=($classname$&& from) noexcept {\n" - " if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {\n" - " if (this != &from) InternalSwap(&from);\n" - " } else {\n" - " CopyFrom(from);\n" - " }\n" - " return *this;\n" - "}\n" - "#endif\n"); + format( + "#if LANG_CXX11\n" + "$classname$($classname$&& from) noexcept\n" + " : $classname$() {\n" + " *this = ::std::move(from);\n" + "}\n" + "\n" + "inline $classname$& operator=($classname$&& from) noexcept {\n" + " if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {\n" + " if (this != &from) InternalSwap(&from);\n" + " } else {\n" + " CopyFrom(from);\n" + " }\n" + " return *this;\n" + "}\n" + "#endif\n"); + std::map<string, string> vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); if (PublicUnknownFieldsAccessors(descriptor_)) { - printer->Print(vars, + format( "inline const $unknown_fields_type$& unknown_fields() const {\n" " return $unknown_fields$;\n" "}\n" @@ -889,10 +1028,10 @@ GenerateClassDefinition(io::Printer* printer) { // MessageLite's implementation which returns NULL rather than generating our // own method which returns NULL, in order to reduce code size. if (SupportsArenas(descriptor_)) { - // virtual method version of GetArenaNoVirtual(), required for generic dispatch given a - // MessageLite* (e.g., in RepeatedField::AddAllocated()). - printer->Print( - "inline ::google::protobuf::Arena* GetArena() const final {\n" + // virtual method version of GetArenaNoVirtual(), required for generic + // dispatch given a MessageLite* (e.g., in RepeatedField::AddAllocated()). + format( + "inline ::$proto_ns$::Arena* GetArena() const final {\n" " return GetArenaNoVirtual();\n" "}\n" "inline void* GetMaybeArenaPointer() const final {\n" @@ -903,229 +1042,240 @@ GenerateClassDefinition(io::Printer* printer) { // Only generate this member if it's not disabled. if (HasDescriptorMethods(descriptor_->file(), options_) && !descriptor_->options().no_standard_descriptor_accessor()) { - printer->Print(vars, - "static const ::google::protobuf::Descriptor* descriptor();\n"); + format( + "static const ::$proto_ns$::Descriptor* descriptor() {\n" + " return default_instance().GetDescriptor();\n" + "}\n"); } - printer->Print(vars, - "static const $classname$& default_instance();\n" - "\n"); + format( + "static const $classname$& default_instance();\n" + "\n"); // Generate enum values for every field in oneofs. One list is generated for // each oneof with an additional *_NOT_SET value. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "enum $camel_oneof_name$Case {\n", - "camel_oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - printer->Print( - "k$field_name$ = $field_number$,\n", - "field_name", - UnderscoresToCamelCase( - descriptor_->oneof_decl(i)->field(j)->name(), true), - "field_number", - SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number())); + for (auto oneof : OneOfRange(descriptor_)) { + format("enum $1$Case {\n", UnderscoresToCamelCase(oneof->name(), true)); + format.Indent(); + for (auto field : FieldRange(oneof)) { + string oneof_enum_case_field_name = + UnderscoresToCamelCase(field->name(), true); + format("k$1$ = $2$,\n", oneof_enum_case_field_name, // 1 + field->number()); // 2 } - printer->Print( - "$cap_oneof_name$_NOT_SET = 0,\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( + format("$1$_NOT_SET = 0,\n", ToUpper(oneof->name())); + format.Outdent(); + format( "};\n" "\n"); } // TODO(gerbens) make this private, while still granting other protos access. - vars["message_index"] = SimpleItoa(index_in_file_messages_); - printer->Print( - vars, + format( "static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY\n" "static inline const $classname$* internal_default_instance() {\n" " return reinterpret_cast<const $classname$*>(\n" " &_$classname$_default_instance_);\n" "}\n" "static constexpr int kIndexInFileMessages =\n" - " $message_index$;\n" - "\n"); + " $1$;\n" + "\n", index_in_file_messages_); if (SupportsArenas(descriptor_)) { - printer->Print(vars, - "void UnsafeArenaSwap($classname$* other);\n"); + format("void UnsafeArenaSwap($classname$* other);\n"); } if (IsAnyMessage(descriptor_)) { - printer->Print(vars, - "// implements Any -----------------------------------------------\n" - "\n" - "void PackFrom(const ::google::protobuf::Message& message);\n" - "void PackFrom(const ::google::protobuf::Message& message,\n" - " const ::std::string& type_url_prefix);\n" - "bool UnpackTo(::google::protobuf::Message* message) const;\n" - "template<typename T> bool Is() const {\n" - " return _any_metadata_.Is<T>();\n" - "}\n" - "static bool ParseAnyTypeUrl(const string& type_url,\n" - " string* full_type_name);\n" - "\n"); + format( + "// implements Any -----------------------------------------------\n" + "\n" + "void PackFrom(const ::$proto_ns$::Message& message);\n" + "void PackFrom(const ::$proto_ns$::Message& message,\n" + " const $string$& type_url_prefix);\n" + "bool UnpackTo(::$proto_ns$::Message* message) const;\n" + "template<typename T> bool Is() const {\n" + " return _any_metadata_.Is<T>();\n" + "}\n" + "static bool ParseAnyTypeUrl(const string& type_url,\n" + " string* full_type_name);\n" + "static bool GetAnyFieldDescriptors(\n" + " const ::$proto_ns$::Message& message,\n" + " const ::$proto_ns$::FieldDescriptor** type_url_field,\n" + " const ::$proto_ns$::FieldDescriptor** value_field);\n"); } - vars["new_final"] = " final"; - - printer->Print(vars, - "void Swap($classname$* other);\n" - "friend void swap($classname$& a, $classname$& b) {\n" - " a.Swap(&b);\n" - "}\n" - "\n" - "// implements Message ----------------------------------------------\n" - "\n" - "inline $classname$* New() const$new_final$ {\n" - " return CreateMaybeMessage<$classname$>(NULL);\n" - "}\n" - "\n" - "$classname$* New(::google::protobuf::Arena* arena) const$new_final$ {\n" - " return CreateMaybeMessage<$classname$>(arena);\n" - "}\n"); + format.Set("new_final", + ShouldMarkNewAsFinal(descriptor_, options_) ? "final" : ""); + + format( + "void Swap($classname$* other);\n" + "friend void swap($classname$& a, $classname$& b) {\n" + " a.Swap(&b);\n" + "}\n" + "\n" + "// implements Message ----------------------------------------------\n" + "\n" + "inline $classname$* New() const$ new_final$ {\n" + " return CreateMaybeMessage<$classname$>(NULL);\n" + "}\n" + "\n" + "$classname$* New(::$proto_ns$::Arena* arena) const$ new_final$ {\n" + " return CreateMaybeMessage<$classname$>(arena);\n" + "}\n"); // For instances that derive from Message (rather than MessageLite), some // methods are virtual and should be marked as final. - string use_final = HasDescriptorMethods(descriptor_->file(), options_) ? - " final" : ""; + format.Set("full_final", HasDescriptorMethods(descriptor_->file(), options_) + ? "final" + : ""); if (HasGeneratedMethods(descriptor_->file(), options_)) { if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print(vars, - "void CopyFrom(const ::google::protobuf::Message& from) final;\n" - "void MergeFrom(const ::google::protobuf::Message& from) final;\n"); + format( + "void CopyFrom(const ::$proto_ns$::Message& from) final;\n" + "void MergeFrom(const ::$proto_ns$::Message& from) final;\n"); } else { - printer->Print(vars, - "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from)\n" - " final;\n"); + format( + "void CheckTypeAndMergeFrom(const ::$proto_ns$::MessageLite& from)\n" + " final;\n"); } - vars["clear_final"] = " final"; - vars["is_initialized_final"] = " final"; - vars["merge_partial_final"] = " final"; + format.Set("clear_final", + ShouldMarkClearAsFinal(descriptor_, options_) ? "final" : ""); + format.Set( + "is_initialized_final", + ShouldMarkIsInitializedAsFinal(descriptor_, options_) ? "final" : ""); + format.Set( + "merge_partial_final", + ShouldMarkMergePartialAsFinal(descriptor_, options_) ? "final" : ""); - printer->Print( - vars, + format( "void CopyFrom(const $classname$& from);\n" "void MergeFrom(const $classname$& from);\n" - "void Clear()$clear_final$;\n" - "bool IsInitialized() const$is_initialized_final$;\n" + "void Clear()$ clear_final$;\n" + "bool IsInitialized() const$ is_initialized_final$;\n" "\n" "size_t ByteSizeLong() const final;\n" + "#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n" + "static const char* _InternalParse(const char* begin, const char* end, " + "void* object, ::$proto_ns$::internal::ParseContext* ctx);\n" + "::$proto_ns$::internal::ParseFunc _ParseFunc() const final { return " + "_InternalParse; }\n" + "#else\n" "bool MergePartialFromCodedStream(\n" - " ::google::protobuf::io::CodedInputStream* input)$merge_partial_final$;\n"); + " ::$proto_ns$::io::CodedInputStream* input)$ " + "merge_partial_final$;\n" + "#endif // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"); + if (descriptor_->options().message_set_wire_format()) { + format( + "#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n" + "static const char* InternalParseMessageSetItem(const char* begin, " + "const char* end, void* object, " + "::$proto_ns$::internal::ParseContext* " + "ctx);\n" + "#endif // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"); + } + if (!options_.table_driven_serialization || descriptor_->options().message_set_wire_format()) { - printer->Print( + format( "void SerializeWithCachedSizes(\n" - " ::google::protobuf::io::CodedOutputStream* output) const " - "final;\n"); + " ::$proto_ns$::io::CodedOutputStream* output) const final;\n"); } // DiscardUnknownFields() is implemented in message.cc using reflections. We // need to implement this function in generated code for messages. if (!UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print( - "void DiscardUnknownFields()$final$;\n", - "final", use_final); + format("void DiscardUnknownFields()$ full_final$;\n"); } if (HasFastArraySerialization(descriptor_->file(), options_)) { - printer->Print( - "::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(\n" - " bool deterministic, ::google::protobuf::uint8* target) const final;\n"); + format( + "$uint8$* InternalSerializeWithCachedSizesToArray(\n" + " bool deterministic, $uint8$* target) const final;\n"); } } - printer->Print( + format( "int GetCachedSize() const final { return _cached_size_.Get(); }" "\n\nprivate:\n" "void SharedCtor();\n" "void SharedDtor();\n" - "void SetCachedSize(int size) const$final$;\n" - "void InternalSwap($classname$* other);\n", - "classname", classname_, "final", use_final); + "void SetCachedSize(int size) const$ full_final$;\n" + "void InternalSwap($classname$* other);\n"); if (SupportsArenas(descriptor_)) { - printer->Print( - // TODO(gerbens) Make this private! Currently people are deriving from - // protos to give access to this constructor, breaking the invariants - // we rely on. - "protected:\n" - "explicit $classname$(::google::protobuf::Arena* arena);\n" - "private:\n" - "static void ArenaDtor(void* object);\n" - "inline void RegisterArenaDtor(::google::protobuf::Arena* arena);\n", - "classname", classname_); + format( + // TODO(gerbens) Make this private! Currently people are deriving from + // protos to give access to this constructor, breaking the invariants + // we rely on. + "protected:\n" + "explicit $classname$(::$proto_ns$::Arena* arena);\n" + "private:\n" + "static void ArenaDtor(void* object);\n" + "inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n"); } if (SupportsArenas(descriptor_)) { - printer->Print( - "private:\n" - "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" - " return _internal_metadata_.arena();\n" - "}\n" - "inline void* MaybeArenaPtr() const {\n" - " return _internal_metadata_.raw_arena_ptr();\n" - "}\n"); + format( + "private:\n" + "inline ::$proto_ns$::Arena* GetArenaNoVirtual() const {\n" + " return _internal_metadata_.arena();\n" + "}\n" + "inline void* MaybeArenaPtr() const {\n" + " return _internal_metadata_.raw_arena_ptr();\n" + "}\n"); } else { - printer->Print( - "private:\n" - "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" - " return NULL;\n" - "}\n" - "inline void* MaybeArenaPtr() const {\n" - " return NULL;\n" - "}\n"); + format( + "private:\n" + "inline ::$proto_ns$::Arena* GetArenaNoVirtual() const {\n" + " return NULL;\n" + "}\n" + "inline void* MaybeArenaPtr() const {\n" + " return NULL;\n" + "}\n"); } - printer->Print( + format( "public:\n" "\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - "::google::protobuf::Metadata GetMetadata() const final;\n" - "\n"); + format( + "::$proto_ns$::Metadata GetMetadata() const final;\n" + "\n"); } else { - printer->Print( - "::std::string GetTypeName() const final;\n" - "\n"); + format( + "$string$ GetTypeName() const final;\n" + "\n"); } - printer->Print( - "// nested types ----------------------------------------------------\n" - "\n"); + format( + "// nested types ----------------------------------------------------\n" + "\n"); // Import all nested message classes into this class's scope with typedefs. for (int i = 0; i < descriptor_->nested_type_count(); i++) { const Descriptor* nested_type = descriptor_->nested_type(i); if (!IsMapEntryMessage(nested_type)) { - printer->Print("typedef $nested_full_name$ $nested_name$;\n", - "nested_name", nested_type->name(), - "nested_full_name", ClassName(nested_type, false)); - printer->Annotate("nested_full_name", nested_type); - printer->Annotate("nested_name", nested_type); + format.Set("nested_full_name", ClassName(nested_type, false)); + format.Set("nested_name", nested_type->name()); + format("typedef ${1$$nested_full_name$$}$ ${1$$nested_name$$}$;\n", + nested_type); } } if (descriptor_->nested_type_count() > 0) { - printer->Print("\n"); + format("\n"); } // Import all nested enums and their values into this class's scope with // typedefs and constants. for (int i = 0; i < descriptor_->enum_type_count(); i++) { enum_generators_[i]->GenerateSymbolImports(printer); - printer->Print("\n"); + format("\n"); } - printer->Print( - "// accessors -------------------------------------------------------\n" - "\n"); + format( + "// accessors -------------------------------------------------------\n" + "\n"); // Generate accessor methods for all fields. GenerateFieldAccessorDeclarations(printer); @@ -1136,49 +1286,37 @@ GenerateClassDefinition(io::Printer* printer) { } - printer->Print( - "// @@protoc_insertion_point(class_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); + format("// @@protoc_insertion_point(class_scope:$full_name$)\n"); // 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() && - !descriptor_->field(i)->options().weak()) { - // set_has_***() generated in all proto1/2 code and in oneofs (only) for - // messages without true field presence. - if (HasFieldPresence(descriptor_->file()) || - descriptor_->field(i)->containing_oneof()) { - printer->Print("void set_has_$name$();\n", "name", - FieldName(descriptor_->field(i))); - } - // clear_has_***() generated only for non-oneof fields - // in proto1/2. - if (!descriptor_->field(i)->containing_oneof() && - HasFieldPresence(descriptor_->file())) { - printer->Print("void clear_has_$name$();\n", "name", - FieldName(descriptor_->field(i))); - } + format.Outdent(); + format(" private:\n"); + format.Indent(); + // TODO(seongkim): Remove hack to track field access and remove this class. + format("class HasBitSetters;\n"); + + + for (auto field : FieldRange(descriptor_)) { + // set_has_***() generated in all oneofs. + if (!field->is_repeated() && !field->options().weak() && + field->containing_oneof()) { + format("void set_has_$1$();\n", FieldName(field)); } } - printer->Print("\n"); + format("\n"); // Generate oneof function declarations - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "inline bool has_$oneof_name$() const;\n" - "inline void clear_has_$oneof_name$();\n\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); + for (auto oneof : OneOfRange(descriptor_)) { + format( + "inline bool has_$1$() const;\n" + "inline void clear_has_$1$();\n\n", + oneof->name()); } if (HasGeneratedMethods(descriptor_->file(), options_) && !descriptor_->options().message_set_wire_format() && num_required_fields_ > 1) { - printer->Print( + format( "// helper for ByteSizeLong()\n" "size_t RequiredFieldsByteSizeFallback() const;\n\n"); } @@ -1187,14 +1325,15 @@ GenerateClassDefinition(io::Printer* printer) { // output will be determined later. bool need_to_emit_cached_size = true; - // TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it. const string cached_size_decl = - "mutable ::google::protobuf::internal::CachedSize _cached_size_;\n"; + "mutable ::$proto_ns$::internal::CachedSize _cached_size_;\n"; const size_t sizeof_has_bits = HasBitsSize(); - const string has_bits_decl = sizeof_has_bits == 0 ? "" : - "::google::protobuf::internal::HasBits<" + SimpleItoa(sizeof_has_bits / 4) + - "> _has_bits_;\n"; + const string has_bits_decl = + sizeof_has_bits == 0 + ? "" + : "::$proto_ns$::internal::HasBits<" + + SimpleItoa(sizeof_has_bits / 4) + "> _has_bits_;\n"; // To minimize padding, data members are divided into three sections: // (1) members assumed to align to 8 bytes @@ -1205,154 +1344,142 @@ GenerateClassDefinition(io::Printer* printer) { // Members assumed to align to 8 bytes: if (descriptor_->extension_range_count() > 0) { - printer->Print( - "::google::protobuf::internal::ExtensionSet _extensions_;\n" - "\n"); + format( + "::$proto_ns$::internal::ExtensionSet _extensions_;\n" + "\n"); } if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print( - "::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n"); + format( + "::$proto_ns$::internal::InternalMetadataWithArena " + "_internal_metadata_;\n"); } else { - printer->Print( - "::google::protobuf::internal::InternalMetadataWithArenaLite " + format( + "::$proto_ns$::internal::InternalMetadataWithArenaLite " "_internal_metadata_;\n"); } if (SupportsArenas(descriptor_)) { - printer->Print( - "template <typename T> friend class ::google::protobuf::Arena::InternalHelper;\n" - "typedef void InternalArenaConstructable_;\n" - "typedef void DestructorSkippable_;\n"); + if (!options_.opensource_runtime) { + format( + "template <typename T> friend struct " + "::proto::internal::EmbeddedMessageHolder;\n"); + } + format( + "template <typename T> friend class " + "::$proto_ns$::Arena::InternalHelper;\n" + "typedef void InternalArenaConstructable_;\n" + "typedef void DestructorSkippable_;\n"); } if (HasFieldPresence(descriptor_->file())) { // _has_bits_ is frequently accessed, so to reduce code size and improve - // speed, it should be close to the start of the object. But, try not to - // waste space:_has_bits_ by itself always makes sense if its size is a - // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together - // will work well. - printer->Print(has_bits_decl.c_str()); - if ((sizeof_has_bits % 8) != 0) { - printer->Print(cached_size_decl.c_str()); - need_to_emit_cached_size = false; - } + // speed, it should be close to the start of the object. Placing + // _cached_size_ together with _has_bits_ improves cache locality despite + // potential alignment padding. + format(has_bits_decl.c_str()); + format(cached_size_decl.c_str()); + need_to_emit_cached_size = false; } // Field members: // Emit some private and static members - for (int i = 0; i < optimized_order_.size(); ++i) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { const FieldGenerator& generator = field_generators_.get(field); generator.GenerateStaticMembers(printer); generator.GeneratePrivateMembers(printer); } // For each oneof generate a union - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "union $camel_oneof_name$Union {\n" + for (auto oneof : OneOfRange(descriptor_)) { + string camel_oneof_name = UnderscoresToCamelCase(oneof->name(), true); + format( + "union $1$Union {\n" // explicit empty constructor is needed when union contains // ArenaStringPtr members for string fields. - " $camel_oneof_name$Union() {}\n", - "camel_oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - field_generators_.get(descriptor_->oneof_decl(i)-> - field(j)).GeneratePrivateMembers(printer); + " $1$Union() {}\n", + camel_oneof_name); + format.Indent(); + for (auto field : FieldRange(oneof)) { + field_generators_.get(field).GeneratePrivateMembers(printer); } - printer->Outdent(); - printer->Print( - "} $oneof_name$_;\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - field_generators_.get(descriptor_->oneof_decl(i)-> - field(j)).GenerateStaticMembers(printer); + format.Outdent(); + format("} $1$_;\n", oneof->name()); + for (auto field : FieldRange(oneof)) { + field_generators_.get(field).GenerateStaticMembers(printer); } } // Members assumed to align to 4 bytes: if (need_to_emit_cached_size) { - printer->Print(cached_size_decl.c_str()); + format(cached_size_decl.c_str()); need_to_emit_cached_size = false; } // Generate _oneof_case_. if (descriptor_->oneof_decl_count() > 0) { - printer->Print(vars, - "::google::protobuf::uint32 _oneof_case_[$oneof_decl_count$];\n" - "\n"); + format( + "$uint32$ _oneof_case_[$1$];\n" + "\n", + descriptor_->oneof_decl_count()); } if (num_weak_fields_) { - printer->Print( - "::google::protobuf::internal::WeakFieldMap _weak_field_map_;\n"); + format("::$proto_ns$::internal::WeakFieldMap _weak_field_map_;\n"); } // Generate _any_metadata_ for the Any type. if (IsAnyMessage(descriptor_)) { - printer->Print(vars, - "::google::protobuf::internal::AnyMetadata _any_metadata_;\n"); + format("::$proto_ns$::internal::AnyMetadata _any_metadata_;\n"); } // The TableStruct struct needs access to the private parts, in order to // construct the offsets of all members. - printer->Print("friend struct ::$file_namespace$::TableStruct;\n", - // Vars. - "scc_name", scc_name_, "file_namespace", - FileLevelNamespace(descriptor_)); + format("friend struct ::$tablename$;\n"); - printer->Outdent(); - printer->Print("};"); + format.Outdent(); + format("};"); GOOGLE_DCHECK(!need_to_emit_cached_size); } -void MessageGenerator:: -GenerateInlineMethods(io::Printer* printer) { +void MessageGenerator::GenerateInlineMethods(io::Printer* printer) { if (IsMapEntryMessage(descriptor_)) return; GenerateFieldAccessorDefinitions(printer); // Generate oneof_case() functions. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - std::map<string, string> vars; - vars["class_name"] = classname_; - vars["camel_oneof_name"] = UnderscoresToCamelCase( - descriptor_->oneof_decl(i)->name(), true); - vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); - printer->Print( - vars, - "inline $class_name$::$camel_oneof_name$Case $class_name$::" + for (auto oneof : OneOfRange(descriptor_)) { + Formatter format(printer, variables_); + format.Set("camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true)); + format.Set("oneof_name", oneof->name()); + format.Set("oneof_index", oneof->index()); + format( + "inline $classname$::$camel_oneof_name$Case $classname$::" "$oneof_name$_case() const {\n" - " return $class_name$::$camel_oneof_name$Case(" + " return $classname$::$camel_oneof_name$Case(" "_oneof_case_[$oneof_index$]);\n" "}\n"); } } -void MessageGenerator:: -GenerateExtraDefaultFields(io::Printer* printer) { +void MessageGenerator::GenerateExtraDefaultFields(io::Printer* printer) { // Generate oneof default instance and weak field instances for reflection // usage. + Formatter format(printer, variables_); if (descriptor_->oneof_decl_count() > 0 || num_weak_fields_ > 0) { - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + for (auto oneof : OneOfRange(descriptor_)) { + for (auto field : FieldRange(oneof)) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && - EffectiveStringCType(field) != FieldOptions::STRING)) { - printer->Print("const "); + EffectiveStringCType(field, options_) != FieldOptions::STRING)) { + format("const "); } field_generators_.get(field).GeneratePrivateMembers(printer); } } - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); + for (auto field : FieldRange(descriptor_)) { if (field->options().weak()) { - printer->Print( - " const ::google::protobuf::Message* $name$_;\n", "name", FieldName(field)); + format(" const ::$proto_ns$::Message* $1$_;\n", FieldName(field)); } } } @@ -1360,130 +1487,78 @@ GenerateExtraDefaultFields(io::Printer* printer) { bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset, size_t aux_offset) { + Formatter format(printer, variables_); + if (!table_driven_) { - printer->Print("{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },\n"); + format("{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },\n"); return false; } - std::map<string, string> vars; - - vars["classname"] = ClassName(descriptor_); - vars["classtype"] = QualifiedClassName(descriptor_); - vars["offset"] = SimpleItoa(offset); - vars["aux_offset"] = SimpleItoa(aux_offset); - int max_field_number = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); + for (auto field : FieldRange(descriptor_)) { if (max_field_number < field->number()) { max_field_number = field->number(); } } - vars["max_field_number"] = SimpleItoa(max_field_number); - - printer->Print("{\n"); - printer->Indent(); + format("{\n"); + format.Indent(); - printer->Print(vars, - "TableStruct::entries + $offset$,\n" - "TableStruct::aux + $aux_offset$,\n" - "$max_field_number$,\n"); + format( + "$tablename$::entries + $1$,\n" + "$tablename$::aux + $2$,\n" + "$3$,\n", + offset, aux_offset, max_field_number); if (!HasFieldPresence(descriptor_->file())) { // If we don't have field presence, then _has_bits_ does not exist. - printer->Print(vars, "-1,\n"); + format("-1,\n"); } else { - printer->Print(vars, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n" - " $classtype$, _has_bits_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n"); } if (descriptor_->oneof_decl_count() > 0) { - printer->Print(vars, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n" - " $classtype$, _oneof_case_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_),\n"); } else { - printer->Print("-1, // no _oneof_case_\n"); + format("-1, // no _oneof_case_\n"); } if (descriptor_->extension_range_count() > 0) { - printer->Print(vars, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classtype$, " - "_extensions_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _extensions_),\n"); } else { - printer->Print("-1, // no _extensions_\n"); + format("-1, // no _extensions_\n"); } // TODO(ckennelly): Consolidate this with the calculation for // AuxillaryParseTableField. - vars["ns"] = Namespace(descriptor_); - - printer->Print(vars, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n" - " $classtype$, _internal_metadata_),\n" - "&$ns$::_$classname$_default_instance_,\n"); + format( + "PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_),\n" + "&$package_ns$::_$classname$_default_instance_,\n"); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(vars, "true,\n"); + format("true,\n"); } else { - printer->Print(vars, "false,\n"); + format("false,\n"); } - printer->Outdent(); - printer->Print("},\n"); + format.Outdent(); + format("},\n"); return true; } void MessageGenerator::GenerateSchema(io::Printer* printer, int offset, int has_offset) { - std::map<string, string> vars; - - vars["classname"] = QualifiedClassName(descriptor_); - vars["offset"] = SimpleItoa(offset); - vars["has_bits_offsets"] = + Formatter format(printer, variables_); + has_offset = HasFieldPresence(descriptor_->file()) || IsMapEntryMessage(descriptor_) - ? SimpleItoa(offset + has_offset) - : "-1"; + ? offset + has_offset + : -1; - printer->Print(vars, - "{ $offset$, $has_bits_offsets$, sizeof($classname$)},\n"); + format("{ $1$, $2$, sizeof($classtype$)},\n", offset, has_offset); } namespace { -// TODO(gerbens) remove this after the next sync with GitHub code base. -// Then the opensource testing has gained the functionality to compile -// the CalcFieldNum given the symbols defined in generated-message-util. -#ifdef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP -// We need a clean version of CalcFieldNum that doesn't use new functionality -// in the runtime, because this functionality is not yet in the opensource -// runtime - -uint32 CalculateType(uint32 type, uint32 type_class) { - return (type - 1) + type_class * 20; -} - -uint32 CalcFieldNum(const FieldGenerator&, const FieldDescriptor* field, - const Options& options) { - bool is_a_map = IsMapEntryMessage(field->containing_type()); - int type = field->type(); - if (field->containing_oneof()) { - return CalculateType(type, 4); - } - if (field->is_packed()) { - return CalculateType(type, 3); - } else if (field->is_repeated()) { - return CalculateType(type, 2); - } else if (!HasFieldPresence(field->file()) && - field->containing_oneof() == NULL && !is_a_map) { - return CalculateType(type, 1); - } else { - return CalculateType(type, 0); - } -} - -#else // We need to calculate for each field what function the table driven code // should use to serialize it. This returns the index in a lookup table. uint32 CalcFieldNum(const FieldGenerator& generator, @@ -1495,6 +1570,12 @@ uint32 CalcFieldNum(const FieldGenerator& generator, if (generator.IsInlined()) { type = internal::FieldMetadata::kInlinedType; } + // string field + if (IsCord(field, options)) { + type = internal::FieldMetadata::kCordType; + } else if (IsStringPiece(field, options)) { + type = internal::FieldMetadata::kStringPieceType; + } } if (field->containing_oneof()) { return internal::FieldMetadata::CalculateType( @@ -1515,7 +1596,6 @@ uint32 CalcFieldNum(const FieldGenerator& generator, type, internal::FieldMetadata::kPresence); } } -#endif int FindMessageIndexInFile(const Descriptor* descriptor) { std::vector<const Descriptor*> flatten = @@ -1527,12 +1607,11 @@ int FindMessageIndexInFile(const Descriptor* descriptor) { } // namespace int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) { + Formatter format(printer, variables_); if (!options_.table_driven_serialization) { return 0; } - string full_classname = QualifiedClassName(descriptor_); - std::vector<const FieldDescriptor*> sorted = SortFieldsByNumber(descriptor_); if (IsMapEntryMessage(descriptor_)) { for (int i = 0; i < 2; i++) { @@ -1543,36 +1622,39 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) { field->number(), WireFormat::WireTypeForFieldType(field->type())); std::map<string, string> vars; - vars["classname"] = QualifiedClassName(descriptor_); + vars["classtype"] = QualifiedClassName(descriptor_); vars["field_name"] = FieldName(field); vars["tag"] = SimpleItoa(tag); vars["hasbit"] = SimpleItoa(i); - vars["type"] = SimpleItoa(CalcFieldNum(generator, field, options_)); + vars["type"] = + SimpleItoa(CalcFieldNum(generator, field, options_)); vars["ptr"] = "NULL"; if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { GOOGLE_CHECK(!IsMapEntryMessage(field->message_type())); - { + if (!IsProto1(field->message_type()->file(), options_)) { vars["ptr"] = - "::" + FileLevelNamespace(field->message_type()) + - "::TableStruct::serialization_table + " + - SimpleItoa(FindMessageIndexInFile(field->message_type())); + "::" + + UniqueName("TableStruct", field->message_type(), options_) + + "::serialization_table + " + + SimpleItoa( + FindMessageIndexInFile(field->message_type())); } } - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" - "::google::protobuf::internal::MapEntryHelper<$classname$::" - "SuperType>, $field_name$_), $tag$," - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" - "::google::protobuf::internal::MapEntryHelper<$classname$::" - "SuperType>, _has_bits_) * 8 + $hasbit$, $type$, " - "$ptr$},\n"); + Formatter::SaveState saver(&format); + format.AddMap(vars); + format( + "{PROTOBUF_FIELD_OFFSET(" + "::$proto_ns$::internal::MapEntryHelper<$classtype$::" + "SuperType>, $field_name$_), $tag$," + "PROTOBUF_FIELD_OFFSET(" + "::$proto_ns$::internal::MapEntryHelper<$classtype$::" + "SuperType>, _has_bits_) * 8 + $hasbit$, $type$, " + "$ptr$},\n"); } return 2; } - printer->Print( - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_cached_size_), 0, 0, 0, NULL},\n", - "classname", full_classname); + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, _cached_size_), 0, 0, 0, NULL},\n"); std::vector<const Descriptor::ExtensionRange*> sorted_extensions; for (int i = 0; i < descriptor_->extension_range_count(); ++i) { sorted_extensions.push_back(descriptor_->extension_range(i)); @@ -1586,14 +1668,12 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) { extension_idx++) { const Descriptor::ExtensionRange* range = sorted_extensions[extension_idx]; - printer->Print( - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_extensions_), $start$, $end$, " - "::google::protobuf::internal::FieldMetadata::kSpecial, " + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, _extensions_), " + "$1$, $2$, ::$proto_ns$::internal::FieldMetadata::kSpecial, " "reinterpret_cast<const " - "void*>(::google::protobuf::internal::ExtensionSerializer)},\n", - "classname", full_classname, "start", SimpleItoa(range->start), "end", - SimpleItoa(range->end)); + "void*>(::$proto_ns$::internal::ExtensionSerializer)},\n", + range->start, range->end); } if (i == sorted.size()) break; const FieldDescriptor* field = sorted[i]; @@ -1609,105 +1689,116 @@ int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) { if (field->containing_oneof()) { classfieldname = field->containing_oneof()->name(); } - std::map<string, string> vars; - vars["classname"] = full_classname; - vars["field_name"] = classfieldname; - vars["tag"] = SimpleItoa(tag); - vars["ptr"] = "NULL"; + format.Set("field_name", classfieldname); + string ptr = "NULL"; if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (IsMapEntryMessage(field->message_type())) { - vars["idx"] = SimpleItoa(FindMessageIndexInFile(field->message_type())); - vars["fieldclassname"] = QualifiedClassName(field->message_type()); - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, $field_name$_), $tag$, $idx$, " - "::google::protobuf::internal::FieldMetadata::kSpecial, " - "reinterpret_cast<const void*>(static_cast< " - "::google::protobuf::internal::SpecialSerializer>(" - "::google::protobuf::internal::MapFieldSerializer< " - "::google::protobuf::internal::MapEntryToMapField<" - "$fieldclassname$>::MapFieldType, " - "TableStruct::serialization_table>))},\n"); + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), $1$, $2$, " + "::$proto_ns$::internal::FieldMetadata::kSpecial, " + "reinterpret_cast<const void*>(static_cast< " + "::$proto_ns$::internal::SpecialSerializer>(" + "::$proto_ns$::internal::MapFieldSerializer< " + "::$proto_ns$::internal::MapEntryToMapField<" + "$3$>::MapFieldType, " + "$tablename$::serialization_table>))},\n", + tag, FindMessageIndexInFile(field->message_type()), + QualifiedClassName(field->message_type())); continue; - } else { - vars["ptr"] = - "::" + FileLevelNamespace(field->message_type()) + - "::TableStruct::serialization_table + " + + } else if (!IsProto1(field->message_type()->file(), options_) && + !field->message_type()->options().message_set_wire_format()) { + // Proto1 or message_set don't have the usual table and we need to + // dispatch to generated serializer, hence ptr stays zero. + ptr = + "::" + UniqueName("TableStruct", field->message_type(), options_) + + "::serialization_table + " + SimpleItoa(FindMessageIndexInFile(field->message_type())); } } const FieldGenerator& generator = field_generators_.get(field); - vars["type"] = SimpleItoa(CalcFieldNum(generator, field, options_)); + int type = CalcFieldNum(generator, field, options_); + if (IsLazy(field, options_)) { + type = internal::FieldMetadata::kSpecial; + ptr = "reinterpret_cast<const void*>(::" + variables_["proto_ns"] + + "::internal::LazyFieldSerializer"; + if (field->containing_oneof()) { + ptr += "OneOf"; + } else if (!HasFieldPresence(descriptor_->file()) || + has_bit_indices_[field->index()] == -1) { + ptr += "NoPresence"; + } + ptr += ")"; + } if (field->options().weak()) { // TODO(gerbens) merge weak fields into ranges - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, _weak_field_map_), $tag$, $tag$, " - "::google::protobuf::internal::FieldMetadata::kSpecial, " - "reinterpret_cast<const " - "void*>(::google::protobuf::internal::WeakFieldSerializer)},\n"); + format( + "{PROTOBUF_FIELD_OFFSET(" + "$classtype$, _weak_field_map_), $1$, $1$, " + "::$proto_ns$::internal::FieldMetadata::kSpecial, " + "reinterpret_cast<const " + "void*>(::$proto_ns$::internal::WeakFieldSerializer)},\n", + tag); } else if (field->containing_oneof()) { - vars["oneofoffset"] = - SimpleItoa(sizeof(uint32) * field->containing_oneof()->index()); - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, $field_name$_), $tag$, " - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, _oneof_case_) + $oneofoffset$, " - "$type$, $ptr$},\n"); + format.Set("oneofoffset", + sizeof(uint32) * field->containing_oneof()->index()); + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), $1$," + " PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_) + " + "$oneofoffset$, $2$, $3$},\n", + tag, type, ptr); } else if (HasFieldPresence(descriptor_->file()) && has_bit_indices_[field->index()] != -1) { - vars["hasbitsoffset"] = SimpleItoa(has_bit_indices_[field->index()]); - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, $field_name$_), $tag$, " - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, _has_bits_) * 8 + $hasbitsoffset$, $type$, " - "$ptr$},\n"); + format.Set("hasbitsoffset", has_bit_indices_[field->index()]); + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), " + "$1$, PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_) * 8 + " + "$hasbitsoffset$, $2$, $3$},\n", + tag, type, ptr); } else { - printer->Print(vars, - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($" - "classname$, $field_name$_), $tag$, ~0u, $type$, " - "$ptr$},\n"); + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), " + "$1$, ~0u, $2$, $3$},\n", + tag, type, ptr); } } int num_field_metadata = 1 + sorted.size() + sorted_extensions.size(); num_field_metadata++; string serializer = UseUnknownFieldSet(descriptor_->file(), options_) - ? "::google::protobuf::internal::UnknownFieldSetSerializer" - : "::google::protobuf::internal::UnknownFieldSerializerLite"; - printer->Print( - "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_internal_metadata_), 0, ~0u, " - "::google::protobuf::internal::FieldMetadata::kSpecial, reinterpret_cast<const " - "void*>($serializer$)},\n", - "classname", full_classname, "serializer", serializer); + ? "UnknownFieldSetSerializer" + : "UnknownFieldSerializerLite"; + format( + "{PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_), 0, ~0u, " + "::$proto_ns$::internal::FieldMetadata::kSpecial, reinterpret_cast<const " + "void*>(::$proto_ns$::internal::$1$)},\n", + serializer); return num_field_metadata; } void MessageGenerator::GenerateFieldDefaultInstances(io::Printer* printer) { // Construct the default instances for all fields that need one. - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateDefaultInstanceAllocator(printer); + for (auto field : FieldRange(descriptor_)) { + field_generators_.get(field).GenerateDefaultInstanceAllocator(printer); } } -void MessageGenerator:: -GenerateDefaultInstanceInitializer(io::Printer* printer) { +void MessageGenerator::GenerateDefaultInstanceInitializer( + io::Printer* printer) { + Formatter format(printer, variables_); + // The default instance needs all of its embedded message pointers // cross-linked to other default instances. We can't do this initialization // in the constructor because some other default instances may not have been // constructed yet at that time. // TODO(kenton): Maybe all message fields (even for non-default messages) // should be initialized to point at default instances rather than NULL? - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); + for (auto field : FieldRange(descriptor_)) { + Formatter::SaveState saver(&format); if (!field->is_repeated() && + !IsLazy(field, options_) && field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && (field->containing_oneof() == NULL || HasDescriptorMethods(descriptor_->file(), options_))) { @@ -1719,201 +1810,294 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) { "_" + classname_ + "_default_instance_._instance.get_mutable()->"; } name += FieldName(field); - printer->Print( - "$ns$::$name$_ = const_cast< $type$*>(\n" - " $type$::internal_default_instance());\n", - // Vars. - "name", name, "type", FieldMessageTypeName(field), "ns", - Namespace(descriptor_)); + format.Set("name", name); + if (IsWeak(field, options_)) { + const FileDescriptor* dependency = field->message_type()->file(); + string default_instance = QualifiedFileLevelSymbol( + dependency->package(), + "_" + ClassName(field->message_type()) + "_default_instance_"); + format( + "$package_ns$::$name$_ = reinterpret_cast<const " + "::$proto_ns$::Message*>(&$1$);\n" + "if ($package_ns$::$name$_ == NULL) {\n" + " $package_ns$::$name$_ = " + "::$proto_ns$::Empty::internal_default_instance();\n" + "}\n", + default_instance); // 1 + continue; + } + format( + "$package_ns$::$name$_ = const_cast< $1$*>(\n" + " $1$::internal_default_instance());\n", + FieldMessageTypeName(field)); } else if (field->containing_oneof() && HasDescriptorMethods(descriptor_->file(), options_)) { - field_generators_.get(descriptor_->field(i)) - .GenerateConstructorCode(printer); + field_generators_.get(field).GenerateConstructorCode(printer); } } } -void MessageGenerator:: -GenerateClassMethods(io::Printer* printer) { +void MessageGenerator::GenerateClassMethods(io::Printer* printer) { + Formatter format(printer, variables_); if (IsMapEntryMessage(descriptor_)) { - printer->Print( + format( "$classname$::$classname$() {}\n" - "$classname$::$classname$(::google::protobuf::Arena* arena) : " - "SuperType(arena) {}\n" + "$classname$::$classname$(::$proto_ns$::Arena* arena)\n" + " : SuperType(arena) {}\n" "void $classname$::MergeFrom(const $classname$& other) {\n" " MergeFromInternal(other);\n" - "}\n", - "classname", classname_); + "}\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" - " ::$file_namespace$::protobuf_AssignDescriptorsOnce();\n" - " return ::$file_namespace$::file_level_metadata[$index$];\n" - "}\n" + format( + "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n" + " " + "::$proto_ns$::internal::AssignDescriptors(&::$assign_desc_table$);\n" + " return ::$file_level_metadata$[$1$];\n" + "}\n", + index_in_file_messages_); + format( "void $classname$::MergeFrom(\n" - " const ::google::protobuf::Message& other) {\n" - " ::google::protobuf::Message::MergeFrom(other);\n" + " const ::$proto_ns$::Message& other) {\n" + " ::$proto_ns$::Message::MergeFrom(other);\n" "}\n" - "\n", - "file_namespace", FileLevelNamespace(descriptor_), - "classname", classname_, "index", - SimpleItoa(index_in_file_messages_)); + "\n"); + } + format( + "#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n" + "bool $classname$::_ParseMap(const char* begin, const " + "char* end, void* object, ::google::protobuf::internal::ParseContext* ctx) {\n" + " using MF = ::$proto_ns$::internal::MapField$1$<\n" + " $classname$, EntryKeyType, EntryValueType,\n" + " kEntryKeyFieldType, kEntryValueFieldType,\n" + " kEntryDefaultEnumValue>;\n" + " auto mf = static_cast<MF*>(object);\n" + " Parser<MF, ::$proto_ns$::Map<EntryKeyType, EntryValueType>> " + "parser(mf);\n" + "#define DO_(x) if (!(x)) return false\n", + HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite"); + const FieldDescriptor* key = descriptor_->FindFieldByName("key"); + const FieldDescriptor* val = descriptor_->FindFieldByName("value"); + GOOGLE_CHECK(val); + string key_string; + string value_string; + if (HasFieldPresence(descriptor_->file()) && + val->type() == FieldDescriptor::TYPE_ENUM) { + format( + " DO_(parser.ParseMapEnumValidation(\n" + " begin, end, ctx->extra_parse_data().field_number,\n" + " static_cast<::google::protobuf::internal::InternalMetadataWithArena$1$*>(" + "ctx->extra_parse_data().unknown_fields), $2$_IsValid));\n", + HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite", + QualifiedClassName(val->enum_type())); + key_string = "parser.entry_key()"; + value_string = "parser.entry_value()"; + } else { + format(" DO_(parser.ParseMap(begin, end));\n"); + key_string = "parser.key()"; + value_string = "parser.value()"; + } + format.Indent(); + if (key->type() == FieldDescriptor::TYPE_STRING) { + GenerateUtf8CheckCodeForString( + key, options_, true, + StrCat(key_string, ".data(), static_cast<int>(", key_string, + ".length()),\n") + .data(), + format); } + if (val->type() == FieldDescriptor::TYPE_STRING) { + GenerateUtf8CheckCodeForString( + val, options_, true, + StrCat(value_string, ".data(), static_cast<int>(", value_string, + ".length()),\n") + .data(), + format); + } + format.Outdent(); + format( + "#undef DO_\n" + " return true;\n" + "}\n" + "#endif // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"); + format("\n"); return; } // TODO(gerbens) Remove this function. With a little bit of cleanup and // refactoring this is superfluous. - printer->Print("void $classname$::InitAsDefaultInstance() {\n", "classname", - classname_); - printer->Indent(); + format("void $classname$::InitAsDefaultInstance() {\n"); + format.Indent(); GenerateDefaultInstanceInitializer(printer); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); if (IsAnyMessage(descriptor_)) { - printer->Print( - "void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n" - " _any_metadata_.PackFrom(message);\n" - "}\n" - "\n" - "void $classname$::PackFrom(const ::google::protobuf::Message& message,\n" - " const ::std::string& type_url_prefix) {\n" - " _any_metadata_.PackFrom(message, type_url_prefix);\n" - "}\n" - "\n" - "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\n" - " return _any_metadata_.UnpackTo(message);\n" - "}\n" - "bool $classname$::ParseAnyTypeUrl(const string& type_url,\n" - " string* full_type_name) {\n" - " return ::google::protobuf::internal::ParseAnyTypeUrl(type_url,\n" - " full_type_name);\n" - "}\n" - "\n", - "classname", classname_); + format( + "void $classname$::PackFrom(const ::$proto_ns$::Message& message) {\n" + " _any_metadata_.PackFrom(message);\n" + "}\n" + "\n" + "void $classname$::PackFrom(const ::$proto_ns$::Message& message,\n" + " const $string$& type_url_prefix) {\n" + " _any_metadata_.PackFrom(message, type_url_prefix);\n" + "}\n" + "\n" + "bool $classname$::UnpackTo(::$proto_ns$::Message* message) const {\n" + " return _any_metadata_.UnpackTo(message);\n" + "}\n" + "bool $classname$::ParseAnyTypeUrl(const string& type_url,\n" + " string* full_type_name) {\n" + " return ::$proto_ns$::internal::ParseAnyTypeUrl(type_url,\n" + " full_type_name);\n" + "}\n" + "bool $classname$::GetAnyFieldDescriptors(\n" + " const ::$proto_ns$::Message& message,\n" + " const ::$proto_ns$::FieldDescriptor** type_url_field,\n" + " const ::$proto_ns$::FieldDescriptor** value_field) {\n" + " return ::$proto_ns$::internal::GetAnyFieldDescriptors(\n" + " message, type_url_field, value_field);\n" + "}\n" + "\n"); + } + + format( + "class $classname$::HasBitSetters {\n" + " public:\n"); + format.Indent(); + for (auto field : FieldRange(descriptor_)) { + field_generators_.get(field).GenerateInternalAccessorDeclarations(printer); + if (HasFieldPresence(descriptor_->file()) && !field->is_repeated() && + !field->options().weak() && !field->containing_oneof()) { + int has_bit_index = has_bit_indices_[field->index()]; + GOOGLE_CHECK_GE(has_bit_index, 0); + + format.Set("has_array_index", has_bit_index / 32); + format.Set("has_mask", + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + format( + "static void set_has_$1$($classname$* msg) {\n" + " msg->_has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" + "}\n", + FieldName(field)); + } + } + format.Outdent(); + format("};\n\n"); + for (auto field : FieldRange(descriptor_)) { + field_generators_.get(field).GenerateInternalAccessorDefinitions(printer); } // Generate non-inline field definitions. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - field_generators_.get(field) - .GenerateNonInlineAccessorDefinitions(printer); + for (auto field : FieldRange(descriptor_)) { + field_generators_.get(field).GenerateNonInlineAccessorDefinitions(printer); if (IsCrossFileMaybeMap(field)) { + Formatter::SaveState saver(&format); std::map<string, string> vars; SetCommonFieldVariables(field, &vars, options_); if (field->containing_oneof()) { SetCommonOneofFieldVariables(field, &vars); } - GenerateFieldClear(field, vars, false, printer); + format.AddMap(vars); + GenerateFieldClear(field, false, format); } } // Generate field number constants. - printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor *field = descriptor_->field(i); - printer->Print( - "const int $classname$::$constant_name$;\n", - "classname", ClassName(FieldScope(field), false), - "constant_name", FieldConstantName(field)); - } - printer->Print( - "#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n" - "\n"); + format("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); + for (auto field : FieldRange(descriptor_)) { + format("const int $classname$::$1$;\n", FieldConstantName(field)); + } + format( + "#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n" + "\n"); GenerateStructors(printer); - printer->Print("\n"); + format("\n"); if (descriptor_->oneof_decl_count() > 0) { GenerateOneofClear(printer); - printer->Print("\n"); + format("\n"); } if (HasGeneratedMethods(descriptor_->file(), options_)) { GenerateClear(printer); - printer->Print("\n"); + format("\n"); GenerateMergeFromCodedStream(printer); - printer->Print("\n"); + format("\n"); GenerateSerializeWithCachedSizes(printer); - printer->Print("\n"); + format("\n"); if (HasFastArraySerialization(descriptor_->file(), options_)) { GenerateSerializeWithCachedSizesToArray(printer); - printer->Print("\n"); + format("\n"); } GenerateByteSize(printer); - printer->Print("\n"); + format("\n"); GenerateMergeFrom(printer); - printer->Print("\n"); + format("\n"); GenerateCopyFrom(printer); - printer->Print("\n"); + format("\n"); GenerateIsInitialized(printer); - printer->Print("\n"); + format("\n"); } GenerateSwap(printer); - printer->Print("\n"); + format("\n"); if (options_.table_driven_serialization) { - printer->Print( + format( "const void* $classname$::InternalGetTable() const {\n" - " return ::$file_namespace$::TableStruct::serialization_table + " - "$index$;\n" + " return ::$tablename$::serialization_table + $1$;\n" "}\n" "\n", - "classname", classname_, "index", SimpleItoa(index_in_file_messages_), - "file_namespace", FileLevelNamespace(descriptor_)); + index_in_file_messages_); } if (HasDescriptorMethods(descriptor_->file(), options_)) { - printer->Print( - "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" - " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" - " return ::" - "$file_namespace$::file_level_metadata[kIndexInFileMessages];\n" + format( + "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n" + " ::$proto_ns$::internal::AssignDescriptors(&::$assign_desc_table$);\n" + " return ::$file_level_metadata$[kIndexInFileMessages];\n" "}\n" - "\n", - "classname", classname_, "file_namespace", - FileLevelNamespace(descriptor_)); + "\n"); } else { - printer->Print( - "::std::string $classname$::GetTypeName() const {\n" - " return \"$type_name$\";\n" - "}\n" - "\n", - "classname", classname_, - "type_name", descriptor_->full_name()); + format( + "$string$ $classname$::GetTypeName() const {\n" + " return \"$full_name$\";\n" + "}\n" + "\n"); } } size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) { + Formatter format(printer, variables_); + if (!table_driven_) { return 0; } // Field "0" is special: We use it in our switch statement of processing // types to handle the successful end tag case. - printer->Print("{0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},\n"); + format("{0, 0, 0, ::$proto_ns$::internal::kInvalidMask, 0, 0},\n"); int last_field_number = 1; std::vector<const FieldDescriptor*> ordered_fields = SortFieldsByNumber(descriptor_); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = ordered_fields[i]; + for (auto field : ordered_fields) { + Formatter::SaveState saver(&format); GOOGLE_CHECK_GE(field->number(), last_field_number); for (; last_field_number < field->number(); last_field_number++) { - printer->Print( - "{ 0, 0, ::google::protobuf::internal::kInvalidMask,\n" - " ::google::protobuf::internal::kInvalidMask, 0, 0 },\n"); + format( + "{ 0, 0, ::$proto_ns$::internal::kInvalidMask,\n" + " ::$proto_ns$::internal::kInvalidMask, 0, 0 },\n"); } last_field_number++; @@ -1929,30 +2113,39 @@ size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) { processing_type = static_cast<unsigned>(field->type()); const FieldGenerator& generator = field_generators_.get(field); if (field->type() == FieldDescriptor::TYPE_STRING) { - switch (EffectiveStringCType(field)) { + switch (EffectiveStringCType(field, options_)) { case FieldOptions::STRING: - default: { if (generator.IsInlined()) { processing_type = internal::TYPE_STRING_INLINED; break; } break; - } + case FieldOptions::CORD: + processing_type = internal::TYPE_STRING_CORD; + break; + case FieldOptions::STRING_PIECE: + processing_type = internal::TYPE_STRING_STRING_PIECE; + break; } } else if (field->type() == FieldDescriptor::TYPE_BYTES) { - switch (EffectiveStringCType(field)) { + switch (EffectiveStringCType(field, options_)) { case FieldOptions::STRING: - default: if (generator.IsInlined()) { processing_type = internal::TYPE_BYTES_INLINED; break; } break; + case FieldOptions::CORD: + processing_type = internal::TYPE_BYTES_CORD; + break; + case FieldOptions::STRING_PIECE: + processing_type = internal::TYPE_BYTES_STRING_PIECE; + break; } } processing_type |= static_cast<unsigned>( - field->is_repeated() ? internal::kRepeatedMask : 0); + field->is_repeated() ? internal::kRepeatedMask : 0); processing_type |= static_cast<unsigned>( field->containing_oneof() ? internal::kOneofMask : 0); @@ -1961,13 +2154,13 @@ size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) { } const unsigned char tag_size = - WireFormat::TagSize(field->number(), field->type()); + WireFormat::TagSize(field->number(), field->type()); std::map<string, string> vars; - vars["classname"] = QualifiedClassName(descriptor_); if (field->containing_oneof() != NULL) { vars["name"] = field->containing_oneof()->name(); - vars["presence"] = SimpleItoa(field->containing_oneof()->index()); + vars["presence"] = + SimpleItoa(field->containing_oneof()->index()); } else { vars["name"] = FieldName(field); vars["presence"] = SimpleItoa(has_bit_indices_[field->index()]); @@ -1977,19 +2170,22 @@ size_t MessageGenerator::GenerateParseOffsets(io::Printer* printer) { vars["ptype"] = SimpleItoa(processing_type); vars["tag_size"] = SimpleItoa(tag_size); - printer->Print(vars, - "{\n" - " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n" - " $classname$, $name$_),\n" - " static_cast<::google::protobuf::uint32>($presence$),\n" - " $nwtype$, $pwtype$, $ptype$, $tag_size$\n" - "},\n"); + format.AddMap(vars); + + format( + "{\n" + " PROTOBUF_FIELD_OFFSET($classtype$, $name$_),\n" + " static_cast<$uint32$>($presence$),\n" + " $nwtype$, $pwtype$, $ptype$, $tag_size$\n" + "},\n"); } return last_field_number; } size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) { + Formatter format(printer, variables_); + if (!table_driven_) { return 0; } @@ -1997,74 +2193,71 @@ size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) { std::vector<const FieldDescriptor*> ordered_fields = SortFieldsByNumber(descriptor_); - printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n"); + format("::$proto_ns$::internal::AuxillaryParseTableField(),\n"); int last_field_number = 1; - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = ordered_fields[i]; + for (auto field : ordered_fields) { + Formatter::SaveState saver(&format); GOOGLE_CHECK_GE(field->number(), last_field_number); for (; last_field_number < field->number(); last_field_number++) { - printer->Print("::google::protobuf::internal::AuxillaryParseTableField(),\n"); + format("::$proto_ns$::internal::AuxillaryParseTableField(),\n"); } std::map<string, string> vars; SetCommonFieldVariables(field, &vars, options_); + format.AddMap(vars); switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_ENUM: - vars["type"] = ClassName(field->enum_type(), true); - printer->Print( - vars, - "{::google::protobuf::internal::AuxillaryParseTableField::enum_aux{" - "$type$_IsValid}},\n"); + format( + "{::$proto_ns$::internal::AuxillaryParseTableField::enum_aux{" + "$1$_IsValid}},\n", + ClassName(field->enum_type(), true)); last_field_number++; break; case FieldDescriptor::CPPTYPE_MESSAGE: { if (field->is_map()) { - vars["classname"] = QualifiedClassName(field->message_type()); - printer->Print(vars, - "{::google::protobuf::internal::AuxillaryParseTableField::map_" - "aux{&::google::protobuf::internal::ParseMap<$classname$>}},\n"); + format( + "{::$proto_ns$::internal::AuxillaryParseTableField::map_" + "aux{&::$proto_ns$::internal::ParseMap<$1$>}},\n", + QualifiedClassName(field->message_type())); last_field_number++; break; - } else { - vars["classname"] = ClassName(field->message_type(), false); } - vars["ns"] = Namespace(field->message_type()); - vars["type"] = FieldMessageTypeName(field); - vars["file_namespace"] = - FileLevelNamespace(field->message_type()); - - printer->Print( - vars, - "{::google::protobuf::internal::AuxillaryParseTableField::message_aux{\n" - " &$ns$::_$classname$_default_instance_}},\n"); + format.Set("field_classname", ClassName(field->message_type(), false)); + format.Set("ns", Namespace(field->message_type())); + + format( + "{::$proto_ns$::internal::AuxillaryParseTableField::message_aux{\n" + " &$ns$::_$field_classname$_default_instance_}},\n"); last_field_number++; break; } - case FieldDescriptor::CPPTYPE_STRING: - switch (EffectiveStringCType(field)) { + case FieldDescriptor::CPPTYPE_STRING: { + string default_val; + switch (EffectiveStringCType(field, options_)) { case FieldOptions::STRING: - vars["default"] = - field->default_value_string().empty() - ? "&::google::protobuf::internal::fixed_address_empty_string" - : "&" + Namespace(field) + " ::" + classname_ + - "::" + MakeDefaultName(field); + default_val = field->default_value_string().empty() + ? "&::" + variables_["proto_ns"] + + "::internal::fixed_address_empty_string" + : "&" + Namespace(field) + " ::" + classname_ + + "::" + MakeDefaultName(field); break; case FieldOptions::CORD: case FieldOptions::STRING_PIECE: - vars["default"] = + default_val = "\"" + CEscape(field->default_value_string()) + "\""; break; } - vars["full_name"] = field->full_name(); - printer->Print(vars, - "{::google::protobuf::internal::AuxillaryParseTableField::string_aux{\n" - " $default$,\n" - " \"$full_name$\"\n" - "}},\n"); + format( + "{::$proto_ns$::internal::AuxillaryParseTableField::string_aux{\n" + " $1$,\n" + " \"$2$\"\n" + "}},\n", + default_val, field->full_name()); last_field_number++; break; + } default: break; } @@ -2075,171 +2268,149 @@ size_t MessageGenerator::GenerateParseAuxTable(io::Printer* printer) { std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( io::Printer* printer) { - std::map<string, string> variables; - string full_classname = QualifiedClassName(descriptor_); - variables["classname"] = full_classname; + Formatter format(printer, variables_); if (HasFieldPresence(descriptor_->file()) || IsMapEntryMessage(descriptor_)) { - printer->Print( - variables, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_has_bits_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n"); } else { - printer->Print("~0u, // no _has_bits_\n"); + format("~0u, // no _has_bits_\n"); } - printer->Print(variables, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_internal_metadata_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_),\n"); if (descriptor_->extension_range_count() > 0) { - printer->Print( - variables, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " - "_extensions_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _extensions_),\n"); } else { - printer->Print("~0u, // no _extensions_\n"); + format("~0u, // no _extensions_\n"); } if (descriptor_->oneof_decl_count() > 0) { - printer->Print(variables, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" - "$classname$, _oneof_case_[0]),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_[0]),\n"); } else { - printer->Print("~0u, // no _oneof_case_\n"); + format("~0u, // no _oneof_case_\n"); } if (num_weak_fields_ > 0) { - printer->Print(variables, - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$," - " _weak_field_map_),\n"); + format("PROTOBUF_FIELD_OFFSET($classtype$, _weak_field_map_),\n"); } else { - printer->Print("~0u, // no _weak_field_map_\n"); + format("~0u, // no _weak_field_map_\n"); } const int kNumGenericOffsets = 5; // the number of fixed offsets above - const size_t offsets = kNumGenericOffsets + - descriptor_->field_count() + + const size_t offsets = kNumGenericOffsets + descriptor_->field_count() + descriptor_->oneof_decl_count(); size_t entries = offsets; - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); + for (auto field : FieldRange(descriptor_)) { if (field->containing_oneof() || field->options().weak()) { - printer->Print("offsetof($classname$DefaultTypeInternal, $name$_)", - "classname", full_classname, "name", FieldName(field)); + format("offsetof($classtype$DefaultTypeInternal, $1$_)", + FieldName(field)); } else { - printer->Print( - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_)", - "classname", full_classname, "name", FieldName(field)); + format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_)", FieldName(field)); } uint32 tag = field_generators_.get(field).CalculateFieldTag(); if (tag != 0) { - printer->Print(" | $tag$", "tag", SimpleItoa(tag)); + format(" | $1$", tag); } - printer->Print(",\n"); + format(",\n"); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof = descriptor_->oneof_decl(i); - printer->Print( - "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", - "classname", full_classname, "name", oneof->name()); + for (auto oneof : OneOfRange(descriptor_)) { + format("PROTOBUF_FIELD_OFFSET($classtype$, $1$_),\n", oneof->name()); } if (IsMapEntryMessage(descriptor_)) { entries += 2; - printer->Print( + format( "0,\n" "1,\n"); } else if (HasFieldPresence(descriptor_->file())) { entries += has_bit_indices_.size(); for (int i = 0; i < has_bit_indices_.size(); i++) { - const string index = has_bit_indices_[i] >= 0 ? - SimpleItoa(has_bit_indices_[i]) : "~0u"; - printer->Print("$index$,\n", "index", index); + const string index = has_bit_indices_[i] >= 0 + ? SimpleItoa(has_bit_indices_[i]) + : "~0u"; + format("$1$,\n", index); } } return std::make_pair(entries, offsets); } -void MessageGenerator:: -GenerateSharedConstructorCode(io::Printer* printer) { - printer->Print( - "void $classname$::SharedCtor() {\n", - "classname", classname_); - printer->Indent(); +void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) { + Formatter format(printer, variables_); + + format("void $classname$::SharedCtor() {\n"); + if (scc_analyzer_ + ->GetSCCAnalysis(scc_analyzer_->GetSCC(descriptor_)) + .constructor_requires_initialization) { + format( + " ::$proto_ns$::internal::InitSCC(\n" + " &scc_info_$scc_name$.base);\n"); + } + + format.Indent(); std::vector<bool> processed(optimized_order_.size(), false); GenerateConstructorBody(printer, processed, false); - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "clear_has_$oneof_name$();\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); + for (auto oneof : OneOfRange(descriptor_)) { + format("clear_has_$1$();\n", oneof->name()); } - printer->Outdent(); - printer->Print("}\n\n"); + format.Outdent(); + format("}\n\n"); } -void MessageGenerator:: -GenerateSharedDestructorCode(io::Printer* printer) { - printer->Print( - "void $classname$::SharedDtor() {\n", - "classname", classname_); - printer->Indent(); +void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) { + Formatter format(printer, variables_); + + format("void $classname$::SharedDtor() {\n"); + format.Indent(); if (SupportsArenas(descriptor_)) { - printer->Print( - "GOOGLE_DCHECK(GetArenaNoVirtual() == NULL);\n"); + format("$DCHK$(GetArenaNoVirtual() == NULL);\n"); } // Write the destructors for each field except oneof members. // optimized_order_ does not contain oneof fields. - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { field_generators_.get(field).GenerateDestructorCode(printer); } // Generate code to destruct oneofs. Clearing should do the work. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "if (has_$oneof_name$()) {\n" - " clear_$oneof_name$();\n" + for (auto oneof : OneOfRange(descriptor_)) { + format( + "if (has_$1$()) {\n" + " clear_$1$();\n" "}\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); + oneof->name()); } if (num_weak_fields_) { - printer->Print("_weak_field_map_.ClearAll();\n"); + format("_weak_field_map_.ClearAll();\n"); } - printer->Outdent(); - printer->Print( - "}\n" - "\n"); + format.Outdent(); + format( + "}\n" + "\n"); } -void MessageGenerator:: -GenerateArenaDestructorCode(io::Printer* printer) { +void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) { + Formatter format(printer, variables_); + // Generate the ArenaDtor() method. Track whether any fields actually produced // code that needs to be called. - printer->Print( - "void $classname$::ArenaDtor(void* object) {\n", - "classname", classname_); - printer->Indent(); + format("void $classname$::ArenaDtor(void* object) {\n"); + format.Indent(); // This code is placed inside a static method, rather than an ordinary one, // since that simplifies Arena's destructor list (ordinary function pointers // rather than member function pointers). _this is the object being // destructed. - printer->Print( + format( "$classname$* _this = reinterpret_cast< $classname$* >(object);\n" // avoid an "unused variable" warning in case no fields have dtor code. - "(void)_this;\n", - "classname", classname_); + "(void)_this;\n"); bool need_registration = false; // Process non-oneof fields first. - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (field_generators_.get(field) - .GenerateArenaDestructorCode(printer)) { + for (auto field : optimized_order_) { + if (field_generators_.get(field).GenerateArenaDestructorCode(printer)) { need_registration = true; } } @@ -2248,13 +2419,9 @@ GenerateArenaDestructorCode(io::Printer* printer) { // // Note: As of 10/5/2016, GenerateArenaDestructorCode does not emit anything // and returns false for oneof fields. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof = descriptor_->oneof_decl(i); - - for (int j = 0; j < oneof->field_count(); j++) { - const FieldDescriptor* field = oneof->field(j); - if (field_generators_.get(field) - .GenerateArenaDestructorCode(printer)) { + for (auto oneof : OneOfRange(descriptor_)) { + for (auto field : FieldRange(oneof)) { + if (field_generators_.get(field).GenerateArenaDestructorCode(printer)) { need_registration = true; } } @@ -2262,42 +2429,40 @@ GenerateArenaDestructorCode(io::Printer* printer) { if (num_weak_fields_) { // _this is the object being destructed (we are inside a static method // here). - printer->Print("_this->_weak_field_map_.ClearAll();\n"); + format("_this->_weak_field_map_.ClearAll();\n"); need_registration = true; } - printer->Outdent(); - printer->Print( - "}\n"); + format.Outdent(); + format("}\n"); if (need_registration) { - printer->Print( - "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n" + format( + "inline void $classname$::RegisterArenaDtor(::$proto_ns$::Arena* " + "arena) {\n" " if (arena != NULL) {\n" " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n" " }\n" - "}\n", - "classname", classname_); + "}\n"); } else { - printer->Print( - "void $classname$::RegisterArenaDtor(::google::protobuf::Arena*) {\n" - "}\n", - "classname", classname_); + format( + "void $classname$::RegisterArenaDtor(::$proto_ns$::Arena*) {\n" + "}\n"); } } void MessageGenerator::GenerateConstructorBody(io::Printer* printer, std::vector<bool> processed, bool copy_constructor) const { + Formatter format(printer, variables_); const FieldDescriptor* last_start = NULL; // RunMap maps from fields that start each run to the number of fields in that // run. This is optimized for the common case that there are very few runs in // a message and that most of the eligible fields appear together. - typedef hash_map<const FieldDescriptor*, size_t> RunMap; + typedef std::unordered_map<const FieldDescriptor*, size_t> RunMap; RunMap runs; - for (int i = 0; i < optimized_order_.size(); ++i) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { if ((copy_constructor && IsPOD(field)) || (!copy_constructor && CanConstructByZeroing(field, options_))) { if (last_start == NULL) { @@ -2340,9 +2505,10 @@ void MessageGenerator::GenerateConstructorBody(io::Printer* printer, const string last_field_name = FieldName(optimized_order_[i + run_length - 1]); - printer->Print(pod_template.c_str(), - "first", first_field_name, - "last", last_field_name); + format.Set("first", first_field_name); + format.Set("last", last_field_name); + + format(pod_template.c_str()); i += run_length - 1; // ++i at the top of the loop. @@ -2356,8 +2522,9 @@ void MessageGenerator::GenerateConstructorBody(io::Printer* printer, } } -void MessageGenerator:: -GenerateStructors(io::Printer* printer) { +void MessageGenerator::GenerateStructors(io::Printer* printer) { + Formatter format(printer, variables_); + string superclass; superclass = SuperClassName(descriptor_, options_); string initializer_with_arena = superclass + "()"; @@ -2369,13 +2536,15 @@ GenerateStructors(io::Printer* printer) { initializer_with_arena += ",\n _internal_metadata_(arena)"; // Initialize member variables with arena constructor. - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - + for (auto field : optimized_order_) { bool has_arena_constructor = field->is_repeated(); + if (field->containing_oneof() == NULL && + (IsLazy(field, options_) || IsStringPiece(field, options_))) { + has_arena_constructor = true; + } if (has_arena_constructor) { - initializer_with_arena += string(",\n ") + - FieldName(field) + string("_(arena)"); + initializer_with_arena += + string(",\n ") + FieldName(field) + string("_(arena)"); } } @@ -2394,33 +2563,23 @@ GenerateStructors(io::Printer* printer) { initializer_null += ", _weak_field_map_(nullptr)"; } - printer->Print( + format( "$classname$::$classname$()\n" - " : $initializer$ {\n" - " ::google::protobuf::internal::InitSCC(\n" - " &$file_namespace$::scc_info_$scc_name$.base);\n" + " : $1$ {\n" " SharedCtor();\n" " // @@protoc_insertion_point(constructor:$full_name$)\n" "}\n", - "classname", classname_, "full_name", descriptor_->full_name(), - "scc_name", scc_name_, "initializer", initializer_null, "file_namespace", - FileLevelNamespace(descriptor_)); + initializer_null); if (SupportsArenas(descriptor_)) { - printer->Print( - "$classname$::$classname$(::google::protobuf::Arena* arena)\n" - " : $initializer$ {\n" - " " - "::google::protobuf::internal::InitSCC(&$file_namespace$::scc_info_$scc_name$." - "base);\n" + format( + "$classname$::$classname$(::$proto_ns$::Arena* arena)\n" + " : $1$ {\n" " SharedCtor();\n" " RegisterArenaDtor(arena);\n" " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" "}\n", - "initializer", initializer_with_arena, "classname", classname_, - "superclass", superclass, "full_name", descriptor_->full_name(), - "scc_name", scc_name_, "file_namespace", - FileLevelNamespace(descriptor_)); + initializer_with_arena); } // Generate the copy constructor. @@ -2429,117 +2588,98 @@ GenerateStructors(io::Printer* printer) { // one-liner copy constructor that delegates to MergeFrom. This saves some // code size and also cuts down on the complexity of implicit weak fields. // We might eventually want to do this for all lite protos. - printer->Print( - "$classname$::$classname$(const $classname$& from)\n" - " : $classname$() {\n" - " MergeFrom(from);\n" - "}\n", - "classname", classname_); + format( + "$classname$::$classname$(const $classname$& from)\n" + " : $classname$() {\n" + " MergeFrom(from);\n" + "}\n"); } else { - printer->Print( - "$classname$::$classname$(const $classname$& from)\n" - " : $superclass$()", - "classname", classname_, - "superclass", superclass, - "full_name", descriptor_->full_name()); - printer->Indent(); - printer->Indent(); - printer->Indent(); - - printer->Print( - ",\n_internal_metadata_(NULL)"); + format( + "$classname$::$classname$(const $classname$& from)\n" + " : $superclass$()"); + format.Indent(); + format.Indent(); + format.Indent(); + format(",\n_internal_metadata_(NULL)"); if (HasFieldPresence(descriptor_->file())) { - printer->Print(",\n_has_bits_(from._has_bits_)"); + if (!IsProto2MessageSet(descriptor_, options_)) { + format(",\n_has_bits_(from._has_bits_)"); + } } std::vector<bool> processed(optimized_order_.size(), false); - for (int i = 0; i < optimized_order_.size(); ++i) { - const FieldDescriptor* field = optimized_order_[i]; - - if (!(field->is_repeated() && !(field->is_map())) - ) { + for (int i = 0; i < optimized_order_.size(); i++) { + auto field = optimized_order_[i]; + if (!(field->is_repeated() && !(field->is_map())) && + !IsCord(field, options_)) { continue; } processed[i] = true; - printer->Print(",\n$name$_(from.$name$_)", - "name", FieldName(field)); + format(",\n$1$_(from.$1$_)", FieldName(field)); } if (IsAnyMessage(descriptor_)) { - printer->Print(",\n_any_metadata_(&type_url_, &value_)"); + format(",\n_any_metadata_(&type_url_, &value_)"); } if (num_weak_fields_ > 0) { - printer->Print(",\n_weak_field_map_(from._weak_field_map_)"); + format(",\n_weak_field_map_(from._weak_field_map_)"); } - printer->Outdent(); - printer->Outdent(); - printer->Print(" {\n"); + format.Outdent(); + format.Outdent(); + format(" {\n"); - printer->Print( - "_internal_metadata_.MergeFrom(from._internal_metadata_);\n"); + format("_internal_metadata_.MergeFrom(from._internal_metadata_);\n"); if (descriptor_->extension_range_count() > 0) { - printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); + format("_extensions_.MergeFrom(from._extensions_);\n"); } GenerateConstructorBody(printer, processed, true); // Copy oneof fields. Oneof field requires oneof case check. - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - printer->Print( - "clear_has_$oneofname$();\n" - "switch (from.$oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); + for (auto oneof : OneOfRange(descriptor_)) { + format( + "clear_has_$1$();\n" + "switch (from.$1$_case()) {\n", + oneof->name()); + format.Indent(); + for (auto field : FieldRange(oneof)) { + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); field_generators_.get(field).GenerateMergingCode(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); + format("break;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" + format( + "case $1$_NOT_SET: {\n" " break;\n" "}\n", - "oneof_index", - SimpleItoa(descriptor_->oneof_decl(i)->index()), - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "}\n"); + ToUpper(oneof->name())); + format.Outdent(); + format("}\n"); } - printer->Outdent(); - printer->Print( - " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" - "}\n" - "\n", - "full_name", descriptor_->full_name()); + format.Outdent(); + format( + " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" + "}\n" + "\n"); } // Generate the shared constructor code. GenerateSharedConstructorCode(printer); // Generate the destructor. - printer->Print( - "$classname$::~$classname$() {\n" - " // @@protoc_insertion_point(destructor:$full_name$)\n" - " SharedDtor();\n" - "}\n" - "\n", - "classname", classname_, - "full_name", descriptor_->full_name()); + format( + "$classname$::~$classname$() {\n" + " // @@protoc_insertion_point(destructor:$full_name$)\n" + " SharedDtor();\n" + "}\n" + "\n"); // Generate the shared destructor code. GenerateSharedDestructorCode(printer); @@ -2550,90 +2690,60 @@ GenerateStructors(io::Printer* printer) { } // Generate SetCachedSize. - printer->Print( + format( "void $classname$::SetCachedSize(int size) const {\n" " _cached_size_.Set(size);\n" - "}\n", - "classname", classname_); - - // Only generate this member if it's not disabled. - if (HasDescriptorMethods(descriptor_->file(), options_) && - !descriptor_->options().no_standard_descriptor_accessor()) { - printer->Print( - "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" - " ::$file_namespace$::protobuf_AssignDescriptorsOnce();\n" - " return ::" - "$file_namespace$::file_level_metadata[kIndexInFileMessages]." - "descriptor;\n" - "}\n" - "\n", - "classname", classname_, "file_namespace", - FileLevelNamespace(descriptor_)); - } + "}\n"); - printer->Print( + format( "const $classname$& $classname$::default_instance() {\n" " " - "::google::protobuf::internal::InitSCC(&$file_namespace$::scc_info_$scc_name$.base)" + "::$proto_ns$::internal::InitSCC(&::scc_info_$scc_name$.base)" ";\n" " return *internal_default_instance();\n" - "}\n\n", - "classname", classname_, "scc_name", scc_name_, "file_namespace", - FileLevelNamespace(descriptor_)); + "}\n\n"); } void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) { - printer->Print( + Formatter format(printer, variables_); + format( "template<> " - "GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE " - "$classname$* Arena::CreateMaybeMessage< $classname$ >(Arena* arena) {\n" - " return Arena::$create_func$Internal< $classname$ >(arena);\n" + "PROTOBUF_NOINLINE " + "$classtype$* Arena::CreateMaybeMessage< $classtype$ >(Arena* arena) {\n" + " return Arena::$1$Internal< $classtype$ >(arena);\n" "}\n", - "classname", QualifiedClassName(descriptor_), - "create_func", MessageCreateFunction(descriptor_)); -} - -// Return the number of bits set in n, a non-negative integer. -static int popcnt(uint32 n) { - int result = 0; - while (n != 0) { - result += (n & 1); - n = n / 2; - } - return result; + MessageCreateFunction(descriptor_)); } bool MessageGenerator::MaybeGenerateOptionalFieldCondition( io::Printer* printer, const FieldDescriptor* field, int expected_has_bits_index) { + Formatter format(printer, variables_); int has_bit_index = has_bit_indices_[field->index()]; if (!field->options().weak() && expected_has_bits_index == has_bit_index / 32) { const string mask = StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); - printer->Print( - "if (cached_has_bits & 0x$mask$u) {\n", - "mask", mask); + format("if (cached_has_bits & 0x$1$u) {\n", mask); return true; } return false; } -void MessageGenerator:: -GenerateClear(io::Printer* printer) { +void MessageGenerator::GenerateClear(io::Printer* printer) { + Formatter format(printer, variables_); // Performance tuning parameters const int kMaxUnconditionalPrimitiveBytesClear = 4; - printer->Print( + format( "void $classname$::Clear() {\n" - "// @@protoc_insertion_point(message_clear_start:$full_name$)\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); + "// @@protoc_insertion_point(message_clear_start:$full_name$)\n"); + format.Indent(); - printer->Print( + format( // TODO(jwb): It would be better to avoid emitting this if it is not used, // rather than emitting a workaround for the resulting warning. - "::google::protobuf::uint32 cached_has_bits = 0;\n" + "$uint32$ cached_has_bits = 0;\n" "// Prevent compiler warnings about cached_has_bits being unused\n" "(void) cached_has_bits;\n\n"); @@ -2641,7 +2751,7 @@ GenerateClear(io::Printer* printer) { // Step 1: Extensions if (descriptor_->extension_range_count() > 0) { - printer->Print("_extensions_.Clear();\n"); + format("_extensions_.Clear();\n"); } int unconditional_budget = kMaxUnconditionalPrimitiveBytesClear; @@ -2687,6 +2797,8 @@ GenerateClear(io::Printer* printer) { } } + ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio, + HasFieldPresence(descriptor_->file())); for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index]; GOOGLE_CHECK(!chunk.empty()); @@ -2703,6 +2815,8 @@ GenerateClear(io::Printer* printer) { continue; } + cold_skipper.OnStartChunk(chunk_index, cached_has_bit_index, "", printer); + // Step 3: Non-repeated fields that can be cleared by memset-to-0, then // non-repeated, non-zero initializable fields. int last_chunk = HasFieldPresence(descriptor_->file()) @@ -2738,12 +2852,11 @@ GenerateClear(io::Printer* printer) { if (cached_has_bit_index != last_chunk / 4) { cached_has_bit_index = last_chunk / 4; - printer->Print("cached_has_bits = _has_bits_[$idx$];\n", "idx", - SimpleItoa(cached_has_bit_index)); + format("cached_has_bits = _has_bits_[$1$];\n", cached_has_bit_index); } - printer->Print("if (cached_has_bits & $mask$u) {\n", "mask", - SimpleItoa(last_chunk_mask)); - printer->Indent(); + format("if (cached_has_bits & 0x$1$u) {\n", + StrCat(strings::Hex(last_chunk_mask, strings::ZERO_PAD_8))); + format.Indent(); } if (memset_run_start != -1) { @@ -2756,11 +2869,11 @@ GenerateClear(io::Printer* printer) { const string first_field_name = FieldName(chunk[memset_run_start]); const string last_field_name = FieldName(chunk[memset_run_end]); - printer->Print( - "::memset(&$first$_, 0, static_cast<size_t>(\n" - " reinterpret_cast<char*>(&$last$_) -\n" - " reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n", - "first", first_field_name, "last", last_field_name); + format( + "::memset(&$1$_, 0, static_cast<size_t>(\n" + " reinterpret_cast<char*>(&$2$_) -\n" + " reinterpret_cast<char*>(&$1$_)) + sizeof($2$_));\n", + first_field_name, last_field_name); } // Advance last_chunk_start to skip over the fields we zeroed/memset. @@ -2770,7 +2883,6 @@ GenerateClear(io::Printer* printer) { // Go back and emit clears for each of the fields we processed. for (int j = last_chunk_start; j < chunk.size(); j++) { const FieldDescriptor* field = chunk[j]; - const string fieldname = FieldName(field); const FieldGenerator& generator = field_generators_.get(field); // It's faster to just overwrite primitive types, but we should only @@ -2785,121 +2897,101 @@ GenerateClear(io::Printer* printer) { if (should_check_bit && // If no field presence, then always clear strings/messages as well. HasFieldPresence(descriptor_->file())) { - if (!field->options().weak() && - cached_has_bit_index != (has_bit_indices_[field->index()] / 32)) { - cached_has_bit_index = (has_bit_indices_[field->index()] / 32); - printer->Print("cached_has_bits = _has_bits_[$new_index$];\n", - "new_index", SimpleItoa(cached_has_bit_index)); - } - if (!MaybeGenerateOptionalFieldCondition(printer, field, - cached_has_bit_index)) { - printer->Print("if (has_$name$()) {\n", "name", fieldname); - } - printer->Indent(); + PrintPresenceCheck(format, field, has_bit_indices_, printer, + &cached_has_bit_index); have_enclosing_if = true; } generator.GenerateMessageClearingCode(printer); if (have_enclosing_if) { - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } } if (have_outer_if) { - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); + } + + if (cold_skipper.OnEndChunk(chunk_index, printer)) { + // Reset here as it may have been updated in just closed if statement. + cached_has_bit_index = -1; } } // Step 4: Unions. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "clear_$oneof_name$();\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); + for (auto oneof : OneOfRange(descriptor_)) { + format("clear_$1$();\n", oneof->name()); } if (num_weak_fields_) { - printer->Print("_weak_field_map_.ClearAll();\n"); + format("_weak_field_map_.ClearAll();\n"); } if (HasFieldPresence(descriptor_->file())) { // Step 5: Everything else. - printer->Print("_has_bits_.Clear();\n"); + format("_has_bits_.Clear();\n"); } - printer->Print("_internal_metadata_.Clear();\n"); + format("_internal_metadata_.Clear();\n"); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateOneofClear(io::Printer* printer) { +void MessageGenerator::GenerateOneofClear(io::Printer* printer) { // Generated function clears the active field and union case (e.g. foo_case_). for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - std::map<string, string> oneof_vars; - oneof_vars["classname"] = classname_; - oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name(); - oneof_vars["full_name"] = descriptor_->full_name(); - string message_class; - - printer->Print(oneof_vars, - "void $classname$::clear_$oneofname$() {\n" - "// @@protoc_insertion_point(one_of_clear_start:" - "$full_name$)\n"); - printer->Indent(); - printer->Print(oneof_vars, - "switch ($oneofname$_case()) {\n"); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); + auto oneof = descriptor_->oneof_decl(i); + Formatter format(printer, variables_); + format.Set("oneofname", oneof->name()); + + format( + "void $classname$::clear_$oneofname$() {\n" + "// @@protoc_insertion_point(one_of_clear_start:$full_name$)\n"); + format.Indent(); + format("switch ($oneofname$_case()) {\n"); + format.Indent(); + for (auto field : FieldRange(oneof)) { + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); // We clear only allocated objects in oneofs if (!IsStringOrMessage(field)) { - printer->Print( - "// No need to clear\n"); + format("// No need to clear\n"); } else { field_generators_.get(field).GenerateClearingCode(printer); } - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); + format("break;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" + format( + "case $1$_NOT_SET: {\n" " break;\n" "}\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( + ToUpper(oneof->name())); + format.Outdent(); + format( "}\n" - "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n", - "oneof_index", SimpleItoa(i), - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( + "_oneof_case_[$1$] = $2$_NOT_SET;\n", + i, ToUpper(oneof->name())); + format.Outdent(); + format( "}\n" "\n"); } } -void MessageGenerator:: -GenerateSwap(io::Printer* printer) { +void MessageGenerator::GenerateSwap(io::Printer* printer) { + Formatter format(printer, variables_); if (SupportsArenas(descriptor_)) { // Generate the Swap member function. This is a lightweight wrapper around // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory // ownership situation: swapping across arenas or between an arena and a // heap requires copying. - printer->Print( + format( "void $classname$::Swap($classname$* other) {\n" " if (other == this) return;\n" " if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n" @@ -2916,26 +3008,35 @@ GenerateSwap(io::Printer* printer) { "}\n" "void $classname$::UnsafeArenaSwap($classname$* other) {\n" " if (other == this) return;\n" - " GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n" + " $DCHK$(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n" " InternalSwap(other);\n" - "}\n", - "classname", classname_); + "}\n"); } else { - printer->Print( + format( "void $classname$::Swap($classname$* other) {\n" " if (other == this) return;\n" " InternalSwap(other);\n" - "}\n", - "classname", classname_); + "}\n"); } // Generate the UnsafeArenaSwap member function. - printer->Print("void $classname$::InternalSwap($classname$* other) {\n", - "classname", classname_); - printer->Indent(); - printer->Print("using std::swap;\n"); + format("void $classname$::InternalSwap($classname$* other) {\n"); + format.Indent(); + format("using std::swap;\n"); if (HasGeneratedMethods(descriptor_->file(), options_)) { + if (descriptor_->extension_range_count() > 0) { + format("_extensions_.Swap(&other->_extensions_);\n"); + } + + format("_internal_metadata_.Swap(&other->_internal_metadata_);\n"); + + if (HasFieldPresence(descriptor_->file())) { + for (int i = 0; i < HasBitsSize() / 4; ++i) { + format("swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n", i); + } + } + for (int i = 0; i < optimized_order_.size(); i++) { // optimized_order_ does not contain oneof fields, but the field // generators for these fields do not emit swapping code on their own. @@ -2943,163 +3044,125 @@ GenerateSwap(io::Printer* printer) { field_generators_.get(field).GenerateSwappingCode(printer); } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "swap($oneof_name$_, other->$oneof_name$_);\n" - "swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n", - "oneof_name", descriptor_->oneof_decl(i)->name(), - "i", SimpleItoa(i)); + for (auto oneof : OneOfRange(descriptor_)) { + format("swap($1$_, other->$1$_);\n", oneof->name()); } - if (HasFieldPresence(descriptor_->file())) { - for (int i = 0; i < HasBitsSize() / 4; ++i) { - printer->Print("swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", - "i", SimpleItoa(i)); - } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + format( + "swap(_oneof_case_[$1$], other->_oneof_case_[$1$]);\n", i); } - printer->Print("_internal_metadata_.Swap(&other->_internal_metadata_);\n"); - - if (descriptor_->extension_range_count() > 0) { - printer->Print("_extensions_.Swap(&other->_extensions_);\n"); - } if (num_weak_fields_) { - printer->Print( - "_weak_field_map_.UnsafeArenaSwap(&other->_weak_field_map_);\n"); + format("_weak_field_map_.UnsafeArenaSwap(&other->_weak_field_map_);\n"); } } else { - printer->Print("GetReflection()->Swap(this, other);"); + format("GetReflection()->Swap(this, other);"); } - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateMergeFrom(io::Printer* printer) { +void MessageGenerator::GenerateMergeFrom(io::Printer* printer) { + Formatter format(printer, variables_); if (HasDescriptorMethods(descriptor_->file(), options_)) { // Generate the generalized MergeFrom (aka that which takes in the Message // base class as a parameter). - printer->Print( - "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n" + format( + "void $classname$::MergeFrom(const ::$proto_ns$::Message& from) {\n" "// @@protoc_insertion_point(generalized_merge_from_start:" "$full_name$)\n" - " GOOGLE_DCHECK_NE(&from, this);\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); + " $DCHK$_NE(&from, this);\n"); + format.Indent(); // Cast the message to the proper type. If we find that the message is // *not* of the proper type, we can still call Merge via the reflection // system, as the GOOGLE_CHECK above ensured that we have the same descriptor // for each message. - printer->Print( - "const $classname$* source =\n" - " ::google::protobuf::internal::DynamicCastToGenerated<const $classname$>(\n" - " &from);\n" - "if (source == NULL) {\n" - "// @@protoc_insertion_point(generalized_merge_from_cast_fail:" - "$full_name$)\n" - " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" - "} else {\n" - "// @@protoc_insertion_point(generalized_merge_from_cast_success:" - "$full_name$)\n" - " MergeFrom(*source);\n" - "}\n", - "classname", classname_, "full_name", descriptor_->full_name()); + format( + "const $classname$* source =\n" + " ::$proto_ns$::DynamicCastToGenerated<$classname$>(\n" + " &from);\n" + "if (source == NULL) {\n" + "// @@protoc_insertion_point(generalized_merge_from_cast_fail:" + "$full_name$)\n" + " ::$proto_ns$::internal::ReflectionOps::Merge(from, this);\n" + "} else {\n" + "// @@protoc_insertion_point(generalized_merge_from_cast_success:" + "$full_name$)\n" + " MergeFrom(*source);\n" + "}\n"); - printer->Outdent(); - printer->Print("}\n\n"); + format.Outdent(); + format("}\n\n"); } else { // Generate CheckTypeAndMergeFrom(). - printer->Print( - "void $classname$::CheckTypeAndMergeFrom(\n" - " const ::google::protobuf::MessageLite& from) {\n" - " MergeFrom(*::google::protobuf::down_cast<const $classname$*>(&from));\n" - "}\n" - "\n", - "classname", classname_); + format( + "void $classname$::CheckTypeAndMergeFrom(\n" + " const ::$proto_ns$::MessageLite& from) {\n" + " MergeFrom(*::google::protobuf::down_cast<const $classname$*>(&from));\n" + "}\n" + "\n"); } // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast. - printer->Print( + format( "void $classname$::MergeFrom(const $classname$& from) {\n" "// @@protoc_insertion_point(class_specific_merge_from_start:" "$full_name$)\n" - " GOOGLE_DCHECK_NE(&from, this);\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); + " $DCHK$_NE(&from, this);\n"); + format.Indent(); if (descriptor_->extension_range_count() > 0) { - printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); + format("_extensions_.MergeFrom(from._extensions_);\n"); } - printer->Print( - "_internal_metadata_.MergeFrom(from._internal_metadata_);\n" - "::google::protobuf::uint32 cached_has_bits = 0;\n" - "(void) cached_has_bits;\n\n"); + format( + "_internal_metadata_.MergeFrom(from._internal_metadata_);\n" + "$uint32$ cached_has_bits = 0;\n" + "(void) cached_has_bits;\n\n"); - // cached_has_bit_index maintains that: - // cached_has_bits = from._has_bits_[cached_has_bit_index] - // for cached_has_bit_index >= 0 - int cached_has_bit_index = -1; + if (HasFieldPresence(descriptor_->file())) { + std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields( + optimized_order_, MatchRepeatedAndHasByte(&has_bit_indices_, true)); - int last_i = -1; - for (int i = 0; i < optimized_order_.size(); ) { - // Detect infinite loops. - GOOGLE_CHECK_NE(i, last_i); - last_i = i; + ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, + kColdRatio, true); - // Merge Repeated fields. These fields do not require a - // check as we can simply iterate over them. - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (!field->is_repeated()) { - break; - } + // cached_has_bit_index maintains that: + // cached_has_bits = from._has_bits_[cached_has_bit_index] + // for cached_has_bit_index >= 0 + int cached_has_bit_index = -1; - const FieldGenerator& generator = field_generators_.get(field); - generator.GenerateMergingCode(printer); - } + for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { + const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index]; + GOOGLE_CHECK(!chunk.empty()); - // Merge Optional and Required fields (after a _has_bit_ check). - int last_chunk = -1; - int last_chunk_start = -1; - int last_chunk_end = -1; - uint32 last_chunk_mask = 0; - for (; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; - if (field->is_repeated()) { - break; - } + // Merge Repeated fields. These fields do not require a + // check as we can simply iterate over them. + if (chunk.front()->is_repeated()) { + for (int i = 0; i < chunk.size(); i++) { + const FieldDescriptor* field = chunk[i]; - // "index" defines where in the _has_bits_ the field appears. - // "i" is our loop counter within optimized_order_. - int index = HasFieldPresence(descriptor_->file()) ? - has_bit_indices_[field->index()] : 0; - int chunk = index / 8; - - if (last_chunk == -1) { - last_chunk = chunk; - last_chunk_start = i; - } else if (chunk != last_chunk) { - // Emit the fields for this chunk so far. - break; + const FieldGenerator& generator = field_generators_.get(field); + generator.GenerateMergingCode(printer); + } + continue; } - last_chunk_end = i; - last_chunk_mask |= static_cast<uint32>(1) << (index % 32); - } - - if (last_chunk != -1) { - GOOGLE_DCHECK_NE(-1, last_chunk_start); - GOOGLE_DCHECK_NE(-1, last_chunk_end); - GOOGLE_DCHECK_NE(0, last_chunk_mask); + // Merge Optional and Required fields (after a _has_bit_ check). + cold_skipper.OnStartChunk(chunk_index, cached_has_bit_index, "from.", + printer); - const int count = popcnt(last_chunk_mask); - const bool have_outer_if = HasFieldPresence(descriptor_->file()) && - (last_chunk_start != last_chunk_end); + int last_chunk = has_bit_indices_[chunk.front()->index()] / 8; + GOOGLE_DCHECK_NE(-1, last_chunk); + const bool have_outer_if = chunk.size() > 1; if (have_outer_if) { + uint32 last_chunk_mask = GenChunkMask(chunk, has_bit_indices_); + const int count = popcnt(last_chunk_mask); + // Check (up to) 8 has_bits at a time if we have more than one field in // this chunk. Due to field layout ordering, we may check // _has_bits_[last_chunk * 8 / 32] multiple times. @@ -3107,50 +3170,32 @@ GenerateMergeFrom(io::Printer* printer) { GOOGLE_DCHECK_GE(8, count); if (cached_has_bit_index != last_chunk / 4) { - int new_index = last_chunk / 4; - printer->Print("cached_has_bits = from._has_bits_[$new_index$];\n", - "new_index", SimpleItoa(new_index)); - cached_has_bit_index = new_index; + cached_has_bit_index = last_chunk / 4; + format("cached_has_bits = from._has_bits_[$1$];\n", + cached_has_bit_index); } - - printer->Print( - "if (cached_has_bits & $mask$u) {\n", - "mask", SimpleItoa(last_chunk_mask)); - printer->Indent(); + format("if (cached_has_bits & 0x$1$u) {\n", + StrCat(strings::Hex(last_chunk_mask, strings::ZERO_PAD_8))); + format.Indent(); } - // Go back and emit clears for each of the fields we processed. + // Go back and emit merging code for each of the fields we processed. bool deferred_has_bit_changes = false; - for (int j = last_chunk_start; j <= last_chunk_end; j++) { - const FieldDescriptor* field = optimized_order_[j]; + for (const auto field : chunk) { const FieldGenerator& generator = field_generators_.get(field); - bool have_enclosing_if = false; - if (HasFieldPresence(descriptor_->file())) { - // Attempt to use the state of cached_has_bits, if possible. - int has_bit_index = has_bit_indices_[field->index()]; - if (!field->options().weak() && - cached_has_bit_index == has_bit_index / 32) { - const string mask = StrCat( - strings::Hex(1u << (has_bit_index % 32), - strings::ZERO_PAD_8)); - - printer->Print( - "if (cached_has_bits & 0x$mask$u) {\n", "mask", mask); - } else { - printer->Print( - "if (from.has_$name$()) {\n", - "name", FieldName(field)); - } + // Attempt to use the state of cached_has_bits, if possible. + int has_bit_index = has_bit_indices_[field->index()]; + if (!field->options().weak() && + cached_has_bit_index == has_bit_index / 32) { + const string mask = StrCat( + strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); - printer->Indent(); - have_enclosing_if = true; + format("if (cached_has_bits & 0x$1$u) {\n", mask); } else { - // Merge semantics without true field presence: primitive fields are - // merged only if non-zero (numeric) or non-empty (string). - have_enclosing_if = EmitFieldNonDefaultCondition( - printer, "from.", field); + format("if (from.has_$1$()) {\n", FieldName(field)); } + format.Indent(); if (have_outer_if && IsPOD(field)) { // GenerateCopyConstructorCode for enum and primitive scalar fields @@ -3164,181 +3209,234 @@ GenerateMergeFrom(io::Printer* printer) { generator.GenerateMergingCode(printer); } - if (have_enclosing_if) { - printer->Outdent(); - printer->Print("}\n"); - } + format.Outdent(); + format("}\n"); } if (have_outer_if) { if (deferred_has_bit_changes) { // Flush the has bits for the primitives we deferred. GOOGLE_CHECK_LE(0, cached_has_bit_index); - printer->Print( - "_has_bits_[$index$] |= cached_has_bits;\n", - "index", SimpleItoa(cached_has_bit_index)); + format("_has_bits_[$1$] |= cached_has_bits;\n", cached_has_bit_index); } - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); + } + + if (cold_skipper.OnEndChunk(chunk_index, printer)) { + // Reset here as it may have been updated in just closed if statement. + cached_has_bit_index = -1; + } + } + } else { + // proto3 + for (const auto field : optimized_order_) { + const FieldGenerator& generator = field_generators_.get(field); + // Merge semantics without true field presence: primitive fields are + // merged only if non-zero (numeric) or non-empty (string). + bool have_enclosing_if = + EmitFieldNonDefaultCondition(printer, "from.", field); + + generator.GenerateMergingCode(printer); + + if (have_enclosing_if) { + format.Outdent(); + format("}\n"); } } } // Merge oneof fields. Oneof field requires oneof case check. - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - printer->Print( - "switch (from.$oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); + for (auto oneof : OneOfRange(descriptor_)) { + format("switch (from.$1$_case()) {\n", oneof->name()); + format.Indent(); + for (auto field : FieldRange(oneof)) { + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); field_generators_.get(field).GenerateMergingCode(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); + format("break;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" + format( + "case $1$_NOT_SET: {\n" " break;\n" "}\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "}\n"); + ToUpper(oneof->name())); + format.Outdent(); + format("}\n"); } if (num_weak_fields_) { - printer->Print("_weak_field_map_.MergeFrom(from._weak_field_map_);\n"); + format("_weak_field_map_.MergeFrom(from._weak_field_map_);\n"); } - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateCopyFrom(io::Printer* printer) { +void MessageGenerator::GenerateCopyFrom(io::Printer* printer) { + Formatter format(printer, variables_); if (HasDescriptorMethods(descriptor_->file(), options_)) { // Generate the generalized CopyFrom (aka that which takes in the Message // base class as a parameter). - printer->Print( - "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n" + format( + "void $classname$::CopyFrom(const ::$proto_ns$::Message& from) {\n" "// @@protoc_insertion_point(generalized_copy_from_start:" - "$full_name$)\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); - - printer->Print( - "if (&from == this) return;\n" - "Clear();\n" - "MergeFrom(from);\n"); + "$full_name$)\n"); + format.Indent(); + + format("if (&from == this) return;\n"); + + if (!options_.opensource_runtime) { + // This check is disabled in the opensource release because we're + // concerned that many users do not define NDEBUG in their release + // builds. + format( + "#ifndef NDEBUG\n" + "size_t from_size = from.ByteSizeLong();\n" + "#endif\n" + "Clear();\n" + "#ifndef NDEBUG\n" + "$CHK$_EQ(from_size, from.ByteSizeLong())\n" + " << \"Source of CopyFrom changed when clearing target. Either \"\n" + " << \"source is a nested message in target (not allowed), or \"\n" + " << \"another thread is modifying the source.\";\n" + "#endif\n"); + } else { + format("Clear();\n"); + } + format("MergeFrom(from);\n"); - printer->Outdent(); - printer->Print("}\n\n"); + format.Outdent(); + format("}\n\n"); } // Generate the class-specific CopyFrom. - printer->Print( + format( "void $classname$::CopyFrom(const $classname$& from) {\n" "// @@protoc_insertion_point(class_specific_copy_from_start:" - "$full_name$)\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); - - printer->Print( - "if (&from == this) return;\n" - "Clear();\n" - "MergeFrom(from);\n"); + "$full_name$)\n"); + format.Indent(); + + format("if (&from == this) return;\n"); + + if (!options_.opensource_runtime) { + // This check is disabled in the opensource release because we're + // concerned that many users do not define NDEBUG in their release builds. + format( + "#ifndef NDEBUG\n" + "size_t from_size = from.ByteSizeLong();\n" + "#endif\n" + "Clear();\n" + "#ifndef NDEBUG\n" + "$CHK$_EQ(from_size, from.ByteSizeLong())\n" + " << \"Source of CopyFrom changed when clearing target. Either \"\n" + " << \"source is a nested message in target (not allowed), or \"\n" + " << \"another thread is modifying the source.\";\n" + "#endif\n"); + } else { + format("Clear();\n"); + } + format("MergeFrom(from);\n"); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateMergeFromCodedStream(io::Printer* printer) { - std::map<string, string> vars; +void MessageGenerator::GenerateMergeFromCodedStream(io::Printer* printer) { + std::map<string, string> vars = variables_; SetUnknkownFieldsVariable(descriptor_, options_, &vars); + Formatter format(printer, vars); if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. - vars["classname"] = classname_; - printer->Print(vars, - "bool $classname$::MergePartialFromCodedStream(\n" - " ::google::protobuf::io::CodedInputStream* input) {\n" - " return _extensions_.ParseMessageSet(input,\n" - " internal_default_instance(), $mutable_unknown_fields$);\n" - "}\n"); + format( + "#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n" + "const char* $classname$::_InternalParse(const char* begin, const " + "char* end, void* object,\n" + " ::$proto_ns$::internal::ParseContext* ctx) {\n" + " auto msg = static_cast<$classname$*>(object);\n" + " return ::$proto_ns$::internal::ParseMessageSet(begin, end, " + "msg, &msg->_extensions_, &msg->_internal_metadata_, ctx);\n" + "}\n" + "const char* $classname$::InternalParseMessageSetItem(const char* " + "begin, const char* end, void* object,\n" + " ::$proto_ns$::internal::ParseContext* ctx) {\n" + " auto msg = static_cast<$classname$*>(object);\n" + " return " + "msg->_extensions_.ParseMessageSetItem({InternalParseMessageSetItem, " + "msg}, begin, end, internal_default_instance(), " + "&msg->_internal_metadata_, ctx);\n" + "}\n" + "#else\n" + "bool $classname$::MergePartialFromCodedStream(\n" + " ::$proto_ns$::io::CodedInputStream* input) {\n" + " return _extensions_.ParseMessageSet(input,\n" + " internal_default_instance(), $mutable_unknown_fields$);\n" + "}\n" + "#endif // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"); return; } + format("#if $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"); + GenerateParserLoop(descriptor_, options_, scc_analyzer_, printer); + format("#else // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"); std::vector<const FieldDescriptor*> ordered_fields = SortFieldsByNumber(descriptor_); - printer->Print( - "bool $classname$::MergePartialFromCodedStream(\n" - " ::google::protobuf::io::CodedInputStream* input) {\n", - "classname", classname_); + format( + "bool $classname$::MergePartialFromCodedStream(\n" + " ::$proto_ns$::io::CodedInputStream* input) {\n"); if (table_driven_) { - printer->Indent(); + format.Indent(); - const string lite = UseUnknownFieldSet(descriptor_->file(), options_) ? - "" : "Lite"; + const string lite = + UseUnknownFieldSet(descriptor_->file(), options_) ? "" : "Lite"; - printer->Print( - "return ::google::protobuf::internal::MergePartialFromCodedStream$lite$(\n" - " this,\n" - " ::$file_namespace$::TableStruct::schema[\n" - " $classname$::kIndexInFileMessages],\n" - " input);\n", - "classname", classname_, "file_namespace", - FileLevelNamespace(descriptor_), "lite", lite); + format( + "return ::$proto_ns$::internal::MergePartialFromCodedStream$1$(\n" + " this, ::$tablename$::schema[\n" + " $classname$::kIndexInFileMessages], input);\n", + lite); - printer->Outdent(); + format.Outdent(); - printer->Print("}\n"); + format("}\n"); + format("#endif // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"); return; } if (SupportsArenas(descriptor_)) { - for (int i = 0; i < ordered_fields.size(); i++) { - const FieldDescriptor* field = ordered_fields[i]; + for (auto field : ordered_fields) { const FieldGenerator& field_generator = field_generators_.get(field); if (field_generator.MergeFromCodedStreamNeedsArena()) { - printer->Print( - " ::google::protobuf::Arena* arena = GetArenaNoVirtual();\n"); + format(" ::$proto_ns$::Arena* arena = GetArenaNoVirtual();\n"); break; } } } - printer->Print( - "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto " - "failure\n" - " ::google::protobuf::uint32 tag;\n"); + format( + "#define DO_(EXPRESSION) if " + "(!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure\n" + " $uint32$ tag;\n"); if (!UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print( - " ::google::protobuf::internal::LiteUnknownFieldSetter unknown_fields_setter(\n" + format( + " ::$proto_ns$::internal::LiteUnknownFieldSetter " + "unknown_fields_setter(\n" " &_internal_metadata_);\n" - " ::google::protobuf::io::StringOutputStream unknown_fields_output(\n" + " ::$proto_ns$::io::StringOutputStream unknown_fields_output(\n" " unknown_fields_setter.buffer());\n" - " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" - " &unknown_fields_output, false);\n", - "classname", classname_); + " ::$proto_ns$::io::CodedOutputStream unknown_fields_stream(\n" + " &unknown_fields_output, false);\n"); } - printer->Print( - " // @@protoc_insertion_point(parse_start:$full_name$)\n", - "full_name", descriptor_->full_name()); + format(" // @@protoc_insertion_point(parse_start:$full_name$)\n"); - printer->Indent(); - printer->Print("for (;;) {\n"); - printer->Indent(); + format.Indent(); + format("for (;;) {\n"); + format.Indent(); // To calculate the maximum tag to expect, we look at the highest-numbered // field. We need to be prepared to handle more than one wire type if that @@ -3355,8 +3453,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { bool capture_last_tag = false; const Descriptor* parent = descriptor_->containing_type(); if (parent) { - for (int i = 0; i < parent->field_count(); i++) { - const FieldDescriptor* field = parent->field(i); + for (auto field : FieldRange(parent)) { if (field->type() == FieldDescriptor::TYPE_GROUP && field->message_type() == descriptor_) { capture_last_tag = true; @@ -3383,13 +3480,12 @@ GenerateMergeFromCodedStream(io::Printer* printer) { } } - printer->Print("::std::pair<::google::protobuf::uint32, bool> p = " - "input->ReadTagWithCutoffNoLastTag($max$u);\n" - "tag = p.first;\n" - "if (!p.second) goto handle_unusual;\n", - "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 : - (maxtag <= kCutoff1 ? kCutoff1 : - maxtag))); + format( + "::std::pair<$uint32$, bool> p = " + "input->ReadTagWithCutoffNoLastTag($1$u);\n" + "tag = p.first;\n" + "if (!p.second) goto handle_unusual;\n", + maxtag <= kCutoff0 ? kCutoff0 : (maxtag <= kCutoff1 ? kCutoff1 : maxtag)); if (descriptor_->field_count() > 0) { // We don't even want to print the switch() if we have no fields because @@ -3407,182 +3503,189 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // inserts branches that may fail (especially for real world protos that // interleave--in field number order--hot and cold fields). Loadtests // confirmed that removing this optimization is performance neutral. - printer->Print("switch (::google::protobuf::internal::WireFormatLite::" - "GetTagFieldNumber(tag)) {\n"); - - printer->Indent(); - - for (int i = 0; i < ordered_fields.size(); i++) { - const FieldDescriptor* field = ordered_fields[i]; - - PrintFieldComment(printer, field); + if (num_weak_fields_ > 0) { + format("uint32 weak_offset;\n"); + } + format( + "switch (::$proto_ns$::internal::WireFormatLite::" + "GetTagFieldNumber(tag)) {\n"); + + format.Indent(); + + for (auto field : ordered_fields) { + PrintFieldComment(format, field); + if (IsWeak(field, options_)) { + format( + "case $1$:\n" + " weak_offset = offsetof($classname$DefaultTypeInternal, $2$_);\n" + " goto handle_weak_field_map;\n", + field->number(), FieldName(field)); + continue; + } - printer->Print( - "case $number$: {\n", - "number", SimpleItoa(field->number())); - printer->Indent(); + format("case $1$: {\n", field->number()); + format.Indent(); const FieldGenerator& field_generator = field_generators_.get(field); // Emit code to parse the common, expected case. - printer->Print( - "if (static_cast< ::google::protobuf::uint8>(tag) ==\n" - " static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n", - "truncated", SimpleItoa(WireFormat::MakeTag(field) & 0xFF), - "full", SimpleItoa(WireFormat::MakeTag(field))); + // MSVC is warning about truncating constant in the static_cast so + // we truncate the tag explicitly. + format( + "if (static_cast< $uint8$>(tag) == ($1$ & 0xFF)) {\n", + WireFormat::MakeTag(field)); - printer->Indent(); + format.Indent(); if (field->is_packed()) { field_generator.GenerateMergeFromCodedStreamWithPacking(printer); } else { field_generator.GenerateMergeFromCodedStream(printer); } - printer->Outdent(); + format.Outdent(); // Emit code to parse unexpectedly packed or unpacked values. if (field->is_packed()) { internal::WireFormatLite::WireType wiretype = WireFormat::WireTypeForFieldType(field->type()); - const uint32 tag = internal::WireFormatLite::MakeTag( - field->number(), wiretype); - printer->Print( - "} else if (\n" - " static_cast< ::google::protobuf::uint8>(tag) ==\n" - " static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n", - "truncated", SimpleItoa(tag & 0xFF), - "full", SimpleItoa(tag)); - - printer->Indent(); + const uint32 tag = + internal::WireFormatLite::MakeTag(field->number(), wiretype); + format( + "} else if (static_cast< $uint8$>(tag) == ($1$ & 0xFF)) {\n", + tag); + + format.Indent(); field_generator.GenerateMergeFromCodedStream(printer); - printer->Outdent(); + format.Outdent(); } else if (field->is_packable() && !field->is_packed()) { internal::WireFormatLite::WireType wiretype = internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; - const uint32 tag = internal::WireFormatLite::MakeTag( - field->number(), wiretype); - - printer->Print( - "} else if (\n" - " static_cast< ::google::protobuf::uint8>(tag) ==\n" - " static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n", - "truncated", SimpleItoa(tag & 0xFF), - "full", SimpleItoa(tag)); - printer->Indent(); + const uint32 tag = + internal::WireFormatLite::MakeTag(field->number(), wiretype); + format( + "} else if (static_cast< $uint8$>(tag) == ($1$ & 0xFF)) {\n", + tag); + format.Indent(); field_generator.GenerateMergeFromCodedStreamWithPacking(printer); - printer->Outdent(); + format.Outdent(); } - printer->Print( - "} else {\n" - " goto handle_unusual;\n" - "}\n"); + format( + "} else {\n" + " goto handle_unusual;\n" + "}\n"); - printer->Print( - "break;\n"); + format("break;\n"); - printer->Outdent(); - printer->Print("}\n\n"); + format.Outdent(); + format("}\n\n"); } - printer->Print("default: {\n"); - printer->Indent(); + if (num_weak_fields_ > 0) { + format("handle_weak_field_map: {\n"); + format.Indent(); + + format( + "if ((tag & 0x7) != 2) goto handle_unusual;\n" + "DO_(_weak_field_map_.ReadMessage(input, tag >> 3,\n" + " &_$classname$_default_instance_, weak_offset));\n"); + format("break;\n"); + format.Outdent(); + format("}\n\n"); + } + format("default: {\n"); + format.Indent(); } - printer->Outdent(); - printer->Print("handle_unusual:\n"); - printer->Indent(); + format.Outdent(); + format("handle_unusual:\n"); + format.Indent(); // If tag is 0 or an end-group tag then this must be the end of the message. if (capture_last_tag) { - printer->Print( - "if (tag == 0 ||\n" - " ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" - " ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n" - " input->SetLastTag(tag);\n" - " goto success;\n" - "}\n"); + format( + "if (tag == 0 ||\n" + " ::$proto_ns$::internal::WireFormatLite::GetTagWireType(tag) ==\n" + " ::$proto_ns$::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n" + " input->SetLastTag(tag);\n" + " goto success;\n" + "}\n"); } else { - printer->Print( - "if (tag == 0) {\n" - " goto success;\n" - "}\n"); + format( + "if (tag == 0) {\n" + " goto success;\n" + "}\n"); } // Handle extension ranges. if (descriptor_->extension_range_count() > 0) { - printer->Print( - "if ("); + format("if ("); for (int i = 0; i < descriptor_->extension_range_count(); i++) { - const Descriptor::ExtensionRange* range = - descriptor_->extension_range(i); - if (i > 0) printer->Print(" ||\n "); + const Descriptor::ExtensionRange* range = descriptor_->extension_range(i); + if (i > 0) format(" ||\n "); uint32 start_tag = WireFormatLite::MakeTag( - range->start, static_cast<WireFormatLite::WireType>(0)); + range->start, static_cast<WireFormatLite::WireType>(0)); uint32 end_tag = WireFormatLite::MakeTag( - range->end, static_cast<WireFormatLite::WireType>(0)); + range->end, static_cast<WireFormatLite::WireType>(0)); if (range->end > FieldDescriptor::kMaxNumber) { - printer->Print( - "($start$u <= tag)", - "start", SimpleItoa(start_tag)); + format("($1$u <= tag)", start_tag); } else { - printer->Print( - "($start$u <= tag && tag < $end$u)", - "start", SimpleItoa(start_tag), - "end", SimpleItoa(end_tag)); + format("($1$u <= tag && tag < $2$u)", start_tag, end_tag); } } - printer->Print(") {\n"); + format(") {\n"); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(vars, - " DO_(_extensions_.ParseField(tag, input,\n" - " internal_default_instance(),\n" - " $mutable_unknown_fields$));\n"); + format( + " DO_(_extensions_.ParseField(tag, input,\n" + " internal_default_instance(),\n" + " $mutable_unknown_fields$));\n"); } else { - printer->Print( - " DO_(_extensions_.ParseField(tag, input,\n" - " internal_default_instance(),\n" - " &unknown_fields_stream));\n"); + format( + " DO_(_extensions_.ParseField(tag, input,\n" + " internal_default_instance(),\n" + " &unknown_fields_stream));\n"); } - printer->Print( - " continue;\n" - "}\n"); + format( + " continue;\n" + "}\n"); } // We really don't recognize this tag. Skip it. if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(vars, - "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" + format( + "DO_(::$proto_ns$::internal::WireFormat::SkipField(\n" " input, tag, $mutable_unknown_fields$));\n"); } else { - printer->Print( - "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n" + format( + "DO_(::$proto_ns$::internal::WireFormatLite::SkipField(\n" " input, tag, &unknown_fields_stream));\n"); } if (descriptor_->field_count() > 0) { - printer->Print("break;\n"); - printer->Outdent(); - printer->Print("}\n"); // default: - printer->Outdent(); - printer->Print("}\n"); // switch - } - - printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\n" // for (;;) - "success:\n" - " // @@protoc_insertion_point(parse_success:$full_name$)\n" - " return true;\n" - "failure:\n" - " // @@protoc_insertion_point(parse_failure:$full_name$)\n" - " return false;\n" - "#undef DO_\n" - "}\n", "full_name", descriptor_->full_name()); + format("break;\n"); + format.Outdent(); + format("}\n"); // default: + format.Outdent(); + format("}\n"); // switch + } + + format.Outdent(); + format.Outdent(); + format( + " }\n" // for (;;) + "success:\n" + " // @@protoc_insertion_point(parse_success:$full_name$)\n" + " return true;\n" + "failure:\n" + " // @@protoc_insertion_point(parse_failure:$full_name$)\n" + " return false;\n" + "#undef DO_\n" + "}\n"); + format("#endif // $GOOGLE_PROTOBUF$_ENABLE_EXPERIMENTAL_PARSER\n"); } void MessageGenerator::GenerateSerializeOneofFields( io::Printer* printer, const std::vector<const FieldDescriptor*>& fields, bool to_array) { + Formatter format(printer, variables_); GOOGLE_CHECK(!fields.empty()); if (fields.size() == 1) { GenerateSerializeOneField(printer, fields[0], to_array, -1); @@ -3590,39 +3693,35 @@ void MessageGenerator::GenerateSerializeOneofFields( } // We have multiple mutually exclusive choices. Emit a switch statement. const OneofDescriptor* oneof = fields[0]->containing_oneof(); - printer->Print( - "switch ($oneofname$_case()) {\n", - "oneofname", oneof->name()); - printer->Indent(); - for (int i = 0; i < fields.size(); i++) { - const FieldDescriptor* field = fields[i]; - printer->Print( - "case k$field_name$:\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); + format("switch ($1$_case()) {\n", oneof->name()); + format.Indent(); + for (auto field : fields) { + format("case k$1$:\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); if (to_array) { field_generators_.get(field).GenerateSerializeWithCachedSizesToArray( printer); } else { field_generators_.get(field).GenerateSerializeWithCachedSizes(printer); } - printer->Print( - "break;\n"); - printer->Outdent(); + format("break;\n"); + format.Outdent(); } - printer->Outdent(); + format.Outdent(); // Doing nothing is an option. - printer->Print( - " default: ;\n" - "}\n"); + format( + " default: ;\n" + "}\n"); } -void MessageGenerator::GenerateSerializeOneField( - io::Printer* printer, const FieldDescriptor* field, bool to_array, - int cached_has_bits_index) { +void MessageGenerator::GenerateSerializeOneField(io::Printer* printer, + const FieldDescriptor* field, + bool to_array, + int cached_has_bits_index) { + Formatter format(printer, variables_); if (!field->options().weak()) { // For weakfields, PrintFieldComment is called during iteration. - PrintFieldComment(printer, field); + PrintFieldComment(format, field); } bool have_enclosing_if = false; @@ -3631,19 +3730,15 @@ void MessageGenerator::GenerateSerializeOneField( // Attempt to use the state of cached_has_bits, if possible. int has_bit_index = has_bit_indices_[field->index()]; if (cached_has_bits_index == has_bit_index / 32) { - const string mask = StrCat( - strings::Hex(1u << (has_bit_index % 32), - strings::ZERO_PAD_8)); + const string mask = + StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); - printer->Print( - "if (cached_has_bits & 0x$mask$u) {\n", "mask", mask); + format("if (cached_has_bits & 0x$1$u) {\n", mask); } else { - printer->Print( - "if (has_$name$()) {\n", - "name", FieldName(field)); + format("if (has_$1$()) {\n", FieldName(field)); } - printer->Indent(); + format.Indent(); have_enclosing_if = true; } else if (!HasFieldPresence(descriptor_->file())) { have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field); @@ -3657,10 +3752,10 @@ void MessageGenerator::GenerateSerializeOneField( } if (have_enclosing_if) { - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } - printer->Print("\n"); + format("\n"); } void MessageGenerator::GenerateSerializeOneExtensionRange( @@ -3669,110 +3764,100 @@ void MessageGenerator::GenerateSerializeOneExtensionRange( std::map<string, string> vars; vars["start"] = SimpleItoa(range->start); vars["end"] = SimpleItoa(range->end); - printer->Print(vars, - "// Extension range [$start$, $end$)\n"); + Formatter format(printer, vars); + format("// Extension range [$start$, $end$)\n"); if (to_array) { - printer->Print(vars, - "target = _extensions_.InternalSerializeWithCachedSizesToArray(\n" - " $start$, $end$, deterministic, target);\n\n"); + format( + "target = _extensions_.InternalSerializeWithCachedSizesToArray(\n" + " $start$, $end$, deterministic, target);\n\n"); } else { - printer->Print(vars, - "_extensions_.SerializeWithCachedSizes(\n" - " $start$, $end$, output);\n\n"); + format( + "_extensions_.SerializeWithCachedSizes($start$, $end$, output);\n" + "\n"); } } -void MessageGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) { +void MessageGenerator::GenerateSerializeWithCachedSizes(io::Printer* printer) { + Formatter format(printer, variables_); if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. - printer->Print( - "void $classname$::SerializeWithCachedSizes(\n" - " ::google::protobuf::io::CodedOutputStream* output) const {\n" - " _extensions_.SerializeMessageSetWithCachedSizes(output);\n", - "classname", classname_); - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); + format( + "void $classname$::SerializeWithCachedSizes(\n" + " ::$proto_ns$::io::CodedOutputStream* output) const {\n" + " _extensions_.SerializeMessageSetWithCachedSizes(output);\n"); std::map<string, string> vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); - printer->Print(vars, - " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" - " $unknown_fields$, output);\n"); - printer->Print( - "}\n"); + format.AddMap(vars); + format( + " " + "::$proto_ns$::internal::SerializeUnknownMessageSetItems(\n" + " $unknown_fields$, output);\n"); + format("}\n"); return; } if (options_.table_driven_serialization) return; - printer->Print( - "void $classname$::SerializeWithCachedSizes(\n" - " ::google::protobuf::io::CodedOutputStream* output) const {\n", - "classname", classname_); - printer->Indent(); + format( + "void $classname$::SerializeWithCachedSizes(\n" + " ::$proto_ns$::io::CodedOutputStream* output) const {\n"); + format.Indent(); - printer->Print( - "// @@protoc_insertion_point(serialize_start:$full_name$)\n", - "full_name", descriptor_->full_name()); + format("// @@protoc_insertion_point(serialize_start:$full_name$)\n"); GenerateSerializeWithCachedSizesBody(printer, false); - printer->Print( - "// @@protoc_insertion_point(serialize_end:$full_name$)\n", - "full_name", descriptor_->full_name()); + format("// @@protoc_insertion_point(serialize_end:$full_name$)\n"); - printer->Outdent(); - printer->Print( - "}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { +void MessageGenerator::GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) { + Formatter format(printer, variables_); if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. - printer->Print( - "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesToArray(\n" - " bool deterministic, ::google::protobuf::uint8* target) const {\n" - " target = _extensions_." - "InternalSerializeMessageSetWithCachedSizesToArray(\n" - " deterministic, target);\n", - "classname", classname_); + format( + "$uint8$* $classname$::InternalSerializeWithCachedSizesToArray(\n" + " bool deterministic, $uint8$* target) const {\n" + " target = _extensions_." + "InternalSerializeMessageSetWithCachedSizesToArray(\n" + " deterministic, target);\n"); GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); std::map<string, string> vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); - printer->Print(vars, - " target = ::google::protobuf::internal::WireFormat::\n" - " SerializeUnknownMessageSetItemsToArray(\n" - " $unknown_fields$, target);\n"); - printer->Print( - " return target;\n" - "}\n"); + format.AddMap(vars); + format( + " target = ::$proto_ns$::internal::WireFormat::\n" + " SerializeUnknownMessageSetItemsToArray(\n" + " $unknown_fields$, target);\n"); + format( + " return target;\n" + "}\n"); return; } - printer->Print( - "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesToArray(\n" - " bool deterministic, ::google::protobuf::uint8* target) const {\n", - "classname", classname_); - printer->Indent(); + format( + "$uint8$* $classname$::InternalSerializeWithCachedSizesToArray(\n" + " bool deterministic, $uint8$* target) const {\n"); + format.Indent(); - printer->Print("(void)deterministic; // Unused\n"); - printer->Print( - "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", - "full_name", descriptor_->full_name()); + format("(void)deterministic; // Unused\n"); + format("// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n"); GenerateSerializeWithCachedSizesBody(printer, true); - printer->Print( - "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n", - "full_name", descriptor_->full_name()); + format("// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n"); - printer->Outdent(); - printer->Print( - " return target;\n" - "}\n"); + format.Outdent(); + format( + " return target;\n" + "}\n"); } -void MessageGenerator:: -GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { +void MessageGenerator::GenerateSerializeWithCachedSizesBody( + io::Printer* printer, bool to_array) { + Formatter format(printer, variables_); // If there are multiple fields in a row from the same oneof then we // coalesce them and emit a switch statement. This is more efficient // because it lets the C++ compiler know this is a "at most one can happen" @@ -3783,7 +3868,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer, bool to_array) : mg_(mg), - printer_(printer), + format_(printer), to_array_(to_array), eager_(!HasFieldPresence(mg->descriptor_->file())), cached_has_bit_index_(-1) {} @@ -3808,16 +3893,14 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { // Reload. int new_index = has_bit_index / 32; - printer_->Print( - "cached_has_bits = _has_bits_[$new_index$];\n", - "new_index", SimpleItoa(new_index)); + format_("cached_has_bits = _has_bits_[$1$];\n", new_index); cached_has_bit_index_ = new_index; } } - mg_->GenerateSerializeOneField( - printer_, field, to_array_, cached_has_bit_index_); + mg_->GenerateSerializeOneField(format_.printer(), field, to_array_, + cached_has_bit_index_); } else { v_.push_back(field); } @@ -3825,7 +3908,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { void Flush() { if (!v_.empty()) { - mg_->GenerateSerializeOneofFields(printer_, v_, to_array_); + mg_->GenerateSerializeOneofFields(format_.printer(), v_, to_array_); v_.clear(); } } @@ -3839,7 +3922,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { } MessageGenerator* mg_; - io::Printer* printer_; + Formatter format_; const bool to_array_; const bool eager_; std::vector<const FieldDescriptor*> v_; @@ -3860,13 +3943,13 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { std::sort(sorted_extensions.begin(), sorted_extensions.end(), ExtensionRangeSorter()); if (num_weak_fields_) { - printer->Print( - "::google::protobuf::internal::WeakFieldMap::FieldWriter field_writer(" + format( + "::$proto_ns$::internal::WeakFieldMap::FieldWriter field_writer(" "_weak_field_map_);\n"); } - printer->Print( - "::google::protobuf::uint32 cached_has_bits = 0;\n" + format( + "$uint32$ cached_has_bits = 0;\n" "(void) cached_has_bits;\n\n"); // Merge the fields and the extension ranges, both sorted by field number. @@ -3882,7 +3965,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { const FieldDescriptor* field = ordered_fields[i++]; if (field->options().weak()) { last_weak_field = field; - PrintFieldComment(printer, field); + PrintFieldComment(format, field); } else { if (last_weak_field != nullptr) { e.Emit(last_weak_field); @@ -3890,14 +3973,13 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { } e.Emit(field); } - } else { + } else { if (last_weak_field != nullptr) { e.Emit(last_weak_field); last_weak_field = nullptr; } e.Flush(); - GenerateSerializeOneExtensionRange(printer, - sorted_extensions[j++], + GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++], to_array); } } @@ -3908,27 +3990,27 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { std::map<string, string> vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(vars, - "if ($have_unknown_fields$) {\n"); - printer->Indent(); + format("if ($have_unknown_fields$) {\n"); + format.Indent(); if (to_array) { - printer->Print(vars, - "target = " - "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n" - " $unknown_fields$, target);\n"); + format( + "target = " + "::$proto_ns$::internal::WireFormat::SerializeUnknownFieldsToArray(\n" + " $unknown_fields$, target);\n"); } else { - printer->Print(vars, - "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" - " $unknown_fields$, output);\n"); + format( + "::$proto_ns$::internal::WireFormat::SerializeUnknownFields(\n" + " $unknown_fields$, output);\n"); } - printer->Outdent(); + format.Outdent(); - printer->Print("}\n"); + format("}\n"); } else { - printer->Print(vars, - "output->WriteRaw($unknown_fields$.data(),\n" - " static_cast<int>($unknown_fields$.size()));\n"); + format( + "output->WriteRaw($unknown_fields$.data(),\n" + " static_cast<int>($unknown_fields$.size()));\n"); } } @@ -3936,15 +4018,13 @@ std::vector<uint32> MessageGenerator::RequiredFieldsBitMask() const { const int array_size = HasBitsSize(); std::vector<uint32> masks(array_size, 0); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); + for (auto field : FieldRange(descriptor_)) { if (!field->is_required()) { continue; } const int has_bit_index = has_bit_indices_[field->index()]; - masks[has_bit_index / 32] |= - static_cast<uint32>(1) << (has_bit_index % 32); + masks[has_bit_index / 32] |= static_cast<uint32>(1) << (has_bit_index % 32); } return masks; } @@ -3959,35 +4039,36 @@ static string ConditionalToCheckBitmasks(const std::vector<uint32>& masks) { if (masks[i] == 0) continue; string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); // Each xor evaluates to 0 if the expected bits are present. - parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); + parts.push_back( + StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); } GOOGLE_CHECK(!parts.empty()); // If we have multiple parts, each expected to be 0, then bitwise-or them. - string result = parts.size() == 1 - ? parts[0] - : StrCat("(", Join(parts, "\n | "), ")"); + string result = + parts.size() == 1 + ? parts[0] + : StrCat("(", Join(parts, "\n | "), ")"); return result + " == 0"; } -void MessageGenerator:: -GenerateByteSize(io::Printer* printer) { +void MessageGenerator::GenerateByteSize(io::Printer* printer) { + Formatter format(printer, variables_); + if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. - GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); std::map<string, string> vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); - vars["classname"] = classname_; - vars["full_name"] = descriptor_->full_name(); - printer->Print( - vars, + format.AddMap(vars); + format( "size_t $classname$::ByteSizeLong() const {\n" "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n" " size_t total_size = _extensions_.MessageSetByteSize();\n" " if ($have_unknown_fields$) {\n" - " total_size += ::google::protobuf::internal::WireFormat::\n" + " total_size += ::$proto_ns$::internal::\n" " ComputeUnknownMessageSetItemsSize($unknown_fields$);\n" " }\n" - " int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n" + " int cached_size = " + "::$proto_ns$::internal::ToCachedSize(total_size);\n" " SetCachedSize(cached_size);\n" " return total_size;\n" "}\n"); @@ -3997,60 +4078,60 @@ GenerateByteSize(io::Printer* printer) { if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { // Emit a function (rarely used, we hope) that handles the required fields // by checking for each one individually. - printer->Print( + format( "size_t $classname$::RequiredFieldsByteSizeFallback() const {\n" "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:" - "$full_name$)\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); - printer->Print("size_t total_size = 0;\n"); - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + "$full_name$)\n"); + format.Indent(); + format("size_t total_size = 0;\n"); + for (auto field : optimized_order_) { if (field->is_required()) { - printer->Print("\n" - "if (has_$name$()) {\n", - "name", FieldName(field)); - printer->Indent(); - PrintFieldComment(printer, field); + format( + "\n" + "if (has_$1$()) {\n", + FieldName(field)); + format.Indent(); + PrintFieldComment(format, field); field_generators_.get(field).GenerateByteSize(printer); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } } - printer->Print("\n" - "return total_size;\n"); - printer->Outdent(); - printer->Print("}\n"); + format( + "\n" + "return total_size;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( + format( "size_t $classname$::ByteSizeLong() const {\n" - "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n", - "classname", classname_, "full_name", descriptor_->full_name()); - printer->Indent(); - printer->Print( - "size_t total_size = 0;\n" - "\n"); + "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n"); + format.Indent(); + format( + "size_t total_size = 0;\n" + "\n"); if (descriptor_->extension_range_count() > 0) { - printer->Print( - "total_size += _extensions_.ByteSize();\n" - "\n"); + format( + "total_size += _extensions_.ByteSize();\n" + "\n"); } std::map<string, string> vars; SetUnknkownFieldsVariable(descriptor_, options_, &vars); + format.AddMap(vars); if (UseUnknownFieldSet(descriptor_->file(), options_)) { - printer->Print(vars, - "if ($have_unknown_fields$) {\n" - " total_size +=\n" - " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n" - " $unknown_fields$);\n" - "}\n"); + format( + "if ($have_unknown_fields$) {\n" + " total_size +=\n" + " ::$proto_ns$::internal::WireFormat::ComputeUnknownFieldsSize(\n" + " $unknown_fields$);\n" + "}\n"); } else { - printer->Print(vars, - "total_size += $unknown_fields$.size();\n" - "\n"); + format( + "total_size += $unknown_fields$.size();\n" + "\n"); } // Handle required fields (if any). We expect all of them to be @@ -4059,35 +4140,32 @@ GenerateByteSize(io::Printer* printer) { if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { // The fast path works if all required fields are present. const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(); - printer->Print((string("if (") + - ConditionalToCheckBitmasks(masks_for_has_bits) + - ") { // All required fields are present.\n").c_str()); - printer->Indent(); + format("if ($1$) { // All required fields are present.\n", + ConditionalToCheckBitmasks(masks_for_has_bits)); + format.Indent(); // Oneof fields cannot be required, so optimized_order_ contains all of the // fields that we need to potentially emit. - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { if (!field->is_required()) continue; - PrintFieldComment(printer, field); + PrintFieldComment(format, field); field_generators_.get(field).GenerateByteSize(printer); - printer->Print("\n"); + format("\n"); } - printer->Outdent(); - printer->Print("} else {\n" // the slow path - " total_size += RequiredFieldsByteSizeFallback();\n" - "}\n"); + format.Outdent(); + format( + "} else {\n" // the slow path + " total_size += RequiredFieldsByteSizeFallback();\n" + "}\n"); } else { // num_required_fields_ <= 1: no need to be tricky - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { if (!field->is_required()) continue; - PrintFieldComment(printer, field); - printer->Print("if (has_$name$()) {\n", - "name", FieldName(field)); - printer->Indent(); + PrintFieldComment(format, field); + format("if (has_$1$()) {\n", FieldName(field)); + format.Indent(); field_generators_.get(field).GenerateByteSize(printer); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } } @@ -4100,6 +4178,16 @@ GenerateByteSize(io::Printer* printer) { chunks.erase(std::remove_if(chunks.begin(), chunks.end(), IsRequired), chunks.end()); + ColdChunkSkipper cold_skipper(options_, chunks, has_bit_indices_, kColdRatio, + HasFieldPresence(descriptor_->file())); + + format( + "$uint32$ cached_has_bits = 0;\n" + "// Prevent compiler warnings about cached_has_bits being unused\n" + "(void) cached_has_bits;\n\n"); + + int cached_has_bit_index = -1; + for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index]; GOOGLE_CHECK(!chunk.empty()); @@ -4109,14 +4197,16 @@ GenerateByteSize(io::Printer* printer) { for (int i = 0; i < chunk.size(); i++) { const FieldDescriptor* field = chunk[i]; - PrintFieldComment(printer, field); + PrintFieldComment(format, field); const FieldGenerator& generator = field_generators_.get(field); generator.GenerateByteSize(printer); - printer->Print("\n"); + format("\n"); } continue; } + cold_skipper.OnStartChunk(chunk_index, cached_has_bit_index, "", printer); + // Handle optional (non-repeated/oneof) fields. // // These are handled in chunks of 8. The first chunk is @@ -4144,10 +4234,13 @@ GenerateByteSize(io::Printer* printer) { GOOGLE_DCHECK_LE(2, count); GOOGLE_DCHECK_GE(8, count); - printer->Print("if (_has_bits_[$index$ / 32] & $mask$u) {\n", "index", - SimpleItoa(last_chunk * 8), "mask", - SimpleItoa(last_chunk_mask)); - printer->Indent(); + if (cached_has_bit_index != last_chunk / 4) { + cached_has_bit_index = last_chunk / 4; + format("cached_has_bits = _has_bits_[$1$];\n", cached_has_bit_index); + } + format("if (cached_has_bits & 0x$1$u) {\n", + StrCat(strings::Hex(last_chunk_mask, strings::ZERO_PAD_8))); + format.Indent(); } // Go back and emit checks for each of the fields we processed. @@ -4155,12 +4248,12 @@ GenerateByteSize(io::Printer* printer) { const FieldDescriptor* field = chunk[j]; const FieldGenerator& generator = field_generators_.get(field); - PrintFieldComment(printer, field); + PrintFieldComment(format, field); bool have_enclosing_if = false; if (HasFieldPresence(descriptor_->file())) { - printer->Print("if (has_$name$()) {\n", "name", FieldName(field)); - printer->Indent(); + PrintPresenceCheck(format, field, has_bit_indices_, printer, + &cached_has_bit_index); have_enclosing_if = true; } else { // Without field presence: field is serialized only if it has a @@ -4172,54 +4265,50 @@ GenerateByteSize(io::Printer* printer) { generator.GenerateByteSize(printer); if (have_enclosing_if) { - printer->Outdent(); - printer->Print( + format.Outdent(); + format( "}\n" "\n"); } } if (have_outer_if) { - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); + } + + if (cold_skipper.OnEndChunk(chunk_index, printer)) { + // Reset here as it may have been updated in just closed if statement. + cached_has_bit_index = -1; } } // Fields inside a oneof don't use _has_bits_ so we count them in a separate // pass. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "switch ($oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - PrintFieldComment(printer, field); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); + for (auto oneof : OneOfRange(descriptor_)) { + format("switch ($1$_case()) {\n", oneof->name()); + format.Indent(); + for (auto field : FieldRange(oneof)) { + PrintFieldComment(format, field); + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); field_generators_.get(field).GenerateByteSize(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); + format("break;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" + format( + "case $1$_NOT_SET: {\n" " break;\n" "}\n", - "cap_oneof_name", - ToUpper(descriptor_->oneof_decl(i)->name())); - printer->Outdent(); - printer->Print( - "}\n"); + ToUpper(oneof->name())); + format.Outdent(); + format("}\n"); } if (num_weak_fields_) { // TagSize + MessageSize - printer->Print("total_size += _weak_field_map_.ByteSizeLong();\n"); + format("total_size += _weak_field_map_.ByteSizeLong();\n"); } // We update _cached_size_ even though this is a const method. Because @@ -4230,27 +4319,25 @@ GenerateByteSize(io::Printer* printer) { // the underlying atomic. This makes it easier on platforms where even relaxed // memory order might have perf impact to replace it with ordinary loads and // stores. - printer->Print( - "int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n" + format( + "int cached_size = ::$proto_ns$::internal::ToCachedSize(total_size);\n" "SetCachedSize(cached_size);\n" "return total_size;\n"); - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } -void MessageGenerator:: -GenerateIsInitialized(io::Printer* printer) { - printer->Print( - "bool $classname$::IsInitialized() const {\n", - "classname", classname_); - printer->Indent(); +void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { + Formatter format(printer, variables_); + format("bool $classname$::IsInitialized() const {\n"); + format.Indent(); if (descriptor_->extension_range_count() > 0) { - printer->Print( - "if (!_extensions_.IsInitialized()) {\n" - " return false;\n" - "}\n\n"); + format( + "if (!_extensions_.IsInitialized()) {\n" + " return false;\n" + "}\n\n"); } if (HasFieldPresence(descriptor_->file())) { @@ -4267,57 +4354,51 @@ GenerateIsInitialized(io::Printer* printer) { // TODO(ckennelly): Consider doing something similar to ByteSizeLong(), // where we check all of the required fields in a single branch (assuming // that we aren't going to benefit from early termination). - printer->Print( - "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n", - "i", SimpleItoa(i), - "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8))); + format("if ((_has_bits_[$1$] & 0x$2$) != 0x$2$) return false;\n", + i, // 1 + StrCat(strings::Hex(mask, strings::ZERO_PAD_8))); // 2 } } // Now check that all non-oneof embedded messages are initialized. - for (int i = 0; i < optimized_order_.size(); i++) { - const FieldDescriptor* field = optimized_order_[i]; + for (auto field : optimized_order_) { // TODO(ckennelly): Push this down into a generator? if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !ShouldIgnoreRequiredFieldCheck(field, options_) && scc_analyzer_->HasRequiredFields(field->message_type())) { if (field->is_repeated()) { if (IsImplicitWeakField(field, options_, scc_analyzer_)) { - printer->Print( - "if (!::google::protobuf::internal::AllAreInitializedWeak(this->$name$_))" - " return false;\n", - "name", FieldName(field)); + format( + "if (!::$proto_ns$::internal::AllAreInitializedWeak(this->$1$_))" + " return false;\n", + FieldName(field)); } else { - printer->Print( - "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))" - " return false;\n", - "name", FieldName(field)); + format( + "if (!::$proto_ns$::internal::AllAreInitialized(this->$1$()))" + " return false;\n", + FieldName(field)); } } else if (field->options().weak()) { continue; } else { GOOGLE_CHECK(!field->containing_oneof()); - printer->Print( - "if (has_$name$()) {\n" - " if (!this->$name$_->IsInitialized()) return false;\n" + format( + "if (has_$1$()) {\n" + " if (!this->$1$_->IsInitialized()) return false;\n" "}\n", - "name", FieldName(field)); + FieldName(field)); } } } if (num_weak_fields_) { // For Weak fields. - printer->Print("if (!_weak_field_map_.IsInitialized()) return false;\n"); + format("if (!_weak_field_map_.IsInitialized()) return false;\n"); } // Go through the oneof fields, emitting a switch if any might have required // fields. - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - const OneofDescriptor* oneof = descriptor_->oneof_decl(i); - + for (auto oneof : OneOfRange(descriptor_)) { bool has_required_fields = false; - for (int j = 0; j < oneof->field_count(); j++) { - const FieldDescriptor* field = oneof->field(j); - + for (auto field : FieldRange(oneof)) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !ShouldIgnoreRequiredFieldCheck(field, options_) && scc_analyzer_->HasRequiredFields(field->message_type())) { @@ -4330,16 +4411,11 @@ GenerateIsInitialized(io::Printer* printer) { continue; } - printer->Print( - "switch ($oneofname$_case()) {\n", - "oneofname", oneof->name()); - printer->Indent(); - for (int j = 0; j < oneof->field_count(); j++) { - const FieldDescriptor* field = oneof->field(j); - printer->Print( - "case k$field_name$: {\n", - "field_name", UnderscoresToCamelCase(field->name(), true)); - printer->Indent(); + format("switch ($1$_case()) {\n", oneof->name()); + format.Indent(); + for (auto field : FieldRange(oneof)) { + format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); + format.Indent(); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !ShouldIgnoreRequiredFieldCheck(field, options_) && @@ -4348,35 +4424,31 @@ GenerateIsInitialized(io::Printer* printer) { if (field->options().weak()) { // Just skip. } else { - printer->Print( - "if (has_$name$()) {\n" - " if (!this->$name$().IsInitialized()) return false;\n" - "}\n", - "name", FieldName(field)); + format( + "if (has_$1$()) {\n" + " if (!this->$1$().IsInitialized()) return false;\n" + "}\n", + FieldName(field)); } } - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); + format("break;\n"); + format.Outdent(); + format("}\n"); } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" + format( + "case $1$_NOT_SET: {\n" " break;\n" "}\n", - "cap_oneof_name", ToUpper(oneof->name())); - printer->Outdent(); - printer->Print( - "}\n"); + format.Outdent(); + format("}\n"); } - printer->Outdent(); - printer->Print( - " return true;\n" - "}\n"); + format.Outdent(); + format( + " return true;\n" + "}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index ca2ca2c9..6bef8d56 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -45,37 +45,33 @@ namespace google { namespace protobuf { - namespace io { - class Printer; // printer.h - } +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { -class EnumGenerator; // enum.h -class ExtensionGenerator; // extension.h +class EnumGenerator; // enum.h +class ExtensionGenerator; // extension.h class MessageGenerator { public: // See generator.cc for the meaning of dllexport_decl. - MessageGenerator(const Descriptor* descriptor, int index_in_file_messages, - const Options& options, SCCAnalyzer* scc_analyzer); + MessageGenerator(const Descriptor* descriptor, + const std::map<std::string, std::string>& vars, + int index_in_file_messages, const Options& options, + MessageSCCAnalyzer* scc_analyzer); ~MessageGenerator(); // Append the two types of nested generators to the corresponding vector. - void AddGenerators(std::vector<EnumGenerator*>* enum_generators, - std::vector<ExtensionGenerator*>* extension_generators); - - // Header stuff. - - // Return names for forward declarations of this class and all its nested - // types. A given key in {class,enum}_names will map from a class name to the - // descriptor that was responsible for its inclusion in the map. This can be - // used to associate the descriptor with the code generated for it. - void FillMessageForwardDeclarations( - std::map<string, const Descriptor*>* class_names); + void AddGenerators( + std::vector<std::unique_ptr<EnumGenerator>>* enum_generators, + std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators); // Generate definitions for this class and all its nested types. void GenerateClassDefinition(io::Printer* printer); @@ -112,8 +108,8 @@ class MessageGenerator { // generated. size_t GenerateParseOffsets(io::Printer* printer); size_t GenerateParseAuxTable(io::Printer* printer); - // Generates a ParseTable entry. Returns whether the proto uses table-driven - // parsing. + // Generates a ParseTable entry. Returns whether the proto uses + // table-driven parsing. bool GenerateParseTable(io::Printer* printer, size_t offset, size_t aux_offset); @@ -140,8 +136,8 @@ class MessageGenerator { void GenerateArenaDestructorCode(io::Printer* printer); // Helper for GenerateClear and others. Optionally emits a condition that - // assumes the existence of the cached_has_bits variable, and returns true if - // the condition was printed. + // assumes the existence of the cached_has_bits variable, and returns true + // if the condition was printed. bool MaybeGenerateOptionalFieldCondition(io::Printer* printer, const FieldDescriptor* field, int expected_has_bits_index); @@ -166,8 +162,7 @@ class MessageGenerator { // cached_has_bits = _has_bits_[cached_has_bit_index] // for cached_has_bit_index >= 0 void GenerateSerializeOneField(io::Printer* printer, - const FieldDescriptor* field, - bool unbounded, + const FieldDescriptor* field, bool unbounded, int cached_has_bits_index); // Generate a switch statement to serialize 2+ fields from the same oneof. // Or, if fields.size() == 1, just call GenerateSerializeOneField(). @@ -180,19 +175,15 @@ class MessageGenerator { // Generates has_foo() functions and variables for singular field has-bits. void GenerateSingularFieldHasBits(const FieldDescriptor* field, - std::map<string, string> vars, - io::Printer* printer); + Formatter format); // Generates has_foo() functions and variables for oneof field has-bits. void GenerateOneofHasBits(io::Printer* printer); // Generates has_foo_bar() functions for oneof members. void GenerateOneofMemberHasBits(const FieldDescriptor* field, - const std::map<string, string>& vars, - io::Printer* printer); + const Formatter& format); // Generates the clear_foo() method for a field. - void GenerateFieldClear(const FieldDescriptor* field, - const std::map<string, string>& vars, - bool is_inline, - io::Printer* printer); + void GenerateFieldClear(const FieldDescriptor* field, bool is_inline, + Formatter format); void GenerateConstructorBody(io::Printer* printer, std::vector<bool> already_processed, @@ -203,18 +194,19 @@ class MessageGenerator { const Descriptor* descriptor_; int index_in_file_messages_; - string classname_; + std::string classname_; Options options_; FieldGeneratorMap field_generators_; - // optimized_order_ is the order we layout the message's fields in the class. - // This is reused to initialize the fields in-order for cache efficiency. + // optimized_order_ is the order we layout the message's fields in the + // class. This is reused to initialize the fields in-order for cache + // efficiency. // // optimized_order_ excludes oneof fields and weak fields. - std::vector<const FieldDescriptor *> optimized_order_; + std::vector<const FieldDescriptor*> optimized_order_; std::vector<int> has_bit_indices_; int max_has_bit_index_; - std::unique_ptr<std::unique_ptr<EnumGenerator> []> enum_generators_; - std::unique_ptr<std::unique_ptr<ExtensionGenerator> []> extension_generators_; + std::vector<const EnumGenerator*> enum_generators_; + std::vector<const ExtensionGenerator*> extension_generators_; int num_required_fields_; int num_weak_fields_; // table_driven_ indicates the generated message uses table-driven parsing. @@ -222,8 +214,9 @@ class MessageGenerator { std::unique_ptr<MessageLayoutHelper> message_layout_helper_; - SCCAnalyzer* scc_analyzer_; - string scc_name_; + MessageSCCAnalyzer* scc_analyzer_; + + std::map<std::string, std::string> variables_; friend class FileGenerator; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); @@ -232,6 +225,6 @@ class MessageGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index c1e15c52..afb27273 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -101,9 +101,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor, MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, const Options& options, - SCCAnalyzer* scc_analyzer) - : FieldGenerator(options), - descriptor_(descriptor), + MessageSCCAnalyzer* scc_analyzer) + : FieldGenerator(descriptor, options), implicit_weak_field_( IsImplicitWeakField(descriptor, options, scc_analyzer)) { SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_); @@ -113,364 +112,388 @@ MessageFieldGenerator::~MessageFieldGenerator() {} void MessageFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { + Formatter format(printer, variables_); if (implicit_weak_field_) { - printer->Print(variables_, "::google::protobuf::MessageLite* $name$_;\n"); + format("::$proto_ns$::MessageLite* $name$_;\n"); } else { - printer->Print(variables_, "$type$* $name$_;\n"); + format("$type$* $name$_;\n"); } } void MessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { - if (implicit_weak_field_) { - // These private accessors are used by MergeFrom and - // MergePartialFromCodedStream, and their purpose is to provide access to - // the field without creating a strong dependency on the message type. - printer->Print(variables_, - "private:\n" - "const ::google::protobuf::MessageLite& _internal_$name$() const;\n" - "::google::protobuf::MessageLite* _internal_mutable_$name$();\n" - "public:\n"); - } else { - // This inline accessor directly returns member field and is used in - // Serialize such that AFDO profile correctly captures access information to - // message fields under serialize. - printer->Print(variables_, - "private:\n" - "const $type$& _internal_$name$() const;\n" - "public:\n"); - } - printer->Print(variables_, - "$deprecated_attr$const $type$& $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, "$deprecated_attr$$type$* $release_name$();\n"); - printer->Annotate("release_name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$$type$* ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_allocated_$name$$}$" - "($type$* $name$);\n"); - printer->Annotate("{", "}", descriptor_); + Formatter format(printer, variables_); + format( + "$deprecated_attr$const $type$& ${1$$name$$}$() const;\n" + "$deprecated_attr$$type$* ${1$$release_name$$}$();\n" + "$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n" + "$deprecated_attr$void ${1$set_allocated_$name$$}$" + "($type$* $name$);\n", + descriptor_); if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "$deprecated_attr$void " - "${$unsafe_arena_set_allocated_$name$$}$(\n" - " $type$* $name$);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$$type$* ${$unsafe_arena_release_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); + format( + "$deprecated_attr$void " + "${1$unsafe_arena_set_allocated_$name$$}$(\n" + " $type$* $name$);\n" + "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$();\n", + descriptor_); } } void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( io::Printer* printer) const { - if (implicit_weak_field_) { - printer->Print(variables_, - "const ::google::protobuf::MessageLite& $classname$::_internal_$name$() const {\n" - " if ($name$_ != NULL) {\n" - " return *$name$_;\n" - " } else if (&$type_default_instance$ != NULL) {\n" - " return *reinterpret_cast<const ::google::protobuf::MessageLite*>(\n" - " &$type_default_instance$);\n" - " } else {\n" - " return " - "*::google::protobuf::internal::ImplicitWeakMessage::default_instance();\n" - " }\n" - "}\n"); - } + Formatter format(printer, variables_); if (SupportsArenas(descriptor_)) { - if (implicit_weak_field_) { - printer->Print(variables_, - "::google::protobuf::MessageLite* $classname$::_internal_mutable_$name$() {\n" - " $set_hasbit$\n" - " if ($name$_ == NULL) {\n" - " if (&$type_default_instance$ == NULL) {\n" - " $name$_ = ::google::protobuf::Arena::CreateMessage<\n" - " ::google::protobuf::internal::ImplicitWeakMessage>(\n" - " GetArenaNoVirtual());\n" - " } else {\n" - " $name$_ = reinterpret_cast<const ::google::protobuf::MessageLite*>(\n" - " &$type_default_instance$)->New(GetArenaNoVirtual());\n" - " }\n" + format( + "void $classname$::unsafe_arena_set_allocated_$name$(\n" + " $type$* $name$) {\n" + // If we're not on an arena, free whatever we were holding before. + // (If we are on arena, we can just forget the earlier pointer.) + " if (GetArenaNoVirtual() == NULL) {\n" + " delete $name$_;\n" " }\n" - " return $name$_;\n" - "}\n"); - } - - printer->Print(variables_, - "void $classname$::unsafe_arena_set_allocated_$name$(\n" - " $type$* $name$) {\n" - // If we're not on an arena, free whatever we were holding before. - // (If we are on arena, we can just forget the earlier pointer.) - " if (GetArenaNoVirtual() == NULL) {\n" - " delete $name$_;\n" - " }\n" - " $name$_ = $name$;\n" - " if ($name$) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" - ":$full_name$)\n" - "}\n"); - } else if (implicit_weak_field_) { - printer->Print(variables_, - "::google::protobuf::MessageLite* $classname$::_internal_mutable_$name$() {\n" - " $set_hasbit$\n" - " if ($name$_ == NULL) {\n" - " if (&$type_default_instance$ == NULL) {\n" - " $name$_ = new ::google::protobuf::internal::ImplicitWeakMessage;\n" - " } else {\n" - " $name$_ = reinterpret_cast<const ::google::protobuf::MessageLite*>(\n" - " &$type_default_instance$)->New();\n" - " }\n" + " $name$_ = $name$;\n" + " if ($name$) {\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" " }\n" - " return $name$_;\n" + " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" + ":$full_name$)\n" "}\n"); } } void MessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { - if (!implicit_weak_field_) { - printer->Print(variables_, - "inline const $type$& $classname$::_internal_$name$() const {\n" - " return *$field_member$;\n" + Formatter format(printer, variables_); + format( + "inline const $type$& $classname$::$name$() const {\n" + " const $type$* p = $casted_member$;\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return p != NULL ? *p : *reinterpret_cast<const $type$*>(\n" + " &$type_default_instance$);\n" "}\n"); - } - printer->Print(variables_, - "inline const $type$& $classname$::$name$() const {\n" - " const $type$* p = $casted_member$;\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return p != NULL ? *p : *reinterpret_cast<const $type$*>(\n" - " &$type_default_instance$);\n" - "}\n"); - - printer->Print(variables_, - "inline $type$* $classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - "$type_reference_function$" - " $clear_hasbit$\n" - " $type$* temp = $casted_member$;\n"); - if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - " if (GetArenaNoVirtual() != NULL) {\n" - " temp = ::google::protobuf::internal::DuplicateIfNonNull(temp);\n" - " }\n"); - } - printer->Print(variables_, - " $name$_ = NULL;\n" - " return temp;\n" - "}\n"); - if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" - " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" + format( + "inline $type$* $classname$::$release_name$() {\n" + " // @@protoc_insertion_point(field_release:$full_name$)\n" "$type_reference_function$" " $clear_hasbit$\n" - " $type$* temp = $casted_member$;\n" + " $type$* temp = $casted_member$;\n"); + if (SupportsArenas(descriptor_)) { + format( + " if (GetArenaNoVirtual() != NULL) {\n" + " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n" + " }\n"); + } + format( " $name$_ = NULL;\n" " return temp;\n" "}\n"); + + if (SupportsArenas(descriptor_)) { + format( + "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" + " // " + "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" + "$type_reference_function$" + " $clear_hasbit$\n" + " $type$* temp = $casted_member$;\n" + " $name$_ = NULL;\n" + " return temp;\n" + "}\n"); } - printer->Print(variables_, - "inline $type$* $classname$::mutable_$name$() {\n" - " $set_hasbit$\n" - " if ($name$_ == NULL) {\n" - " auto* p = CreateMaybeMessage<$type$>(GetArenaNoVirtual());\n"); + format( + "inline $type$* $classname$::mutable_$name$() {\n" + " $set_hasbit$\n" + " if ($name$_ == NULL) {\n" + " auto* p = CreateMaybeMessage<$type$>(GetArenaNoVirtual());\n"); if (implicit_weak_field_) { - printer->Print(variables_, - " $name$_ = reinterpret_cast<::google::protobuf::MessageLite*>(p);\n"); + format(" $name$_ = reinterpret_cast<::$proto_ns$::MessageLite*>(p);\n"); } else { - printer->Print(variables_, - " $name$_ = p;\n"); + format(" $name$_ = p;\n"); } - printer->Print(variables_, - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $casted_member$;\n" - "}\n"); + format( + " }\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return $casted_member$;\n" + "}\n"); // We handle the most common case inline, and delegate less common cases to // the slow fallback function. - printer->Print(variables_, - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" - " ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"); - printer->Print(variables_, - " if (message_arena == NULL) {\n"); + format( + "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + " ::$proto_ns$::Arena* message_arena = GetArenaNoVirtual();\n"); + format(" if (message_arena == NULL) {\n"); if (IsCrossFileMessage(descriptor_)) { - printer->Print(variables_, - " delete reinterpret_cast< ::google::protobuf::MessageLite*>($name$_);\n"); + format( + " delete reinterpret_cast< ::$proto_ns$::MessageLite*>($name$_);\n"); } else { - printer->Print(variables_, - " delete $name$_;\n"); + format(" delete $name$_;\n"); } - printer->Print(variables_, - " }\n" - " if ($name$) {\n"); + format( + " }\n" + " if ($name$) {\n"); if (SupportsArenas(descriptor_->message_type()) && IsCrossFileMessage(descriptor_)) { // We have to read the arena through the virtual method, because the type // isn't defined in this file. - printer->Print(variables_, - " ::google::protobuf::Arena* submessage_arena =\n" - " reinterpret_cast<::google::protobuf::MessageLite*>($name$)->GetArena();\n"); + format( + " ::$proto_ns$::Arena* submessage_arena =\n" + " " + "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n"); } else if (!SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, - " ::google::protobuf::Arena* submessage_arena = NULL;\n"); + format(" ::$proto_ns$::Arena* submessage_arena = NULL;\n"); } else { - printer->Print(variables_, - " ::google::protobuf::Arena* submessage_arena =\n" - " ::google::protobuf::Arena::GetArena($name$);\n"); + format( + " ::$proto_ns$::Arena* submessage_arena =\n" + " ::$proto_ns$::Arena::GetArena($name$);\n"); } - printer->Print(variables_, - " if (message_arena != submessage_arena) {\n" - " $name$ = ::google::protobuf::internal::GetOwnedMessage(\n" - " message_arena, $name$, submessage_arena);\n" - " }\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n"); + format( + " if (message_arena != submessage_arena) {\n" + " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n" + " message_arena, $name$, submessage_arena);\n" + " }\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" + " }\n"); if (implicit_weak_field_) { - printer->Print(variables_, - " $name$_ = reinterpret_cast<MessageLite*>($name$);\n"); + format(" $name$_ = reinterpret_cast<MessageLite*>($name$);\n"); + } else { + format(" $name$_ = $name$;\n"); + } + format( + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "}\n"); +} + +void MessageFieldGenerator:: +GenerateInternalAccessorDeclarations(io::Printer* printer) const { + Formatter format(printer, variables_); + if (implicit_weak_field_) { + format( + "static const ::$proto_ns$::MessageLite& $name$(" + "const $classname$* msg);\n" + "static ::$proto_ns$::MessageLite* mutable_$name$(" + "$classname$* msg);\n"); + } else { + format("static const $type$& $name$(const $classname$* msg);\n"); + } +} + +void MessageFieldGenerator:: +GenerateInternalAccessorDefinitions(io::Printer* printer) const { + // In theory, these accessors could be inline in HasBitSetters. However, in + // practice, the linker is then not able to throw them out making implicit + // weak dependencies not work at all. + Formatter format(printer, variables_); + if (implicit_weak_field_) { + // These private accessors are used by MergeFrom and + // MergePartialFromCodedStream, and their purpose is to provide access to + // the field without creating a strong dependency on the message type. + format( + "const ::$proto_ns$::MessageLite& $classname$::HasBitSetters::$name$(\n" + " const $classname$* msg) {\n" + " if (msg->$name$_ != NULL) {\n" + " return *msg->$name$_;\n" + " } else if (&$type_default_instance$ != NULL) {\n" + " return *reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n" + " &$type_default_instance$);\n" + " } else {\n" + " return " + "*::$proto_ns$::internal::ImplicitWeakMessage::default_instance();\n" + " }\n" + "}\n"); + if (SupportsArenas(descriptor_)) { + format( + "::$proto_ns$::MessageLite*\n" + "$classname$::HasBitSetters::mutable_$name$($classname$* msg) {\n"); + if (HasFieldPresence(descriptor_->file())) { + format(" msg->$set_hasbit$\n"); + } + format( + " if (msg->$name$_ == NULL) {\n" + " if (&$type_default_instance$ == NULL) {\n" + " msg->$name$_ = ::$proto_ns$::Arena::CreateMessage<\n" + " ::$proto_ns$::internal::ImplicitWeakMessage>(\n" + " msg->GetArenaNoVirtual());\n" + " } else {\n" + " msg->$name$_ = reinterpret_cast<const " + "::$proto_ns$::MessageLite*>(\n" + " &$type_default_instance$)->New(" + "msg->GetArenaNoVirtual());\n" + " }\n" + " }\n" + " return msg->$name$_;\n" + "}\n"); + } else { + format( + "::$proto_ns$::MessageLite*\n" + "$classname$::HasBitSetters::mutable_$name$($classname$* msg) {\n"); + if (HasFieldPresence(descriptor_->file())) { + format(" msg->$set_hasbit$\n"); + } + format( + " if (msg->$name$_ == NULL) {\n" + " if (&$type_default_instance$ == NULL) {\n" + " msg->$name$_ = " + "new ::$proto_ns$::internal::ImplicitWeakMessage;\n" + " } else {\n" + " msg->$name$_ = " + "reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n" + " &$type_default_instance$)->New();\n" + " }\n" + " }\n" + " return msg->$name$_;\n" + "}\n"); + } } else { - printer->Print(variables_, - " $name$_ = $name$;\n"); + // This inline accessor directly returns member field and is used in + // Serialize such that AFDO profile correctly captures access information to + // message fields under serialize. + format( + "const $type$&\n" + "$classname$::HasBitSetters::$name$(const $classname$* msg) {\n" + " return *msg->$field_member$;\n" + "}\n"); } - printer->Print(variables_, - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n"); } void MessageFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); if (!HasFieldPresence(descriptor_->file())) { // If we don't have has-bits, message presence is indicated only by ptr != // NULL. Thus on clear, we need to delete the object. - printer->Print(variables_, - "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) {\n" - " delete $name$_;\n" - "}\n" - "$name$_ = NULL;\n"); + format( + "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) {\n" + " delete $name$_;\n" + "}\n" + "$name$_ = NULL;\n"); } else { - printer->Print(variables_, - "if ($name$_ != NULL) $name$_->Clear();\n"); + format("if ($name$_ != NULL) $name$_->Clear();\n"); } } void MessageFieldGenerator:: GenerateMessageClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); if (!HasFieldPresence(descriptor_->file())) { // If we don't have has-bits, message presence is indicated only by ptr != // NULL. Thus on clear, we need to delete the object. - printer->Print(variables_, - "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) {\n" - " delete $name$_;\n" - "}\n" - "$name$_ = NULL;\n"); + format( + "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) {\n" + " delete $name$_;\n" + "}\n" + "$name$_ = NULL;\n"); } else { - printer->Print(variables_, - "GOOGLE_DCHECK($name$_ != NULL);\n" - "$name$_->Clear();\n"); + format( + "$DCHK$($name$_ != NULL);\n" + "$name$_->Clear();\n"); } } void MessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { + Formatter format(printer, variables_); if (implicit_weak_field_) { - printer->Print(variables_, - "_internal_mutable_$name$()->CheckTypeAndMergeFrom(\n" - " from._internal_$name$());\n"); + format( + "HasBitSetters::mutable_$name$(this)->CheckTypeAndMergeFrom(\n" + " HasBitSetters::$name$(&from));\n"); } else { - printer->Print(variables_, - "mutable_$name$()->$type$::MergeFrom(from.$name$());\n"); + format("mutable_$name$()->$type$::MergeFrom(from.$name$());\n"); } } void MessageFieldGenerator:: GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "swap($name$_, other->$name$_);\n"); + Formatter format(printer, variables_); + format("swap($name$_, other->$name$_);\n"); } void MessageFieldGenerator:: GenerateDestructorCode(io::Printer* printer) const { - // TODO(gerbens) Remove this when we don't need to destruct default instances. - // In google3 a default instance will never get deleted so we don't need to - // worry about that but in opensource protobuf default instances are deleted - // in shutdown process and we need to take special care when handling them. - printer->Print(variables_, - "if (this != internal_default_instance()) "); - printer->Print(variables_, "delete $name$_;\n"); + Formatter format(printer, variables_); + if (options_.opensource_runtime) { + // TODO(gerbens) Remove this when we don't need to destruct default + // instances. In google3 a default instance will never get deleted so we + // don't need to worry about that but in opensource protobuf default + // instances are deleted in shutdown process and we need to take special + // care when handling them. + format("if (this != internal_default_instance()) "); + } + format("delete $name$_;\n"); } void MessageFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = NULL;\n"); + Formatter format(printer, variables_); + format("$name$_ = NULL;\n"); } void MessageFieldGenerator:: GenerateCopyConstructorCode(io::Printer* printer) const { - printer->Print(variables_, - "if (from.has_$name$()) {\n" - " $name$_ = new $type$(*from.$name$_);\n" - "} else {\n" - " $name$_ = NULL;\n" - "}\n"); + Formatter format(printer, variables_); + format( + "if (from.has_$name$()) {\n" + " $name$_ = new $type$(*from.$name$_);\n" + "} else {\n" + " $name$_ = NULL;\n" + "}\n"); } void MessageFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { + Formatter format(printer, variables_); if (implicit_weak_field_) { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(\n" - " input, _internal_mutable_$name$()));\n"); + format( + "DO_(::$proto_ns$::internal::WireFormatLite::ReadMessage(\n" + " input, HasBitSetters::mutable_$name$(this)));\n"); } else if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(\n" - " input, mutable_$name$()));\n"); + format( + "DO_(::$proto_ns$::internal::WireFormatLite::ReadMessage(\n" + " input, mutable_$name$()));\n"); } else { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::ReadGroup(\n" - " $number$, input, mutable_$name$()));\n"); + format( + "DO_(::$proto_ns$::internal::WireFormatLite::ReadGroup(\n" + " $number$, input, mutable_$name$()));\n"); } } void MessageFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" - " $number$, this->_internal_$name$(), output);\n"); + Formatter format(printer, variables_); + format( + "::$proto_ns$::internal::WireFormatLite::Write$stream_writer$(\n" + " $number$, HasBitSetters::$name$(this), output);\n"); } void MessageFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormatLite::\n" - " InternalWrite$declared_type$ToArray(\n" - " $number$, this->_internal_$name$(), deterministic, target);\n"); + Formatter format(printer, variables_); + format( + "target = ::$proto_ns$::internal::WireFormatLite::\n" + " InternalWrite$declared_type$ToArray(\n" + " $number$, HasBitSetters::$name$(this), deterministic, target);\n"); } void MessageFieldGenerator:: GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" - " *$field_member$);\n"); + Formatter format(printer, variables_); + format( + "total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" + " *$field_member$);\n"); } // =================================================================== MessageOneofFieldGenerator::MessageOneofFieldGenerator( const FieldDescriptor* descriptor, const Options& options, - SCCAnalyzer* scc_analyzer) + MessageSCCAnalyzer* scc_analyzer) : MessageFieldGenerator(descriptor, options, scc_analyzer) { SetCommonOneofFieldVariables(descriptor, &variables_); } @@ -479,126 +502,122 @@ MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions( io::Printer* printer) const { - printer->Print(variables_, - "void $classname$::set_allocated_$name$($type$* $name$) {\n" - " ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n" - " clear_$oneof_name$();\n" - " if ($name$) {\n"); + Formatter format(printer, variables_); + format( + "void $classname$::set_allocated_$name$($type$* $name$) {\n" + " ::$proto_ns$::Arena* message_arena = GetArenaNoVirtual();\n" + " clear_$oneof_name$();\n" + " if ($name$) {\n"); if (SupportsArenas(descriptor_->message_type()) && descriptor_->file() != descriptor_->message_type()->file()) { // We have to read the arena through the virtual method, because the type // isn't defined in this file. - printer->Print(variables_, - " ::google::protobuf::Arena* submessage_arena =\n" - " reinterpret_cast<::google::protobuf::MessageLite*>($name$)->GetArena();\n"); + format( + " ::$proto_ns$::Arena* submessage_arena =\n" + " " + "reinterpret_cast<::$proto_ns$::MessageLite*>($name$)->GetArena();\n"); } else if (!SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, - " ::google::protobuf::Arena* submessage_arena = NULL;\n"); + format(" ::$proto_ns$::Arena* submessage_arena = NULL;\n"); } else { - printer->Print(variables_, - " ::google::protobuf::Arena* submessage_arena =\n" - " ::google::protobuf::Arena::GetArena($name$);\n"); + format( + " ::$proto_ns$::Arena* submessage_arena =\n" + " ::$proto_ns$::Arena::GetArena($name$);\n"); } - printer->Print(variables_, - " if (message_arena != submessage_arena) {\n" - " $name$ = ::google::protobuf::internal::GetOwnedMessage(\n" - " message_arena, $name$, submessage_arena);\n" - " }\n" - " set_has_$name$();\n" - " $field_member$ = $name$;\n" - " }\n" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n"); + format( + " if (message_arena != submessage_arena) {\n" + " $name$ = ::$proto_ns$::internal::GetOwnedMessage(\n" + " message_arena, $name$, submessage_arena);\n" + " }\n" + " set_has_$name$();\n" + " $field_member$ = $name$;\n" + " }\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" + "}\n"); } void MessageOneofFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { - if (!implicit_weak_field_) { - printer->Print(variables_, - "inline const $type$& $classname$::_internal_$name$() const {\n" - " return *$field_member$;\n" - "}\n"); - } - printer->Print(variables_, - "inline $type$* $classname$::$release_name$() {\n" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " if (has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " $type$* temp = $field_member$;\n"); - if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - " if (GetArenaNoVirtual() != NULL) {\n" - " temp = ::google::protobuf::internal::DuplicateIfNonNull(temp);\n" - " }\n"); - } - printer->Print(variables_, - " $field_member$ = NULL;\n" - " return temp;\n" - " } else {\n" - " return NULL;\n" - " }\n" - "}\n"); - - printer->Print(variables_, - "inline const $type$& $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return has_$name$()\n" - " ? *$field_member$\n" - " : *reinterpret_cast< $type$*>(&$type_default_instance$);\n" - "}\n"); - - if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" - " // @@protoc_insertion_point(field_unsafe_arena_release" - ":$full_name$)\n" + Formatter format(printer, variables_); + format( + "inline $type$* $classname$::$release_name$() {\n" + " // @@protoc_insertion_point(field_release:$full_name$)\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" - " $type$* temp = $field_member$;\n" + " $type$* temp = $field_member$;\n"); + if (SupportsArenas(descriptor_)) { + format( + " if (GetArenaNoVirtual() != NULL) {\n" + " temp = ::$proto_ns$::internal::DuplicateIfNonNull(temp);\n" + " }\n"); + } + format( " $field_member$ = NULL;\n" " return temp;\n" " } else {\n" " return NULL;\n" " }\n" - "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$" - "($type$* $name$) {\n" - // We rely on the oneof clear method to free the earlier contents of this - // oneof. We can directly use the pointer we're given to set the new - // value. - " clear_$oneof_name$();\n" - " if ($name$) {\n" - " set_has_$name$();\n" - " $field_member$ = $name$;\n" - " }\n" - " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" - "$full_name$)\n" "}\n"); + + format( + "inline const $type$& $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return has_$name$()\n" + " ? *$field_member$\n" + " : *reinterpret_cast< $type$*>(&$type_default_instance$);\n" + "}\n"); + + if (SupportsArenas(descriptor_)) { + format( + "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" + " // @@protoc_insertion_point(field_unsafe_arena_release" + ":$full_name$)\n" + " if (has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " $type$* temp = $field_member$;\n" + " $field_member$ = NULL;\n" + " return temp;\n" + " } else {\n" + " return NULL;\n" + " }\n" + "}\n" + "inline void $classname$::unsafe_arena_set_allocated_$name$" + "($type$* $name$) {\n" + // We rely on the oneof clear method to free the earlier contents of + // this oneof. We can directly use the pointer we're given to set the + // new value. + " clear_$oneof_name$();\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " $field_member$ = $name$;\n" + " }\n" + " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" + "$full_name$)\n" + "}\n"); } - printer->Print(variables_, - "inline $type$* $classname$::mutable_$name$() {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field_member$ = CreateMaybeMessage< $type$ >(\n" - " GetArenaNoVirtual());\n" - " }\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $field_member$;\n" - "}\n"); + format( + "inline $type$* $classname$::mutable_$name$() {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$ = CreateMaybeMessage< $type$ >(\n" + " GetArenaNoVirtual());\n" + " }\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return $field_member$;\n" + "}\n"); } void MessageOneofFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "if (GetArenaNoVirtual() == NULL) {\n" - " delete $field_member$;\n" - "}\n"); + format( + "if (GetArenaNoVirtual() == NULL) {\n" + " delete $field_member$;\n" + "}\n"); } else { - printer->Print(variables_, - "delete $field_member$;\n"); + format("delete $field_member$;\n"); } } @@ -628,9 +647,8 @@ GenerateConstructorCode(io::Printer* printer) const { RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( const FieldDescriptor* descriptor, const Options& options, - SCCAnalyzer* scc_analyzer) - : FieldGenerator(options), - descriptor_(descriptor), + MessageSCCAnalyzer* scc_analyzer) + : FieldGenerator(descriptor, options), implicit_weak_field_( IsImplicitWeakField(descriptor, options, scc_analyzer)) { SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_); @@ -640,108 +658,101 @@ RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} void RepeatedMessageFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n"); + Formatter format(printer, variables_); + format("::$proto_ns$::RepeatedPtrField< $type$ > $name$_;\n"); } void RepeatedMessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, - "$deprecated_attr$$type$* ${$mutable_$name$$}$(int index);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n" - " ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - - printer->Print(variables_, - "$deprecated_attr$const $type$& $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, "$deprecated_attr$$type$* ${$add_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - " $name$() const;\n"); - printer->Annotate("name", descriptor_); + Formatter format(printer, variables_); + format( + "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index);\n" + "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n" + " ${1$mutable_$name$$}$();\n" + "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const;\n" + "$deprecated_attr$$type$* ${1$add_$name$$}$();\n" + "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n" + " ${1$$name$$}$() const;\n", + descriptor_); } void RepeatedMessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$* $classname$::mutable_$name$(int index) {\n" - // TODO(dlj): move insertion points - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - "$type_reference_function$" - " return $name$_.Mutable(index);\n" - "}\n" - "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" - "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - "$type_reference_function$" - " return &$name$_;\n" - "}\n"); + Formatter format(printer, variables_); + format( + "inline $type$* $classname$::mutable_$name$(int index) {\n" + // TODO(dlj): move insertion points + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + "$type_reference_function$" + " return $name$_.Mutable(index);\n" + "}\n" + "inline ::$proto_ns$::RepeatedPtrField< $type$ >*\n" + "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" + "$type_reference_function$" + " return &$name$_;\n" + "}\n"); if (options_.safe_boundary_check) { - printer->Print(variables_, - "inline const $type$& $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.InternalCheckedGet(index,\n" - " *reinterpret_cast<const $type$*>(&$type_default_instance$));\n" - "}\n"); + format( + "inline const $type$& $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $name$_.InternalCheckedGet(index,\n" + " *reinterpret_cast<const $type$*>(&$type_default_instance$));\n" + "}\n"); } else { - printer->Print(variables_, - "inline const $type$& $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - "$type_reference_function$" - " return $name$_.Get(index);\n" - "}\n"); + format( + "inline const $type$& $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + "$type_reference_function$" + " return $name$_.Get(index);\n" + "}\n"); } - printer->Print(variables_, - "inline $type$* $classname$::add_$name$() {\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - " return $name$_.Add();\n" - "}\n"); + format( + "inline $type$* $classname$::add_$name$() {\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" + " return $name$_.Add();\n" + "}\n"); - printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" - "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - "$type_reference_function$" - " return $name$_;\n" - "}\n"); + format( + "inline const ::$proto_ns$::RepeatedPtrField< $type$ >&\n" + "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" + "$type_reference_function$" + " return $name$_;\n" + "}\n"); } void RepeatedMessageFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); if (implicit_weak_field_) { - printer->Print( - variables_, + format( "CastToBase(&$name$_)->Clear<" - "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>();\n"); + "::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>();\n"); } else { - printer->Print(variables_, "$name$_.Clear();\n"); + format("$name$_.Clear();\n"); } } void RepeatedMessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { + Formatter format(printer, variables_); if (implicit_weak_field_) { - printer->Print( - variables_, + format( "CastToBase(&$name$_)->MergeFrom<" - "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>(CastToBase(" + "::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>(CastToBase(" "from.$name$_));\n"); } else { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); + format("$name$_.MergeFrom(from.$name$_);\n"); } } void RepeatedMessageFieldGenerator:: GenerateSwappingCode(io::Printer* printer) const { - printer->Print( - variables_, - "CastToBase(&$name$_)->InternalSwap(CastToBase(&other->$name$_));\n"); + Formatter format(printer, variables_); + format("CastToBase(&$name$_)->InternalSwap(CastToBase(&other->$name$_));\n"); } void RepeatedMessageFieldGenerator:: @@ -751,83 +762,85 @@ GenerateConstructorCode(io::Printer* printer) const { void RepeatedMessageFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { + Formatter format(printer, variables_); if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { if (implicit_weak_field_) { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::" - "ReadMessage(input, CastToBase(&$name$_)->AddWeak(\n" - " reinterpret_cast<const ::google::protobuf::MessageLite*>(\n" - " &$type_default_instance$))));\n"); + format( + "DO_(::$proto_ns$::internal::WireFormatLite::" + "ReadMessage(input, CastToBase(&$name$_)->AddWeak(\n" + " reinterpret_cast<const ::$proto_ns$::MessageLite*>(\n" + " &$type_default_instance$))));\n"); } else { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::" - "ReadMessage(\n" - " input, add_$name$()));\n"); + format( + "DO_(::$proto_ns$::internal::WireFormatLite::" + "ReadMessage(\n" + " input, add_$name$()));\n"); } } else { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::" - "ReadGroup($number$, input, add_$name$()));\n"); + format( + "DO_(::$proto_ns$::internal::WireFormatLite::" + "ReadGroup($number$, input, add_$name$()));\n"); } } void RepeatedMessageFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "for (unsigned int i = 0,\n" - " n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n" - " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" - " $number$,\n"); + Formatter format(printer, variables_); + format( + "for (unsigned int i = 0,\n" + " n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n" + " ::$proto_ns$::internal::WireFormatLite::Write$stream_writer$(\n" + " $number$,\n"); if (implicit_weak_field_) { - printer->Print( - variables_, + format( " CastToBase($name$_).Get<" - "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>(" + "::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>(" "static_cast<int>(i)),\n"); } else { - printer->Print(variables_, - " this->$name$(static_cast<int>(i)),\n"); + format(" this->$name$(static_cast<int>(i)),\n"); } - printer->Print(variables_, - " output);\n" - "}\n"); + format( + " output);\n" + "}\n"); } void RepeatedMessageFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "for (unsigned int i = 0,\n" - " n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n" - " target = ::google::protobuf::internal::WireFormatLite::\n" - " InternalWrite$declared_type$ToArray(\n" - " $number$, this->$name$(static_cast<int>(i)), deterministic, target);\n" - "}\n"); + Formatter format(printer, variables_); + format( + "for (unsigned int i = 0,\n" + " n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n" + " target = ::$proto_ns$::internal::WireFormatLite::\n" + " InternalWrite$declared_type$ToArray(\n" + " $number$, this->$name$(static_cast<int>(i)), deterministic, " + "target);\n" + "}\n"); } void RepeatedMessageFieldGenerator:: GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "{\n" - " unsigned int count = static_cast<unsigned int>(this->$name$_size());\n"); - printer->Indent(); - printer->Print(variables_, - "total_size += $tag_size$UL * count;\n" - "for (unsigned int i = 0; i < count; i++) {\n" - " total_size +=\n" - " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"); + Formatter format(printer, variables_); + format( + "{\n" + " unsigned int count = static_cast<unsigned " + "int>(this->$name$_size());\n"); + format.Indent(); + format( + "total_size += $tag_size$UL * count;\n" + "for (unsigned int i = 0; i < count; i++) {\n" + " total_size +=\n" + " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"); if (implicit_weak_field_) { - printer->Print( - variables_, + format( " CastToBase($name$_).Get<" - "::google::protobuf::internal::ImplicitWeakTypeHandler<$type$>>(" + "::$proto_ns$::internal::ImplicitWeakTypeHandler<$type$>>(" "static_cast<int>(i)));\n"); } else { - printer->Print(variables_, - " this->$name$(static_cast<int>(i)));\n"); + format(" this->$name$(static_cast<int>(i)));\n"); } - printer->Print(variables_, "}\n"); - printer->Outdent(); - printer->Print("}\n"); + format("}\n"); + format.Outdent(); + format("}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index 6879539c..eed8e4f5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -48,7 +48,8 @@ namespace cpp { class MessageFieldGenerator : public FieldGenerator { public: MessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options, SCCAnalyzer* scc_analyzer); + const Options& options, + MessageSCCAnalyzer* scc_analyzer); ~MessageFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -56,6 +57,8 @@ class MessageFieldGenerator : public FieldGenerator { void GenerateAccessorDeclarations(io::Printer* printer) const; void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInternalAccessorDeclarations(io::Printer* printer) const; + void GenerateInternalAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMessageClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; @@ -69,9 +72,7 @@ class MessageFieldGenerator : public FieldGenerator { void GenerateByteSize(io::Printer* printer) const; protected: - const FieldDescriptor* descriptor_; const bool implicit_weak_field_; - std::map<string, string> variables_; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); @@ -80,7 +81,8 @@ class MessageFieldGenerator : public FieldGenerator { class MessageOneofFieldGenerator : public MessageFieldGenerator { public: MessageOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options, SCCAnalyzer* scc_analyzer); + const Options& options, + MessageSCCAnalyzer* scc_analyzer); ~MessageOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -103,7 +105,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { public: RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Options& options, - SCCAnalyzer* scc_analyzer); + MessageSCCAnalyzer* scc_analyzer); ~RepeatedMessageFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -121,9 +123,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { void GenerateByteSize(io::Printer* printer) const; private: - const FieldDescriptor* descriptor_; const bool implicit_weak_field_; - std::map<string, string> variables_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); }; @@ -131,6 +131,6 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h b/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h index d502a6f0..67eeff0a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h @@ -56,6 +56,6 @@ class MessageLayoutHelper { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h index f09885be..84c18622 100644 --- a/src/google/protobuf/compiler/cpp/cpp_options.h +++ b/src/google/protobuf/compiler/cpp/cpp_options.h @@ -35,7 +35,6 @@ #include <string> -#include <google/protobuf/stubs/common.h> namespace google { namespace protobuf { namespace compiler { @@ -45,39 +44,28 @@ namespace cpp { // Generator options (see generator.cc for a description of each): struct Options { - Options() - : safe_boundary_check(false), - proto_h(false), - transitive_pb_h(true), - annotate_headers(false), - enforce_lite(false), - table_driven_parsing(false), - table_driven_serialization(false), - lite_implicit_weak_fields(false), - bootstrap(false), - num_cc_files(0), - access_info_map(NULL) {} - - string dllexport_decl; - bool safe_boundary_check; - bool proto_h; - bool transitive_pb_h; - bool annotate_headers; - bool enforce_lite; - bool table_driven_parsing; - bool table_driven_serialization; - bool lite_implicit_weak_fields; - bool bootstrap; - int num_cc_files; - string annotation_pragma_name; - string annotation_guard_name; - const AccessInfoMap* access_info_map; + std::string dllexport_decl; + bool safe_boundary_check = false; + bool proto_h = false; + bool transitive_pb_h = true; + bool annotate_headers = false; + bool enforce_lite = false; + bool table_driven_parsing = false; + bool table_driven_serialization = false; + bool lite_implicit_weak_fields = false; + bool bootstrap = false; + bool opensource_runtime = false; + bool opensource_include_paths = false; + int num_cc_files = 0; + std::string annotation_pragma_name; + std::string annotation_guard_name; + const AccessInfoMap* access_info_map = nullptr; }; } // namespace cpp } // namespace compiler } // namespace protobuf +} // namespace google -} // namespace google #endif // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc index e9303865..2f78bda5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc +++ b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc @@ -106,6 +106,8 @@ class FieldGroup { // STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and // calls ArenaStringPtr::Destroy on each. // +// LAZY_MESSAGE is grouped next, as it interferes with the ability to memset +// non-repeated fields otherwise. // // MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls // delete on each. We initialize these fields with a NULL pointer (see @@ -122,6 +124,9 @@ void PaddingOptimizer::OptimizeLayout( enum Family { REPEATED = 0, STRING = 1, + // Laying out LAZY_MESSAGE before MESSAGE allows a single memset to zero + // MESSAGE and ZERO_INITIALIZABLE fields together. + LAZY_MESSAGE = 2, MESSAGE = 3, ZERO_INITIALIZABLE = 4, OTHER = 5, @@ -142,7 +147,9 @@ void PaddingOptimizer::OptimizeLayout( f = STRING; } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { f = MESSAGE; - + if (IsLazy(field, options)) { + f = LAZY_MESSAGE; + } } else if (CanInitializeByZeroing(field)) { f = ZERO_INITIALIZABLE; } diff --git a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h index 42a3b5cd..2382081b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h +++ b/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h @@ -59,6 +59,6 @@ class PaddingOptimizer : public MessageLayoutHelper { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc index ff6ba0f8..4f8a23ed 100644 --- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc @@ -219,7 +219,7 @@ TEST(CppPluginTest, PluginTest) { "}\n", true)); - google::protobuf::compiler::CommandLineInterface cli; + CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); CppGenerator cpp_generator; diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index 701f9d2d..2f6a0504 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -83,16 +83,16 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, std::map<string, string>* variables, const Options& options) { SetCommonFieldVariables(descriptor, variables, options); - (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type()); - (*variables)["default"] = DefaultValue(descriptor); - (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + (*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type()); + (*variables)["default"] = DefaultValue(options, descriptor); + (*variables)["tag"] = + SimpleItoa(internal::WireFormat::MakeTag(descriptor)); int fixed_size = FixedSize(descriptor->type()); if (fixed_size != -1) { (*variables)["fixed_size"] = SimpleItoa(fixed_size); } - (*variables)["wire_format_field_type"] = - "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name( - static_cast<FieldDescriptorProto_Type>(descriptor->type())); + (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name( + static_cast<FieldDescriptorProto_Type>(descriptor->type())); (*variables)["full_name"] = descriptor->full_name(); } @@ -102,7 +102,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, PrimitiveFieldGenerator::PrimitiveFieldGenerator( const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetPrimitiveVariables(descriptor, &variables_, options); } @@ -110,91 +110,103 @@ PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} void PrimitiveFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, "$type$ $name$_;\n"); + Formatter format(printer, variables_); + format("$type$ $name$_;\n"); } void PrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_$name$$}$($type$ value);\n"); - printer->Annotate("{", "}", descriptor_); + Formatter format(printer, variables_); + format( + "$deprecated_attr$$type$ ${1$$name$$}$() const;\n" + "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n", + descriptor_); } void PrimitiveFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_;\n" - "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" - " $set_hasbit$\n" - " $name$_ = value;\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $name$_;\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + " $set_hasbit$\n" + " $name$_ = value;\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n"); } void PrimitiveFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); + Formatter format(printer, variables_); + format("$name$_ = $default$;\n"); } void PrimitiveFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "set_$name$(from.$name$());\n"); + Formatter format(printer, variables_); + format("set_$name$(from.$name$());\n"); } void PrimitiveFieldGenerator:: GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "swap($name$_, other->$name$_);\n"); + Formatter format(printer, variables_); + format("swap($name$_, other->$name$_);\n"); } void PrimitiveFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $default$;\n"); + Formatter format(printer, variables_); + format("$name$_ = $default$;\n"); } void PrimitiveFieldGenerator:: GenerateCopyConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = from.$name$_;\n"); + Formatter format(printer, variables_); + format("$name$_ = from.$name$_;\n"); } void PrimitiveFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "$set_hasbit$\n" - "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " $type$, $wire_format_field_type$>(\n" - " input, &$name$_)));\n"); + Formatter format(printer, variables_); + format( + "$set_hasbit_io$\n" + "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n" + " $type$, " + "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n" + " input, &$name$_)));\n"); } void PrimitiveFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::Write$declared_type$(" + Formatter format(printer, variables_); + format( + "::$proto_ns$::internal::WireFormatLite::Write$declared_type$(" "$number$, this->$name$(), output);\n"); } void PrimitiveFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(" + Formatter format(printer, variables_); + format( + "target = " + "::$proto_ns$::internal::WireFormatLite::Write$declared_type$ToArray(" "$number$, this->$name$(), target);\n"); } void PrimitiveFieldGenerator:: GenerateByteSize(io::Printer* printer) const { + Formatter format(printer, variables_); int fixed_size = FixedSize(descriptor_->type()); if (fixed_size == -1) { - printer->Print(variables_, - "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" - " this->$name$());\n"); + format( + "total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" + " this->$name$());\n"); } else { - printer->Print(variables_, - "total_size += $tag_size$ + $fixed_size$;\n"); + format("total_size += $tag_size$ + $fixed_size$;\n"); } } @@ -211,27 +223,29 @@ PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} void PrimitiveOneofFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " if (has_$name$()) {\n" - " return $field_member$;\n" - " }\n" - " return $default$;\n" - "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" - " if (!has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " }\n" - " $field_member$ = value;\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " if (has_$name$()) {\n" + " return $field_member$;\n" + " }\n" + " return $default$;\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " }\n" + " $field_member$ = value;\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n"); } void PrimitiveOneofFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$field_member$ = $default$;\n"); + Formatter format(printer, variables_); + format("$field_member$ = $default$;\n"); } void PrimitiveOneofFieldGenerator:: @@ -241,25 +255,27 @@ GenerateSwappingCode(io::Printer* printer) const { void PrimitiveOneofFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { - printer->Print(variables_, - "$ns$::_$classname$_default_instance_.$name$_ = $default$;\n"); + Formatter format(printer, variables_); + format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n"); } void PrimitiveOneofFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "clear_$oneof_name$();\n" - "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" - " $type$, $wire_format_field_type$>(\n" - " input, &$field_member$)));\n" - "set_has_$name$();\n"); + Formatter format(printer, variables_); + format( + "clear_$oneof_name$();\n" + "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n" + " $type$, " + "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n" + " input, &$field_member$)));\n" + "set_has_$name$();\n"); } // =================================================================== RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetPrimitiveVariables(descriptor, &variables_, options); if (descriptor->is_packed()) { @@ -275,77 +291,72 @@ RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} void RepeatedPrimitiveFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::RepeatedField< $type$ > $name$_;\n"); + Formatter format(printer, variables_); + format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n"); if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file(), options_)) { - printer->Print(variables_, - "mutable int _$name$_cached_byte_size_;\n"); + format("mutable std::atomic<int> _$name$_cached_byte_size_;\n"); } } void RepeatedPrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { - printer->Print(variables_, - "$deprecated_attr$$type$ $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$add_$name$$}$($type$ value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n" - " $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n" - " ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); + Formatter format(printer, variables_); + format( + "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n" + "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n" + "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n" + " ${1$$name$$}$() const;\n" + "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n" + " ${1$mutable_$name$$}$();\n", + descriptor_); } void RepeatedPrimitiveFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.Get(index);\n" - "}\n" - "inline void $classname$::set_$name$(int index, $type$ value) {\n" - " $name$_.Set(index, value);\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "inline void $classname$::add_$name$($type$ value) {\n" - " $name$_.Add(value);\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "inline const ::google::protobuf::RepeatedField< $type$ >&\n" - "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $name$_;\n" - "}\n" - "inline ::google::protobuf::RepeatedField< $type$ >*\n" - "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$name$_;\n" - "}\n"); + Formatter format(printer, variables_); + format( + "inline $type$ $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $name$_.Get(index);\n" + "}\n" + "inline void $classname$::set_$name$(int index, $type$ value) {\n" + " $name$_.Set(index, value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + "}\n" + "inline void $classname$::add_$name$($type$ value) {\n" + " $name$_.Add(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" + "}\n" + "inline const ::$proto_ns$::RepeatedField< $type$ >&\n" + "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" + " return $name$_;\n" + "}\n" + "inline ::$proto_ns$::RepeatedField< $type$ >*\n" + "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" + " return &$name$_;\n" + "}\n"); } void RepeatedPrimitiveFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); + Formatter format(printer, variables_); + format("$name$_.Clear();\n"); } void RepeatedPrimitiveFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); + Formatter format(printer, variables_); + format("$name$_.MergeFrom(from.$name$_);\n"); } void RepeatedPrimitiveFieldGenerator:: GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.InternalSwap(&other->$name$_);\n"); + Formatter format(printer, variables_); + format("$name$_.InternalSwap(&other->$name$_);\n"); } void RepeatedPrimitiveFieldGenerator:: @@ -355,124 +366,135 @@ GenerateConstructorCode(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: GenerateCopyConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.CopyFrom(from.$name$_);\n"); + Formatter format(printer, variables_); + format("$name$_.CopyFrom(from.$name$_);\n"); } void RepeatedPrimitiveFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n" - " $type$, $wire_format_field_type$>(\n" - " $tag_size$, $tag$u, input, this->mutable_$name$())));\n"); + Formatter format(printer, variables_); + format( + "DO_((::$proto_ns$::internal::WireFormatLite::$repeated_reader$<\n" + " $type$, " + "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n" + " $tag_size$, $tag$u, input, this->mutable_$name$())));\n"); } void RepeatedPrimitiveFieldGenerator:: GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { - printer->Print(variables_, - "DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n" - " $type$, $wire_format_field_type$>(\n" - " input, this->mutable_$name$())));\n"); + Formatter format(printer, variables_); + format( + "DO_((::$proto_ns$::internal::WireFormatLite::$packed_reader$<\n" + " $type$, " + "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n" + " input, this->mutable_$name$())));\n"); } void RepeatedPrimitiveFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { + Formatter format(printer, variables_); bool array_written = false; if (descriptor_->is_packed()) { // Write the tag and the size. - printer->Print(variables_, - "if (this->$name$_size() > 0) {\n" - " ::google::protobuf::internal::WireFormatLite::WriteTag(" - "$number$, " - "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, " - "output);\n" - " output->WriteVarint32(static_cast< ::google::protobuf::uint32>(\n" - " _$name$_cached_byte_size_));\n"); + format( + "if (this->$name$_size() > 0) {\n" + " ::$proto_ns$::internal::WireFormatLite::WriteTag(" + "$number$, " + "::$proto_ns$::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, " + "output);\n" + " output->WriteVarint32(_$name$_cached_byte_size_.load(\n" + " std::memory_order_relaxed));\n"); if (FixedSize(descriptor_->type()) > 0) { // TODO(ckennelly): Use RepeatedField<T>::unsafe_data() via // WireFormatLite to access the contents of this->$name$_ to save a branch // here. - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$Array(\n" - " this->$name$().data(), this->$name$_size(), output);\n"); + format( + " " + "::$proto_ns$::internal::WireFormatLite::Write$declared_type$Array(\n" + " this->$name$().data(), this->$name$_size(), output);\n"); array_written = true; // Wrote array all at once } - printer->Print(variables_, "}\n"); + format("}\n"); } if (!array_written) { - printer->Print(variables_, - "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); + format("for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); if (descriptor_->is_packed()) { - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n" - " this->$name$(i), output);\n"); + format( + " " + "::$proto_ns$::internal::WireFormatLite::Write$declared_type$NoTag(\n" + " this->$name$(i), output);\n"); } else { - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" - " $number$, this->$name$(i), output);\n"); + format( + " ::$proto_ns$::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(i), output);\n"); } - printer->Print("}\n"); + format("}\n"); } } void RepeatedPrimitiveFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + Formatter format(printer, variables_); if (descriptor_->is_packed()) { // Write the tag and the size. - printer->Print(variables_, - "if (this->$name$_size() > 0) {\n" - " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" - " $number$,\n" - " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" - " target);\n" - " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n" - " static_cast< ::google::protobuf::int32>(\n" - " _$name$_cached_byte_size_), target);\n" - " target = ::google::protobuf::internal::WireFormatLite::\n" - " Write$declared_type$NoTagToArray(this->$name$_, target);\n" - "}\n"); + format( + "if (this->$name$_size() > 0) {\n" + " target = ::$proto_ns$::internal::WireFormatLite::WriteTagToArray(\n" + " $number$,\n" + " " + "::$proto_ns$::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " target);\n" + " target = " + "::$proto_ns$::io::CodedOutputStream::WriteVarint32ToArray(\n" + " _$name$_cached_byte_size_.load(std::memory_order_relaxed),\n" + " target);\n" + " target = ::$proto_ns$::internal::WireFormatLite::\n" + " Write$declared_type$NoTagToArray(this->$name$_, target);\n" + "}\n"); } else { - printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormatLite::\n" - " Write$declared_type$ToArray($number$, this->$name$_, target);\n"); + format( + "target = ::$proto_ns$::internal::WireFormatLite::\n" + " Write$declared_type$ToArray($number$, this->$name$_, target);\n"); } } void RepeatedPrimitiveFieldGenerator:: GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, "{\n"); - printer->Indent(); + Formatter format(printer, variables_); + format("{\n"); + format.Indent(); int fixed_size = FixedSize(descriptor_->type()); if (fixed_size == -1) { - printer->Print(variables_, - "size_t data_size = ::google::protobuf::internal::WireFormatLite::\n" - " $declared_type$Size(this->$name$_);\n"); + format( + "size_t data_size = ::$proto_ns$::internal::WireFormatLite::\n" + " $declared_type$Size(this->$name$_);\n"); } else { - printer->Print(variables_, - "unsigned int count = static_cast<unsigned int>(this->$name$_size());\n" - "size_t data_size = $fixed_size$UL * count;\n"); + format( + "unsigned int count = static_cast<unsigned int>(this->$name$_size());\n" + "size_t data_size = $fixed_size$UL * count;\n"); } if (descriptor_->is_packed()) { - printer->Print(variables_, - "if (data_size > 0) {\n" - " total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::Int32Size(\n" - " static_cast< ::google::protobuf::int32>(data_size));\n" - "}\n" - "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" - "_$name$_cached_byte_size_ = cached_size;\n" - "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" - "total_size += data_size;\n"); + format( + "if (data_size > 0) {\n" + " total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::Int32Size(\n" + " static_cast<$int32$>(data_size));\n" + "}\n" + "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n" + "_$name$_cached_byte_size_.store(cached_size,\n" + " std::memory_order_relaxed);\n" + "total_size += data_size;\n"); } else { - printer->Print(variables_, - "total_size += $tag_size$ *\n" - " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n" - "total_size += data_size;\n"); + format( + "total_size += $tag_size$ *\n" + " " + "::$proto_ns$::internal::FromIntSize(this->$name$_size());\n" + "total_size += data_size;\n"); } - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h index d52228e9..77389aa0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h @@ -64,10 +64,6 @@ class PrimitiveFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - protected: - const FieldDescriptor* descriptor_; - std::map<string, string> variables_; - private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; @@ -111,15 +107,12 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { void GenerateByteSize(io::Printer* printer) const; private: - const FieldDescriptor* descriptor_; - std::map<string, string> variables_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc index 95357d9f..677b7374 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.cc +++ b/src/google/protobuf/compiler/cpp/cpp_service.cc @@ -42,151 +42,153 @@ namespace protobuf { namespace compiler { namespace cpp { +namespace { + +void InitMethodVariables(const MethodDescriptor* method, Formatter* format) { + format->Set("name", method->name()); + format->Set("input_type", QualifiedClassName(method->input_type())); + format->Set("output_type", QualifiedClassName(method->output_type())); +} + +} // namespace + ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor, + const std::map<string, string>& vars, const Options& options) - : descriptor_(descriptor) { + : descriptor_(descriptor), vars_(vars) { vars_["classname"] = descriptor_->name(); - vars_["file_namespace"] = FileLevelNamespace(descriptor_->file()->name()); vars_["full_name"] = descriptor_->full_name(); - if (options.dllexport_decl.empty()) { - vars_["dllexport"] = ""; - } else { - vars_["dllexport"] = options.dllexport_decl + " "; - } } ServiceGenerator::~ServiceGenerator() {} void ServiceGenerator::GenerateDeclarations(io::Printer* printer) { + Formatter format(printer, vars_); // Forward-declare the stub type. - printer->Print(vars_, - "class $classname$_Stub;\n" - "\n"); + format( + "class $classname$_Stub;\n" + "\n"); GenerateInterface(printer); GenerateStubDefinition(printer); } void ServiceGenerator::GenerateInterface(io::Printer* printer) { - printer->Print(vars_, - "class $dllexport$$classname$ : public ::google::protobuf::Service {\n" - " protected:\n" - " // This class should be treated as an abstract interface.\n" - " inline $classname$() {};\n" - " public:\n" - " virtual ~$classname$();\n"); + Formatter format(printer, vars_); + format( + "class $dllexport_decl $$classname$ : public ::$proto_ns$::Service {\n" + " protected:\n" + " // This class should be treated as an abstract interface.\n" + " inline $classname$() {};\n" + " public:\n" + " virtual ~$classname$();\n"); printer->Indent(); - printer->Print(vars_, - "\n" - "typedef $classname$_Stub Stub;\n" - "\n" - "static const ::google::protobuf::ServiceDescriptor* descriptor();\n" - "\n"); + format( + "\n" + "typedef $classname$_Stub Stub;\n" + "\n" + "static const ::$proto_ns$::ServiceDescriptor* descriptor();\n" + "\n"); GenerateMethodSignatures(VIRTUAL, printer); - printer->Print( - "\n" - "// implements Service ----------------------------------------------\n" - "\n" - "const ::google::protobuf::ServiceDescriptor* GetDescriptor();\n" - "void CallMethod(const ::google::protobuf::MethodDescriptor* method,\n" - " ::google::protobuf::RpcController* controller,\n" - " const ::google::protobuf::Message* request,\n" - " ::google::protobuf::Message* response,\n" - " ::google::protobuf::Closure* done);\n" - "const ::google::protobuf::Message& GetRequestPrototype(\n" - " const ::google::protobuf::MethodDescriptor* method) const;\n" - "const ::google::protobuf::Message& GetResponsePrototype(\n" - " const ::google::protobuf::MethodDescriptor* method) const;\n"); + format( + "\n" + "// implements Service ----------------------------------------------\n" + "\n" + "const ::$proto_ns$::ServiceDescriptor* GetDescriptor();\n" + "void CallMethod(const ::$proto_ns$::MethodDescriptor* method,\n" + " ::$proto_ns$::RpcController* controller,\n" + " const ::$proto_ns$::Message* request,\n" + " ::$proto_ns$::Message* response,\n" + " ::google::protobuf::Closure* done);\n" + "const ::$proto_ns$::Message& GetRequestPrototype(\n" + " const ::$proto_ns$::MethodDescriptor* method) const;\n" + "const ::$proto_ns$::Message& GetResponsePrototype(\n" + " const ::$proto_ns$::MethodDescriptor* method) const;\n"); printer->Outdent(); - printer->Print(vars_, - "\n" - " private:\n" - " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n" - "};\n" - "\n"); + format( + "\n" + " private:\n" + " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n" + "};\n" + "\n"); } void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) { - printer->Print(vars_, - "class $dllexport$$classname$_Stub : public $classname$ {\n" - " public:\n"); + Formatter format(printer, vars_); + format( + "class $dllexport_decl $$classname$_Stub : public $classname$ {\n" + " public:\n"); printer->Indent(); - printer->Print(vars_, - "$classname$_Stub(::google::protobuf::RpcChannel* channel);\n" - "$classname$_Stub(::google::protobuf::RpcChannel* channel,\n" - " ::google::protobuf::Service::ChannelOwnership ownership);\n" - "~$classname$_Stub();\n" - "\n" - "inline ::google::protobuf::RpcChannel* channel() { return channel_; }\n" - "\n" - "// implements $classname$ ------------------------------------------\n" - "\n"); + format( + "$classname$_Stub(::$proto_ns$::RpcChannel* channel);\n" + "$classname$_Stub(::$proto_ns$::RpcChannel* channel,\n" + " ::$proto_ns$::Service::ChannelOwnership ownership);\n" + "~$classname$_Stub();\n" + "\n" + "inline ::$proto_ns$::RpcChannel* channel() { return channel_; }\n" + "\n" + "// implements $classname$ ------------------------------------------\n" + "\n"); GenerateMethodSignatures(NON_VIRTUAL, printer); printer->Outdent(); - printer->Print(vars_, - " private:\n" - " ::google::protobuf::RpcChannel* channel_;\n" - " bool owns_channel_;\n" - " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n" - "};\n" - "\n"); + format( + " private:\n" + " ::$proto_ns$::RpcChannel* channel_;\n" + " bool owns_channel_;\n" + " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n" + "};\n" + "\n"); } -void ServiceGenerator::GenerateMethodSignatures( - VirtualOrNon virtual_or_non, io::Printer* printer) { +void ServiceGenerator::GenerateMethodSignatures(VirtualOrNon virtual_or_non, + io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map<string, string> sub_vars; - sub_vars["name"] = method->name(); - sub_vars["input_type"] = ClassName(method->input_type(), true); - sub_vars["output_type"] = ClassName(method->output_type(), true); - sub_vars["virtual"] = virtual_or_non == VIRTUAL ? "virtual " : ""; - - printer->Print(sub_vars, - "$virtual$void $name$(::google::protobuf::RpcController* controller,\n" - " const $input_type$* request,\n" - " $output_type$* response,\n" - " ::google::protobuf::Closure* done);\n"); + Formatter format(printer, vars_); + InitMethodVariables(method, &format); + format.Set("virtual", virtual_or_non == VIRTUAL ? "virtual " : ""); + format( + "$virtual$void $name$(::$proto_ns$::RpcController* controller,\n" + " const $input_type$* request,\n" + " $output_type$* response,\n" + " ::google::protobuf::Closure* done);\n"); } } // =================================================================== -void ServiceGenerator::GenerateDescriptorInitializer( - io::Printer* printer, int index) { - std::map<string, string> vars; - vars["classname"] = descriptor_->name(); - vars["index"] = SimpleItoa(index); - - printer->Print(vars, - "$classname$_descriptor_ = file->service($index$);\n"); +void ServiceGenerator::GenerateDescriptorInitializer(io::Printer* printer, + int index) { + Formatter format(printer, vars_); + format("$classname$_descriptor_ = file->service($1$);\n", index); } // =================================================================== void ServiceGenerator::GenerateImplementation(io::Printer* printer) { - vars_["index"] = SimpleItoa(index_in_metadata_); - printer->Print( - vars_, + Formatter format(printer, vars_); + format( "$classname$::~$classname$() {}\n" "\n" - "const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n" - " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" - " return $file_namespace$::file_level_service_descriptors[$index$];\n" + "const ::$proto_ns$::ServiceDescriptor* $classname$::descriptor() {\n" + " " + "::$proto_ns$::internal::AssignDescriptors(&$assign_desc_table$);\n" + " return $file_level_service_descriptors$[$1$];\n" "}\n" "\n" - "const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n" + "const ::$proto_ns$::ServiceDescriptor* $classname$::GetDescriptor() {\n" " return descriptor();\n" "}\n" - "\n"); + "\n", + index_in_metadata_); // Generate methods of the interface. GenerateNotImplementedMethods(printer); @@ -195,18 +197,20 @@ void ServiceGenerator::GenerateImplementation(io::Printer* printer) { GenerateGetPrototype(RESPONSE, printer); // Generate stub implementation. - printer->Print(vars_, - "$classname$_Stub::$classname$_Stub(::google::protobuf::RpcChannel* channel)\n" - " : channel_(channel), owns_channel_(false) {}\n" - "$classname$_Stub::$classname$_Stub(\n" - " ::google::protobuf::RpcChannel* channel,\n" - " ::google::protobuf::Service::ChannelOwnership ownership)\n" - " : channel_(channel),\n" - " owns_channel_(ownership == ::google::protobuf::Service::STUB_OWNS_CHANNEL) {}\n" - "$classname$_Stub::~$classname$_Stub() {\n" - " if (owns_channel_) delete channel_;\n" - "}\n" - "\n"); + format( + "$classname$_Stub::$classname$_Stub(::$proto_ns$::RpcChannel* channel)\n" + " : channel_(channel), owns_channel_(false) {}\n" + "$classname$_Stub::$classname$_Stub(\n" + " ::$proto_ns$::RpcChannel* channel,\n" + " ::$proto_ns$::Service::ChannelOwnership ownership)\n" + " : channel_(channel),\n" + " owns_channel_(ownership == " + "::$proto_ns$::Service::STUB_OWNS_CHANNEL) " + "{}\n" + "$classname$_Stub::~$classname$_Stub() {\n" + " if (owns_channel_) delete channel_;\n" + "}\n" + "\n"); GenerateStubMethods(printer); } @@ -214,123 +218,110 @@ void ServiceGenerator::GenerateImplementation(io::Printer* printer) { void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map<string, string> sub_vars; - sub_vars["classname"] = descriptor_->name(); - sub_vars["name"] = method->name(); - sub_vars["index"] = SimpleItoa(i); - sub_vars["input_type"] = ClassName(method->input_type(), true); - sub_vars["output_type"] = ClassName(method->output_type(), true); - - printer->Print(sub_vars, - "void $classname$::$name$(::google::protobuf::RpcController* controller,\n" - " const $input_type$*,\n" - " $output_type$*,\n" - " ::google::protobuf::Closure* done) {\n" - " controller->SetFailed(\"Method $name$() not implemented.\");\n" - " done->Run();\n" - "}\n" - "\n"); + Formatter format(printer, vars_); + InitMethodVariables(method, &format); + format( + "void $classname$::$name$(::$proto_ns$::RpcController* controller,\n" + " const $input_type$*,\n" + " $output_type$*,\n" + " ::google::protobuf::Closure* done) {\n" + " controller->SetFailed(\"Method $name$() not implemented.\");\n" + " done->Run();\n" + "}\n" + "\n"); } } void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { - printer->Print( - vars_, - "void $classname$::CallMethod(const ::google::protobuf::MethodDescriptor* method,\n" - " ::google::protobuf::RpcController* controller,\n" - " const ::google::protobuf::Message* request,\n" - " ::google::protobuf::Message* response,\n" + Formatter format(printer, vars_); + format( + "void $classname$::CallMethod(const ::$proto_ns$::MethodDescriptor* " + "method,\n" + " ::$proto_ns$::RpcController* controller,\n" + " const ::$proto_ns$::Message* request,\n" + " ::$proto_ns$::Message* response,\n" " ::google::protobuf::Closure* done) {\n" - " GOOGLE_DCHECK_EQ(method->service(), " - "$file_namespace$::file_level_service_descriptors[$index$]);\n" - " switch(method->index()) {\n"); + " GOOGLE_DCHECK_EQ(method->service(), $file_level_service_descriptors$[$1$]);\n" + " switch(method->index()) {\n", + index_in_metadata_); for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map<string, string> sub_vars; - sub_vars["name"] = method->name(); - sub_vars["index"] = SimpleItoa(i); - sub_vars["input_type"] = ClassName(method->input_type(), true); - sub_vars["output_type"] = ClassName(method->output_type(), true); + Formatter format(printer, vars_); + InitMethodVariables(method, &format); // Note: down_cast does not work here because it only works on pointers, // not references. - printer->Print(sub_vars, - " case $index$:\n" - " $name$(controller,\n" - " ::google::protobuf::down_cast<const $input_type$*>(request),\n" - " ::google::protobuf::down_cast< $output_type$*>(response),\n" - " done);\n" - " break;\n"); + format( + " case $1$:\n" + " $name$(controller,\n" + " ::google::protobuf::down_cast<const $input_type$*>(request),\n" + " ::google::protobuf::down_cast< $output_type$*>(response),\n" + " done);\n" + " break;\n", + i); } - printer->Print(vars_, - " default:\n" - " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" - " break;\n" - " }\n" - "}\n" - "\n"); + format( + " default:\n" + " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" + " break;\n" + " }\n" + "}\n" + "\n"); } void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, io::Printer* printer) { + Formatter format(printer, vars_); if (which == REQUEST) { - printer->Print(vars_, - "const ::google::protobuf::Message& $classname$::GetRequestPrototype(\n"); + format("const ::$proto_ns$::Message& $classname$::GetRequestPrototype(\n"); } else { - printer->Print(vars_, - "const ::google::protobuf::Message& $classname$::GetResponsePrototype(\n"); + format("const ::$proto_ns$::Message& $classname$::GetResponsePrototype(\n"); } - printer->Print(vars_, - " const ::google::protobuf::MethodDescriptor* method) const {\n" - " GOOGLE_DCHECK_EQ(method->service(), descriptor());\n" - " switch(method->index()) {\n"); + format( + " const ::$proto_ns$::MethodDescriptor* method) const {\n" + " GOOGLE_DCHECK_EQ(method->service(), descriptor());\n" + " switch(method->index()) {\n"); for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); const Descriptor* type = - (which == REQUEST) ? method->input_type() : method->output_type(); - - std::map<string, string> sub_vars; - sub_vars["index"] = SimpleItoa(i); - sub_vars["type"] = ClassName(type, true); + (which == REQUEST) ? method->input_type() : method->output_type(); - printer->Print(sub_vars, - " case $index$:\n" - " return $type$::default_instance();\n"); + format( + " case $1$:\n" + " return $2$::default_instance();\n", + i, QualifiedClassName(type)); } - printer->Print( - " default:\n" - " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" - " return *::google::protobuf::MessageFactory::generated_factory()\n" - " ->GetPrototype(method->$input_or_output$_type());\n" - " }\n" - "}\n" - "\n", - "input_or_output", which == REQUEST ? "input" : "output"); + format( + " default:\n" + " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" + " return *::$proto_ns$::MessageFactory::generated_factory()\n" + " ->GetPrototype(method->$1$_type());\n" + " }\n" + "}\n" + "\n", + which == REQUEST ? "input" : "output"); } void ServiceGenerator::GenerateStubMethods(io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map<string, string> sub_vars; - sub_vars["classname"] = descriptor_->name(); - sub_vars["name"] = method->name(); - sub_vars["index"] = SimpleItoa(i); - sub_vars["input_type"] = ClassName(method->input_type(), true); - sub_vars["output_type"] = ClassName(method->output_type(), true); - - printer->Print(sub_vars, - "void $classname$_Stub::$name$(::google::protobuf::RpcController* controller,\n" - " const $input_type$* request,\n" - " $output_type$* response,\n" - " ::google::protobuf::Closure* done) {\n" - " channel_->CallMethod(descriptor()->method($index$),\n" - " controller, request, response, done);\n" - "}\n"); + Formatter format(printer, vars_); + InitMethodVariables(method, &format); + format( + "void $classname$_Stub::$name$(::$proto_ns$::RpcController* " + "controller,\n" + " const $input_type$* request,\n" + " $output_type$* response,\n" + " ::google::protobuf::Closure* done) {\n" + " channel_->CallMethod(descriptor()->method($1$),\n" + " controller, request, response, done);\n" + "}\n", + i); } } diff --git a/src/google/protobuf/compiler/cpp/cpp_service.h b/src/google/protobuf/compiler/cpp/cpp_service.h index 33c02547..2952e413 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.h +++ b/src/google/protobuf/compiler/cpp/cpp_service.h @@ -42,11 +42,13 @@ namespace google { namespace protobuf { - namespace io { - class Printer; // printer.h - } +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace cpp { @@ -55,6 +57,7 @@ class ServiceGenerator { public: // See generator.cc for the meaning of dllexport_decl. explicit ServiceGenerator(const ServiceDescriptor* descriptor, + const std::map<std::string, std::string>& vars, const Options& options); ~ServiceGenerator(); @@ -70,7 +73,8 @@ class ServiceGenerator { // descriptor. void GenerateDescriptorInitializer(io::Printer* printer, int index); - // Generate implementations of everything declared by GenerateDeclarations(). + // Generate implementations of everything declared by + // GenerateDeclarations(). void GenerateImplementation(io::Printer* printer); private: @@ -105,7 +109,7 @@ class ServiceGenerator { void GenerateStubMethods(io::Printer* printer); const ServiceDescriptor* descriptor_; - std::map<string, string> vars_; + std::map<std::string, std::string> vars_; int index_in_metadata_; @@ -116,6 +120,6 @@ class ServiceGenerator { } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index cf6c4b33..ecfabe64 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -36,9 +36,9 @@ #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/io/printer.h> - #include <google/protobuf/stubs/strutil.h> + namespace google { namespace protobuf { namespace compiler { @@ -50,19 +50,20 @@ void SetStringVariables(const FieldDescriptor* descriptor, std::map<string, string>* variables, const Options& options) { SetCommonFieldVariables(descriptor, variables, options); - (*variables)["default"] = DefaultValue(descriptor); + (*variables)["default"] = DefaultValue(options, descriptor); (*variables)["default_length"] = SimpleItoa(descriptor->default_value_string().length()); string default_variable_string = MakeDefaultName(descriptor); (*variables)["default_variable_name"] = default_variable_string; (*variables)["default_variable"] = descriptor->default_value_string().empty() - ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()" + ? "&::" + (*variables)["proto_ns"] + + "::internal::GetEmptyStringAlreadyInited()" : "&" + Namespace(descriptor) + "::" + (*variables)["classname"] + "::" + default_variable_string + ".get()"; (*variables)["pointer_type"] = descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; - (*variables)["null_check"] = "GOOGLE_DCHECK(value != NULL);\n"; + (*variables)["null_check"] = (*variables)["DCHK"] + "(value != NULL);\n"; // NOTE: Escaped here to unblock proto1->proto2 migration. // TODO(liujisi): Extend this to apply for other conflicting methods. (*variables)["release_name"] = @@ -70,7 +71,11 @@ void SetStringVariables(const FieldDescriptor* descriptor, descriptor, "release_"); (*variables)["full_name"] = descriptor->full_name(); - (*variables)["string_piece"] = "::std::string"; + if (options.opensource_runtime) { + (*variables)["string_piece"] = "::std::string"; + } else { + (*variables)["string_piece"] = "::StringPiece"; + } (*variables)["lite"] = HasDescriptorMethods(descriptor->file(), options) ? "" : "Lite"; @@ -82,8 +87,7 @@ void SetStringVariables(const FieldDescriptor* descriptor, StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), - descriptor_(descriptor), + : FieldGenerator(descriptor, options), lite_(!HasDescriptorMethods(descriptor->file(), options)), inlined_(false) { @@ -107,9 +111,9 @@ StringFieldGenerator::~StringFieldGenerator() {} void StringFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { + Formatter format(printer, variables_); if (inlined_) { - printer->Print(variables_, - "::google::protobuf::internal::InlinedStringField $name$_;\n"); + format("::$proto_ns$::internal::InlinedStringField $name$_;\n"); } else { // N.B. that we continue to use |ArenaStringPtr| instead of |string*| for // string fields, even when SupportArenas(descriptor_) == false. Why? The @@ -123,25 +127,27 @@ GeneratePrivateMembers(io::Printer* printer) const { // conditionals. It's simpler to stick with this but use lightweight // accessors that assume arena == NULL. There should be very little // overhead anyway because it's just a tagged pointer in-memory. - printer->Print(variables_, "::google::protobuf::internal::ArenaStringPtr $name$_;\n"); + format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n"); } } void StringFieldGenerator:: GenerateStaticMembers(io::Printer* printer) const { + Formatter format(printer, variables_); if (!descriptor_->default_value_string().empty()) { // We make the default instance public, so it can be initialized by // non-friend code. - printer->Print(variables_, - "public:\n" - "static ::google::protobuf::internal::ExplicitlyConstructed< ::std::string>" - " $default_variable_name$;\n" - "private:\n"); + format( + "public:\n" + "static ::$proto_ns$::internal::ExplicitlyConstructed<$string$>" + " $default_variable_name$;\n" + "private:\n"); } } void StringFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { + Formatter format(printer, variables_); // If we're using StringFieldGenerator for a field with a ctype, it's // because that ctype isn't actually implemented. In particular, this is // true of ctype=CORD and ctype=STRING_PIECE in the open source release. @@ -159,90 +165,82 @@ GenerateAccessorDeclarations(io::Printer* printer) const { // reflection interface since the reflection interface is independent of // the string's underlying representation. - bool unknown_ctype = - descriptor_->options().ctype() != EffectiveStringCType(descriptor_); + bool unknown_ctype = descriptor_->options().ctype() != + EffectiveStringCType(descriptor_, options_); if (unknown_ctype) { - printer->Outdent(); - printer->Print( - " private:\n" - " // Hidden due to unknown ctype option.\n"); - printer->Indent(); + format.Outdent(); + format( + " private:\n" + " // Hidden due to unknown ctype option.\n"); + format.Indent(); } - printer->Print(variables_, - "$deprecated_attr$const ::std::string& $name$() const;\n"); - printer->Annotate("name", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$set_$name$$}$(const ::std::string& value);\n"); - printer->Annotate("{", "}", descriptor_); - - printer->Print(variables_, - "#if LANG_CXX11\n" - "$deprecated_attr$void ${$set_$name$$}$(::std::string&& value);\n" - "#endif\n"); - printer->Annotate("{", "}", descriptor_); - - printer->Print( - variables_, - "$deprecated_attr$void ${$set_$name$$}$(const char* value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_$name$$}$(const $pointer_type$* " - "value, size_t size)" - ";\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::std::string* ${$mutable_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, "$deprecated_attr$::std::string* $release_name$();\n"); - printer->Annotate("release_name", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$set_allocated_$name$$}$(::std::string* $name$);\n"); - printer->Annotate("{", "}", descriptor_); - if (SupportsArenas(descriptor_)) { - printer->Print( - variables_, - "PROTOBUF_RUNTIME_DEPRECATED(\"The unsafe_arena_ accessors for\"\n" - "\" string fields are deprecated and will be removed in a\"\n" - "\" future release.\")\n" - "::std::string* ${$unsafe_arena_release_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "PROTOBUF_RUNTIME_DEPRECATED(\"The unsafe_arena_ accessors for\"\n" - "\" string fields are deprecated and will be removed in a\"\n" - "\" future release.\")\n" - "void ${$unsafe_arena_set_allocated_$name$$}$(\n" - " ::std::string* $name$);\n"); - printer->Annotate("{", "}", descriptor_); + format( + "$deprecated_attr$const $string$& ${1$$name$$}$() const;\n" + "$deprecated_attr$void ${1$set_$name$$}$(const $string$& value);\n" + "#if LANG_CXX11\n" + "$deprecated_attr$void ${1$set_$name$$}$($string$&& value);\n" + "#endif\n" + "$deprecated_attr$void ${1$set_$name$$}$(const char* value);\n", + descriptor_); + if (!options_.opensource_runtime) { + format( + "$deprecated_attr$void ${1$set_$name$$}$(::StringPiece value);\n" + "#ifdef HAS_GLOBAL_STRING\n" + "$deprecated_attr$void ${1$set_$name$$}$(const ::std::string& value);\n" + "#endif\n", + descriptor_); + } + format( + "$deprecated_attr$void ${1$set_$name$$}$(const $pointer_type$* " + "value, size_t size)" + ";\n" + "$deprecated_attr$$string$* ${1$mutable_$name$$}$();\n" + "$deprecated_attr$$string$* ${1$$release_name$$}$();\n" + "$deprecated_attr$void ${1$set_allocated_$name$$}$($string$* $name$);\n", + descriptor_); + if (options_.opensource_runtime) { + if (SupportsArenas(descriptor_)) { + format( + "$GOOGLE_PROTOBUF$_RUNTIME_DEPRECATED(\"The unsafe_arena_ accessors " + "for\"\n" + "\" string fields are deprecated and will be removed in a\"\n" + "\" future release.\")\n" + "$string$* ${1$unsafe_arena_release_$name$$}$();\n" + "$GOOGLE_PROTOBUF$_RUNTIME_DEPRECATED(\"The unsafe_arena_ accessors " + "for\"\n" + "\" string fields are deprecated and will be removed in a\"\n" + "\" future release.\")\n" + "void ${1$unsafe_arena_set_allocated_$name$$}$(\n" + " $string$* $name$);\n", + descriptor_); + } } if (unknown_ctype) { - printer->Outdent(); - printer->Print(" public:\n"); - printer->Indent(); + format.Outdent(); + format(" public:\n"); + format.Indent(); } } void StringFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { + Formatter format(printer, variables_); if (SupportsArenas(descriptor_)) { - printer->Print( - variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + format( + "inline const $string$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.Get();\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "inline void $classname$::set_$name$(const $string$& value) {\n" " $set_hasbit$\n" " $name$_.Set$lite$($default_variable$, value, GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "#if LANG_CXX11\n" - "inline void $classname$::set_$name$(::std::string&& value) {\n" + "inline void $classname$::set_$name$($string$&& value) {\n" " $set_hasbit$\n" " $name$_.Set$lite$(\n" " $default_variable$, ::std::move(value), GetArenaNoVirtual());\n" @@ -255,7 +253,26 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $name$_.Set$lite$($default_variable$, $string_piece$(value),\n" " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n" + "}\n"); + if (!options_.opensource_runtime) { + format( + "inline void $classname$::set_$name$(::StringPiece value) {\n" + " $set_hasbit$\n" + " $name$_.Set$lite$($default_variable$, value, " + "GetArenaNoVirtual());\n" + " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" + "}\n" + "#ifdef HAS_GLOBAL_STRING\n" + "inline void $classname$::set_$name$(const ::std::string& value) {\n" + " $set_hasbit$\n" + " $name$_.Set$lite$($default_variable$, " + "::StringPiece(value.data(),\n" + " value.size()), GetArenaNoVirtual());\n" + " // @@protoc_insertion_point(field_set_std_string:$full_name$)\n" + "}\n" + "#endif\n"); + } + format( "inline " "void $classname$::set_$name$(const $pointer_type$* value,\n" " size_t size) {\n" @@ -265,31 +282,32 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "inline $string$* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "inline $string$* $classname$::$release_name$() {\n" " // @@protoc_insertion_point(field_release:$full_name$)\n"); if (HasFieldPresence(descriptor_->file())) { - printer->Print(variables_, - " if (!has_$name$()) {\n" - " return NULL;\n" - " }\n" - " $clear_hasbit$\n" - " return $name$_.ReleaseNonDefault(" - "$default_variable$, GetArenaNoVirtual());\n"); + format( + " if (!has_$name$()) {\n" + " return NULL;\n" + " }\n" + " $clear_hasbit$\n" + " return $name$_.ReleaseNonDefault(" + "$default_variable$, GetArenaNoVirtual());\n"); } else { - printer->Print(variables_, - " $clear_hasbit$\n" - " return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"); + format( + " $clear_hasbit$\n" + " return $name$_.Release($default_variable$, " + "GetArenaNoVirtual());\n"); } - printer->Print(variables_, + format( "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + "inline void $classname$::set_allocated_$name$($string$* $name$) {\n" " if ($name$ != NULL) {\n" " $set_hasbit$\n" " } else {\n" @@ -298,43 +316,45 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $name$_.SetAllocated($default_variable$, $name$,\n" " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n" - "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n" - " // " - "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" - " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" - " $clear_hasbit$\n" - " return $name$_.UnsafeArenaRelease($default_variable$,\n" - " GetArenaNoVirtual());\n" - "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$(\n" - " ::std::string* $name$) {\n" - " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" - " if ($name$ != NULL) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - " $name$_.UnsafeArenaSetAllocated($default_variable$,\n" - " $name$, GetArenaNoVirtual());\n" - " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" - "$full_name$)\n" "}\n"); + if (options_.opensource_runtime) { + format( + "inline $string$* $classname$::unsafe_arena_release_$name$() {\n" + " // " + "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" + " $DCHK$(GetArenaNoVirtual() != NULL);\n" + " $clear_hasbit$\n" + " return $name$_.UnsafeArenaRelease($default_variable$,\n" + " GetArenaNoVirtual());\n" + "}\n" + "inline void $classname$::unsafe_arena_set_allocated_$name$(\n" + " $string$* $name$) {\n" + " $DCHK$(GetArenaNoVirtual() != NULL);\n" + " if ($name$ != NULL) {\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" + " }\n" + " $name$_.UnsafeArenaSetAllocated($default_variable$,\n" + " $name$, GetArenaNoVirtual());\n" + " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" + "$full_name$)\n" + "}\n"); + } } else { // No-arena case. - printer->Print( - variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + format( + "inline const $string$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.GetNoArena();\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "inline void $classname$::set_$name$(const $string$& value) {\n" " $set_hasbit$\n" " $name$_.SetNoArena($default_variable$, value);\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "#if LANG_CXX11\n" - "inline void $classname$::set_$name$(::std::string&& value) {\n" + "inline void $classname$::set_$name$($string$&& value) {\n" " $set_hasbit$\n" " $name$_.SetNoArena(\n" " $default_variable$, ::std::move(value));\n" @@ -346,7 +366,24 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $set_hasbit$\n" " $name$_.SetNoArena($default_variable$, $string_piece$(value));\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n" + "}\n"); + if (!options_.opensource_runtime) { + format( + "inline void $classname$::set_$name$(::StringPiece value) {\n" + " $set_hasbit$\n" + " $name$_.SetNoArena($default_variable$, value);\n" + " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" + "}\n" + "#ifdef HAS_GLOBAL_STRING\n" + "inline void $classname$::set_$name$(const ::std::string& value) {\n" + " $set_hasbit$\n" + " $name$_.SetNoArena($default_variable$,\n" + " ::StringPiece(value.data(), value.size()));\n" + " // @@protoc_insertion_point(field_set_std_string:$full_name$)\n" + "}\n" + "#endif\n"); + } + format( "inline " "void $classname$::set_$name$(const $pointer_type$* value, " "size_t size) {\n" @@ -355,30 +392,30 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $string_piece$(reinterpret_cast<const char*>(value), size));\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "inline $string$* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.MutableNoArena($default_variable$);\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "inline $string$* $classname$::$release_name$() {\n" " // @@protoc_insertion_point(field_release:$full_name$)\n"); if (HasFieldPresence(descriptor_->file())) { - printer->Print(variables_, - " if (!has_$name$()) {\n" - " return NULL;\n" - " }\n" - " $clear_hasbit$\n" - " return $name$_.ReleaseNonDefaultNoArena($default_variable$);\n"); + format( + " if (!has_$name$()) {\n" + " return NULL;\n" + " }\n" + " $clear_hasbit$\n" + " return $name$_.ReleaseNonDefaultNoArena($default_variable$);\n"); } else { - printer->Print(variables_, - " $clear_hasbit$\n" - " return $name$_.ReleaseNoArena($default_variable$);\n"); + format( + " $clear_hasbit$\n" + " return $name$_.ReleaseNoArena($default_variable$);\n"); } - printer->Print(variables_, + format( "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + "inline void $classname$::set_allocated_$name$($string$* $name$) {\n" " if ($name$ != NULL) {\n" " $set_hasbit$\n" " } else {\n" @@ -392,41 +429,42 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { void StringFieldGenerator:: GenerateNonInlineAccessorDefinitions(io::Printer* printer) const { + Formatter format(printer, variables_); if (!descriptor_->default_value_string().empty()) { // Initialized in GenerateDefaultInstanceAllocator. - printer->Print(variables_, - "::google::protobuf::internal::ExplicitlyConstructed<::std::string> " - "$classname$::$default_variable_name$;\n"); + format( + "::$proto_ns$::internal::ExplicitlyConstructed<$string$> " + "$classname$::$default_variable_name$;\n"); } } void StringFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); // Two-dimension specialization here: supporting arenas or not, and default // value is the empty string or not. Complexity here ensures the minimal // number of branches / amount of extraneous code at runtime (given that the // below methods are inlined one-liners)! if (SupportsArenas(descriptor_)) { if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n"); + format( + "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n"); } else { - printer->Print(variables_, - "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n"); + format( + "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n"); } } else { if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "$name$_.ClearToEmptyNoArena($default_variable$);\n"); + format("$name$_.ClearToEmptyNoArena($default_variable$);\n"); } else { - printer->Print(variables_, - "$name$_.ClearToDefaultNoArena($default_variable$);\n"); + format("$name$_.ClearToDefaultNoArena($default_variable$);\n"); } } } void StringFieldGenerator:: GenerateMessageClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); // Two-dimension specialization here: supporting arenas, field presence, or // not, and default value is the empty string or not. Complexity here ensures // the minimal number of branches / amount of extraneous code at runtime @@ -447,67 +485,60 @@ GenerateMessageClearingCode(io::Printer* printer) const { // // For non-inlined strings, we distinguish from non-default by comparing // instances, rather than contents. - printer->Print(variables_, - "GOOGLE_DCHECK(!$name$_.IsDefault($default_variable$));\n"); + format("$DCHK$(!$name$_.IsDefault($default_variable$));\n"); } if (SupportsArenas(descriptor_)) { if (descriptor_->default_value_string().empty()) { if (must_be_present) { - printer->Print(variables_, - "$name$_.ClearNonDefaultToEmpty();\n"); + format("$name$_.ClearNonDefaultToEmpty();\n"); } else { - printer->Print(variables_, - "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n"); + format( + "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n"); } } else { // Clear to a non-empty default is more involved, as we try to use the // Arena if one is present and may need to reallocate the string. - printer->Print(variables_, - "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n"); + format( + "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n"); } } else if (must_be_present) { // When Arenas are disabled and field presence has been checked, we can // safely treat the ArenaStringPtr as a string*. if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, "$name$_.ClearNonDefaultToEmptyNoArena();\n"); + format("$name$_.ClearNonDefaultToEmptyNoArena();\n"); } else { - printer->Print( - variables_, - "$name$_.UnsafeMutablePointer()->assign(*$default_variable$);\n"); + format("$name$_.UnsafeMutablePointer()->assign(*$default_variable$);\n"); } } else { if (descriptor_->default_value_string().empty()) { - printer->Print(variables_, - "$name$_.ClearToEmptyNoArena($default_variable$);\n"); + format("$name$_.ClearToEmptyNoArena($default_variable$);\n"); } else { - printer->Print(variables_, - "$name$_.ClearToDefaultNoArena($default_variable$);\n"); + format("$name$_.ClearToDefaultNoArena($default_variable$);\n"); } } } void StringFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { + Formatter format(printer, variables_); if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) { // TODO(gpike): improve this - printer->Print(variables_, "set_$name$(from.$name$());\n"); + format("set_$name$(from.$name$());\n"); } else { - printer->Print(variables_, - "$set_hasbit$\n" - "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n"); + format( + "$set_hasbit$\n" + "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n"); } } void StringFieldGenerator:: GenerateSwappingCode(io::Printer* printer) const { + Formatter format(printer, variables_); if (inlined_) { - printer->Print( - variables_, - "$name$_.Swap(&other->$name$_);\n"); + format("$name$_.Swap(&other->$name$_);\n"); } else { - printer->Print( - variables_, + format( "$name$_.Swap(&other->$name$_, $default_variable$,\n" " GetArenaNoVirtual());\n"); } @@ -515,6 +546,7 @@ GenerateSwappingCode(io::Printer* printer) const { void StringFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { + Formatter format(printer, variables_); // TODO(ckennelly): Construct non-empty strings as part of the initializer // list. if (inlined_ && descriptor_->default_value_string().empty()) { @@ -522,125 +554,149 @@ GenerateConstructorCode(io::Printer* printer) const { return; } - printer->Print(variables_, - "$name$_.UnsafeSetDefault($default_variable$);\n"); + format("$name$_.UnsafeSetDefault($default_variable$);\n"); } void StringFieldGenerator:: GenerateCopyConstructorCode(io::Printer* printer) const { + Formatter format(printer, variables_); GenerateConstructorCode(printer); if (HasFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if (from.has_$name$()) {\n"); + format("if (from.has_$name$()) {\n"); } else { - printer->Print(variables_, - "if (from.$name$().size() > 0) {\n"); + format("if (from.$name$().size() > 0) {\n"); } - printer->Indent(); + format.Indent(); if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) { // TODO(gpike): improve this - printer->Print(variables_, - "$name$_.Set$lite$($default_variable$, from.$name$(),\n" - " GetArenaNoVirtual());\n"); + format( + "$name$_.Set$lite$($default_variable$, from.$name$(),\n" + " GetArenaNoVirtual());\n"); } else { - printer->Print(variables_, - "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n"); + format("$name$_.AssignWithDefault($default_variable$, from.$name$_);\n"); } - printer->Outdent(); - printer->Print("}\n"); + format.Outdent(); + format("}\n"); } void StringFieldGenerator:: GenerateDestructorCode(io::Printer* printer) const { + Formatter format(printer, variables_); if (inlined_) { // The destructor is automatically invoked. return; } - printer->Print(variables_, "$name$_.DestroyNoArena($default_variable$);\n"); + format("$name$_.DestroyNoArena($default_variable$);\n"); } bool StringFieldGenerator::GenerateArenaDestructorCode( io::Printer* printer) const { + Formatter format(printer, variables_); if (!inlined_) { return false; } - printer->Print(variables_, - "_this->$name$_.DestroyNoArena($default_variable$);\n"); + format("_this->$name$_.DestroyNoArena($default_variable$);\n"); return true; } void StringFieldGenerator:: GenerateDefaultInstanceAllocator(io::Printer* printer) const { + Formatter format(printer, variables_); if (!descriptor_->default_value_string().empty()) { - printer->Print( - variables_, + format( "$ns$::$classname$::$default_variable_name$.DefaultConstruct();\n" "*$ns$::$classname$::$default_variable_name$.get_mutable() = " - "::std::string($default$, $default_length$);\n" - "::google::protobuf::internal::OnShutdownDestroyString(\n" - " $ns$::$classname$::$default_variable_name$.get_mutable());\n" - ); + "$string$($default$, $default_length$);\n" + "::$proto_ns$::internal::OnShutdownDestroyString(\n" + " $ns$::$classname$::$default_variable_name$.get_mutable());\n"); } } void StringFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" - " input, this->mutable_$name$()));\n"); + Formatter format(printer, variables_); + // The google3 version of proto2 has ArenaStrings and parses into them + // directly, but for the open-source release, we always parse into ::std::string + // instances. Note that for lite, we do similarly to the open source release + // and use ::std::string, not ArenaString. + if (!options_.opensource_runtime && !inlined_ && + SupportsArenas(descriptor_) && !lite_) { + // If arena != NULL, the current string is either an ArenaString (no + // destructor necessary) or a materialized ::std::string (and is on the Arena's + // destructor list). No call to ArenaStringPtr::Destroy is needed. + format( + "if (arena != NULL) {\n" + " ::$proto_ns$::internal::TaggedPtr<$string$> str =\n" + " ::$proto_ns$::internal::ReadArenaString(input, arena);\n" + " DO_(!str.IsNull());\n" + " $set_hasbit_io$\n" + " $name$_.UnsafeSetTaggedPointer(str);\n" + "} else {\n" + " DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n" + " input, this->mutable_$name$()));\n" + "}\n"); + } else { + format( + "DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n" + " input, this->mutable_$name$()));\n"); + } if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, options_, true, variables_, + descriptor_, options_, true, "this->$name$().data(), static_cast<int>(this->$name$().length()),\n", - printer); + format); } } bool StringFieldGenerator:: MergeFromCodedStreamNeedsArena() const { - return false; + return !lite_ && !inlined_ && !options_.opensource_runtime; } void StringFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { + Formatter format(printer, variables_); if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, options_, false, variables_, + descriptor_, options_, false, "this->$name$().data(), static_cast<int>(this->$name$().length()),\n", - printer); + format); } - printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n" - " $number$, this->$name$(), output);\n"); + format( + "::$proto_ns$::internal::WireFormatLite::Write$declared_type$" + "MaybeAliased(\n" + " $number$, this->$name$(), output);\n"); } void StringFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + Formatter format(printer, variables_); if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, options_, false, variables_, + descriptor_, options_, false, "this->$name$().data(), static_cast<int>(this->$name$().length()),\n", - printer); + format); } - printer->Print(variables_, - "target =\n" - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n" - " $number$, this->$name$(), target);\n"); + format( + "target =\n" + " ::$proto_ns$::internal::WireFormatLite::Write$declared_type$ToArray(\n" + " $number$, this->$name$(), target);\n"); } void StringFieldGenerator:: GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" - " this->$name$());\n"); + Formatter format(printer, variables_); + format( + "total_size += $tag_size$ +\n" + " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" + " this->$name$());\n"); } uint32 StringFieldGenerator::CalculateFieldTag() const { @@ -661,17 +717,17 @@ StringOneofFieldGenerator::~StringOneofFieldGenerator() {} void StringOneofFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { + Formatter format(printer, variables_); if (SupportsArenas(descriptor_)) { - printer->Print( - variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + format( + "inline const $string$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" " return $field_member$.Get();\n" " }\n" " return *$default_variable$;\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "inline void $classname$::set_$name$(const $string$& value) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -682,7 +738,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "#if LANG_CXX11\n" - "inline void $classname$::set_$name$(::std::string&& value) {\n" + "inline void $classname$::set_$name$($string$&& value) {\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" @@ -704,7 +760,34 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $field_member$.Set$lite$($default_variable$,\n" " $string_piece$(value), GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n" + "}\n"); + if (!options_.opensource_runtime) { + format( + "inline void $classname$::set_$name$(::StringPiece value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " }\n" + " $field_member$.Set$lite$($default_variable$, value,\n" + " GetArenaNoVirtual());\n" + " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" + "}\n" + "#ifdef HAS_GLOBAL_STRING\n" + "inline void $classname$::set_$name$(const ::std::string& value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " }\n" + " $field_member$.Set$lite$($default_variable$,\n" + " ::StringPiece(value.data(), value.size()), " + "GetArenaNoVirtual());\n" + " // @@protoc_insertion_point(field_set_std_string:$full_name$)\n" + "}\n" + "#endif\n"); + } + format( "inline " "void $classname$::set_$name$(const $pointer_type$* value,\n" " size_t size) {\n" @@ -719,7 +802,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "inline $string$* $classname$::mutable_$name$() {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -729,7 +812,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "inline $string$* $classname$::$release_name$() {\n" " // @@protoc_insertion_point(field_release:$full_name$)\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" @@ -739,57 +822,57 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" - " if (!has_$name$()) {\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" + "inline void $classname$::set_allocated_$name$($string$* $name$) {\n" + " if (has_$oneof_name$()) {\n" + " clear_$oneof_name$();\n" " }\n" - " clear_$oneof_name$();\n" " if ($name$ != NULL) {\n" " set_has_$name$();\n" - " $field_member$.SetAllocated($default_variable$, $name$,\n" - " GetArenaNoVirtual());\n" + " $field_member$.UnsafeSetDefault($name$);\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n" - "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n" - " // " - "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" - " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" - " if (has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " return $field_member$.UnsafeArenaRelease(\n" - " $default_variable$, GetArenaNoVirtual());\n" - " } else {\n" - " return NULL;\n" - " }\n" - "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$(" - "::std::string* $name$) {\n" - " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" - " if (!has_$name$()) {\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" - " }\n" - " clear_$oneof_name$();\n" - " if ($name$) {\n" - " set_has_$name$();\n" - " $field_member$.UnsafeArenaSetAllocated($default_variable$, " - "$name$, GetArenaNoVirtual());\n" - " }\n" - " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" - "$full_name$)\n" "}\n"); + if (options_.opensource_runtime) { + format( + "inline $string$* $classname$::unsafe_arena_release_$name$() {\n" + " // " + "@@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n" + " $DCHK$(GetArenaNoVirtual() != NULL);\n" + " if (has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " return $field_member$.UnsafeArenaRelease(\n" + " $default_variable$, GetArenaNoVirtual());\n" + " } else {\n" + " return NULL;\n" + " }\n" + "}\n" + "inline void $classname$::unsafe_arena_set_allocated_$name$(" + "$string$* $name$) {\n" + " $DCHK$(GetArenaNoVirtual() != NULL);\n" + " if (!has_$name$()) {\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " }\n" + " clear_$oneof_name$();\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " $field_member$.UnsafeArenaSetAllocated($default_variable$, " + "$name$, GetArenaNoVirtual());\n" + " }\n" + " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:" + "$full_name$)\n" + "}\n"); + } } else { // No-arena case. - printer->Print( - variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + format( + "inline const $string$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" " return $field_member$.GetNoArena();\n" " }\n" " return *$default_variable$;\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "inline void $classname$::set_$name$(const $string$& value) {\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" @@ -800,7 +883,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "#if LANG_CXX11\n" - "inline void $classname$::set_$name$(::std::string&& value) {\n" + "inline void $classname$::set_$name$($string$&& value) {\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" @@ -821,7 +904,32 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $field_member$.SetNoArena($default_variable$,\n" " $string_piece$(value));\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n" + "}\n"); + if (!options_.opensource_runtime) { + format( + "inline void $classname$::set_$name$(::StringPiece value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " }\n" + " $field_member$.SetNoArena($default_variable$, value);\n" + " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" + "}\n" + "#ifdef HAS_GLOBAL_STRING\n" + "inline void $classname$::set_$name$(const ::std::string& value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " }\n" + " $field_member$.SetNoArena($default_variable$,\n" + " ::StringPiece(value.data(), value.size()));\n" + " // @@protoc_insertion_point(field_set_std_string:$full_name$)\n" + "}\n" + "#endif\n"); + } + format( "inline " "void $classname$::set_$name$(const $pointer_type$* value, size_t " "size) {\n" @@ -834,7 +942,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " reinterpret_cast<const char*>(value), size));\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "inline $string$* $classname$::mutable_$name$() {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -843,7 +951,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $field_member$.MutableNoArena($default_variable$);\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "inline $string$* $classname$::$release_name$() {\n" " // @@protoc_insertion_point(field_release:$full_name$)\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" @@ -852,14 +960,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" - " if (!has_$name$()) {\n" - " $field_member$.UnsafeSetDefault($default_variable$);\n" + "inline void $classname$::set_allocated_$name$($string$* $name$) {\n" + " if (has_$oneof_name$()) {\n" + " clear_$oneof_name$();\n" " }\n" - " clear_$oneof_name$();\n" " if ($name$ != NULL) {\n" " set_has_$name$();\n" - " $field_member$.SetAllocatedNoArena($default_variable$, $name$);\n" + " $field_member$.UnsafeSetDefault($name$);\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); @@ -868,13 +975,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { void StringOneofFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { + Formatter format(printer, variables_); if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "$field_member$.Destroy($default_variable$,\n" - " GetArenaNoVirtual());\n"); + format( + "$field_member$.Destroy($default_variable$,\n" + " GetArenaNoVirtual());\n"); } else { - printer->Print(variables_, - "$field_member$.DestroyNoArena($default_variable$);\n"); + format("$field_member$.DestroyNoArena($default_variable$);\n"); } } @@ -890,31 +997,55 @@ GenerateSwappingCode(io::Printer* printer) const { void StringOneofFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { - printer->Print( - variables_, + Formatter format(printer, variables_); + format( "$ns$::_$classname$_default_instance_.$name$_.UnsafeSetDefault(\n" " $default_variable$);\n"); } void StringOneofFieldGenerator:: GenerateDestructorCode(io::Printer* printer) const { - printer->Print(variables_, - "if (has_$name$()) {\n" - " $field_member$.DestroyNoArena($default_variable$);\n" - "}\n"); + Formatter format(printer, variables_); + format( + "if (has_$name$()) {\n" + " $field_member$.DestroyNoArena($default_variable$);\n" + "}\n"); } void StringOneofFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" - " input, this->mutable_$name$()));\n"); + Formatter format(printer, variables_); + // See above: ArenaString is not included in the open-source release. + if (!options_.opensource_runtime && SupportsArenas(descriptor_) && !lite_) { + // If has_$name$(), then the current string is either an ArenaString (no + // destructor necessary) or a materialized ::std::string (and is on the Arena's + // destructor list). No call to ArenaStringPtr::Destroy is needed. + format( + "if (arena != NULL) {\n" + " clear_$oneof_name$();\n" + " if (!has_$name$()) {\n" + " $field_member$.UnsafeSetDefault($default_variable$);\n" + " set_has_$name$();\n" + " }\n" + " ::$proto_ns$::internal::TaggedPtr<$string$> new_value =\n" + " ::$proto_ns$::internal::ReadArenaString(input, arena);\n" + " DO_(!new_value.IsNull());\n" + " $field_member$.UnsafeSetTaggedPointer(new_value);\n" + "} else {\n" + " DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n" + " input, this->mutable_$name$()));\n" + "}\n"); + } else { + format( + "DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n" + " input, this->mutable_$name$()));\n"); + } if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, options_, true, variables_, + descriptor_, options_, true, "this->$name$().data(), static_cast<int>(this->$name$().length()),\n", - printer); + format); } } @@ -923,7 +1054,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { RepeatedStringFieldGenerator::RepeatedStringFieldGenerator( const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(options), descriptor_(descriptor) { + : FieldGenerator(descriptor, options) { SetStringVariables(descriptor, &variables_, options); } @@ -931,182 +1062,210 @@ RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {} void RepeatedStringFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { - printer->Print(variables_, - "::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n"); + Formatter format(printer, variables_); + format("::$proto_ns$::RepeatedPtrField<$string$> $name$_;\n"); } void RepeatedStringFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { + Formatter format(printer, variables_); // See comment above about unknown ctypes. - bool unknown_ctype = - descriptor_->options().ctype() != EffectiveStringCType(descriptor_); + bool unknown_ctype = descriptor_->options().ctype() != + EffectiveStringCType(descriptor_, options_); if (unknown_ctype) { - printer->Outdent(); - printer->Print( - " private:\n" - " // Hidden due to unknown ctype option.\n"); - printer->Indent(); + format.Outdent(); + format( + " private:\n" + " // Hidden due to unknown ctype option.\n"); + format.Indent(); } - printer->Print(variables_, - "$deprecated_attr$const ::std::string& $name$(int index) const;\n"); - printer->Annotate("name", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$::std::string* ${$mutable_$name$$}$(int index);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_$name$$}$(int index, const " - "::std::string& value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, + format( + "$deprecated_attr$const $string$& ${1$$name$$}$(int index) const;\n" + "$deprecated_attr$$string$* ${1$mutable_$name$$}$(int index);\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, const " + "$string$& value);\n" + "#if LANG_CXX11\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, $string$&& value);\n" + "#endif\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, const " + "char* value);\n", + descriptor_); + if (!options_.opensource_runtime) { + format( + "$deprecated_attr$void ${1$set_$name$$}$(int index, " + "StringPiece value);\n" + "#ifdef HAS_GLOBAL_STRING\n" + "$deprecated_attr$void ${1$set_$name$$}$(int index, const " + "::std::string& value);\n" + "#endif\n", + descriptor_); + } + format( + "$deprecated_attr$void ${1$set_$name$$}$(" + "int index, const $pointer_type$* value, size_t size);\n" + "$deprecated_attr$$string$* ${1$add_$name$$}$();\n" + "$deprecated_attr$void ${1$add_$name$$}$(const $string$& value);\n" "#if LANG_CXX11\n" - "$deprecated_attr$void ${$set_$name$$}$(int index, ::std::string&& value);\n" - "#endif\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$set_$name$$}$(int index, const " - "char* value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "" - "$deprecated_attr$void ${$set_$name$$}$(" - "int index, const $pointer_type$* value, size_t size);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::std::string* ${$add_$name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$add_$name$$}$(const ::std::string& value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "#if LANG_CXX11\n" - "$deprecated_attr$void ${$add_$name$$}$(::std::string&& value);\n" - "#endif\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$void ${$add_$name$$}$(const char* value);\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print(variables_, - "$deprecated_attr$void ${$add_$name$$}$(const $pointer_type$* " - "value, size_t size)" - ";\n"); - printer->Annotate("{", "}", descriptor_); - printer->Print( - variables_, - "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() " - "const;\n"); - printer->Annotate("name", descriptor_); - printer->Print(variables_, - "$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* " - "${$mutable_$name$$}$()" - ";\n"); - printer->Annotate("{", "}", descriptor_); + "$deprecated_attr$void ${1$add_$name$$}$($string$&& value);\n" + "#endif\n" + "$deprecated_attr$void ${1$add_$name$$}$(const char* value);\n", + descriptor_); + if (!options_.opensource_runtime) { + format( + "$deprecated_attr$void ${1$add_$name$$}$(StringPiece value);\n" + "#ifdef HAS_GLOBAL_STRING\n" + "$deprecated_attr$void ${1$add_$name$$}$(const ::std::string& value);\n" + "#endif\n", + descriptor_); + } + format( + "$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* " + "value, size_t size)" + ";\n" + "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField<$string$>& " + "${1$$name$$}$() " + "const;\n" + "$deprecated_attr$::$proto_ns$::RepeatedPtrField<$string$>* " + "${1$mutable_$name$$}$()" + ";\n", + descriptor_); if (unknown_ctype) { - printer->Outdent(); - printer->Print(" public:\n"); - printer->Indent(); + format.Outdent(); + format(" public:\n"); + format.Indent(); } } void RepeatedStringFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { + Formatter format(printer, variables_); if (options_.safe_boundary_check) { - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.InternalCheckedGet(\n" - " index, ::google::protobuf::internal::GetEmptyStringAlreadyInited());\n" - "}\n"); + format( + "inline const $string$& $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $name$_.InternalCheckedGet(\n" + " index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n" + "}\n"); } else { - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$(int index) const {\n" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return $name$_.Get(index);\n" + format( + "inline const $string$& $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" + " return $name$_.Get(index);\n" + "}\n"); + } + format( + "inline $string$* $classname$::mutable_$name$(int index) {\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" + " return $name$_.Mutable(index);\n" + "}\n" + "inline void $classname$::set_$name$(int index, const $string$& value) " + "{\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + " $name$_.Mutable(index)->assign(value);\n" + "}\n" + "#if LANG_CXX11\n" + "inline void $classname$::set_$name$(int index, $string$&& value) {\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" + " $name$_.Mutable(index)->assign(std::move(value));\n" + "}\n" + "#endif\n" + "inline void $classname$::set_$name$(int index, const char* value) {\n" + " $null_check$" + " $name$_.Mutable(index)->assign(value);\n" + " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n"); + if (!options_.opensource_runtime) { + format( + "inline void " + "$classname$::set_$name$(int index, StringPiece value) {\n" + " $name$_.Mutable(index)->assign(value.data(), value.size());\n" + " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" + "}\n" + "#ifdef HAS_GLOBAL_STRING\n" + "inline void " + "$classname$::set_$name$(int index, const std::string& value) {\n" + " $name$_.Mutable(index)->assign(value.data(), value.size());\n" + " // @@protoc_insertion_point(field_set_std_string:$full_name$)\n" + "}\n" + "#endif\n"); } - printer->Print(variables_, - "inline ::std::string* $classname$::mutable_$name$(int index) {\n" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $name$_.Mutable(index);\n" - "}\n" - "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - " $name$_.Mutable(index)->assign(value);\n" - "}\n" - "#if LANG_CXX11\n" - "inline void $classname$::set_$name$(int index, ::std::string&& value) {\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - " $name$_.Mutable(index)->assign(std::move(value));\n" - "}\n" - "#endif\n" - "inline void $classname$::set_$name$(int index, const char* value) {\n" - " $null_check$" - " $name$_.Mutable(index)->assign(value);\n" - " // @@protoc_insertion_point(field_set_char:$full_name$)\n" - "}\n" - "inline void " - "$classname$::set_$name$" - "(int index, const $pointer_type$* value, size_t size) {\n" - " $name$_.Mutable(index)->assign(\n" - " reinterpret_cast<const char*>(value), size);\n" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "inline ::std::string* $classname$::add_$name$() {\n" - " // @@protoc_insertion_point(field_add_mutable:$full_name$)\n" - " return $name$_.Add();\n" - "}\n" - "inline void $classname$::add_$name$(const ::std::string& value) {\n" - " $name$_.Add()->assign(value);\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "#if LANG_CXX11\n" - "inline void $classname$::add_$name$(::std::string&& value) {\n" - " $name$_.Add(std::move(value));\n" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "#endif\n" - "inline void $classname$::add_$name$(const char* value) {\n" - " $null_check$" - " $name$_.Add()->assign(value);\n" - " // @@protoc_insertion_point(field_add_char:$full_name$)\n" - "}\n" - "inline void " - "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" - " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n" - " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" - "}\n" - "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" - "$classname$::$name$() const {\n" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $name$_;\n" - "}\n" - "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n" - "$classname$::mutable_$name$() {\n" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$name$_;\n" - "}\n"); + format( + "inline void " + "$classname$::set_$name$" + "(int index, const $pointer_type$* value, size_t size) {\n" + " $name$_.Mutable(index)->assign(\n" + " reinterpret_cast<const char*>(value), size);\n" + " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" + "}\n" + "inline $string$* $classname$::add_$name$() {\n" + " // @@protoc_insertion_point(field_add_mutable:$full_name$)\n" + " return $name$_.Add();\n" + "}\n" + "inline void $classname$::add_$name$(const $string$& value) {\n" + " $name$_.Add()->assign(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" + "}\n" + "#if LANG_CXX11\n" + "inline void $classname$::add_$name$($string$&& value) {\n" + " $name$_.Add(std::move(value));\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" + "}\n" + "#endif\n" + "inline void $classname$::add_$name$(const char* value) {\n" + " $null_check$" + " $name$_.Add()->assign(value);\n" + " // @@protoc_insertion_point(field_add_char:$full_name$)\n" + "}\n"); + if (!options_.opensource_runtime) { + format( + "inline void $classname$::add_$name$(StringPiece value) {\n" + " $name$_.Add()->assign(value.data(), value.size());\n" + " // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n" + "}\n" + "#ifdef HAS_GLOBAL_STRING\n" + "inline void $classname$::add_$name$(const ::std::string& value) {\n" + " $name$_.Add()->assign(value.data(), value.size());\n" + " // @@protoc_insertion_point(field_add_std_string:$full_name$)\n" + "}\n" + "#endif\n"); + } + format( + "inline void " + "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" + " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n" + " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" + "}\n" + "inline const ::$proto_ns$::RepeatedPtrField<$string$>&\n" + "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" + " return $name$_;\n" + "}\n" + "inline ::$proto_ns$::RepeatedPtrField<$string$>*\n" + "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" + " return &$name$_;\n" + "}\n"); } void RepeatedStringFieldGenerator:: GenerateClearingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.Clear();\n"); + Formatter format(printer, variables_); + format("$name$_.Clear();\n"); } void RepeatedStringFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n"); + Formatter format(printer, variables_); + format("$name$_.MergeFrom(from.$name$_);\n"); } void RepeatedStringFieldGenerator:: GenerateSwappingCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_.InternalSwap(CastToBase(&other->$name$_));\n"); + Formatter format(printer, variables_); + format("$name$_.InternalSwap(CastToBase(&other->$name$_));\n"); } void RepeatedStringFieldGenerator:: @@ -1116,68 +1275,72 @@ GenerateConstructorCode(io::Printer* printer) const { void RepeatedStringFieldGenerator:: GenerateCopyConstructorCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.CopyFrom(from.$name$_);"); + Formatter format(printer, variables_); + format("$name$_.CopyFrom(from.$name$_);"); } void RepeatedStringFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { - printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" - " input, this->add_$name$()));\n"); + Formatter format(printer, variables_); + format( + "DO_(::$proto_ns$::internal::WireFormatLite::Read$declared_type$(\n" + " input, this->add_$name$()));\n"); if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, options_, true, variables_, + descriptor_, options_, true, "this->$name$(this->$name$_size() - 1).data(),\n" "static_cast<int>(this->$name$(this->$name$_size() - 1).length()),\n", - printer); + format); } } void RepeatedStringFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); - printer->Indent(); + Formatter format(printer, variables_); + format("for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); + format.Indent(); if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, options_, false, variables_, + descriptor_, options_, false, "this->$name$(i).data(), static_cast<int>(this->$name$(i).length()),\n", - printer); + format); } - printer->Outdent(); - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" - " $number$, this->$name$(i), output);\n" - "}\n"); + format.Outdent(); + format( + " ::$proto_ns$::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(i), output);\n" + "}\n"); } void RepeatedStringFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); - printer->Indent(); + Formatter format(printer, variables_); + format("for (int i = 0, n = this->$name$_size(); i < n; i++) {\n"); + format.Indent(); if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { GenerateUtf8CheckCodeForString( - descriptor_, options_, false, variables_, + descriptor_, options_, false, "this->$name$(i).data(), static_cast<int>(this->$name$(i).length()),\n", - printer); + format); } - printer->Outdent(); - printer->Print(variables_, - " target = ::google::protobuf::internal::WireFormatLite::\n" - " Write$declared_type$ToArray($number$, this->$name$(i), target);\n" - "}\n"); + format.Outdent(); + format( + " target = ::$proto_ns$::internal::WireFormatLite::\n" + " Write$declared_type$ToArray($number$, this->$name$(i), target);\n" + "}\n"); } void RepeatedStringFieldGenerator:: GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "total_size += $tag_size$ *\n" - " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n" - "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n" - " total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" - " this->$name$(i));\n" - "}\n"); + Formatter format(printer, variables_); + format( + "total_size += $tag_size$ *\n" + " ::$proto_ns$::internal::FromIntSize(this->$name$_size());\n" + "for (int i = 0, n = this->$name$_size(); i < n; i++) {\n" + " total_size += " + "::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" + " this->$name$(i));\n" + "}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index 6cbf722f..3a1de551 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -75,8 +75,6 @@ class StringFieldGenerator : public FieldGenerator { bool MergeFromCodedStreamNeedsArena() const; protected: - const FieldDescriptor* descriptor_; - std::map<string, string> variables_; const bool lite_; bool inlined_; @@ -127,15 +125,12 @@ class RepeatedStringFieldGenerator : public FieldGenerator { void GenerateByteSize(io::Printer* printer) const; private: - const FieldDescriptor* descriptor_; - std::map<string, string> variables_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator); }; } // namespace cpp } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 22b759a9..2cf030eb 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -33,7 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. // // To test the code generator, we actually use it to generate code for -// google/protobuf/unittest.proto, then test that. This means that we +// net/proto2/internal/unittest.proto, then test that. This means that we // are actually testing the parser and other parts of the system at the same // time, and that problems in the generator may show up as compile-time errors // rather than unittest failures, which may be surprising. However, testing @@ -60,7 +60,7 @@ #define HELPERS_TEST_NAME HelpersTest #define DESCRIPTOR_INIT_TEST_NAME DescriptorInitializationTest -#define UNITTEST_PROTO_PATH "google/protobuf/unittest.proto" +#define UNITTEST_PROTO_PATH "net/proto2/internal/unittest.proto" #define UNITTEST ::protobuf_unittest #define UNITTEST_IMPORT ::protobuf_unittest_import diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.h b/src/google/protobuf/compiler/cpp/cpp_unittest.h index 69c8f44c..c5dc767a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.h +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.h @@ -46,6 +46,6 @@ namespace google { namespace protobuf { namespace protobuf_unittest {} } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_CPP_UNITTEST_H__ diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.inc b/src/google/protobuf/compiler/cpp/cpp_unittest.inc index ff6354f8..898b1fbb 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.inc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.inc @@ -33,7 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. // // To test the code generator, we actually use it to generate code for -// google/protobuf/unittest.proto, then test that. This means that we +// net/proto2/internal/unittest.proto, then test that. This means that we // are actually testing the parser and other parts of the system at the same // time, and that problems in the generator may show up as compile-time errors // rather than unittest failures, which may be surprising. However, testing @@ -50,6 +50,7 @@ #include <vector> #include <google/protobuf/unittest_no_arena.pb.h> + #if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER) // We exclude this large proto from cmake build because it's too large for // visual studio to compile (report internal errors). @@ -57,7 +58,9 @@ #endif #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h> +#include <google/protobuf/compiler/scc.h> #include <google/protobuf/compiler/importer.h> +#include <google/protobuf/test_util2.h> #include <google/protobuf/unittest_no_generic_services.pb.h> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/zero_copy_stream_impl.h> @@ -72,8 +75,11 @@ #include <google/protobuf/stubs/substitute.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> +#include <google/protobuf/stubs/casts.h> #include <google/protobuf/stubs/stl_util.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { @@ -110,12 +116,12 @@ TEST(GENERATED_DESCRIPTOR_TEST_NAME, IdenticalDescriptors) { // Set up the Importer. MockErrorCollector error_collector; DiskSourceTree source_tree; - source_tree.MapPath("", TestSourceDir()); + source_tree.MapPath("", TestUtil::TestSourceDir()); Importer importer(&source_tree, &error_collector); // Import (parse) unittest.proto. const FileDescriptor* parsed_descriptor = - importer.Import(UNITTEST_PROTO_PATH); + importer.Import(TestUtil::MaybeTranslatePath(UNITTEST_PROTO_PATH)); EXPECT_EQ("", error_collector.text_); ASSERT_TRUE(parsed_descriptor != NULL); @@ -165,21 +171,6 @@ TEST(GENERATED_MESSAGE_TEST_NAME, Defaults) { &message.optional_import_message()); } -#ifndef PROTOBUF_USE_DLLS -TEST(GENERATED_MESSAGE_TEST_NAME, Int32StringConversion) { - EXPECT_EQ("971", Int32ToString(971)); - EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min)); - EXPECT_EQ("2147483647", Int32ToString(kint32max)); -} - -TEST(GENERATED_MESSAGE_TEST_NAME, Int64StringConversion) { - EXPECT_EQ("GOOGLE_LONGLONG(971)", Int64ToString(971)); - EXPECT_EQ("GOOGLE_LONGLONG(-2147483648)", Int64ToString(kint32min)); - EXPECT_EQ("GOOGLE_LONGLONG(~0x7fffffffffffffff)", Int64ToString(kint64min)); - EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max)); -} -#endif // !PROTOBUF_USE_DLLS - TEST(GENERATED_MESSAGE_TEST_NAME, FloatingPointDefaults) { const UNITTEST::TestExtremeDefaultValues& extreme_default = UNITTEST::TestExtremeDefaultValues::default_instance(); @@ -214,7 +205,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, ExtremeSmallIntegerDefault) { const UNITTEST::TestExtremeDefaultValues& extreme_default = UNITTEST::TestExtremeDefaultValues::default_instance(); EXPECT_EQ(~0x7fffffff, kint32min); - EXPECT_EQ(GOOGLE_LONGLONG(~0x7fffffffffffffff), kint64min); + EXPECT_EQ(PROTOBUF_LONGLONG(~0x7fffffffffffffff), kint64min); EXPECT_EQ(kint32min, extreme_default.really_small_int32()); EXPECT_EQ(kint64min, extreme_default.really_small_int64()); } @@ -667,8 +658,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, CopyAssignmentOperator) { TestUtil::ExpectAllFieldsSet(message2); } -#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || \ - !defined(GOOGLE_PROTOBUF_NO_RTTI) +#if !defined(PROTOBUF_TEST_NO_DESCRIPTORS) || PROTOBUF_RTTI TEST(GENERATED_MESSAGE_TEST_NAME, UpcastCopyFrom) { // Test the CopyFrom method that takes in the generic const Message& // parameter. @@ -676,7 +666,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, UpcastCopyFrom) { TestUtil::SetAllFields(&message1); - const Message* source = implicit_cast<const Message*>(&message1); + const Message* source = ::google::protobuf::implicit_cast<const Message*>(&message1); message2.CopyFrom(*source); TestUtil::ExpectAllFieldsSet(message2); @@ -709,7 +699,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, DynamicMessageCopyFrom) { TEST(GENERATED_MESSAGE_TEST_NAME, NonEmptyMergeFrom) { // Test merging with a non-empty message. Code is a modified form - // of that found in google/protobuf/reflection_ops_unittest.cc. + // of that found in net/proto2/internal/reflection_ops_unittest.cc. UNITTEST::TestAllTypes message1, message2; TestUtil::SetAllFields(&message1); @@ -741,7 +731,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, SerializationToArray) { TestUtil::SetAllFields(&message1); int size = message1.ByteSizeLong(); data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); + uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data)); uint8* end = message1.SerializeWithCachedSizesToArray(start); EXPECT_EQ(size, end - start); EXPECT_TRUE(message2.ParseFromString(data)); @@ -755,7 +745,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, PackedFieldsSerializationToArray) { TestUtil::SetPackedFields(&packed_message1); int packed_size = packed_message1.ByteSizeLong(); packed_data.resize(packed_size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&packed_data)); + uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&packed_data)); uint8* end = packed_message1.SerializeWithCachedSizesToArray(start); EXPECT_EQ(packed_size, end - start); EXPECT_TRUE(packed_message2.ParseFromString(packed_data)); @@ -772,7 +762,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, SerializationToStream) { data.resize(size); { // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); message1.SerializeWithCachedSizes(&output_stream); EXPECT_FALSE(output_stream.HadError()); @@ -791,7 +781,7 @@ TEST(GENERATED_MESSAGE_TEST_NAME, PackedFieldsSerializationToStream) { data.resize(size); { // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); message1.SerializeWithCachedSizes(&output_stream); EXPECT_FALSE(output_stream.HadError()); @@ -1872,7 +1862,7 @@ TEST_F(OneofTest, CopyAssignmentOperator) { EXPECT_EQ(message2.foo_message().qux_int(), 123); // Make sure that self-assignment does something sane. - message2 = message2; + message2 = *&message2; // Avoid -Wself-assign. EXPECT_EQ(message2.foo_message().qux_int(), 123); } @@ -1883,7 +1873,7 @@ TEST_F(OneofTest, UpcastCopyFrom) { message1.mutable_foogroup()->set_a(123); EXPECT_TRUE(message1.has_foogroup()); - const Message* source = implicit_cast<const Message*>(&message1); + const Message* source = ::google::protobuf::implicit_cast<const Message*>(&message1); message2.CopyFrom(*source); EXPECT_TRUE(message2.has_foogroup()); @@ -1902,7 +1892,7 @@ TEST_F(OneofTest, SerializationToArray) { message1.set_foo_int(123); int size = message1.ByteSizeLong(); data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); + uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data)); uint8* end = message1.SerializeWithCachedSizesToArray(start); EXPECT_EQ(size, end - start); EXPECT_TRUE(message2.ParseFromString(data)); @@ -1916,7 +1906,7 @@ TEST_F(OneofTest, SerializationToArray) { message1.set_foo_string("foo"); int size = message1.ByteSizeLong(); data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); + uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data)); uint8* end = message1.SerializeWithCachedSizesToArray(start); EXPECT_EQ(size, end - start); EXPECT_TRUE(message2.ParseFromString(data)); @@ -1931,7 +1921,7 @@ TEST_F(OneofTest, SerializationToArray) { message1.set_foo_bytes("qux"); int size = message1.ByteSizeLong(); data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); + uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data)); uint8* end = message1.SerializeWithCachedSizesToArray(start); EXPECT_EQ(size, end - start); EXPECT_TRUE(message2.ParseFromString(data)); @@ -1945,7 +1935,7 @@ TEST_F(OneofTest, SerializationToArray) { message1.set_foo_enum(UNITTEST::TestOneof2::FOO); int size = message1.ByteSizeLong(); data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); + uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data)); uint8* end = message1.SerializeWithCachedSizesToArray(start); EXPECT_EQ(size, end - start); EXPECT_TRUE(message2.ParseFromString(data)); @@ -1959,7 +1949,7 @@ TEST_F(OneofTest, SerializationToArray) { message1.mutable_foo_message()->set_qux_int(234); int size = message1.ByteSizeLong(); data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); + uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data)); uint8* end = message1.SerializeWithCachedSizesToArray(start); EXPECT_EQ(size, end - start); EXPECT_TRUE(message2.ParseFromString(data)); @@ -1973,7 +1963,7 @@ TEST_F(OneofTest, SerializationToArray) { message1.mutable_foogroup()->set_a(345); int size = message1.ByteSizeLong(); data.resize(size); - uint8* start = reinterpret_cast<uint8*>(string_as_array(&data)); + uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data)); uint8* end = message1.SerializeWithCachedSizesToArray(start); EXPECT_EQ(size, end - start); EXPECT_TRUE(message2.ParseFromString(data)); @@ -1998,7 +1988,7 @@ TEST_F(OneofTest, SerializationToStream) { { // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); message1.SerializeWithCachedSizes(&output_stream); EXPECT_FALSE(output_stream.HadError()); @@ -2019,7 +2009,7 @@ TEST_F(OneofTest, SerializationToStream) { { // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); message1.SerializeWithCachedSizes(&output_stream); EXPECT_FALSE(output_stream.HadError()); @@ -2041,7 +2031,7 @@ TEST_F(OneofTest, SerializationToStream) { { // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); message1.SerializeWithCachedSizes(&output_stream); EXPECT_FALSE(output_stream.HadError()); @@ -2062,7 +2052,7 @@ TEST_F(OneofTest, SerializationToStream) { { // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); message1.SerializeWithCachedSizes(&output_stream); EXPECT_FALSE(output_stream.HadError()); @@ -2083,7 +2073,7 @@ TEST_F(OneofTest, SerializationToStream) { { // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); message1.SerializeWithCachedSizes(&output_stream); EXPECT_FALSE(output_stream.HadError()); @@ -2104,7 +2094,7 @@ TEST_F(OneofTest, SerializationToStream) { { // Allow the output stream to buffer only one byte at a time. - io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1); io::CodedOutputStream output_stream(&array_stream); message1.SerializeWithCachedSizes(&output_stream); EXPECT_FALSE(output_stream.HadError()); @@ -2161,7 +2151,7 @@ TEST_F(OneofTest, MergeFrom) { TEST(HELPERS_TEST_NAME, TestSCC) { UNITTEST::TestMutualRecursionA a; - SCCAnalyzer scc_analyzer((Options())); + MessageSCCAnalyzer scc_analyzer((Options())); const SCC* scc = scc_analyzer.GetSCC(a.GetDescriptor()); std::vector<string> names; for (int i = 0; i < scc->descriptors.size(); i++) { @@ -2185,7 +2175,7 @@ TEST(HELPERS_TEST_NAME, TestSCC) { TEST(HELPERS_TEST_NAME, TestSCCAnalysis) { { UNITTEST::TestRecursiveMessage msg; - SCCAnalyzer scc_analyzer((Options())); + MessageSCCAnalyzer scc_analyzer((Options())); const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor()); MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); EXPECT_EQ(result.is_recursive, true); @@ -2195,7 +2185,7 @@ TEST(HELPERS_TEST_NAME, TestSCCAnalysis) { } { UNITTEST::TestAllExtensions msg; - SCCAnalyzer scc_analyzer((Options())); + MessageSCCAnalyzer scc_analyzer((Options())); const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor()); MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); EXPECT_EQ(result.is_recursive, false); @@ -2205,7 +2195,7 @@ TEST(HELPERS_TEST_NAME, TestSCCAnalysis) { } { UNITTEST::TestRequired msg; - SCCAnalyzer scc_analyzer((Options())); + MessageSCCAnalyzer scc_analyzer((Options())); const SCC* scc = scc_analyzer.GetSCC(msg.GetDescriptor()); MessageAnalysis result = scc_analyzer.GetSCCAnalysis(scc); EXPECT_EQ(result.is_recursive, false); @@ -2269,8 +2259,8 @@ TEST(DESCRIPTOR_INIT_TEST_NAME, Initialized) { #endif EXPECT_EQ(should_have_descriptors, - DescriptorPool::generated_pool()->InternalIsFileLoaded( - UNITTEST_PROTO_PATH)); + DescriptorPool::generated_pool()->InternalIsFileLoaded( + TestUtil::MaybeTranslatePath(UNITTEST_PROTO_PATH))); } } // namespace cpp_unittest @@ -2279,3 +2269,5 @@ TEST(DESCRIPTOR_INIT_TEST_NAME, Initialized) { } // namespace compiler } // namespace protobuf } // namespace google + +#include <google/protobuf/port_undef.inc> diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc index 2ad4edd2..77636fe9 100644 --- a/src/google/protobuf/compiler/cpp/metadata_test.cc +++ b/src/google/protobuf/compiler/cpp/metadata_test.cc @@ -42,11 +42,12 @@ #include <gtest/gtest.h> namespace google { -namespace atu = ::google::protobuf::compiler::annotation_test_util; - namespace protobuf { namespace compiler { namespace cpp { + +namespace atu = annotation_test_util; + namespace { class CppMetadataTest : public ::testing::Test { @@ -59,7 +60,7 @@ class CppMetadataTest : public ::testing::Test { string* pb_h, GeneratedCodeInfo* pb_h_info, string* proto_h, GeneratedCodeInfo* proto_h_info, string* pb_cc) { - google::protobuf::compiler::CommandLineInterface cli; + CommandLineInterface cli; CppGenerator cpp_generator; cli.RegisterGenerator("--cpp_out", &cpp_generator, ""); string cpp_out = diff --git a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc index 8c38e52f..33c56198 100644 --- a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc @@ -90,7 +90,7 @@ class MockGeneratorContext : public GeneratorContext { string actual_contents; GOOGLE_CHECK_OK( - File::GetContents(TestSourceDir() + "/" + physical_filename, + File::GetContentsAsText(TestSourceDir() + "/" + physical_filename, &actual_contents, true)) << "Unable to get " << physical_filename; EXPECT_TRUE(actual_contents == *expected_contents) diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.h b/src/google/protobuf/compiler/csharp/csharp_enum.h index 8925cdf2..5170d839 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum.h @@ -35,6 +35,8 @@ #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/compiler/csharp/csharp_source_generator_base.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/io/printer.h> namespace google { namespace protobuf { diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 9ceffa8c..df599614 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -47,8 +47,8 @@ namespace compiler { namespace csharp { EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, const Options *options) - : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) { + int presenceIndex, const Options *options) + : PrimitiveFieldGenerator(descriptor, presenceIndex, options) { } EnumFieldGenerator::~EnumFieldGenerator() { @@ -56,7 +56,7 @@ EnumFieldGenerator::~EnumFieldGenerator() { void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print(variables_, - "$name$_ = ($type_name$) input.ReadEnum();\n"); + "$property_name$ = ($type_name$) input.ReadEnum();\n"); } void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { @@ -82,8 +82,8 @@ void EnumFieldGenerator::GenerateCodecCode(io::Printer* printer) { } EnumOneofFieldGenerator::EnumOneofFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options) { } EnumOneofFieldGenerator::~EnumOneofFieldGenerator() { diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h index 631632bc..bfb9bc81 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h @@ -44,7 +44,7 @@ namespace csharp { class EnumFieldGenerator : public PrimitiveFieldGenerator { public: EnumFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~EnumFieldGenerator(); @@ -60,7 +60,7 @@ class EnumFieldGenerator : public PrimitiveFieldGenerator { class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator { public: EnumOneofFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~EnumOneofFieldGenerator(); diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 7e737e47..f8808264 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -57,6 +57,9 @@ void FieldGeneratorBase::SetCommonFieldVariables( // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which // never effects the tag size. int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); + if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { + tag_size /= 2; + } uint tag = internal::WireFormat::MakeTag(descriptor_); uint8 tag_array[5]; io::CodedOutputStream::WriteTagToArray(tag, tag_array); @@ -75,34 +78,52 @@ void FieldGeneratorBase::SetCommonFieldVariables( (*variables)["name"] = name(); (*variables)["descriptor_name"] = descriptor_->name(); (*variables)["default_value"] = default_value(); - if (has_default_value()) { + (*variables)["capitalized_type_name"] = capitalized_type_name(); + (*variables)["number"] = number(); + if (has_default_value() && !IsProto2(descriptor_->file())) { (*variables)["name_def_message"] = (*variables)["name"] + "_ = " + (*variables)["default_value"]; } else { (*variables)["name_def_message"] = (*variables)["name"] + "_"; } - (*variables)["capitalized_type_name"] = capitalized_type_name(); - (*variables)["number"] = number(); - (*variables)["has_property_check"] = - (*variables)["property_name"] + " != " + (*variables)["default_value"]; - (*variables)["other_has_property_check"] = "other." + - (*variables)["property_name"] + " != " + (*variables)["default_value"]; + if (IsProto2(descriptor_->file())) { + (*variables)["has_property_check"] = "Has" + (*variables)["property_name"]; + (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"]; + (*variables)["has_not_property_check"] = "!" + (*variables)["has_property_check"]; + (*variables)["other_has_not_property_check"] = "!" + (*variables)["other_has_property_check"]; + if (presenceIndex_ != -1) { + string hasBitsNumber = SimpleItoa(presenceIndex_ / 32); + string hasBitsMask = SimpleItoa(1 << (presenceIndex_ % 32)); + (*variables)["has_field_check"] = "(_hasBits" + hasBitsNumber + " & " + hasBitsMask + ") != 0"; + (*variables)["set_has_field"] = "_hasBits" + hasBitsNumber + " |= " + hasBitsMask; + (*variables)["clear_has_field"] = "_hasBits" + hasBitsNumber + " &= ~" + hasBitsMask; + } + } else { + (*variables)["has_property_check"] = + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + (*variables)["other_has_property_check"] = "other." + + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + } } void FieldGeneratorBase::SetCommonOneofFieldVariables( std::map<string, string>* variables) { (*variables)["oneof_name"] = oneof_name(); - (*variables)["has_property_check"] = - oneof_name() + "Case_ == " + oneof_property_name() + - "OneofCase." + property_name(); + if (IsProto2(descriptor_->file())) { + (*variables)["has_property_check"] = "Has" + property_name(); + } else { + (*variables)["has_property_check"] = + oneof_name() + "Case_ == " + oneof_property_name() + + "OneofCase." + property_name(); + } (*variables)["oneof_property_name"] = oneof_property_name(); } FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor, - int fieldOrdinal, const Options* options) + int presenceIndex, const Options* options) : SourceGeneratorBase(descriptor->file(), options), descriptor_(descriptor), - fieldOrdinal_(fieldOrdinal) { + presenceIndex_(presenceIndex) { SetCommonFieldVariables(&variables_); } @@ -251,36 +272,6 @@ bool FieldGeneratorBase::has_default_value() { } } -bool FieldGeneratorBase::is_nullable_type() { - switch (descriptor_->type()) { - case FieldDescriptor::TYPE_ENUM: - case FieldDescriptor::TYPE_DOUBLE: - case FieldDescriptor::TYPE_FLOAT: - case FieldDescriptor::TYPE_INT64: - case FieldDescriptor::TYPE_UINT64: - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_FIXED64: - case FieldDescriptor::TYPE_FIXED32: - case FieldDescriptor::TYPE_BOOL: - case FieldDescriptor::TYPE_UINT32: - case FieldDescriptor::TYPE_SFIXED32: - case FieldDescriptor::TYPE_SFIXED64: - case FieldDescriptor::TYPE_SINT32: - case FieldDescriptor::TYPE_SINT64: - return false; - - case FieldDescriptor::TYPE_MESSAGE: - case FieldDescriptor::TYPE_GROUP: - case FieldDescriptor::TYPE_STRING: - case FieldDescriptor::TYPE_BYTES: - return true; - - default: - GOOGLE_LOG(FATAL)<< "Unknown field type."; - return true; - } -} - bool AllPrintableAscii(const std::string& text) { for(int i = 0; i < text.size(); i++) { if (text[i] < 0x20 || text[i] > 0x7e) { @@ -290,14 +281,18 @@ bool AllPrintableAscii(const std::string& text) { return true; } -std::string FieldGeneratorBase::GetStringDefaultValueInternal() { - // No other default values needed for proto3... - return "\"\""; +std::string FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescriptor* descriptor) { + if (descriptor->default_value_string().empty()) + return "\"\""; + else + return "global::System.Encoding.UTF8.GetString(global::System.Convert.FromBase64String(\" +" + StringToBase64(descriptor->default_value_string()) + " +\"))"; } -std::string FieldGeneratorBase::GetBytesDefaultValueInternal() { - // No other default values needed for proto3... - return "pb::ByteString.Empty"; +std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) { + if (descriptor->default_value_string().empty()) + return "pb::ByteString.Empty"; + else + return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor->default_value_string()) + "\")"; } std::string FieldGeneratorBase::default_value() { @@ -307,9 +302,13 @@ std::string FieldGeneratorBase::default_value() { std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) { switch (descriptor->type()) { case FieldDescriptor::TYPE_ENUM: - // All proto3 enums have a default value of 0, and there's an implicit conversion from the constant 0 to - // any C# enum. This means we don't need to work out what we actually mapped the enum value name to. - return "0"; + if (IsProto2(descriptor_->file())) { + return GetClassName(descriptor->default_value_enum()->type()) + "." + + GetEnumValueName(descriptor->default_value_enum()->type()->name(), descriptor->default_value_enum()->name()); + } + else { + return "0"; + } case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_GROUP: if (IsWrapperType(descriptor)) { @@ -357,9 +356,9 @@ std::string FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) return "false"; } case FieldDescriptor::TYPE_STRING: - return GetStringDefaultValueInternal(); + return GetStringDefaultValueInternal(descriptor); case FieldDescriptor::TYPE_BYTES: - return GetBytesDefaultValueInternal(); + return GetBytesDefaultValueInternal(descriptor); case FieldDescriptor::TYPE_UINT32: return SimpleItoa(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_SFIXED32: diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index df26853b..7eee6bf1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -36,6 +36,8 @@ #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/compiler/csharp/csharp_source_generator_base.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/io/printer.h> namespace google { namespace protobuf { @@ -45,7 +47,7 @@ namespace csharp { class FieldGeneratorBase : public SourceGeneratorBase { public: FieldGeneratorBase(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options* options); ~FieldGeneratorBase(); @@ -65,7 +67,7 @@ class FieldGeneratorBase : public SourceGeneratorBase { protected: const FieldDescriptor* descriptor_; - const int fieldOrdinal_; + const int presenceIndex_; std::map<string, string> variables_; void AddDeprecatedFlag(io::Printer* printer); @@ -82,7 +84,6 @@ class FieldGeneratorBase : public SourceGeneratorBase { std::string type_name(); std::string type_name(const FieldDescriptor* descriptor); bool has_default_value(); - bool is_nullable_type(); std::string default_value(); std::string default_value(const FieldDescriptor* descriptor); std::string number(); @@ -90,8 +91,8 @@ class FieldGeneratorBase : public SourceGeneratorBase { private: void SetCommonFieldVariables(std::map<string, string>* variables); - std::string GetStringDefaultValueInternal(); - std::string GetBytesDefaultValueInternal(); + std::string GetStringDefaultValueInternal(const FieldDescriptor* descriptor); + std::string GetBytesDefaultValueInternal(const FieldDescriptor* descriptor); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorBase); }; diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index 0c93fc29..c0597fe4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -65,11 +65,11 @@ bool Generator::Generate( std::vector<std::pair<string, string> > options; ParseGeneratorParameter(parameter, &options); - // We only support proto3 - but we make an exception for descriptor.proto. + // We only support proto3 - but we make an exception for descriptor.proto. if (file->syntax() != FileDescriptor::SYNTAX_PROTO3 && !IsDescriptorProto(file)) { - *error = "C# code generation only supports proto3 syntax"; + *error = "C# code generation only supports proto3 syntax"; return false; - } + } struct Options cli_options; diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.h b/src/google/protobuf/compiler/csharp/csharp_generator.h index c8b19529..dc7319b1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.h +++ b/src/google/protobuf/compiler/csharp/csharp_generator.h @@ -37,6 +37,8 @@ #include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { @@ -46,9 +48,9 @@ namespace csharp { // header. If you create your own protocol compiler binary and you want // it to support C# output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT Generator +class PROTOC_EXPORT Generator : public google::protobuf::compiler::CodeGenerator { -public: + public: virtual bool Generate( const FileDescriptor* file, const string& parameter, @@ -61,4 +63,6 @@ public: } // namespace protobuf } // namespace google +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 04b61074..dace4100 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -36,6 +36,7 @@ #include <google/protobuf/stubs/hash.h> #include <limits> #include <vector> +#include <sstream> #include <google/protobuf/compiler/csharp/csharp_helpers.h> #include <google/protobuf/compiler/csharp/csharp_names.h> @@ -452,55 +453,89 @@ std::string FileDescriptorToBase64(const FileDescriptor* descriptor) { } FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options* options) { switch (descriptor->type()) { case FieldDescriptor::TYPE_GROUP: case FieldDescriptor::TYPE_MESSAGE: if (descriptor->is_repeated()) { if (descriptor->is_map()) { - return new MapFieldGenerator(descriptor, fieldOrdinal, options); + return new MapFieldGenerator(descriptor, presenceIndex, options); } else { - return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal, options); + return new RepeatedMessageFieldGenerator(descriptor, presenceIndex, options); } } else { if (IsWrapperType(descriptor)) { if (descriptor->containing_oneof()) { - return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal, options); + return new WrapperOneofFieldGenerator(descriptor, presenceIndex, options); } else { - return new WrapperFieldGenerator(descriptor, fieldOrdinal, options); + return new WrapperFieldGenerator(descriptor, presenceIndex, options); } } else { if (descriptor->containing_oneof()) { - return new MessageOneofFieldGenerator(descriptor, fieldOrdinal, options); + return new MessageOneofFieldGenerator(descriptor, presenceIndex, options); } else { - return new MessageFieldGenerator(descriptor, fieldOrdinal, options); + return new MessageFieldGenerator(descriptor, presenceIndex, options); } } } case FieldDescriptor::TYPE_ENUM: if (descriptor->is_repeated()) { - return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal, options); + return new RepeatedEnumFieldGenerator(descriptor, presenceIndex, options); } else { if (descriptor->containing_oneof()) { - return new EnumOneofFieldGenerator(descriptor, fieldOrdinal, options); + return new EnumOneofFieldGenerator(descriptor, presenceIndex, options); } else { - return new EnumFieldGenerator(descriptor, fieldOrdinal, options); + return new EnumFieldGenerator(descriptor, presenceIndex, options); } } default: if (descriptor->is_repeated()) { - return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal, options); + return new RepeatedPrimitiveFieldGenerator(descriptor, presenceIndex, options); } else { if (descriptor->containing_oneof()) { - return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal, options); + return new PrimitiveOneofFieldGenerator(descriptor, presenceIndex, options); } else { - return new PrimitiveFieldGenerator(descriptor, fieldOrdinal, options); + return new PrimitiveFieldGenerator(descriptor, presenceIndex, options); } } } } +bool IsNullable(const FieldDescriptor* descriptor) { + if (descriptor->is_repeated()) { + return true; + } + + switch (descriptor->type()) { + case FieldDescriptor::TYPE_ENUM: + case FieldDescriptor::TYPE_DOUBLE: + case FieldDescriptor::TYPE_FLOAT: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_BOOL: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_SFIXED32: + case FieldDescriptor::TYPE_SFIXED64: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SINT64: + return false; + + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + return true; + + default: + GOOGLE_LOG(FATAL) << "Unknown field type."; + return true; + } +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index c317ad0e..5b9f90e0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -42,6 +42,8 @@ #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/io/printer.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { @@ -96,7 +98,8 @@ std::string UnderscoresToPascalCase(const std::string& input); // Note that we wouldn't normally want to export this (we're not expecting // it to be used outside libprotoc itself) but this exposes it for testing. -std::string LIBPROTOBUF_EXPORT GetEnumValueName(const std::string& enum_name, const std::string& enum_value_name); +std::string PROTOC_EXPORT GetEnumValueName(const std::string& enum_name, + const std::string& enum_value_name); // TODO(jtattermusch): perhaps we could move this to strutil std::string StringToBase64(const std::string& input); @@ -104,9 +107,11 @@ std::string StringToBase64(const std::string& input); std::string FileDescriptorToBase64(const FileDescriptor* descriptor); FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options* options); +bool IsNullable(const FieldDescriptor* descriptor); + // Determines whether the given message is a map entry message, // i.e. one implicitly created by protoc due to a map<key, value> field. inline bool IsMapEntryMessage(const Descriptor* descriptor) { @@ -141,8 +146,15 @@ inline bool IsWrapperType(const FieldDescriptor* descriptor) { descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto"; } +inline bool IsProto2(const FileDescriptor* descriptor) { + return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2; +} + } // namespace csharp } // namespace compiler } // namespace protobuf } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc index d58514ce..125bdf1d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc @@ -48,9 +48,9 @@ namespace compiler { namespace csharp { MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options* options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + : FieldGeneratorBase(descriptor, presenceIndex, options) { } MapFieldGenerator::~MapFieldGenerator() { diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h index 84a33a03..91c99bd0 100644 --- a/src/google/protobuf/compiler/csharp/csharp_map_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h @@ -44,7 +44,7 @@ namespace csharp { class MapFieldGenerator : public FieldGeneratorBase { public: MapFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options* options); ~MapFieldGenerator(); diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 8a4307f1..1daae6f5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -61,20 +61,27 @@ bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) { MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Options* options) : SourceGeneratorBase(descriptor->file(), options), - descriptor_(descriptor) { - - // sorted field names - for (int i = 0; i < descriptor_->field_count(); i++) { - field_names_.push_back(descriptor_->field(i)->name()); - } - std::sort(field_names_.begin(), field_names_.end()); - + descriptor_(descriptor), + has_bit_field_count_(0) { // fields by number for (int i = 0; i < descriptor_->field_count(); i++) { fields_by_number_.push_back(descriptor_->field(i)); } std::sort(fields_by_number_.begin(), fields_by_number_.end(), CompareFieldNumbers); + + if (IsProto2(descriptor_->file())) { + int primitiveCount = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!IsNullable(field)) { + primitiveCount++; + if (has_bit_field_count_ == 0 || (primitiveCount % 32) == 0) { + has_bit_field_count_++; + } + } + } + } } MessageGenerator::~MessageGenerator() { @@ -88,10 +95,6 @@ std::string MessageGenerator::full_class_name() { return GetClassName(descriptor_); } -const std::vector<std::string>& MessageGenerator::field_names() { - return field_names_; -} - const std::vector<const FieldDescriptor*>& MessageGenerator::fields_by_number() { return fields_by_number_; } @@ -123,6 +126,12 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print( "private pb::UnknownFieldSet _unknownFields;\n"); + for (int i = 0; i < has_bit_field_count_; i++) { + // don't use arrays since all arrays are heap allocated, saving allocations + // use ints instead of bytes since bytes lack bitwise operators, saving casts + printer->Print("private int _hasBits$i$;\n", "i", SimpleItoa(i)); + } + WriteGeneratedCodeAttributes(printer); printer->Print( @@ -288,6 +297,9 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { vars, "public $class_name$($class_name$ other) : this() {\n"); printer->Indent(); + for (int i = 0; i < has_bit_field_count_; i++) { + printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", SimpleItoa(i)); + } // Clone non-oneof fields first for (int i = 0; i < descriptor_->field_count(); i++) { if (!descriptor_->field(i)->containing_oneof()) { @@ -559,19 +571,29 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Print("}\n\n"); // method } -int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) { - for (int i = 0; i < field_names().size(); i++) { - if (field_names()[i] == descriptor->name()) { - return i; +// it's a waste of space to track presence for all values, so we only track them if they're not nullable +int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) { + if (IsNullable(descriptor) || !IsProto2(descriptor_->file())) { + return -1; + } + + int index = 0; + for (int i = 0; i < fields_by_number().size(); i++) { + const FieldDescriptor* field = fields_by_number()[i]; + if (field == descriptor) { + return index; + } + if (!IsNullable(field)) { + index++; } } - GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name(); + GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name(); return -1; } FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal( const FieldDescriptor* descriptor) { - return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor), this->options()); + return CreateFieldGenerator(descriptor, GetPresenceIndex(descriptor), this->options()); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index e7f3b4d0..b20bec3d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -57,13 +57,13 @@ class MessageGenerator : public SourceGeneratorBase { private: const Descriptor* descriptor_; - std::vector<std::string> field_names_; std::vector<const FieldDescriptor*> fields_by_number_; + int has_bit_field_count_; void GenerateMessageSerializationMethods(io::Printer* printer); void GenerateMergingMethods(io::Printer* printer); - int GetFieldOrdinal(const FieldDescriptor* descriptor); + int GetPresenceIndex(const FieldDescriptor* descriptor); FieldGeneratorBase* CreateFieldGeneratorInternal( const FieldDescriptor* descriptor); @@ -74,9 +74,6 @@ class MessageGenerator : public SourceGeneratorBase { std::string class_name(); std::string full_class_name(); - // field names sorted alphabetically - const std::vector<std::string>& field_names(); - // field descriptors sorted by number const std::vector<const FieldDescriptor*>& fields_by_number(); diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index cf1b4dbf..16714603 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -49,11 +49,13 @@ namespace compiler { namespace csharp { MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { - variables_["has_property_check"] = name() + "_ != null"; - variables_["has_not_property_check"] = name() + "_ == null"; + : FieldGeneratorBase(descriptor, presenceIndex, options) { + if (!IsProto2(descriptor_->file())) { + variables_["has_property_check"] = name() + "_ != null"; + variables_["has_not_property_check"] = name() + "_ == null"; + } } MessageFieldGenerator::~MessageFieldGenerator() { @@ -74,6 +76,26 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { " $name$_ = value;\n" " }\n" "}\n"); + if (IsProto2(descriptor_->file())) { + printer->Print( + variables_, + "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return $name$_ != null; }\n" + "}\n"); + printer->Print( + variables_, + "/// <summary>Clears the value of the $descriptor_name$ field</summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n" + " $name$_ = null;\n" + "}\n"); + } } void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -81,7 +103,7 @@ void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { variables_, "if (other.$has_property_check$) {\n" " if ($has_not_property_check$) {\n" - " $name$_ = new $type_name$();\n" + " $property_name$ = new $type_name$();\n" " }\n" " $property_name$.MergeFrom(other.$property_name$);\n" "}\n"); @@ -91,10 +113,9 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, "if ($has_not_property_check$) {\n" - " $name$_ = new $type_name$();\n" + " $property_name$ = new $type_name$();\n" "}\n" - // TODO(jonskeet): Do we really need merging behaviour like this? - "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP... + "input.ReadMessage($property_name$);\n"); } void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { @@ -130,7 +151,6 @@ void MessageFieldGenerator::WriteToString(io::Printer* printer) { variables_, "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n"); } - void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) { printer->Print(variables_, "$name$_ = other.$has_property_check$ ? other.$name$_.Clone() : null;\n"); @@ -147,9 +167,9 @@ void MessageFieldGenerator::GenerateCodecCode(io::Printer* printer) { MessageOneofFieldGenerator::MessageOneofFieldGenerator( const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options) - : MessageFieldGenerator(descriptor, fieldOrdinal, options) { + : MessageFieldGenerator(descriptor, presenceIndex, options) { SetCommonOneofFieldVariables(&variables_); } @@ -169,6 +189,28 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" " }\n" "}\n"); + if (IsProto2(descriptor_->file())) { + printer->Print( + variables_, + "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n" + "}\n"); + printer->Print( + variables_, + "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n" + " if ($has_property_check$) {\n" + " Clear$oneof_property_name$();\n" + " }\n" + "}\n"); + } } void MessageOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -187,7 +229,7 @@ void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { "if ($has_property_check$) {\n" " subBuilder.MergeFrom($property_name$);\n" "}\n" - "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP + "input.ReadMessage(subBuilder);\n" "$property_name$ = subBuilder;\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h index c41ee88a..104fb027 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -44,7 +44,7 @@ namespace csharp { class MessageFieldGenerator : public FieldGeneratorBase { public: MessageFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~MessageFieldGenerator(); @@ -68,7 +68,7 @@ class MessageFieldGenerator : public FieldGeneratorBase { class MessageOneofFieldGenerator : public MessageFieldGenerator { public: MessageOneofFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~MessageOneofFieldGenerator(); diff --git a/src/google/protobuf/compiler/csharp/csharp_names.h b/src/google/protobuf/compiler/csharp/csharp_names.h index 21758f28..87a16515 100644 --- a/src/google/protobuf/compiler/csharp/csharp_names.h +++ b/src/google/protobuf/compiler/csharp/csharp_names.h @@ -41,6 +41,8 @@ #include <string> #include <google/protobuf/stubs/port.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { @@ -57,14 +59,14 @@ namespace csharp { // // Returns: // The namespace to use for given file descriptor. -string LIBPROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor); +string PROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor); // Requires: // descriptor != NULL // // Returns: // The fully-qualified C# class name. -string LIBPROTOC_EXPORT GetClassName(const Descriptor* descriptor); +string PROTOC_EXPORT GetClassName(const Descriptor* descriptor); // Requires: // descriptor != NULL @@ -73,7 +75,7 @@ string LIBPROTOC_EXPORT GetClassName(const Descriptor* descriptor); // The fully-qualified name of the C# class that provides // access to the file descriptor. Proto compiler generates // such class for each .proto file processed. -string LIBPROTOC_EXPORT GetReflectionClassName(const FileDescriptor* descriptor); +string PROTOC_EXPORT GetReflectionClassName(const FileDescriptor* descriptor); // Generates output file name for given file descriptor. If generate_directories // is true, the output file will be put under directory corresponding to file's @@ -89,16 +91,16 @@ string LIBPROTOC_EXPORT GetReflectionClassName(const FileDescriptor* descriptor) // The file name to use as output file for given file descriptor. In case // of failure, this function will return empty string and error parameter // will contain the error message. -string LIBPROTOC_EXPORT GetOutputFile( - const google::protobuf::FileDescriptor* descriptor, - const string file_extension, - const bool generate_directories, - const string base_namespace, - string* error); +string PROTOC_EXPORT +GetOutputFile(const google::protobuf::FileDescriptor* descriptor, + const string file_extension, const bool generate_directories, + const string base_namespace, string* error); } // namespace csharp } // namespace compiler } // namespace protobuf } // namespace google +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index c3003e3d..b83468d3 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -49,12 +49,12 @@ namespace compiler { namespace csharp { PrimitiveFieldGenerator::PrimitiveFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : FieldGeneratorBase(descriptor, presenceIndex, options) { // TODO(jonskeet): Make this cleaner... is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING && descriptor->type() != FieldDescriptor::TYPE_BYTES; - if (!is_value_type) { + if (!is_value_type && !IsProto2(descriptor_->file())) { variables_["has_property_check"] = variables_["property_name"] + ".Length != 0"; variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0"; } @@ -67,16 +67,44 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { // TODO(jonskeet): Work out whether we want to prevent the fields from ever being // null, or whether we just handle it, in the cases of bytes and string. // (Basically, should null-handling code be in the getter or the setter?) + if (IsProto2(descriptor_->file())) { + printer->Print( + variables_, + "private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n"); + } + printer->Print( variables_, "private $type_name$ $name_def_message$;\n"); + WritePropertyDocComment(printer, descriptor_); AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "$access_level$ $type_name$ $property_name$ {\n" - " get { return $name$_; }\n" - " set {\n"); + if (IsProto2(descriptor_->file())) { + if (presenceIndex_ == -1) { + printer->Print( + variables_, + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $name$_ ?? $property_name$DefaultValue; }\n" + " set {\n"); + } else { + printer->Print( + variables_, + "$access_level$ $type_name$ $property_name$ {\n" + " get { if ($has_field_check$) { return $name$_; } else { return $property_name$DefaultValue; } }\n" + " set {\n"); + } + } else { + printer->Print( + variables_, + "$access_level$ $type_name$ $property_name$ {\n" + " get { return $name$_; }\n" + " set {\n"); + } + if (presenceIndex_ != -1) { + printer->Print( + variables_, + " $set_has_field$;\n"); + } if (is_value_type) { printer->Print( variables_, @@ -89,6 +117,36 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( " }\n" "}\n"); + if (IsProto2(descriptor_->file())) { + printer->Print(variables_, "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return "); + if (IsNullable(descriptor_)) { + printer->Print( + variables_, + "$name$_ != null; }\n}\n"); + } else { + printer->Print( + variables_, + "$has_field_check$; }\n}\n"); + } + } + if (IsProto2(descriptor_->file())) { + printer->Print(variables_, "/// <summary>Clears the value of the \"$descriptor_name$\" field</summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n"); + if (IsNullable(descriptor_)) { + printer->Print(variables_, " $name$_ = null;\n"); + } else { + printer->Print(variables_, " $clear_has_field$;\n"); + } + printer->Print("}\n"); + } } void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -172,8 +230,8 @@ void PrimitiveFieldGenerator::GenerateCodecCode(io::Printer* printer) { } PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : PrimitiveFieldGenerator(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : PrimitiveFieldGenerator(descriptor, presenceIndex, options) { SetCommonOneofFieldVariables(&variables_); } @@ -188,20 +246,42 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { "$access_level$ $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" " set {\n"); - if (is_value_type) { - printer->Print( - variables_, - " $oneof_name$_ = value;\n"); - } else { - printer->Print( - variables_, - " $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n"); - } + if (is_value_type) { printer->Print( variables_, - " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " $oneof_name$_ = value;\n"); + } else { + printer->Print( + variables_, + " $oneof_name$_ = pb::ProtoPreconditions.CheckNotNull(value, \"value\");\n"); + } + printer->Print( + variables_, + " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " }\n" + "}\n"); + if (IsProto2(descriptor_->file())) { + printer->Print( + variables_, + "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n" + "}\n"); + printer->Print( + variables_, + "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n" + " if ($has_property_check$) {\n" + " Clear$oneof_property_name$();\n" " }\n" "}\n"); + } } void PrimitiveOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h index ca7b8b3d..010ceb21 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h @@ -46,7 +46,7 @@ struct Options; class PrimitiveFieldGenerator : public FieldGeneratorBase { public: PrimitiveFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~PrimitiveFieldGenerator(); @@ -72,7 +72,7 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase { class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { public: PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~PrimitiveOneofFieldGenerator(); diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.h b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h index e0c69f31..3291d65b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.h +++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h @@ -35,6 +35,8 @@ #include <google/protobuf/compiler/code_generator.h> #include <google/protobuf/compiler/csharp/csharp_source_generator_base.h> +#include <google/protobuf/descriptor.h> +#include <google/protobuf/io/printer.h> namespace google { namespace protobuf { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index 683c4b0b..a69e97b2 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -48,8 +48,8 @@ namespace compiler { namespace csharp { RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : FieldGeneratorBase(descriptor, presenceIndex, options) { } RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h index 819b5832..58252225 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -46,7 +46,7 @@ namespace csharp { class RepeatedEnumFieldGenerator : public FieldGeneratorBase { public: RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~RepeatedEnumFieldGenerator(); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 90af569c..d4216597 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -49,8 +49,8 @@ namespace compiler { namespace csharp { RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : FieldGeneratorBase(descriptor, presenceIndex, options) { } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { @@ -67,11 +67,11 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { // function, but it doesn't seem worth it for just this. if (IsWrapperType(descriptor_)) { std::unique_ptr<FieldGeneratorBase> single_generator( - new WrapperFieldGenerator(descriptor_, fieldOrdinal_, this->options())); + new WrapperFieldGenerator(descriptor_, presenceIndex_, this->options())); single_generator->GenerateCodecCode(printer); } else { std::unique_ptr<FieldGeneratorBase> single_generator( - new MessageFieldGenerator(descriptor_, fieldOrdinal_, this->options())); + new MessageFieldGenerator(descriptor_, presenceIndex_, this->options())); single_generator->GenerateCodecCode(printer); } printer->Print(";\n"); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h index 6e33648b..ebc760fa 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -46,7 +46,7 @@ struct Options; class RepeatedMessageFieldGenerator : public FieldGeneratorBase { public: RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~RepeatedMessageFieldGenerator(); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index cd91506f..bc25627f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -48,8 +48,8 @@ namespace compiler { namespace csharp { RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : FieldGeneratorBase(descriptor, presenceIndex, options) { } RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h index a59348a9..340688eb 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -43,7 +43,7 @@ namespace csharp { class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase { public: - RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options); + RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int presenceIndex, const Options *options); ~RepeatedPrimitiveFieldGenerator(); virtual void GenerateCloningCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h index c741080e..790fb1be 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -34,6 +34,7 @@ #include <string> #include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/io/printer.h> namespace google { namespace protobuf { diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc index 047edf73..1dcbf97b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc @@ -48,8 +48,8 @@ namespace compiler { namespace csharp { WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, const Options *options) - : FieldGeneratorBase(descriptor, fieldOrdinal, options) { + int presenceIndex, const Options *options) + : FieldGeneratorBase(descriptor, presenceIndex, options) { variables_["has_property_check"] = name() + "_ != null"; variables_["has_not_property_check"] = name() + "_ == null"; const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); @@ -81,7 +81,27 @@ void WrapperFieldGenerator::GenerateMembers(io::Printer* printer) { " set {\n" " $name$_ = value;\n" " }\n" - "}\n"); + "}\n\n"); + if (IsProto2(descriptor_->file())) { + printer->Print( + variables_, + "/// <summary>Gets whether the $descriptor_name$ field is set</summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return $name$_ != null; }\n" + "}\n\n"); + printer->Print( + variables_, + "/// <summary>Clears the value of the $descriptor_name$ field</summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n" + " $name$_ = null;\n" + "}\n"); + } } void WrapperFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -163,8 +183,8 @@ void WrapperFieldGenerator::GenerateCodecCode(io::Printer* printer) { } WrapperOneofFieldGenerator::WrapperOneofFieldGenerator( - const FieldDescriptor* descriptor, int fieldOrdinal, const Options *options) - : WrapperFieldGenerator(descriptor, fieldOrdinal, options) { + const FieldDescriptor* descriptor, int presenceIndex, const Options *options) + : WrapperFieldGenerator(descriptor, presenceIndex, options) { SetCommonOneofFieldVariables(&variables_); } @@ -189,6 +209,28 @@ void WrapperOneofFieldGenerator::GenerateMembers(io::Printer* printer) { " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" " }\n" "}\n"); + if (IsProto2(descriptor_->file())) { + printer->Print( + variables_, + "/// <summary>Gets whether the \"$descriptor_name$\" field is set</summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ bool Has$property_name$ {\n" + " get { return $oneof_name$Case_ == $oneof_property_name$OneofCase.$property_name$; }\n" + "}\n"); + printer->Print( + variables_, + "/// <summary> Clears the value of the oneof if it's currently set to \"$descriptor_name$\" </summary>\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "$access_level$ void Clear$property_name$() {\n" + " if ($has_property_check$) {\n" + " Clear$oneof_property_name$();\n" + " }\n" + "}\n"); + } } void WrapperOneofFieldGenerator::GenerateMergingCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h index 452531fb..08cae548 100644 --- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h @@ -46,7 +46,7 @@ struct Options; class WrapperFieldGenerator : public FieldGeneratorBase { public: WrapperFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~WrapperFieldGenerator(); @@ -70,7 +70,7 @@ class WrapperFieldGenerator : public FieldGeneratorBase { class WrapperOneofFieldGenerator : public WrapperFieldGenerator { public: WrapperOneofFieldGenerator(const FieldDescriptor* descriptor, - int fieldOrdinal, + int presenceIndex, const Options *options); ~WrapperOneofFieldGenerator(); diff --git a/src/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h index bf6d3de3..cf6b0123 100644 --- a/src/google/protobuf/compiler/importer.h +++ b/src/google/protobuf/compiler/importer.h @@ -45,6 +45,8 @@ #include <google/protobuf/descriptor_database.h> #include <google/protobuf/compiler/parser.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { @@ -73,7 +75,7 @@ class DiskSourceTree; // // Note: This class does not implement FindFileContainingSymbol() or // FindFileContainingExtension(); these will always return false. -class LIBPROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase { +class PROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase { public: SourceTreeDescriptorDatabase(SourceTree* source_tree); ~SourceTreeDescriptorDatabase(); @@ -96,11 +98,11 @@ class LIBPROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabas } // implements DescriptorDatabase ----------------------------------- - bool FindFileByName(const string& filename, + bool FindFileByName(const std::string& filename, FileDescriptorProto* output) override; - bool FindFileContainingSymbol(const string& symbol_name, - FileDescriptorProto*output) override; - bool FindFileContainingExtension(const string& containing_type, + bool FindFileContainingSymbol(const std::string& symbol_name, + FileDescriptorProto* output) override; + bool FindFileContainingExtension(const std::string& containing_type, int field_number, FileDescriptorProto* output) override; @@ -110,23 +112,20 @@ class LIBPROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabas SourceTree* source_tree_; MultiFileErrorCollector* error_collector_; - class LIBPROTOBUF_EXPORT ValidationErrorCollector : public DescriptorPool::ErrorCollector { + class PROTOBUF_EXPORT ValidationErrorCollector + : public DescriptorPool::ErrorCollector { public: ValidationErrorCollector(SourceTreeDescriptorDatabase* owner); ~ValidationErrorCollector(); // implements ErrorCollector --------------------------------------- - void AddError(const string& filename, - const string& element_name, - const Message* descriptor, - ErrorLocation location, - const string& message) override; - - virtual void AddWarning(const string& filename, - const string& element_name, - const Message* descriptor, - ErrorLocation location, - const string& message) override; + void AddError(const std::string& filename, const std::string& element_name, + const Message* descriptor, ErrorLocation location, + const std::string& message) override; + + void AddWarning(const std::string& filename, const std::string& element_name, + const Message* descriptor, ErrorLocation location, + const std::string& message) override; private: SourceTreeDescriptorDatabase* owner_; @@ -146,7 +145,7 @@ class LIBPROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabas // You may find that SourceTreeDescriptorDatabase is more flexible. // // TODO(kenton): I feel like this class is not well-named. -class LIBPROTOBUF_EXPORT Importer { +class PROTOBUF_EXPORT Importer { public: Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector); @@ -165,7 +164,7 @@ class LIBPROTOBUF_EXPORT Importer { // you want to see errors for the same files repeatedly, you can use a // separate Importer object to import each one (but use the same // DescriptorPool so that they can be cross-linked). - const FileDescriptor* Import(const string& filename); + const FileDescriptor* Import(const std::string& filename); // The DescriptorPool in which all imported FileDescriptors and their // contents are stored. @@ -173,7 +172,7 @@ class LIBPROTOBUF_EXPORT Importer { return &pool_; } - void AddUnusedImportTrackFile(const string& file_name); + void AddUnusedImportTrackFile(const std::string& file_name); void ClearUnusedImportTrackFiles(); @@ -186,18 +185,18 @@ class LIBPROTOBUF_EXPORT Importer { // If the importer encounters problems while trying to import the proto files, // it reports them to a MultiFileErrorCollector. -class LIBPROTOBUF_EXPORT MultiFileErrorCollector { +class PROTOBUF_EXPORT MultiFileErrorCollector { public: inline MultiFileErrorCollector() {} virtual ~MultiFileErrorCollector(); // Line and column numbers are zero-based. A line number of -1 indicates // an error with the entire file (e.g. "not found"). - virtual void AddError(const string& filename, int line, int column, - const string& message) = 0; + virtual void AddError(const std::string& filename, int line, int column, + const std::string& message) = 0; - virtual void AddWarning(const string& filename, int line, int column, - const string& message) {} + virtual void AddWarning(const std::string& filename, int line, int column, + const std::string& message) {} private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector); @@ -207,7 +206,7 @@ class LIBPROTOBUF_EXPORT MultiFileErrorCollector { // Used by the default implementation of Importer to resolve import statements // Most users will probably want to use the DiskSourceTree implementation, // below. -class LIBPROTOBUF_EXPORT SourceTree { +class PROTOBUF_EXPORT SourceTree { public: inline SourceTree() {} virtual ~SourceTree(); @@ -216,14 +215,14 @@ class LIBPROTOBUF_EXPORT SourceTree { // found. The caller takes ownership of the returned object. The filename // must be a path relative to the root of the source tree and must not // contain "." or ".." components. - virtual io::ZeroCopyInputStream* Open(const string& filename) = 0; + virtual io::ZeroCopyInputStream* Open(const std::string& filename) = 0; // If Open() returns NULL, calling this method immediately will return an // description of the error. // Subclasses should implement this method and return a meaningful value for // better error reporting. // TODO(xiaofeng): change this to a pure virtual function. - virtual string GetLastErrorMessage(); + virtual std::string GetLastErrorMessage(); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree); @@ -232,7 +231,7 @@ class LIBPROTOBUF_EXPORT SourceTree { // An implementation of SourceTree which loads files from locations on disk. // Multiple mappings can be set up to map locations in the DiskSourceTree to // locations in the physical filesystem. -class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { +class PROTOBUF_EXPORT DiskSourceTree : public SourceTree { public: DiskSourceTree(); ~DiskSourceTree(); @@ -253,7 +252,7 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { // // disk_path may be an absolute path or relative to the current directory, // just like a path you'd pass to open(). - void MapPath(const string& virtual_path, const string& disk_path); + void MapPath(const std::string& virtual_path, const std::string& disk_path); // Return type for DiskFileToVirtualFile(). enum DiskFileToVirtualFileResult { @@ -284,45 +283,47 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { // * NO_MAPPING: Indicates that no mapping was found which contains this // file. DiskFileToVirtualFileResult - DiskFileToVirtualFile(const string& disk_file, - string* virtual_file, - string* shadowing_disk_file); + DiskFileToVirtualFile(const std::string& disk_file, + std::string* virtual_file, + std::string* shadowing_disk_file); // Given a virtual path, find the path to the file on disk. // Return true and update disk_file with the on-disk path if the file exists. // Return false and leave disk_file untouched if the file doesn't exist. - bool VirtualFileToDiskFile(const string& virtual_file, string* disk_file); + bool VirtualFileToDiskFile(const std::string& virtual_file, std::string* disk_file); // implements SourceTree ------------------------------------------- - virtual io::ZeroCopyInputStream* Open(const string& filename) override; + io::ZeroCopyInputStream* Open(const std::string& filename) override; - virtual string GetLastErrorMessage() override; + std::string GetLastErrorMessage() override; private: struct Mapping { - string virtual_path; - string disk_path; + std::string virtual_path; + std::string disk_path; - inline Mapping(const string& virtual_path_param, - const string& disk_path_param) + inline Mapping(const std::string& virtual_path_param, + const std::string& disk_path_param) : virtual_path(virtual_path_param), disk_path(disk_path_param) {} }; std::vector<Mapping> mappings_; - string last_error_message_; + std::string last_error_message_; // Like Open(), but returns the on-disk path in disk_file if disk_file is // non-NULL and the file could be successfully opened. - io::ZeroCopyInputStream* OpenVirtualFile(const string& virtual_file, - string* disk_file); + io::ZeroCopyInputStream* OpenVirtualFile(const std::string& virtual_file, + std::string* disk_file); // Like Open() but given the actual on-disk path. - io::ZeroCopyInputStream* OpenDiskFile(const string& filename); + io::ZeroCopyInputStream* OpenDiskFile(const std::string& filename); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DiskSourceTree); }; } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__ diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc index 73bef3f4..5108809d 100644 --- a/src/google/protobuf/compiler/importer_unittest.cc +++ b/src/google/protobuf/compiler/importer_unittest.cc @@ -34,8 +34,8 @@ #include <google/protobuf/compiler/importer.h> -#include <google/protobuf/stubs/hash.h> #include <memory> +#include <unordered_map> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> @@ -112,7 +112,7 @@ class MockSourceTree : public SourceTree { } private: - hash_map<string, const char*> files_; + std::unordered_map<string, const char*> files_; }; // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h index 9de7415a..fd41a270 100644 --- a/src/google/protobuf/compiler/java/java_context.h +++ b/src/google/protobuf/compiler/java/java_context.h @@ -51,7 +51,9 @@ namespace protobuf { } } } // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -106,6 +108,6 @@ class Context { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ diff --git a/src/google/protobuf/compiler/java/java_doc_comment.h b/src/google/protobuf/compiler/java/java_doc_comment.h index 7d9535c9..ef9b3a90 100644 --- a/src/google/protobuf/compiler/java/java_doc_comment.h +++ b/src/google/protobuf/compiler/java/java_doc_comment.h @@ -37,13 +37,17 @@ #include <google/protobuf/descriptor.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { - namespace io { - class Printer; // printer.h - } +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -59,11 +63,13 @@ void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method); // Exposed for testing only. -LIBPROTOC_EXPORT string EscapeJavadoc(const string& input); +PROTOC_EXPORT std::string EscapeJavadoc(const std::string& input); } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index bef69f1a..1ca7ba95 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -190,10 +190,9 @@ void EnumGenerator::Generate(io::Printer* printer) { printer->Indent(); for (int i = 0; i < canonical_values_.size(); i++) { - printer->Print( - "case $number$: return $name$;\n", - "name", canonical_values_[i]->name(), - "number", SimpleItoa(canonical_values_[i]->number())); + printer->Print("case $number$: return $name$;\n", "name", + canonical_values_[i]->name(), "number", + SimpleItoa(canonical_values_[i]->number())); } printer->Outdent(); @@ -242,19 +241,22 @@ void EnumGenerator::Generate(io::Printer* printer) { // extensions in both the mutable and immutable cases. (In the mutable api // this is accomplished by attempting to load the immutable outer class). printer->Print( - " return $file$.getDescriptor().getEnumTypes().get($index$);\n", - "file", name_resolver_->GetClassName(descriptor_->file(), - immutable_api_), - "index", SimpleItoa(descriptor_->index())); + " return $file$.getDescriptor().getEnumTypes().get($index$);\n", + "file", + name_resolver_->GetClassName(descriptor_->file(), immutable_api_), + "index", SimpleItoa(descriptor_->index())); } else { printer->Print( " return $parent$.$descriptor$.getEnumTypes().get($index$);\n", - "parent", name_resolver_->GetClassName(descriptor_->containing_type(), - immutable_api_), - "descriptor", descriptor_->containing_type()->options() - .no_standard_descriptor_accessor() - ? "getDefaultInstance().getDescriptorForType()" - : "getDescriptor()", + "parent", + name_resolver_->GetClassName(descriptor_->containing_type(), + immutable_api_), + "descriptor", + descriptor_->containing_type() + ->options() + .no_standard_descriptor_accessor() + ? "getDefaultInstance().getDescriptorForType()" + : "getDescriptor()", "index", SimpleItoa(descriptor_->index())); } diff --git a/src/google/protobuf/compiler/java/java_enum.h b/src/google/protobuf/compiler/java/java_enum.h index 13dfc32d..d650924c 100644 --- a/src/google/protobuf/compiler/java/java_enum.h +++ b/src/google/protobuf/compiler/java/java_enum.h @@ -41,17 +41,19 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h +namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h } } +namespace io { + class Printer; // printer.h +} +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -67,9 +69,9 @@ class EnumGenerator { private: const EnumDescriptor* descriptor_; - // The proto language allows multiple enum constants to have the same numeric - // value. Java, however, does not allow multiple enum constants to be - // considered equivalent. We treat the first defined constant for any + // The proto language allows multiple enum constants to have the same + // numeric value. Java, however, does not allow multiple enum constants to + // be considered equivalent. We treat the first defined constant for any // given numeric value as "canonical" and the rest as aliases of that // canonical value. std::vector<const EnumValueDescriptor*> canonical_values_; @@ -93,6 +95,6 @@ class EnumGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_H__ diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index ef64d88b..9d0bcd2c 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -66,10 +66,10 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->enum_type()); (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["default_number"] = SimpleItoa( - descriptor->default_value_enum()->number()); - (*variables)["tag"] = - SimpleItoa(static_cast<int32>(internal::WireFormat::MakeTag(descriptor))); + (*variables)["default_number"] = + SimpleItoa(descriptor->default_value_enum()->number()); + (*variables)["tag"] = SimpleItoa( + static_cast<int32>(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 @@ -305,15 +305,11 @@ GenerateBuildingCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n" - " result.$name$_ = $name$_;\n" " $set_has_field_bit_to_local$;\n" - "} else {\n" - " result.$name$_ = $default_number$;\n" "}\n"); - } else { - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); } + printer->Print(variables_, + "result.$name$_ = $name$_;\n"); } void ImmutableEnumFieldGenerator:: diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h index 924ff281..723102d8 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.h +++ b/src/google/protobuf/compiler/java/java_enum_field.h @@ -41,26 +41,29 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { public: - explicit ImmutableEnumFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex, + Context* context); ~ImmutableEnumFieldGenerator(); - // implements ImmutableFieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator + // --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -78,11 +81,11 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; const int builderBitIndex_; Context* context_; @@ -94,9 +97,9 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator { public: - ImmutableEnumOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex, + Context* context); ~ImmutableEnumOneofFieldGenerator(); void GenerateMembers(io::Printer* printer) const; @@ -139,11 +142,11 @@ class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; const int builderBitIndex_; Context* context_; @@ -155,6 +158,6 @@ class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc index f1fe71b0..353a2f6e 100644 --- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc @@ -66,10 +66,10 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->enum_type()); (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["default_number"] = SimpleItoa( - descriptor->default_value_enum()->number()); - (*variables)["tag"] = - SimpleItoa(static_cast<int32>(internal::WireFormat::MakeTag(descriptor))); + (*variables)["default_number"] = + SimpleItoa(descriptor->default_value_enum()->number()); + (*variables)["tag"] = SimpleItoa( + static_cast<int32>(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 @@ -120,14 +120,12 @@ void SetEnumVariables(const FieldDescriptor* descriptor, ImmutableEnumFieldLiteGenerator:: ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), - name_resolver_(context->GetNameResolver()) { - SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + context_(context), name_resolver_(context->GetNameResolver()) { + SetEnumVariables(descriptor, messageBitIndex, 0, + context->GetFieldGeneratorInfo(descriptor), name_resolver_, + &variables_); } ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {} @@ -136,10 +134,6 @@ int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const { return 1; } -int ImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - void ImmutableEnumFieldLiteGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { @@ -363,13 +357,9 @@ string ImmutableEnumFieldLiteGenerator::GetBoxedType() const { // =================================================================== -ImmutableEnumOneofFieldLiteGenerator:: -ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableEnumFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { +ImmutableEnumOneofFieldLiteGenerator::ImmutableEnumOneofFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : ImmutableEnumFieldLiteGenerator(descriptor, messageBitIndex, context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); @@ -570,16 +560,16 @@ GenerateHashCode(io::Printer* printer) const { // =================================================================== RepeatedImmutableEnumFieldLiteGenerator:: -RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetEnumVariables(descriptor, messageBitIndex, 0, + context->GetFieldGeneratorInfo(descriptor), name_resolver_, + &variables_); } RepeatedImmutableEnumFieldLiteGenerator:: @@ -589,10 +579,6 @@ int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - void RepeatedImmutableEnumFieldLiteGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h index fa004720..bf25ffaa 100644 --- a/src/google/protobuf/compiler/java/java_enum_field_lite.h +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h @@ -41,28 +41,30 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: - explicit ImmutableEnumFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutableEnumFieldLiteGenerator(); - // implements ImmutableFieldLiteGenerator ------------------------------------ + // implements ImmutableFieldLiteGenerator + // ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; @@ -77,13 +79,12 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; - const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; @@ -94,9 +95,8 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { class ImmutableEnumOneofFieldLiteGenerator : public ImmutableEnumFieldLiteGenerator { public: - ImmutableEnumOneofFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, Context* context); ~ImmutableEnumOneofFieldLiteGenerator(); void GenerateMembers(io::Printer* printer) const; @@ -116,13 +116,11 @@ class RepeatedImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: explicit RepeatedImmutableEnumFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + const FieldDescriptor* descriptor, int messageBitIndex, Context* context); ~RepeatedImmutableEnumFieldLiteGenerator(); // implements ImmutableFieldLiteGenerator ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; @@ -138,13 +136,12 @@ class RepeatedImmutableEnumFieldLiteGenerator void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; - const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; @@ -154,6 +151,6 @@ class RepeatedImmutableEnumFieldLiteGenerator } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc index 806008ee..deebe523 100644 --- a/src/google/protobuf/compiler/java/java_enum_lite.cc +++ b/src/google/protobuf/compiler/java/java_enum_lite.cc @@ -43,6 +43,7 @@ #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/map_util.h> namespace google { namespace protobuf { @@ -163,33 +164,47 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { printer->Indent(); for (int i = 0; i < canonical_values_.size(); i++) { - printer->Print( - "case $number$: return $name$;\n", - "name", canonical_values_[i]->name(), - "number", SimpleItoa(canonical_values_[i]->number())); + printer->Print("case $number$: return $name$;\n", "name", + canonical_values_[i]->name(), "number", + SimpleItoa(canonical_values_[i]->number())); } printer->Outdent(); printer->Outdent(); printer->Print( - " default: return null;\n" - " }\n" - "}\n" - "\n" - "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" - " internalGetValueMap() {\n" - " return internalValueMap;\n" - "}\n" - "private static final com.google.protobuf.Internal.EnumLiteMap<\n" - " $classname$> internalValueMap =\n" - " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" - " @java.lang.Override\n" - " public $classname$ findValueByNumber(int number) {\n" - " return $classname$.forNumber(number);\n" - " }\n" - " };\n" - "\n", - "classname", descriptor_->name()); + " default: return null;\n" + " }\n" + "}\n" + "\n" + "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" + " internalGetValueMap() {\n" + " return internalValueMap;\n" + "}\n" + "private static final com.google.protobuf.Internal.EnumLiteMap<\n" + " $classname$> internalValueMap =\n" + " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" + " @java.lang.Override\n" + " public $classname$ findValueByNumber(int number) {\n" + " return $classname$.forNumber(number);\n" + " }\n" + " };\n" + "\n" + "public static com.google.protobuf.Internal.EnumVerifier \n" + " internalGetVerifier() {\n" + " return $classname$Verifier.INSTANCE;\n" + "}\n" + "\n" + "private static final class $classname$Verifier implements \n" + " com.google.protobuf.Internal.EnumVerifier { \n" + " static final com.google.protobuf.Internal.EnumVerifier " + " INSTANCE = new $classname$Verifier();\n" + " @java.lang.Override\n" + " public boolean isInRange(int number) {\n" + " return $classname$.forNumber(number) != null;\n" + " }\n" + " };\n" + "\n", + "classname", descriptor_->name()); printer->Print( "private final int value;\n\n" diff --git a/src/google/protobuf/compiler/java/java_enum_lite.h b/src/google/protobuf/compiler/java/java_enum_lite.h index b7be912c..9e20e6fb 100644 --- a/src/google/protobuf/compiler/java/java_enum_lite.h +++ b/src/google/protobuf/compiler/java/java_enum_lite.h @@ -41,17 +41,19 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h +namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h } } +namespace io { + class Printer; // printer.h +} +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -67,9 +69,9 @@ class EnumLiteGenerator { private: const EnumDescriptor* descriptor_; - // The proto language allows multiple enum constants to have the same numeric - // value. Java, however, does not allow multiple enum constants to be - // considered equivalent. We treat the first defined constant for any + // The proto language allows multiple enum constants to have the same + // numeric value. Java, however, does not allow multiple enum constants to + // be considered equivalent. We treat the first defined constant for any // given numeric value as "canonical" and the rest as aliases of that // canonical value. std::vector<const EnumValueDescriptor*> canonical_values_; @@ -93,6 +95,6 @@ class EnumLiteGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc index 3eb1370d..1ee97710 100644 --- a/src/google/protobuf/compiler/java/java_extension.cc +++ b/src/google/protobuf/compiler/java/java_extension.cc @@ -151,8 +151,8 @@ int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( // Only applies to non-nested extensions. printer->Print( "$name$.internalInit(descriptor.getExtensions().get($index$));\n", - "name", UnderscoresToCamelCase(descriptor_), - "index", SimpleItoa(descriptor_->index())); + "name", UnderscoresToCamelCase(descriptor_), "index", + SimpleItoa(descriptor_->index())); bytecode_estimate += 21; } return bytecode_estimate; diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h index fb8d5201..1f11324c 100644 --- a/src/google/protobuf/compiler/java/java_extension.h +++ b/src/google/protobuf/compiler/java/java_extension.h @@ -42,18 +42,20 @@ namespace google { namespace protobuf { - class FieldDescriptor; // descriptor.h - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +class FieldDescriptor; // descriptor.h +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -68,18 +70,19 @@ class ExtensionGenerator { virtual void Generate(io::Printer* printer) = 0; - // Returns an estimate of the number of bytes the printed code will compile to + // Returns an estimate of the number of bytes the printed code will compile + // to virtual int GenerateNonNestedInitializationCode(io::Printer* printer) = 0; - // Returns an estimate of the number of bytes the printed code will compile to + // Returns an estimate of the number of bytes the printed code will compile + // to virtual int GenerateRegistrationCode(io::Printer* printer) = 0; protected: static void InitTemplateVars(const FieldDescriptor* descriptor, - const string& scope, - bool immutable, + const std::string& scope, bool immutable, ClassNameResolver* name_resolver, - std::map<string, string>* vars_pointer); + std::map<std::string, std::string>* vars_pointer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); @@ -99,7 +102,7 @@ class ImmutableExtensionGenerator : public ExtensionGenerator { const FieldDescriptor* descriptor_; Context* context_; ClassNameResolver* name_resolver_; - string scope_; + std::string scope_; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionGenerator); @@ -108,6 +111,6 @@ class ImmutableExtensionGenerator : public ExtensionGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ diff --git a/src/google/protobuf/compiler/java/java_extension_lite.h b/src/google/protobuf/compiler/java/java_extension_lite.h index 4cd49bda..eaa90a4b 100644 --- a/src/google/protobuf/compiler/java/java_extension_lite.h +++ b/src/google/protobuf/compiler/java/java_extension_lite.h @@ -63,7 +63,7 @@ class ImmutableExtensionLiteGenerator : public ExtensionGenerator { const FieldDescriptor* descriptor_; Context* context_; ClassNameResolver* name_resolver_; - string scope_; + std::string scope_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionLiteGenerator); }; @@ -71,6 +71,6 @@ class ImmutableExtensionLiteGenerator : public ExtensionGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc index 93de0229..fec20a7f 100644 --- a/src/google/protobuf/compiler/java/java_field.cc +++ b/src/google/protobuf/compiler/java/java_field.cc @@ -121,58 +121,57 @@ ImmutableFieldGenerator* MakeImmutableGenerator( } ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator( - const FieldDescriptor* field, int messageBitIndex, int builderBitIndex, - Context* context) { + const FieldDescriptor* field, int messageBitIndex, Context* context) { if (field->is_repeated()) { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: if (IsMapEntry(field->message_type())) { - return new ImmutableMapFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableMapFieldLiteGenerator(field, messageBitIndex, + context); } else { return new RepeatedImmutableMessageFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); } case JAVATYPE_ENUM: return new RepeatedImmutableEnumFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); case JAVATYPE_STRING: return new RepeatedImmutableStringFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); default: return new RepeatedImmutablePrimitiveFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); } } else { if (field->containing_oneof()) { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: return new ImmutableMessageOneofFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); case JAVATYPE_ENUM: return new ImmutableEnumOneofFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); case JAVATYPE_STRING: return new ImmutableStringOneofFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); default: return new ImmutablePrimitiveOneofFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); } } else { switch (GetJavaType(field)) { case JAVATYPE_MESSAGE: - return new ImmutableMessageFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableMessageFieldLiteGenerator(field, messageBitIndex, + context); case JAVATYPE_ENUM: - return new ImmutableEnumFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableEnumFieldLiteGenerator(field, messageBitIndex, + context); case JAVATYPE_STRING: - return new ImmutableStringFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + return new ImmutableStringFieldLiteGenerator(field, messageBitIndex, + context); default: return new ImmutablePrimitiveFieldLiteGenerator( - field, messageBitIndex, builderBitIndex, context); + field, messageBitIndex, context); } } } @@ -210,9 +209,7 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { template <> FieldGeneratorMap<ImmutableFieldGenerator>::FieldGeneratorMap( const Descriptor* descriptor, Context* context) - : descriptor_(descriptor), - field_generators_(descriptor->field_count()) { - + : descriptor_(descriptor), field_generators_(descriptor->field_count()) { // Construct all the FieldGenerators and assign them bit indices for their // bit fields. int messageBitIndex = 0; @@ -232,18 +229,15 @@ FieldGeneratorMap<ImmutableFieldGenerator>::~FieldGeneratorMap() {} template <> FieldGeneratorMap<ImmutableFieldLiteGenerator>::FieldGeneratorMap( const Descriptor* descriptor, Context* context) - : descriptor_(descriptor), - field_generators_(descriptor->field_count()) { + : descriptor_(descriptor), field_generators_(descriptor->field_count()) { // Construct all the FieldGenerators and assign them bit indices for their // bit fields. int messageBitIndex = 0; - int builderBitIndex = 0; for (int i = 0; i < descriptor->field_count(); i++) { ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator( - descriptor->field(i), messageBitIndex, builderBitIndex, context); + descriptor->field(i), messageBitIndex, context); field_generators_[i].reset(generator); messageBitIndex += generator->GetNumBitsForMessage(); - builderBitIndex += generator->GetNumBitsForBuilder(); } } @@ -276,12 +270,12 @@ void SetCommonOneofVariables(const FieldDescriptor* descriptor, (*variables)["oneof_capitalized_name"] = info->capitalized_name; (*variables)["oneof_index"] = SimpleItoa(descriptor->containing_oneof()->index()); - (*variables)["set_oneof_case_message"] = info->name + - "Case_ = " + SimpleItoa(descriptor->number()); + (*variables)["set_oneof_case_message"] = + info->name + "Case_ = " + SimpleItoa(descriptor->number()); (*variables)["clear_oneof_case_message"] = info->name + "Case_ = 0"; - (*variables)["has_oneof_case_message"] = info->name + - "Case_ == " + SimpleItoa(descriptor->number()); + (*variables)["has_oneof_case_message"] = + info->name + "Case_ == " + SimpleItoa(descriptor->number()); } void PrintExtraFieldInfo(const std::map<string, string>& variables, diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index 7275c099..abefc589 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -45,17 +45,19 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -79,13 +81,13 @@ class ImmutableFieldGenerator { virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0; virtual void GenerateSerializationCode(io::Printer* printer) const = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; - virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) - const = 0; + virtual void 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; + virtual std::string GetBoxedType() const = 0; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator); @@ -97,7 +99,6 @@ class ImmutableFieldLiteGenerator { virtual ~ImmutableFieldLiteGenerator(); virtual int GetNumBitsForMessage() const = 0; - virtual int GetNumBitsForBuilder() const = 0; virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0; virtual void GenerateMembers(io::Printer* printer) const = 0; virtual void GenerateBuilderMembers(io::Printer* printer) const = 0; @@ -117,7 +118,7 @@ class ImmutableFieldLiteGenerator { virtual void GenerateHashCode(io::Printer* printer) const = 0; - virtual string GetBoxedType() const = 0; + virtual std::string GetBoxedType() const = 0; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldLiteGenerator); @@ -170,34 +171,34 @@ FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap(); // Field information used in FieldGeneartors. struct FieldGeneratorInfo { - string name; - string capitalized_name; - string disambiguated_reason; + std::string name; + std::string capitalized_name; + std::string disambiguated_reason; }; // Oneof information used in OneofFieldGenerators. struct OneofGeneratorInfo { - string name; - string capitalized_name; + std::string name; + std::string capitalized_name; }; // Set some common variables used in variable FieldGenerators. void SetCommonFieldVariables(const FieldDescriptor* descriptor, const FieldGeneratorInfo* info, - std::map<string, string>* variables); + std::map<std::string, std::string>* variables); // Set some common oneof variables used in OneofFieldGenerators. void SetCommonOneofVariables(const FieldDescriptor* descriptor, const OneofGeneratorInfo* info, - std::map<string, string>* variables); + std::map<std::string, std::string>* variables); // Print useful comments before a field's accessors. -void PrintExtraFieldInfo(const std::map<string, string>& variables, +void PrintExtraFieldInfo(const std::map<std::string, std::string>& variables, io::Printer* printer); } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index 5583b779..5356512c 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -172,7 +172,8 @@ void MaybeRestartJavaMethod(io::Printer* printer, if ((*bytecode_estimate) > bytesPerMethod) { ++(*method_num); - printer->Print(chain_statement, "method_num", SimpleItoa(*method_num)); + printer->Print(chain_statement, "method_num", + SimpleItoa(*method_num)); printer->Outdent(); printer->Print("}\n"); printer->Print(method_decl, "method_num", SimpleItoa(*method_num)); @@ -231,7 +232,9 @@ bool FileGenerator::Validate(string* error) { << "will be ignored by protoc in the future and protoc will always " << "generate full runtime code for Java. To use Java Lite runtime, " << "users should use the Java Lite plugin instead. See:\n" - << " https://github.com/google/protobuf/blob/master/java/lite.md"; + << " " + "https://github.com/protocolbuffers/protobuf/blob/master/java/" + "lite.md"; } return true; } @@ -545,11 +548,13 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* " $scope$.getExtensions().get($index$),\n" " (com.google.protobuf.Message) defaultExtensionInstance);\n" "}\n", - "scope", scope, "index", SimpleItoa(field->index()), "class", + "scope", scope, "index", SimpleItoa(field->index()), + "class", name_resolver_->GetImmutableClassName(field->message_type())); } else { printer->Print("registry.add($scope$.getExtensions().get($index$));\n", - "scope", scope, "index", SimpleItoa(field->index())); + "scope", scope, "index", + SimpleItoa(field->index())); } } printer->Print( diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h index 78833a45..9dca82bb 100644 --- a/src/google/protobuf/compiler/java/java_file.h +++ b/src/google/protobuf/compiler/java/java_file.h @@ -43,22 +43,24 @@ namespace google { namespace protobuf { - class FileDescriptor; // descriptor.h - namespace io { - class Printer; // printer.h - } - namespace compiler { - class GeneratorContext; // code_generator.h - namespace java { - class Context; // context.h - class MessageGenerator; // message.h - class GeneratorFactory; // generator_factory.h - class ExtensionGenerator; // extension.h - class ClassNameResolver; // name_resolver.h - } +class FileDescriptor; // descriptor.h +namespace io { + class Printer; // printer.h +} +namespace compiler { + class GeneratorContext; // code_generator.h + namespace java { + class Context; // context.h + class MessageGenerator; // message.h + class GeneratorFactory; // generator_factory.h + class ExtensionGenerator; // extension.h + class ClassNameResolver; // name_resolver.h } } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -72,20 +74,20 @@ class FileGenerator { // Checks for problems that would otherwise lead to cryptic compile errors. // Returns true if there are no problems, or writes an error description to // the given string and returns false otherwise. - bool Validate(string* error); + bool Validate(std::string* error); void Generate(io::Printer* printer); // If we aren't putting everything into one file, this will write all the // files other than the outer file (i.e. one for each message, enum, and // service type). - void GenerateSiblings(const string& package_dir, + void GenerateSiblings(const std::string& package_dir, GeneratorContext* generator_context, - std::vector<string>* file_list, - std::vector<string>* annotation_list); + std::vector<std::string>* file_list, + std::vector<std::string>* annotation_list); - const string& java_package() { return java_package_; } - const string& classname() { return classname_; } + const std::string& java_package() { return java_package_; } + const std::string& classname() { return classname_; } private: void GenerateDescriptorInitializationCodeForImmutable(io::Printer* printer); @@ -95,8 +97,8 @@ class FileGenerator { bool immutable_api_); const FileDescriptor* file_; - string java_package_; - string classname_; + std::string java_package_; + std::string classname_; std::vector<std::unique_ptr<MessageGenerator>> message_generators_; std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_; @@ -112,6 +114,6 @@ class FileGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc index a5b2e784..fd2591da 100644 --- a/src/google/protobuf/compiler/java/java_generator.cc +++ b/src/google/protobuf/compiler/java/java_generator.cc @@ -34,6 +34,7 @@ #include <google/protobuf/compiler/java/java_generator.h> + #include <memory> #include <google/protobuf/compiler/java/java_file.h> @@ -117,6 +118,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file, file_generators.push_back(new FileGenerator(file, file_options, /* mutable = */ false)); } + for (int i = 0; i < file_generators.size(); ++i) { if (!file_generators[i]->Validate(error)) { for (int j = 0; j < file_generators.size(); ++j) { @@ -163,6 +165,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file, } } + for (int i = 0; i < file_generators.size(); ++i) { delete file_generators[i]; } diff --git a/src/google/protobuf/compiler/java/java_generator.h b/src/google/protobuf/compiler/java/java_generator.h index 47f76be9..21873581 100644 --- a/src/google/protobuf/compiler/java/java_generator.h +++ b/src/google/protobuf/compiler/java/java_generator.h @@ -40,6 +40,8 @@ #include <string> #include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { @@ -49,16 +51,16 @@ namespace java { // own protocol compiler binary and you want it to support Java output, you // can do so by registering an instance of this CodeGenerator with the // CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator { +class PROTOC_EXPORT JavaGenerator : public CodeGenerator { public: JavaGenerator(); ~JavaGenerator(); // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* context, - string* error) const; + std::string* error) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaGenerator); @@ -67,6 +69,8 @@ class LIBPROTOC_EXPORT JavaGenerator : public CodeGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/java/java_generator_factory.h b/src/google/protobuf/compiler/java/java_generator_factory.h index 55365a9d..505cd3ac 100644 --- a/src/google/protobuf/compiler/java/java_generator_factory.h +++ b/src/google/protobuf/compiler/java/java_generator_factory.h @@ -37,19 +37,21 @@ namespace google { namespace protobuf { - class FieldDescriptor; // descriptor.h - class Descriptor; // descriptor.h - class ServiceDescriptor; // descriptor.h - namespace compiler { - namespace java { - class MessageGenerator; // message.h - class ExtensionGenerator; // extension.h - class ServiceGenerator; // service.h - class Context; // context.h - } +class FieldDescriptor; // descriptor.h +class Descriptor; // descriptor.h +class ServiceDescriptor; // descriptor.h +namespace compiler { + namespace java { + class MessageGenerator; // message.h + class ExtensionGenerator; // extension.h + class ServiceGenerator; // service.h + class Context; // context.h } } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -96,6 +98,6 @@ class ImmutableGeneratorFactory : public GeneratorFactory { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index 957076cb..dbd1604a 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -33,8 +33,8 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <algorithm> -#include <google/protobuf/stubs/hash.h> #include <limits> +#include <unordered_set> #include <vector> #include <google/protobuf/stubs/stringprintf.h> @@ -135,6 +135,29 @@ void PrintGeneratedAnnotation(io::Printer* printer, char delimiter, printer->Print(ptemplate.c_str(), "annotation_file", annotation_file); } +void PrintEnumVerifierLogic(io::Printer* printer, + const FieldDescriptor* descriptor, + const std::map<string, string>& variables, + const char* var_name, + const char* terminating_string, + bool enforce_lite) { + std::string enum_verifier_string = + (descriptor->enum_type()->file()->options().optimize_for() == + FileOptions::LITE_RUNTIME) || enforce_lite + ? StrCat(var_name, ".internalGetVerifier()") + : StrCat( + "new com.google.protobuf.Internal.EnumVerifier() {\n" + " @java.lang.Override\n" + " public boolean isInRange(int number) {\n" + " return ", var_name, ".forNumber(number) != null;\n" + " }\n" + " }" + ); + printer->Print( + variables, + StrCat(enum_verifier_string, terminating_string).c_str()); +} + string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { string result; // Note: I distrust ctype.h due to locales. @@ -178,6 +201,10 @@ string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { return UnderscoresToCamelCase(FieldName(field), true); } +string CapitalizedFieldName(const FieldDescriptor* field) { + return UnderscoresToCapitalizedCamelCase(field); +} + string UnderscoresToCamelCase(const MethodDescriptor* method) { return UnderscoresToCamelCase(method->name(), false); } @@ -223,6 +250,10 @@ string FileJavaPackage(const FileDescriptor* file, bool immutable) { return result; } +string FileJavaPackage(const FileDescriptor* file) { + return FileJavaPackage(file, true /* immutable */); +} + string JavaPackageToDir(string package_name) { string package_dir = StringReplace(package_name, ".", "/", true); @@ -369,6 +400,10 @@ const char* PrimitiveTypeName(JavaType type) { return NULL; } +const char* PrimitiveTypeName(const FieldDescriptor* descriptor) { + return PrimitiveTypeName(GetJavaType(descriptor)); +} + const char* BoxedPrimitiveTypeName(JavaType type) { switch (type) { case JAVATYPE_INT : return "java.lang.Integer"; @@ -389,6 +424,10 @@ const char* BoxedPrimitiveTypeName(JavaType type) { return NULL; } +const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor) { + return BoxedPrimitiveTypeName(GetJavaType(descriptor)); +} + const char* FieldTypeName(FieldDescriptor::Type field_type) { switch (field_type) { @@ -437,11 +476,13 @@ string DefaultValue(const FieldDescriptor* field, bool immutable, return SimpleItoa(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: // Need to print as a signed int since Java has no unsigned. - return SimpleItoa(static_cast<int32>(field->default_value_uint32())); + return SimpleItoa( + static_cast<int32>(field->default_value_uint32())); case FieldDescriptor::CPPTYPE_INT64: return SimpleItoa(field->default_value_int64()) + "L"; case FieldDescriptor::CPPTYPE_UINT64: - return SimpleItoa(static_cast<int64>(field->default_value_uint64())) + + return SimpleItoa( + static_cast<int64>(field->default_value_uint64())) + "L"; case FieldDescriptor::CPPTYPE_DOUBLE: { double value = field->default_value_double(); @@ -749,9 +790,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { // // already_seen is used to avoid checking the same type multiple times // (and also to protect against recursion). -bool HasRequiredFields( - const Descriptor* type, - hash_set<const Descriptor*>* already_seen) { +bool HasRequiredFields(const Descriptor* type, + std::unordered_set<const Descriptor*>* already_seen) { if (already_seen->count(type) > 0) { // The type is already in cache. This means that either: // a. The type has no required fields. @@ -786,7 +826,7 @@ bool HasRequiredFields( } bool HasRequiredFields(const Descriptor* type) { - hash_set<const Descriptor*> already_seen; + std::unordered_set<const Descriptor*> already_seen; return HasRequiredFields(type, &already_seen); } @@ -932,22 +972,6 @@ void EscapeUtf16ToString(uint16 code, string* output) { } } -std::pair<int, int> GetTableDrivenNumberOfEntriesAndLookUpStartFieldNumber( - const FieldDescriptor** fields, int count) { - GOOGLE_CHECK_GT(count, 0); - int table_driven_number_of_entries = count; - int look_up_start_field_number = 0; - for (int i = 0; i < count; i++) { - const int field_number = fields[i]->number(); - if (ShouldUseTable(fields[0]->number(), field_number, i + 1)) { - table_driven_number_of_entries = - field_number - fields[0]->number() + 1 + count - i - 1; - look_up_start_field_number = field_number + 1; - } - } - return std::make_pair( - table_driven_number_of_entries, look_up_start_field_number); -} } // 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 dd9b65b8..93caa3dc 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -60,79 +60,89 @@ extern const char kThinSeparator[]; // annotation_file should be generated from the filename of the source file // being annotated (which in turn must be a Java identifier plus ".java"). void PrintGeneratedAnnotation(io::Printer* printer, char delimiter = '$', - const string& annotation_file = ""); + const std::string& annotation_file = ""); + +// If a GeneratedMessageLite contains non-lite enums, then its verifier +// must be instantiated inline, rather than retrieved from the enum class. +void PrintEnumVerifierLogic(io::Printer* printer, + const FieldDescriptor* descriptor, + const std::map<std::string, std::string>& variables, + const char* var_name, + const char* terminating_string, + bool enforce_lite); // Converts a name to camel-case. If cap_first_letter is true, capitalize the // first letter. -string UnderscoresToCamelCase(const string& name, bool cap_first_letter); +std::string UnderscoresToCamelCase(const std::string& name, bool cap_first_letter); // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes // "fooBarBaz" or "FooBarBaz", respectively. -string UnderscoresToCamelCase(const FieldDescriptor* field); -string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); +std::string UnderscoresToCamelCase(const FieldDescriptor* field); +std::string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); // Similar, but for method names. (Typically, this merely has the effect // of lower-casing the first letter of the name.) -string UnderscoresToCamelCase(const MethodDescriptor* method); +std::string UnderscoresToCamelCase(const MethodDescriptor* method); // Similar to UnderscoresToCamelCase, but guarentees that the result is a // complete Java identifier by adding a _ if needed. -string CamelCaseFieldName(const FieldDescriptor* field); +std::string CamelCaseFieldName(const FieldDescriptor* field); // Get an identifier that uniquely identifies this type within the file. // This is used to declare static variables related to this type at the // outermost file scope. -string UniqueFileScopeIdentifier(const Descriptor* descriptor); +std::string UniqueFileScopeIdentifier(const Descriptor* descriptor); // Strips ".proto" or ".protodevel" from the end of a filename. -string StripProto(const string& filename); +std::string StripProto(const std::string& filename); // Gets the unqualified class name for the file. For each .proto file, there // will be one Java class containing all the immutable messages and another // Java class containing all the mutable messages. // TODO(xiaofeng): remove the default value after updating client code. -string FileClassName(const FileDescriptor* file, bool immutable = true); +std::string FileClassName(const FileDescriptor* file, bool immutable = true); // Returns the file's Java package name. -string FileJavaPackage(const FileDescriptor* file, bool immutable = true); +std::string FileJavaPackage(const FileDescriptor* file); +std::string FileJavaPackage(const FileDescriptor* file, bool immutable); // Returns output directory for the given package name. -string JavaPackageToDir(string package_name); +std::string JavaPackageToDir(std::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. // TODO(xiaofeng): this method is deprecated and should be removed in the // future. -string ToJavaName(const string& full_name, +std::string ToJavaName(const std::string& full_name, const FileDescriptor* file); // TODO(xiaofeng): the following methods are kept for they are exposed -// publicly in //google/protobuf/compiler/java/names.h. They return +// publicly in //net/proto2/compiler/java/public/names.h. They return // immutable names only and should be removed after mutable API is // integrated into google3. -string ClassName(const Descriptor* descriptor); -string ClassName(const EnumDescriptor* descriptor); -string ClassName(const ServiceDescriptor* descriptor); -string ClassName(const FileDescriptor* descriptor); +std::string ClassName(const Descriptor* descriptor); +std::string ClassName(const EnumDescriptor* descriptor); +std::string ClassName(const ServiceDescriptor* descriptor); +std::string ClassName(const FileDescriptor* descriptor); // Comma-separate list of option-specified interfaces implemented by the // Message, to follow the "implements" declaration of the Message definition. -string ExtraMessageInterfaces(const Descriptor* descriptor); +std::string ExtraMessageInterfaces(const Descriptor* descriptor); // Comma-separate list of option-specified interfaces implemented by the // MutableMessage, to follow the "implements" declaration of the MutableMessage // definition. -string ExtraMutableMessageInterfaces(const Descriptor* descriptor); +std::string ExtraMutableMessageInterfaces(const Descriptor* descriptor); // Comma-separate list of option-specified interfaces implemented by the // Builder, to follow the "implements" declaration of the Builder definition. -string ExtraBuilderInterfaces(const Descriptor* descriptor); +std::string ExtraBuilderInterfaces(const Descriptor* descriptor); // Comma-separate list of option-specified interfaces extended by the // MessageOrBuilder, to follow the "extends" declaration of the // MessageOrBuilder definition. -string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor); +std::string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor); // Get the unqualified Java class name for mutable messages. i.e. without // package or outer classnames. -inline string ShortMutableJavaClassName(const Descriptor* descriptor) { +inline std::string ShortMutableJavaClassName(const Descriptor* descriptor) { return descriptor->name(); } @@ -140,7 +150,8 @@ inline string ShortMutableJavaClassName(const Descriptor* descriptor) { // cannot currently use the new runtime with core protos since there is a // bootstrapping problem with obtaining their descriptors. inline bool IsDescriptorProto(const Descriptor* descriptor) { - return descriptor->file()->name() == "google/protobuf/descriptor.proto"; + return descriptor->file()->name() == "net/proto2/proto/descriptor.proto" || + descriptor->file()->name() == "google/protobuf/descriptor.proto"; } @@ -168,14 +179,14 @@ inline bool IsOwnFile(const ServiceDescriptor* descriptor, bool immutable) { // annotation data for that descriptor. `suffix` is usually empty, but may // (e.g.) be "OrBuilder" for some generated interfaces. template <typename Descriptor> -string AnnotationFileName(const Descriptor* descriptor, const string& suffix) { +std::string AnnotationFileName(const Descriptor* descriptor, const std::string& suffix) { return descriptor->name() + suffix + ".java.pb.meta"; } template <typename Descriptor> void MaybePrintGeneratedAnnotation(Context* context, io::Printer* printer, Descriptor* descriptor, bool immutable, - const string& suffix = "") { + const std::string& suffix = "") { if (context->options().annotate_code && IsOwnFile(descriptor, immutable)) { PrintGeneratedAnnotation(printer, '$', AnnotationFileName(descriptor, suffix)); @@ -184,7 +195,7 @@ void MaybePrintGeneratedAnnotation(Context* context, io::Printer* printer, // Get the unqualified name that should be used for a field's field // number constant. -string FieldConstantName(const FieldDescriptor *field); +std::string FieldConstantName(const FieldDescriptor *field); // Returns the type of the FieldDescriptor. // This does nothing interesting for the open source release, but is used for @@ -218,9 +229,9 @@ const char* BoxedPrimitiveTypeName(JavaType type); const char* FieldTypeName(const FieldDescriptor::Type field_type); class ClassNameResolver; -string DefaultValue(const FieldDescriptor* field, bool immutable, +std::string DefaultValue(const FieldDescriptor* field, bool immutable, ClassNameResolver* name_resolver); -inline string ImmutableDefaultValue(const FieldDescriptor* field, +inline std::string ImmutableDefaultValue(const FieldDescriptor* field, ClassNameResolver* name_resolver) { return DefaultValue(field, true, name_resolver); } @@ -256,50 +267,50 @@ inline bool HasGenericServices(const FileDescriptor *file, bool enforce_lite) { // Methods for shared bitfields. // Gets the name of the shared bitfield for the given index. -string GetBitFieldName(int index); +std::string GetBitFieldName(int index); // Gets the name of the shared bitfield for the given bit index. // Effectively, GetBitFieldName(bitIndex / 32) -string GetBitFieldNameForBit(int bitIndex); +std::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); +std::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); +std::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); +std::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); +std::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); +std::string GenerateSetBitToLocal(int bitIndex); // Does the same as GenerateGetBit but operates on the bit field on a local // variable. This is used by the parsing constructor to record if a repeated // field is mutable. // Example: "((mutable_bitField1_ & 0x04) == 0x04)" -string GenerateGetBitMutableLocal(int bitIndex); +std::string GenerateGetBitMutableLocal(int bitIndex); // Does the same as GenerateSetBit but operates on the bit field on a local // variable. This is used by the parsing constructor to record if a repeated // field is mutable. // Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)" -string GenerateSetBitMutableLocal(int bitIndex); +std::string GenerateSetBitMutableLocal(int bitIndex); // Returns whether the JavaType is a reference type. bool IsReferenceType(JavaType type); @@ -387,14 +398,10 @@ inline bool CheckUtf8(const FieldDescriptor* descriptor) { descriptor->file()->options().java_string_check_utf8(); } -inline string GeneratedCodeVersionSuffix() { +inline std::string GeneratedCodeVersionSuffix() { return "V3"; } -inline bool EnableExperimentalRuntime(Context* context) { - return false; -} - void WriteUInt32ToUtf16CharSequence(uint32 number, std::vector<uint16>* output); inline void WriteIntToUtf16CharSequence(int value, @@ -403,7 +410,7 @@ inline void WriteIntToUtf16CharSequence(int value, } // Escape a UTF-16 character so it can be embedded in a Java string literal. -void EscapeUtf16ToString(uint16 code, string* output); +void EscapeUtf16ToString(uint16 code, std::string* output); // Only the lowest two bytes of the return value are used. The lowest byte // is the integer value of a j/c/g/protobuf/FieldType enum. For the other @@ -422,6 +429,6 @@ std::pair<int, int> GetTableDrivenNumberOfEntriesAndLookUpStartFieldNumber( } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc deleted file mode 100644 index 6544bea0..00000000 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc +++ /dev/null @@ -1,811 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: niwasaki@google.com (Naoki Iwasaki) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_lazy_message_field.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> -#include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/io/printer.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -ImmutableLazyMessageFieldGenerator:: -ImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { -} - -ImmutableLazyMessageFieldGenerator::~ImmutableLazyMessageFieldGenerator() {} - -void ImmutableLazyMessageFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.LazyFieldLite $name$_ =\n" - " new com.google.protobuf.LazyFieldLite();\n"); - - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " return $name$_;\n" - "}\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // When using nested-builders, the code initially works just like the - // non-nested builder case. It only creates a nested builder lazily on - // demand and then forever delegates to it after creation. - - printer->Print(variables_, - "private com.google.protobuf.LazyFieldLite $name$_ =\n" - " new com.google.protobuf.LazyFieldLite();\n"); - - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" - "\n"); - - // The comments above the methods below are based on a hypothetical - // field of type "Field" called "Field". - - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "$name$_.setValue(value);\n" - "$on_changed$\n", - - NULL, // Lazy fields are supported only for lite-runtime. - - "$set_has_field_bit_builder$;\n" - "return this;\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "$name$_.setValue(builderForValue.build());\n" - "$on_changed$\n", - - NULL, - - "$set_has_field_bit_builder$;\n" - "return this;\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder merge$capitalized_name$($type$ value)", - - "if ($get_has_field_bit_builder$ &&\n" - " !$name$_.containsDefaultInstance()) {\n" - " $name$_.setValue(\n" - " $type$.newBuilder(\n" - " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" - "} else {\n" - " $name$_.setValue(value);\n" - "}\n" - "$on_changed$\n", - - NULL, - - "$set_has_field_bit_builder$;\n" - "return this;\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "$name$_.clear();\n" - "$on_changed$\n", - - NULL, - - "$clear_has_field_bit_builder$;\n" - "return this;\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" - " $set_has_field_bit_builder$;\n" - " $on_changed$\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n" - " return $name$_;\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); -} - - -void ImmutableLazyMessageFieldGenerator:: -GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.clear();\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateBuilderClearCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_.clear();\n"); - printer->Print(variables_, "$clear_has_field_bit_builder$;\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " $name$_.merge(other.$name$_);\n" - " $set_has_field_bit_builder$;\n" - "}\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " result.$name$_.set($name$_);\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_.setByteString(input.readBytes(), extensionRegistry);\n"); - printer->Print(variables_, - "$set_has_field_bit_message$;\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Do not de-serialize lazy fields. - printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" - " output.writeBytes($number$, $name$_.toByteString());\n" - "}\n"); -} - -void ImmutableLazyMessageFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, $name$_);\n" - "}\n"); -} - -// =================================================================== - -ImmutableLazyMessageOneofFieldGenerator:: -ImmutableLazyMessageOneofFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableLazyMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { - const OneofGeneratorInfo* info = - context->GetOneofGeneratorInfo(descriptor->containing_oneof()); - SetCommonOneofVariables(descriptor, info, &variables_); - variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite"; -} - -ImmutableLazyMessageOneofFieldGenerator:: -~ImmutableLazyMessageOneofFieldGenerator() {} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" - " $type$.getDefaultInstance());\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" - " $type$.getDefaultInstance());\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - "}\n" - "(($lazy_type$) $oneof_name$_).setValue(value);\n" - "$on_changed$\n", - - NULL, // Lazy fields are supported only for lite-runtime. - - "return this;\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - "}\n" - "(($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n" - "$on_changed$\n", - - NULL, - - "return this;\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder merge$capitalized_name$($type$ value)", - - "if ($has_oneof_case_message$ &&\n" - " !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n" - " (($lazy_type$) $oneof_name$_).setValue(\n" - " $type$.newBuilder(\n" - " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" - "} else {\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - " }\n" - " (($lazy_type$) $oneof_name$_).setValue(value);\n" - "}\n" - "$on_changed$\n", - - NULL, - - "return this;\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " $on_changed$\n" - "}\n", - - NULL, - - "return this;\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - "}\n" - "(($lazy_type$) $oneof_name$_).merge(\n" - " ($lazy_type$) other.$oneof_name$_);\n" - "$set_oneof_case_message$;\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateBuildingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n"); - printer->Indent(); - - printer->Print(variables_, - "result.$oneof_name$_ = new $lazy_type$();\n" - "(($lazy_type$) result.$oneof_name$_).set(\n" - " (($lazy_type$) $oneof_name$_));\n"); - printer->Outdent(); - printer->Print("}\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - "}\n" - "(($lazy_type$) $oneof_name$_).setByteString(\n" - " input.readBytes(), extensionRegistry);\n" - "$set_oneof_case_message$;\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Do not de-serialize lazy fields. - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.writeBytes(\n" - " $number$, (($lazy_type$) $oneof_name$_).toByteString());\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n" - "}\n"); -} - -// =================================================================== - -RepeatedImmutableLazyMessageFieldGenerator:: -RepeatedImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : RepeatedImmutableMessageFieldGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { -} - - -RepeatedImmutableLazyMessageFieldGenerator:: -~RepeatedImmutableLazyMessageFieldGenerator() {} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private java.util.List<com.google.protobuf.LazyFieldLite> $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$>\n" - " get$capitalized_name$List() {\n" - " java.util.List<$type$> list =\n" - " new java.util.ArrayList<$type$>($name$_.size());\n" - " for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" - " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" - " }\n" - " return list;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<? extends $type$OrBuilder>\n" - " get$capitalized_name$OrBuilderList() {\n" - " return get$capitalized_name$List();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" - " return ($type$)\n" - " $name$_.get(index).getValue($type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " return ($type$OrBuilder)\n" - " $name$_.get(index).getValue($type$.getDefaultInstance());\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // When using nested-builders, the code initially works just like the - // non-nested builder case. It only creates a nested builder lazily on - // demand and then forever delegates to it after creation. - - printer->Print(variables_, - "private java.util.List<com.google.protobuf.LazyFieldLite> $name$_ =\n" - " java.util.Collections.emptyList();\n" - - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" - " $name$_ =\n" - " new java.util.ArrayList<com.google.protobuf.LazyFieldLite>(\n" - " $name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" - "}\n" - "\n"); - - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.RepeatedFieldBuilder$ver$<\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<Field> getRepeatedFieldList() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public java.util.List<$type$> get$capitalized_name$List()", - - "java.util.List<$type$> list =\n" - " new java.util.ArrayList<$type$>($name$_.size());\n" - "for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" - " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" - "}\n" - "return java.util.Collections.unmodifiableList(list);\n", - - "return $name$Builder_.getMessageList();\n", - - NULL); - - // int getRepeatedFieldCount() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public int get$capitalized_name$Count()", - - "return $name$_.size();\n", - "return $name$Builder_.getCount();\n", - - NULL); - - // Field getRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public $type$ get$capitalized_name$(int index)", - - "return ($type$) $name$_.get(index).getValue(\n" - " $type$.getDefaultInstance());\n", - - "return $name$Builder_.getMessage(index);\n", - - NULL); - - // Builder setRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$ value)", - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "$on_changed$\n", - "$name$Builder_.setMessage(index, value);\n", - "return this;\n"); - - // Builder setRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "$on_changed$\n", - - "$name$Builder_.setMessage(index, builderForValue.build());\n", - - "return this;\n"); - - // Builder addRepeatedField(Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$($type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n" - - "$on_changed$\n", - - "$name$Builder_.addMessage(value);\n", - - "return this;\n"); - - // Builder addRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$ value)", - - "if (value == null) {\n" - " throw new NullPointerException();\n" - "}\n" - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(index, value);\n", - - "return this;\n"); - - // Builder addRepeatedField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(builderForValue.build());\n", - - "return this;\n"); - - // Builder addRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$.Builder builderForValue)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "$on_changed$\n", - - "$name$Builder_.addMessage(index, builderForValue.build());\n", - - "return this;\n"); - - // Builder addAllRepeatedField(Iterable<Field> values) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder addAll$capitalized_name$(\n" - " java.lang.Iterable<? extends $type$> values)", - - "ensure$capitalized_name$IsMutable();\n" - "for (com.google.protobuf.MessageLite v : values) {\n" - " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n" - "}\n" - "$on_changed$\n", - - "$name$Builder_.addAllMessages(values);\n", - - "return this;\n"); - - // Builder clearAllRepeatedField() - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder clear$capitalized_name$()", - - "$name$_ = java.util.Collections.emptyList();\n" - "$clear_mutable_bit_builder$;\n" - "$on_changed$\n", - - "$name$Builder_.clear();\n", - - "return this;\n"); - - // Builder removeRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction(printer, - "$deprecation$public Builder remove$capitalized_name$(int index)", - - "ensure$capitalized_name$IsMutable();\n" - "$name$_.remove(index);\n" - "$on_changed$\n", - - "$name$Builder_.remove(index);\n", - - "return this;\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " if ($name$Builder_ == null) {\n" - " return $name$_.get(index);" - " } else {\n" - " return $name$Builder_.getMessageOrBuilder(index);\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<? extends $type$OrBuilder> \n" - " get$capitalized_name$OrBuilderList() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilderList();\n" - " } else {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - " }\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " index, $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$.Builder> \n" - " get$capitalized_name$BuilderList() {\n" - " return get$capitalized_name$FieldBuilder().getBuilderList();\n" - "}\n" - "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder$ver$<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " $get_mutable_bit_builder$,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ =\n" - " new java.util.ArrayList<com.google.protobuf.LazyFieldLite>();\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "$name$_.add(new com.google.protobuf.LazyFieldLite(\n" - " extensionRegistry, input.readBytes()));\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeBytes($number$, $name$_.get(i).toByteString());\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, $name$_.get(i));\n" - "}\n"); -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.h b/src/google/protobuf/compiler/java/java_lazy_message_field.h deleted file mode 100644 index b1b7f282..00000000 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.h +++ /dev/null @@ -1,121 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: niwasaki@google.com (Naoki Iwasaki) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ - -#include <google/protobuf/compiler/java/java_field.h> -#include <google/protobuf/compiler/java/java_message_field.h> - -namespace google { -namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - } - } -} - -namespace protobuf { -namespace compiler { -namespace java { - -class ImmutableLazyMessageFieldGenerator - : public ImmutableMessageFieldGenerator { - public: - explicit ImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableLazyMessageFieldGenerator(); - - // overroads ImmutableMessageFieldGenerator --------------------------------- - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateInitializationCode(io::Printer* printer) const; - void GenerateBuilderClearCode(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldGenerator); -}; - -class ImmutableLazyMessageOneofFieldGenerator - : public ImmutableLazyMessageFieldGenerator { - public: - ImmutableLazyMessageOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableLazyMessageOneofFieldGenerator(); - - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateMergingCode(io::Printer* printer) const; - void GenerateBuildingCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldGenerator); -}; - -class RepeatedImmutableLazyMessageFieldGenerator - : public RepeatedImmutableMessageFieldGenerator { - public: - explicit RepeatedImmutableLazyMessageFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~RepeatedImmutableLazyMessageFieldGenerator(); - - // overroads RepeatedImmutableMessageFieldGenerator ------------------------- - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldGenerator); -}; - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc deleted file mode 100644 index 51bb11f1..00000000 --- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc +++ /dev/null @@ -1,725 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: niwasaki@google.com (Naoki Iwasaki) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <google/protobuf/compiler/java/java_context.h> -#include <google/protobuf/compiler/java/java_lazy_message_field_lite.h> -#include <google/protobuf/compiler/java/java_doc_comment.h> -#include <google/protobuf/compiler/java/java_helpers.h> -#include <google/protobuf/io/printer.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace java { - -ImmutableLazyMessageFieldLiteGenerator:: -ImmutableLazyMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableMessageFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { -} - -ImmutableLazyMessageFieldLiteGenerator:: -~ImmutableLazyMessageFieldLiteGenerator() {} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.LazyFieldLite $name$_;"); - - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - } else { - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $name$_ != null;\n" - "}\n"); - } - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($name$_ == null) {\n" - " return $type$.getDefaultInstance();\n" - " }\n" - " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " if ($name$_ == null) {\n" - " $name$_ = new com.google.protobuf.LazyFieldLite();\n" - " }\n" - " $name$_.setValue(value);\n" - " $set_has_field_bit_message$\n" - "}\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " if ($name$_ == null) {\n" - " $name$_ = new com.google.protobuf.LazyFieldLite();\n" - " }\n" - " $name$_.setValue(builderForValue.build());\n" - " $set_has_field_bit_message$\n" - "}\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void merge$capitalized_name$($type$ value) {\n" - " if (has$capitalized_name$() &&\n" - " !$name$_.containsDefaultInstance()) {\n" - " $name$_.setValue(\n" - " $type$.newBuilder(\n" - " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" - " } else {\n" - " if ($name$_ == null) {\n" - " $name$_ = new com.google.protobuf.LazyFieldLite();\n" - " }\n" - " $name$_.setValue(value);\n" - " $set_has_field_bit_message$\n" - " }\n" - "}\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $name$_ = null;\n" - " $clear_has_field_bit_message$;\n" - "}\n"); -} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // The comments above the methods below are based on a hypothetical - // field of type "Field" called "Field". - - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(builderForValue);\n" - " return this;\n" - "}\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n" - " copyOnWrite();\n" - " instance.merge$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); -} - - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateInitializationCode(io::Printer* printer) const {} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = visitor.visitLazyMessage($name$_, other.$name$_);\n"); -} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($name$_ == null) {\n" - " $name$_ = new com.google.protobuf.LazyFieldLite();\n" - "}\n" - "$name$_.mergeFrom(input, extensionRegistry);\n"); - printer->Print(variables_, - "$set_has_field_bit_message$\n"); -} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Do not de-serialize lazy fields. - printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " output.writeBytes($number$, $name$_.toByteString());\n" - "}\n"); -} - -void ImmutableLazyMessageFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, $name$_);\n" - "}\n"); -} - - -// =================================================================== - -ImmutableLazyMessageOneofFieldLiteGenerator:: -ImmutableLazyMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableLazyMessageFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { - const OneofGeneratorInfo* info = - context->GetOneofGeneratorInfo(descriptor->containing_oneof()); - SetCommonOneofVariables(descriptor, info, &variables_); - variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite"; -} - -ImmutableLazyMessageOneofFieldLiteGenerator:: -~ImmutableLazyMessageOneofFieldLiteGenerator() {} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $has_oneof_case_message$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" - " $type$.getDefaultInstance());\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - " }\n" - " (($lazy_type$) $oneof_name$_).setValue(value);\n" - "}\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - " }\n" - " (($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n" - "}\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void merge$capitalized_name$($type$ value) {\n" - " if ($has_oneof_case_message$ &&\n" - " !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n" - " (($lazy_type$) $oneof_name$_).setValue(\n" - " $type$.newBuilder(\n" - " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" - " } else {\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - " $set_oneof_case_message$;\n" - " }\n" - " (($lazy_type$) $oneof_name$_).setValue(value);\n" - " }\n" - "}\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " if ($has_oneof_case_message$) {\n" - " $clear_oneof_case_message$;\n" - " $oneof_name$_ = null;\n" - " }\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // boolean hasField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return instance.has$capitalized_name$();\n" - "}\n"); - - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return instance.get$capitalized_name$();\n" - "}\n"); - - // Field.Builder setField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - - // Field.Builder setField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(builderForValue);\n" - " return this;\n" - "}\n"); - - // Field.Builder mergeField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n" - " copyOnWrite();\n" - " instance.merge$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - - // Field.Builder clearField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateVisitCode(io::Printer* printer) const { - printer->Print(variables_, - "$oneof_name$_ = visitor.visitOneofLazyMessage(\n" - " $has_oneof_case_message$,\n" - " ($lazy_type$) $oneof_name$_,\n" - " ($lazy_type$) other.$oneof_name$_);\n"); -} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = new $lazy_type$();\n" - "}\n" - "(($lazy_type$) $oneof_name$_).mergeFrom(input, extensionRegistry);\n" - "$set_oneof_case_message$;\n"); -} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - // Do not de-serialize lazy fields. - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " output.writeBytes(\n" - " $number$, (($lazy_type$) $oneof_name$_).toByteString());\n" - "}\n"); -} - -void ImmutableLazyMessageOneofFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n" - "}\n"); -} - - -// =================================================================== - -RepeatedImmutableLazyMessageFieldLiteGenerator:: -RepeatedImmutableLazyMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : RepeatedImmutableMessageFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { -} - - -RepeatedImmutableLazyMessageFieldLiteGenerator:: -~RepeatedImmutableLazyMessageFieldLiteGenerator() {} - -void RepeatedImmutableLazyMessageFieldLiteGenerator:: -GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.Internal.ProtobufList<\n" - " com.google.protobuf.LazyFieldLite> $name$_;\n"); - PrintExtraFieldInfo(variables_, printer); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$>\n" - " get$capitalized_name$List() {\n" - " java.util.List<$type$> list =\n" - " new java.util.ArrayList<$type$>($name$_.size());\n" - " for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" - " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" - " }\n" - " return java.util.Collections.unmodifiableList(list);\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<? extends $type$OrBuilder>\n" - " get$capitalized_name$OrBuilderList() {\n" - " return get$capitalized_name$List();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return $name$_.size();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" - " return ($type$)\n" - " $name$_.get(index).getValue($type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " return ($type$OrBuilder)\n" - " $name$_.get(index).getValue($type$.getDefaultInstance());\n" - "}\n"); - - printer->Print(variables_, - "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - " }\n" - "}\n" - "\n"); - - // Builder setRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " int index, $type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(\n" - " index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "}\n"); - - // Builder setRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void set$capitalized_name$(\n" - " int index, $type$.Builder builderForValue) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "}\n"); - - // Builder addRepeatedField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$($type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "}\n"); - - // Builder addRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$(\n" - " int index, $type$ value) {\n" - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(\n" - " index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" - "}\n"); - - // Builder addRepeatedField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "}\n"); - - // Builder addRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void add$capitalized_name$(\n" - " int index, $type$.Builder builderForValue) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n" - " builderForValue.build()));\n" - "}\n"); - - // Builder addAllRepeatedField(Iterable<Field> values) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void addAll$capitalized_name$(\n" - " java.lang.Iterable<? extends $type$> values) {\n" - " ensure$capitalized_name$IsMutable();\n" - " for (com.google.protobuf.MessageLite v : values) {\n" - " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n" - " }\n" - "}\n"); - - // Builder clearAllRepeatedField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void clear$capitalized_name$() {\n" - " $name$_ = emptyProtobufList();\n" - "}\n"); - - // Builder removeRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private void remove$capitalized_name$(int index) {\n" - " ensure$capitalized_name$IsMutable();\n" - " $name$_.remove(index);\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldLiteGenerator:: -GenerateBuilderMembers(io::Printer* printer) const { - // List<Field> getRepeatedFieldList() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList(\n" - " instance.get$capitalized_name$List());\n" - "}\n"); - - // int getRepeatedFieldCount() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public int get$capitalized_name$Count() {\n" - " return instance.get$capitalized_name$Count();\n" - "}\n"); - - // Field getRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$(int index) {\n" - " return instance.get$capitalized_name$(index);\n" - "}\n"); - - // Builder setRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$ value) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(index, value);\n" - " return this;\n" - "}\n"); - - // Builder setRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder set$capitalized_name$(\n" - " int index, $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.set$capitalized_name$(index, builderForValue);\n" - " return this;\n" - "}\n"); - - // Builder addRepeatedField(Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(value);\n" - " return this;\n" - "}\n"); - - // Builder addRepeatedField(int index, Field value) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$ value) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(index, value);\n" - " return this;\n" - "}\n"); - - // Builder addRepeatedField(Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$(\n" - " $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(builderForValue);\n" - " return this;\n" - "}\n"); - - // Builder addRepeatedField(int index, Field.Builder builderForValue) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder add$capitalized_name$(\n" - " int index, $type$.Builder builderForValue) {\n" - " copyOnWrite();\n" - " instance.add$capitalized_name$(index, builderForValue);\n" - " return this;\n" - "}\n"); - - // Builder addAllRepeatedField(Iterable<Field> values) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder addAll$capitalized_name$(\n" - " java.lang.Iterable<? extends $type$> values) {\n" - " copyOnWrite();\n" - " instance.addAll$capitalized_name$(values);\n" - " return this;\n" - "}\n"); - - // Builder clearAllRepeatedField() - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder clear$capitalized_name$() {\n" - " copyOnWrite();\n" - " instance.clear$capitalized_name$();\n" - " return this;\n" - "}\n"); - - // Builder removeRepeatedField(int index) - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public Builder remove$capitalized_name$(int index) {\n" - " copyOnWrite();\n" - " instance.remove$capitalized_name$(index);\n" - " return this;\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldLiteGenerator:: -GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (!$is_mutable$) {\n" - " $name$_ =\n" - " com.google.protobuf.GeneratedMessageLite.mutableCopy($name$_);\n" - "}\n" - "$name$_.add(new com.google.protobuf.LazyFieldLite(\n" - " extensionRegistry, input.readBytes()));\n"); -} - -void RepeatedImmutableLazyMessageFieldLiteGenerator:: -GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.writeBytes($number$, $name$_.get(i).toByteString());\n" - "}\n"); -} - -void RepeatedImmutableLazyMessageFieldLiteGenerator:: -GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "for (int i = 0; i < $name$_.size(); i++) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .computeLazyFieldSize($number$, $name$_.get(i));\n" - "}\n"); -} - - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h deleted file mode 100644 index 65b84fbc..00000000 --- a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h +++ /dev/null @@ -1,121 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: niwasaki@google.com (Naoki Iwasaki) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__ -#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__ - -#include <google/protobuf/compiler/java/java_field.h> -#include <google/protobuf/compiler/java/java_message_field_lite.h> - -namespace google { -namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - } - } -} - -namespace protobuf { -namespace compiler { -namespace java { - -class ImmutableLazyMessageFieldLiteGenerator - : public ImmutableMessageFieldLiteGenerator { - public: - explicit ImmutableLazyMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableLazyMessageFieldLiteGenerator(); - - // overroads ImmutableMessageFieldLiteGenerator ------------------------------ - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateInitializationCode(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldLiteGenerator); -}; - -class ImmutableLazyMessageOneofFieldLiteGenerator - : public ImmutableLazyMessageFieldLiteGenerator { - public: - ImmutableLazyMessageOneofFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~ImmutableLazyMessageOneofFieldLiteGenerator(); - - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateVisitCode(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldLiteGenerator); -}; - -class RepeatedImmutableLazyMessageFieldLiteGenerator - : public RepeatedImmutableMessageFieldLiteGenerator { - public: - explicit RepeatedImmutableLazyMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); - ~RepeatedImmutableLazyMessageFieldLiteGenerator(); - - // overroads RepeatedImmutableMessageFieldLiteGenerator ---------------------- - void GenerateMembers(io::Printer* printer) const; - void GenerateBuilderMembers(io::Printer* printer) const; - void GenerateParsingCode(io::Printer* printer) const; - void GenerateSerializationCode(io::Printer* printer) const; - void GenerateSerializedSizeCode(io::Printer* printer) const; - - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldLiteGenerator); -}; - -} // namespace java -} // namespace compiler -} // namespace protobuf - -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h index 47021740..b123b041 100644 --- a/src/google/protobuf/compiler/java/java_map_field.h +++ b/src/google/protobuf/compiler/java/java_map_field.h @@ -63,11 +63,11 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; ClassNameResolver* name_resolver_; void GenerateMapGetters(io::Printer* printer) const; }; @@ -75,6 +75,6 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc index e2e68076..569c38d7 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc @@ -142,12 +142,12 @@ void SetMessageVariables(const FieldDescriptor* descriptor, ImmutableMapFieldLiteGenerator:: ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - context, &variables_); + : descriptor_(descriptor), context_(context), + name_resolver_(context->GetNameResolver()){ + SetMessageVariables(descriptor, messageBitIndex, 0, + context->GetFieldGeneratorInfo(descriptor), context, + &variables_); } ImmutableMapFieldLiteGenerator:: @@ -157,10 +157,6 @@ int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const { return 0; } -int ImmutableMapFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - void ImmutableMapFieldLiteGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h index 94aa4813..df5fe64d 100644 --- a/src/google/protobuf/compiler/java/java_map_field_lite.h +++ b/src/google/protobuf/compiler/java/java_map_field_lite.h @@ -40,14 +40,13 @@ namespace java { class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: - explicit ImmutableMapFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutableMapFieldLiteGenerator(); // implements ImmutableFieldLiteGenerator ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; @@ -63,17 +62,18 @@ class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; + Context* context_; ClassNameResolver* name_resolver_; }; } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 209c0b2a..15142231 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -35,7 +35,6 @@ #include <google/protobuf/compiler/java/java_message.h> #include <algorithm> -#include <google/protobuf/stubs/hash.h> #include <map> #include <memory> #include <vector> @@ -53,8 +52,8 @@ #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/substitute.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/substitute.h> namespace google { @@ -377,10 +376,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { "}\n"); if (context_->HasGeneratedMethods(descriptor_)) { - if (!EnableExperimentalRuntime(context_) || - IsDescriptorProto(descriptor_)) { - GenerateParsingConstructor(printer); - } + GenerateParsingConstructor(printer); } GenerateDescriptorMethods(printer); @@ -421,7 +417,8 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { descriptor_->oneof_decl(i))->name; vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( descriptor_->oneof_decl(i))->capitalized_name; - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + vars["oneof_index"] = + SimpleItoa(descriptor_->oneof_decl(i)->index()); // oneofCase_ and oneof_ printer->Print(vars, "private int $oneof_name$Case_ = 0;\n" @@ -434,11 +431,10 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); printer->Print( - "$deprecation$$field_name$($field_number$),\n", - "deprecation", - field->options().deprecated() ? "@java.lang.Deprecated " : "", - "field_name", ToUpper(field->name()), - "field_number", SimpleItoa(field->number())); + "$deprecation$$field_name$($field_number$),\n", "deprecation", + field->options().deprecated() ? "@java.lang.Deprecated " : "", + "field_name", ToUpper(field->name()), "field_number", + SimpleItoa(field->number())); } printer->Print( "$cap_oneof_name$_NOT_SET(0);\n", @@ -462,12 +458,9 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { " switch (value) {\n"); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - " case $field_number$: return $field_name$;\n", - "field_number", - SimpleItoa(field->number()), - "field_name", - ToUpper(field->name())); + printer->Print(" case $field_number$: return $field_name$;\n", + "field_number", SimpleItoa(field->number()), + "field_name", ToUpper(field->name())); } printer->Print( " case 0: return $cap_oneof_name$_NOT_SET;\n" @@ -497,8 +490,9 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // Fields for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("public static final int $constant_name$ = $number$;\n", - "constant_name", FieldConstantName(descriptor_->field(i)), - "number", SimpleItoa(descriptor_->field(i)->number())); + "constant_name", FieldConstantName(descriptor_->field(i)), + "number", + SimpleItoa(descriptor_->field(i)->number())); field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); printer->Print("\n"); } @@ -591,58 +585,54 @@ GenerateMessageSerializationMethods(io::Printer* printer) { " throws java.io.IOException {\n"); printer->Indent(); - if (EnableExperimentalRuntime(context_) && !IsDescriptorProto(descriptor_)) { - printer->Print("writeToInternal(output);\n"); - } else { - if (HasPackedFields(descriptor_)) { - // writeTo(CodedOutputStream output) might be invoked without - // getSerializedSize() ever being called, but we need the memoized - // sizes in case this message has packed fields. Rather than emit checks - // for each packed field, just call getSerializedSize() up front. In most - // cases, getSerializedSize() will have already been called anyway by one - // of the wrapper writeTo() methods, making this call cheap. - printer->Print("getSerializedSize();\n"); - } - - if (descriptor_->extension_range_count() > 0) { - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "com.google.protobuf.GeneratedMessage$ver$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter\n" - " extensionWriter = newMessageSetExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "ver", GeneratedCodeVersionSuffix()); - } else { - printer->Print( - "com.google.protobuf.GeneratedMessage$ver$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter\n" - " extensionWriter = newExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "ver", GeneratedCodeVersionSuffix()); - } - } + if (HasPackedFields(descriptor_)) { + // writeTo(CodedOutputStream output) might be invoked without + // getSerializedSize() ever being called, but we need the memoized + // sizes in case this message has packed fields. Rather than emit checks + // for each packed field, just call getSerializedSize() up front. In most + // cases, getSerializedSize() will have already been called anyway by one + // of the wrapper writeTo() methods, making this call cheap. + printer->Print("getSerializedSize();\n"); + } - // Merge the fields and the extension ranges, both sorted by field number. - for (int i = 0, j = 0; - i < descriptor_->field_count() || j < sorted_extensions.size();) { - if (i == descriptor_->field_count()) { - GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); - } else if (j == sorted_extensions.size()) { - GenerateSerializeOneField(printer, sorted_fields[i++]); - } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) { - GenerateSerializeOneField(printer, sorted_fields[i++]); - } else { - GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); - } + if (descriptor_->extension_range_count() > 0) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "com.google.protobuf.GeneratedMessage$ver$\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "ver", GeneratedCodeVersionSuffix()); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessage$ver$\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "ver", GeneratedCodeVersionSuffix()); } + } - if (descriptor_->options().message_set_wire_format()) { - printer->Print("unknownFields.writeAsMessageSetTo(output);\n"); + // Merge the fields and the extension ranges, both sorted by field number. + for (int i = 0, j = 0; + i < descriptor_->field_count() || j < sorted_extensions.size();) { + if (i == descriptor_->field_count()) { + GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); + } else if (j == sorted_extensions.size()) { + GenerateSerializeOneField(printer, sorted_fields[i++]); + } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) { + GenerateSerializeOneField(printer, sorted_fields[i++]); } else { - printer->Print("unknownFields.writeTo(output);\n"); + GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); } } + if (descriptor_->options().message_set_wire_format()) { + printer->Print("unknownFields.writeAsMessageSetTo(output);\n"); + } else { + printer->Print("unknownFields.writeTo(output);\n"); + } + printer->Outdent(); printer->Print( "}\n" @@ -653,39 +643,33 @@ GenerateMessageSerializationMethods(io::Printer* printer) { " if (size != -1) return size;\n" "\n"); printer->Indent(); - if (EnableExperimentalRuntime(context_) && !IsDescriptorProto(descriptor_)) { - printer->Print( - "memoizedSize = getSerializedSizeInternal();\n" - "return memoizedSize;\n"); - } else { - printer->Print("size = 0;\n"); + printer->Print("size = 0;\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(sorted_fields[i]) - .GenerateSerializedSizeCode(printer); - } - - if (descriptor_->extension_range_count() > 0) { - if (descriptor_->options().message_set_wire_format()) { - printer->Print("size += extensionsSerializedSizeAsMessageSet();\n"); - } else { - printer->Print("size += extensionsSerializedSize();\n"); - } - } + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(sorted_fields[i]) + .GenerateSerializedSizeCode(printer); + } + if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "size += unknownFields.getSerializedSizeAsMessageSet();\n"); + printer->Print("size += extensionsSerializedSizeAsMessageSet();\n"); } else { - printer->Print("size += unknownFields.getSerializedSize();\n"); + printer->Print("size += extensionsSerializedSize();\n"); } + } + if (descriptor_->options().message_set_wire_format()) { printer->Print( - "memoizedSize = size;\n" - "return size;\n"); + "size += unknownFields.getSerializedSizeAsMessageSet();\n"); + } else { + printer->Print("size += unknownFields.getSerializedSize();\n"); } + printer->Print( + "memoizedSize = size;\n" + "return size;\n"); + printer->Outdent(); printer->Print( "}\n" @@ -779,9 +763,8 @@ void ImmutableMessageGenerator::GenerateSerializeOneField( void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( io::Printer* printer, const Descriptor::ExtensionRange* range) { - printer->Print( - "extensionWriter.writeUntil($end$, output);\n", - "end", SimpleItoa(range->end)); + printer->Print("extensionWriter.writeUntil($end$, output);\n", "end", + SimpleItoa(range->end)); } // =================================================================== @@ -853,10 +836,10 @@ GenerateDescriptorMethods(io::Printer* printer) { const FieldDescriptor* field = map_fields[i]; const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( - "case $number$:\n" - " return internalGet$capitalized_name$();\n", - "number", SimpleItoa(field->number()), - "capitalized_name", info->capitalized_name); + "case $number$:\n" + " return internalGet$capitalized_name$();\n", + "number", SimpleItoa(field->number()), "capitalized_name", + info->capitalized_name); } printer->Print( "default:\n" @@ -944,10 +927,9 @@ void ImmutableMessageGenerator::GenerateIsInitialized( const OneofDescriptor* oneof = field->containing_oneof(); const OneofGeneratorInfo* oneof_info = context_->GetOneofGeneratorInfo(oneof); - printer->Print( - "if ($oneof_name$Case_ == $field_number$) {\n", - "oneof_name", oneof_info->name, - "field_number", SimpleItoa(field->number())); + printer->Print("if ($oneof_name$Case_ == $field_number$) {\n", + "oneof_name", oneof_info->name, "field_number", + SimpleItoa(field->number())); } else { printer->Print( "if (has$name$()) {\n", @@ -1080,10 +1062,8 @@ GenerateEqualsAndHashCode(io::Printer* printer) { printer->Indent(); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case $field_number$:\n", - "field_number", - SimpleItoa(field->number())); + printer->Print("case $field_number$:\n", "field_number", + SimpleItoa(field->number())); printer->Indent(); field_generators_.get(field).GenerateEqualsCode(printer); printer->Print("break;\n"); @@ -1164,10 +1144,8 @@ GenerateEqualsAndHashCode(io::Printer* printer) { printer->Indent(); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case $field_number$:\n", - "field_number", - SimpleItoa(field->number())); + printer->Print("case $field_number$:\n", "field_number", + SimpleItoa(field->number())); printer->Indent(); field_generators_.get(field).GenerateHashCode(printer); printer->Print("break;\n"); @@ -1273,9 +1251,8 @@ GenerateParsingConstructor(io::Printer* printer) { uint32 tag = WireFormatLite::MakeTag(field->number(), WireFormat::WireTypeForFieldType(field->type())); - printer->Print( - "case $tag$: {\n", - "tag", SimpleItoa(static_cast<int32>(tag))); + printer->Print("case $tag$: {\n", "tag", + SimpleItoa(static_cast<int32>(tag))); printer->Indent(); field_generators_.get(field).GenerateParsingCode(printer); @@ -1290,9 +1267,8 @@ GenerateParsingConstructor(io::Printer* printer) { // packed version of this field regardless of field->options().packed(). uint32 packed_tag = WireFormatLite::MakeTag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED); - printer->Print( - "case $tag$: {\n", - "tag", SimpleItoa(static_cast<int32>(packed_tag))); + printer->Print("case $tag$: {\n", "tag", + SimpleItoa(static_cast<int32>(packed_tag))); printer->Indent(); field_generators_.get(field).GenerateParsingCodeFromPacked(printer); @@ -1306,15 +1282,12 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Print( "default: {\n" - " if (!parseUnknownField$suffix$(\n" + " if (!parseUnknownField(\n" " input, unknownFields, extensionRegistry, tag)) {\n" " done = true;\n" // it's an endgroup tag " }\n" " break;\n" - "}\n", - "suffix", - descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ? "Proto3" - : ""); + "}\n"); printer->Outdent(); printer->Outdent(); @@ -1369,16 +1342,7 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n", "classname", descriptor_->name()); - if (EnableExperimentalRuntime(context_) && !IsDescriptorProto(descriptor_)) { - printer->Indent(); - printer->Print( - "$classname$ msg = new $classname$();\n" - "msg.mergeFromInternal(input, extensionRegistry);\n" - "msg.makeImmutableInternal();\n" - "return msg;\n", - "classname", descriptor_->name()); - printer->Outdent(); - } else if (context_->HasGeneratedMethods(descriptor_)) { + if (context_->HasGeneratedMethods(descriptor_)) { printer->Print(" return new $classname$(input, extensionRegistry);\n", "classname", descriptor_->name()); } else { diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index da1447c1..ac0c7659 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -41,17 +41,19 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -66,8 +68,8 @@ class MessageGenerator { // All static variables have to be declared at the top-level of the file // so that we can control initialization order, which is important for // DescriptorProto bootstrapping to work. - virtual void GenerateStaticVariables( - io::Printer* printer, int* bytecode_estimate) = 0; + virtual void GenerateStaticVariables(io::Printer* printer, + int* bytecode_estimate) = 0; // Output code which initializes the static variables generated by // GenerateStaticVariables(). Returns an estimate of bytecode size. @@ -76,7 +78,8 @@ class MessageGenerator { // Generate the class itself. virtual void Generate(io::Printer* printer) = 0; - // Generates the base interface that both the class and its builder implement + // Generates the base interface that both the class and its builder + // implement virtual void GenerateInterface(io::Printer* printer) = 0; // Generate code to register all contained extensions with an @@ -137,6 +140,6 @@ class ImmutableMessageGenerator : public MessageGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc index 4c67e806..0b9db222 100644 --- a/src/google/protobuf/compiler/java/java_message_builder.cc +++ b/src/google/protobuf/compiler/java/java_message_builder.cc @@ -35,7 +35,6 @@ #include <google/protobuf/compiler/java/java_message_builder.h> #include <algorithm> -#include <google/protobuf/stubs/hash.h> #include <map> #include <memory> #include <vector> @@ -51,8 +50,8 @@ #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/substitute.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/substitute.h> namespace google { @@ -126,7 +125,8 @@ Generate(io::Printer* printer) { descriptor_->oneof_decl(i))->name; vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( descriptor_->oneof_decl(i))->capitalized_name; - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + vars["oneof_index"] = + SimpleItoa(descriptor_->oneof_decl(i)->index()); // oneofCase_ and oneof_ printer->Print(vars, "private int $oneof_name$Case_ = 0;\n" @@ -169,8 +169,6 @@ Generate(io::Printer* printer) { .GenerateBuilderMembers(printer); } - bool is_proto3 = - descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; // Override methods declared in GeneratedMessage to return the concrete // generated type so callsites won't depend on GeneratedMessage. This // is needed to keep binary compatibility when we change generated code @@ -180,7 +178,7 @@ Generate(io::Printer* printer) { "@java.lang.Override\n" "public final Builder setUnknownFields(\n" " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" - " return super.setUnknownFields$suffix$(unknownFields);\n" + " return super.setUnknownFields(unknownFields);\n" "}\n" "\n" "@java.lang.Override\n" @@ -188,8 +186,7 @@ Generate(io::Printer* printer) { " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" " return super.mergeUnknownFields(unknownFields);\n" "}\n" - "\n", - "suffix", is_proto3 ? "Proto3" : ""); + "\n"); printer->Print( "\n" @@ -234,10 +231,10 @@ GenerateDescriptorMethods(io::Printer* printer) { const FieldDescriptor* field = map_fields[i]; const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( - "case $number$:\n" - " return internalGet$capitalized_name$();\n", - "number", SimpleItoa(field->number()), - "capitalized_name", info->capitalized_name); + "case $number$:\n" + " return internalGet$capitalized_name$();\n", + "number", SimpleItoa(field->number()), "capitalized_name", + info->capitalized_name); } printer->Print( "default:\n" @@ -260,10 +257,10 @@ GenerateDescriptorMethods(io::Printer* printer) { const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( - "case $number$:\n" - " return internalGetMutable$capitalized_name$();\n", - "number", SimpleItoa(field->number()), - "capitalized_name", info->capitalized_name); + "case $number$:\n" + " return internalGetMutable$capitalized_name$();\n", + "number", SimpleItoa(field->number()), "capitalized_name", + info->capitalized_name); } printer->Print( "default:\n" @@ -686,10 +683,9 @@ void MessageBuilderGenerator::GenerateIsInitialized( const OneofDescriptor* oneof = field->containing_oneof(); const OneofGeneratorInfo* oneof_info = context_->GetOneofGeneratorInfo(oneof); - printer->Print( - "if ($oneof_name$Case_ == $field_number$) {\n", - "oneof_name", oneof_info->name, - "field_number", SimpleItoa(field->number())); + printer->Print("if ($oneof_name$Case_ == $field_number$) {\n", + "oneof_name", oneof_info->name, "field_number", + SimpleItoa(field->number())); } else { printer->Print( "if (has$name$()) {\n", diff --git a/src/google/protobuf/compiler/java/java_message_builder.h b/src/google/protobuf/compiler/java/java_message_builder.h index 015ea062..d67a9c9d 100644 --- a/src/google/protobuf/compiler/java/java_message_builder.h +++ b/src/google/protobuf/compiler/java/java_message_builder.h @@ -41,17 +41,19 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -81,6 +83,6 @@ class MessageBuilderGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__ diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.cc b/src/google/protobuf/compiler/java/java_message_builder_lite.cc index f04d394e..b9a12d4a 100644 --- a/src/google/protobuf/compiler/java/java_message_builder_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_builder_lite.cc @@ -35,7 +35,6 @@ #include <google/protobuf/compiler/java/java_message_builder_lite.h> #include <algorithm> -#include <google/protobuf/stubs/hash.h> #include <map> #include <memory> #include <vector> @@ -51,8 +50,8 @@ #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/substitute.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/substitute.h> namespace google { namespace protobuf { @@ -102,7 +101,8 @@ Generate(io::Printer* printer) { descriptor_->oneof_decl(i))->name; vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( descriptor_->oneof_decl(i))->capitalized_name; - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + vars["oneof_index"] = + SimpleItoa(descriptor_->oneof_decl(i)->index()); // oneofCase() and clearOneof() printer->Print(vars, @@ -120,20 +120,6 @@ Generate(io::Printer* printer) { "\n"); } - if (GenerateHasBits(descriptor_)) { - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForBuilder(); - } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - } - for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("\n"); field_generators_.get(descriptor_->field(i)) diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.h b/src/google/protobuf/compiler/java/java_message_builder_lite.h index 8597b2e6..079d86a9 100644 --- a/src/google/protobuf/compiler/java/java_message_builder_lite.h +++ b/src/google/protobuf/compiler/java/java_message_builder_lite.h @@ -41,17 +41,19 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -59,7 +61,7 @@ namespace java { class MessageBuilderLiteGenerator { public: explicit MessageBuilderLiteGenerator(const Descriptor* descriptor, - Context* context); + Context* context); virtual ~MessageBuilderLiteGenerator(); virtual void Generate(io::Printer* printer); @@ -78,6 +80,6 @@ class MessageBuilderLiteGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index bda4fcc0..92425d06 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -254,8 +254,7 @@ GenerateBuilderMembers(io::Printer* printer) const { bool support_field_presence = SupportFieldPresence(descriptor_->file()); - printer->Print(variables_, - "private $type$ $name$_;\n"); + printer->Print(variables_, "private $type$ $name$_;\n"); printer->Print(variables_, // If this builder is non-null, it is used and the other fields are @@ -443,20 +442,17 @@ GenerateMergingCode(io::Printer* printer) const { void ImmutableMessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n"); + printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n"); printer->Indent(); - PrintNestedBuilderCondition(printer, - "result.$name$_ = $name$_;\n", - "result.$name$_ = $name$Builder_.build();\n"); + PrintNestedBuilderCondition(printer, "result.$name$_ = $name$_;\n", + "result.$name$_ = $name$Builder_.build();\n"); printer->Outdent(); printer->Print(variables_, - " $set_has_field_bit_to_local$;\n" - "}\n"); + " $set_has_field_bit_to_local$;\n" + "}\n"); } else { - PrintNestedBuilderCondition(printer, - "result.$name$_ = $name$_;\n", - "result.$name$_ = $name$Builder_.build();\n"); + PrintNestedBuilderCondition(printer, "result.$name$_ = $name$_;\n", + "result.$name$_ = $name$Builder_.build();\n"); } } diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h index 7ee0edb2..58344e55 100644 --- a/src/google/protobuf/compiler/java/java_message_field.h +++ b/src/google/protobuf/compiler/java/java_message_field.h @@ -41,26 +41,30 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { public: - explicit ImmutableMessageFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context); ~ImmutableMessageFieldGenerator(); - // implements ImmutableFieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator + // --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -78,22 +82,24 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; void PrintNestedBuilderCondition(io::Printer* printer, - const char* regular_case, const char* nested_builder_case) const; + 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; + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator); @@ -102,9 +108,9 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { class ImmutableMessageOneofFieldGenerator : public ImmutableMessageFieldGenerator { public: - ImmutableMessageOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex, + Context* context); ~ImmutableMessageOneofFieldGenerator(); void GenerateMembers(io::Printer* printer) const; @@ -144,22 +150,24 @@ class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; void PrintNestedBuilderCondition(io::Printer* printer, - const char* regular_case, const char* nested_builder_case) const; + 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; + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator); @@ -168,6 +176,6 @@ class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc index 9cf6f363..7bf6426e 100644 --- a/src/google/protobuf/compiler/java/java_message_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc @@ -104,17 +104,15 @@ void SetMessageVariables(const FieldDescriptor* descriptor, // =================================================================== -ImmutableMessageFieldLiteGenerator:: -ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); +ImmutableMessageFieldLiteGenerator::ImmutableMessageFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, 0, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } ImmutableMessageFieldLiteGenerator::~ImmutableMessageFieldLiteGenerator() {} @@ -123,10 +121,6 @@ int ImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const { return 1; } -int ImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - void ImmutableMessageFieldLiteGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); @@ -387,12 +381,10 @@ string ImmutableMessageFieldLiteGenerator::GetBoxedType() const { // =================================================================== ImmutableMessageOneofFieldLiteGenerator:: -ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableMessageFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { + ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context) + : ImmutableMessageFieldLiteGenerator(descriptor, messageBitIndex, context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); @@ -593,14 +585,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { // =================================================================== RepeatedImmutableMessageFieldLiteGenerator:: -RepeatedImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + RepeatedImmutableMessageFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } @@ -612,10 +604,6 @@ int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - void RepeatedImmutableMessageFieldLiteGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { // TODO(jonp): In the future, consider having methods specific to the diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h index 7c814c6d..7e78ca4f 100644 --- a/src/google/protobuf/compiler/java/java_message_field_lite.h +++ b/src/google/protobuf/compiler/java/java_message_field_lite.h @@ -41,28 +41,30 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: - explicit ImmutableMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutableMessageFieldLiteGenerator(); - // implements ImmutableFieldLiteGenerator ------------------------------------ + // implements ImmutableFieldLiteGenerator + // ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; @@ -77,13 +79,12 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; - const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; @@ -94,9 +95,9 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { class ImmutableMessageOneofFieldLiteGenerator : public ImmutableMessageFieldLiteGenerator { public: - ImmutableMessageOneofFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutableMessageOneofFieldLiteGenerator(); void GenerateMembers(io::Printer* printer) const; @@ -115,13 +116,11 @@ class RepeatedImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: explicit RepeatedImmutableMessageFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + const FieldDescriptor* descriptor, int messageBitIndex, Context* context); ~RepeatedImmutableMessageFieldLiteGenerator(); // implements ImmutableFieldLiteGenerator ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; @@ -137,13 +136,12 @@ class RepeatedImmutableMessageFieldLiteGenerator void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; - const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; @@ -154,6 +152,6 @@ class RepeatedImmutableMessageFieldLiteGenerator } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc index 3a512e8d..a131e8cc 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.cc +++ b/src/google/protobuf/compiler/java/java_message_lite.cc @@ -35,7 +35,6 @@ #include <google/protobuf/compiler/java/java_message_lite.h> #include <algorithm> -#include <google/protobuf/stubs/hash.h> #include <map> #include <memory> #include <vector> @@ -53,8 +52,8 @@ #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/substitute.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/substitute.h> namespace google { @@ -266,12 +265,9 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { printer->Indent(); for (int j = 0; j < oneof->field_count(); j++) { const FieldDescriptor* field = oneof->field(j); - printer->Print( - "$field_name$($field_number$),\n", - "field_name", - ToUpper(field->name()), - "field_number", - SimpleItoa(field->number())); + printer->Print("$field_name$($field_number$),\n", "field_name", + ToUpper(field->name()), "field_number", + SimpleItoa(field->number())); } printer->Print( "$cap_oneof_name$_NOT_SET(0);\n", @@ -295,12 +291,9 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { " switch (value) {\n"); for (int j = 0; j < oneof->field_count(); j++) { const FieldDescriptor* field = oneof->field(j); - printer->Print( - " case $field_number$: return $field_name$;\n", - "field_number", - SimpleItoa(field->number()), - "field_name", - ToUpper(field->name())); + printer->Print(" case $field_number$: return $field_name$;\n", + "field_number", SimpleItoa(field->number()), + "field_name", ToUpper(field->name())); } printer->Print( " case 0: return $cap_oneof_name$_NOT_SET;\n" @@ -333,16 +326,14 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { // Fields for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("public static final int $constant_name$ = $number$;\n", - "constant_name", FieldConstantName(descriptor_->field(i)), - "number", SimpleItoa(descriptor_->field(i)->number())); + "constant_name", FieldConstantName(descriptor_->field(i)), + "number", + SimpleItoa(descriptor_->field(i)->number())); field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); printer->Print("\n"); } - if (!EnableExperimentalRuntime(context_)) { - GenerateMessageSerializationMethods(printer); - } - + GenerateMessageSerializationMethods(printer); GenerateParseFromMethods(printer); GenerateBuilder(printer); @@ -737,23 +728,22 @@ void ImmutableMessageLiteGenerator::GenerateSerializeOneField( void ImmutableMessageLiteGenerator::GenerateSerializeOneExtensionRange( io::Printer* printer, const Descriptor::ExtensionRange* range) { - printer->Print( - "extensionWriter.writeUntil($end$, output);\n", - "end", SimpleItoa(range->end)); + printer->Print("extensionWriter.writeUntil($end$, output);\n", "end", + SimpleItoa(range->end)); } // =================================================================== void ImmutableMessageLiteGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( - "public static Builder newBuilder() {\n" - " return (Builder) DEFAULT_INSTANCE.createBuilder();\n" - "}\n" - "public static Builder newBuilder($classname$ prototype) {\n" - " return (Builder) DEFAULT_INSTANCE.createBuilder(prototype);\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "public static Builder newBuilder() {\n" + " return (Builder) DEFAULT_INSTANCE.createBuilder();\n" + "}\n" + "public static Builder newBuilder($classname$ prototype) {\n" + " return (Builder) DEFAULT_INSTANCE.createBuilder(prototype);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); MessageBuilderLiteGenerator builderGenerator(descriptor_, context_); builderGenerator.Generate(printer); @@ -818,10 +808,9 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( const OneofDescriptor* oneof = field->containing_oneof(); const OneofGeneratorInfo* oneof_info = context_->GetOneofGeneratorInfo(oneof); - printer->Print( - "if ($oneof_name$Case_ == $field_number$) {\n", - "oneof_name", oneof_info->name, - "field_number", SimpleItoa(field->number())); + printer->Print("if ($oneof_name$Case_ == $field_number$) {\n", + "oneof_name", oneof_info->name, "field_number", + SimpleItoa(field->number())); } else { printer->Print( "if (has$name$()) {\n", @@ -1002,102 +991,96 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFromStream( printer->Print( "try {\n"); printer->Indent(); - if (EnableExperimentalRuntime(context_)) { - printer->Print( - "mergeFromInternal(input, extensionRegistry);\n" - "return DEFAULT_INSTANCE;\n"); - } else { - printer->Print( - "boolean done = false;\n" - "while (!done) {\n"); - printer->Indent(); + printer->Print( + "boolean done = false;\n" + "while (!done) {\n"); + printer->Indent(); - printer->Print( - "int tag = input.readTag();\n" - "switch (tag) {\n"); + printer->Print( + "int tag = input.readTag();\n" + "switch (tag) {\n"); + printer->Indent(); + + printer->Print( + "case 0:\n" // zero signals EOF / limit reached + " done = true;\n" + " break;\n"); + + std::unique_ptr<const FieldDescriptor* []> sorted_fields( + SortFieldsByNumber(descriptor_)); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = sorted_fields[i]; + uint32 tag = WireFormatLite::MakeTag( + field->number(), WireFormat::WireTypeForFieldType(field->type())); + + printer->Print("case $tag$: {\n", "tag", + SimpleItoa(static_cast<int32>(tag))); printer->Indent(); - printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " done = true;\n" - " break;\n"); + field_generators_.get(field).GenerateParsingCode(printer); - std::unique_ptr<const FieldDescriptor* []> sorted_fields( - SortFieldsByNumber(descriptor_)); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = sorted_fields[i]; - uint32 tag = WireFormatLite::MakeTag( - field->number(), WireFormat::WireTypeForFieldType(field->type())); + printer->Outdent(); + printer->Print( + " break;\n" + "}\n"); + if (field->is_packable()) { + // To make packed = true wire compatible, we generate parsing code from + // a packed version of this field regardless of + // field->options().packed(). + uint32 packed_tag = WireFormatLite::MakeTag( + field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED); printer->Print("case $tag$: {\n", "tag", - SimpleItoa(static_cast<int32>(tag))); + SimpleItoa(static_cast<int32>(packed_tag))); printer->Indent(); - field_generators_.get(field).GenerateParsingCode(printer); + field_generators_.get(field).GenerateParsingCodeFromPacked(printer); printer->Outdent(); printer->Print( - " break;\n" - "}\n"); - - if (field->is_packable()) { - // To make packed = true wire compatible, we generate parsing code from - // a packed version of this field regardless of - // field->options().packed(). - uint32 packed_tag = WireFormatLite::MakeTag( - field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED); - printer->Print("case $tag$: {\n", "tag", - SimpleItoa(static_cast<int32>(packed_tag))); - printer->Indent(); - - field_generators_.get(field).GenerateParsingCodeFromPacked(printer); - - printer->Outdent(); - printer->Print( - " break;\n" - "}\n"); - } + " break;\n" + "}\n"); } + } - if (descriptor_->extension_range_count() > 0) { - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "default: {\n" - " if (!parseUnknownFieldAsMessageSet(\n" - " getDefaultInstanceForType(), input, extensionRegistry,\n" - " tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } else { - printer->Print( - "default: {\n" - " if (!parseUnknownField(getDefaultInstanceForType(),\n" - " input, extensionRegistry, tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } + if (descriptor_->extension_range_count() > 0) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "default: {\n" + " if (!parseUnknownFieldAsMessageSet(\n" + " getDefaultInstanceForType(), input, extensionRegistry,\n" + " tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); } else { printer->Print( "default: {\n" - " if (!parseUnknownField(tag, input)) {\n" + " if (!parseUnknownField(getDefaultInstanceForType(),\n" + " input, extensionRegistry, tag)) {\n" " done = true;\n" // it's an endgroup tag " }\n" " break;\n" "}\n"); } - - printer->Outdent(); - printer->Outdent(); + } else { printer->Print( - " }\n" // switch (tag) - "}\n"); // while (!done) + "default: {\n" + " if (!parseUnknownField(tag, input)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); } printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" // switch (tag) + "}\n"); // while (!done) + + printer->Outdent(); printer->Print( "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" " throw new RuntimeException(e.setUnfinishedMessage(this));\n" diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h index 1e319c6d..d38c54a7 100644 --- a/src/google/protobuf/compiler/java/java_message_lite.h +++ b/src/google/protobuf/compiler/java/java_message_lite.h @@ -87,6 +87,6 @@ class ImmutableMessageLiteGenerator : public MessageGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h index 28b049d1..aa19f007 100644 --- a/src/google/protobuf/compiler/java/java_name_resolver.h +++ b/src/google/protobuf/compiler/java/java_name_resolver.h @@ -56,63 +56,63 @@ class ClassNameResolver { ~ClassNameResolver(); // Gets the unqualified outer class name for the file. - string GetFileClassName(const FileDescriptor* file, bool immutable); + std::string GetFileClassName(const FileDescriptor* file, bool immutable); // Gets the unqualified immutable outer class name of a file. - string GetFileImmutableClassName(const FileDescriptor* file); + std::string GetFileImmutableClassName(const FileDescriptor* file); // Gets the unqualified default immutable outer class name of a file // (converted from the proto file's name). - string GetFileDefaultImmutableClassName(const FileDescriptor* file); + std::string GetFileDefaultImmutableClassName(const FileDescriptor* file); // Check whether there is any type defined in the proto file that has // the given class name. bool HasConflictingClassName(const FileDescriptor* file, - const string& classname); + const std::string& classname); // Gets the name of the outer class that holds descriptor information. // Descriptors are shared between immutable messages and mutable messages. // Since both of them are generated optionally, the descriptors need to be // put in another common place. - string GetDescriptorClassName(const FileDescriptor* file); + std::string GetDescriptorClassName(const FileDescriptor* file); // Gets the fully-qualified class name corresponding to the given descriptor. - string GetClassName(const Descriptor* descriptor, bool immutable); - string GetClassName(const EnumDescriptor* descriptor, bool immutable); - string GetClassName(const ServiceDescriptor* descriptor, bool immutable); - string GetClassName(const FileDescriptor* descriptor, bool immutable); + std::string GetClassName(const Descriptor* descriptor, bool immutable); + std::string GetClassName(const EnumDescriptor* descriptor, bool immutable); + std::string GetClassName(const ServiceDescriptor* descriptor, bool immutable); + std::string GetClassName(const FileDescriptor* descriptor, bool immutable); template<class DescriptorType> - string GetImmutableClassName(const DescriptorType* descriptor) { + std::string GetImmutableClassName(const DescriptorType* descriptor) { return GetClassName(descriptor, true); } template<class DescriptorType> - string GetMutableClassName(const DescriptorType* descriptor) { + std::string GetMutableClassName(const DescriptorType* descriptor) { return GetClassName(descriptor, false); } // Gets the fully qualified name of an extension identifier. - string GetExtensionIdentifierName(const FieldDescriptor* descriptor, + std::string GetExtensionIdentifierName(const FieldDescriptor* descriptor, bool immutable); // Gets the fully qualified name for generated classes in Java convention. // Nested classes will be separated using '$' instead of '.' // For example: // com.package.OuterClass$OuterMessage$InnerMessage - string GetJavaImmutableClassName(const Descriptor* descriptor); - string GetJavaImmutableClassName(const EnumDescriptor* descriptor); + std::string GetJavaImmutableClassName(const Descriptor* descriptor); + std::string GetJavaImmutableClassName(const EnumDescriptor* descriptor); private: // Get the full name of a Java class by prepending the Java package name // or outer class name. - string GetClassFullName(const string& name_without_package, + std::string GetClassFullName(const std::string& name_without_package, const FileDescriptor* file, bool immutable, bool multiple_files); // Get the Java Class style full name of a message. - string GetJavaClassFullName( - const string& name_without_package, + std::string GetJavaClassFullName( + const std::string& name_without_package, const FileDescriptor* file, bool immutable); // Caches the result to provide better performance. - std::map<const FileDescriptor*, string> file_immutable_outer_class_names_; + std::map<const FileDescriptor*, std::string> file_immutable_outer_class_names_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ClassNameResolver); }; @@ -120,6 +120,6 @@ class ClassNameResolver { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ diff --git a/src/google/protobuf/compiler/java/java_names.h b/src/google/protobuf/compiler/java/java_names.h index 0d614335..a8efbb49 100644 --- a/src/google/protobuf/compiler/java/java_names.h +++ b/src/google/protobuf/compiler/java/java_names.h @@ -46,6 +46,7 @@ namespace protobuf { class Descriptor; class EnumDescriptor; class FileDescriptor; +class FieldDescriptor; class ServiceDescriptor; namespace compiler { @@ -56,32 +57,56 @@ namespace java { // // Returns: // The fully-qualified Java class name. -string ClassName(const Descriptor* descriptor); +std::string ClassName(const Descriptor* descriptor); // Requires: // descriptor != NULL // // Returns: // The fully-qualified Java class name. -string ClassName(const EnumDescriptor* descriptor); +std::string ClassName(const EnumDescriptor* descriptor); // Requires: // descriptor != NULL // // Returns: // The fully-qualified Java class name. -string ClassName(const FileDescriptor* descriptor); +std::string ClassName(const FileDescriptor* descriptor); // Requires: // descriptor != NULL // // Returns: // The fully-qualified Java class name. -string ClassName(const ServiceDescriptor* descriptor); +std::string ClassName(const ServiceDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// +// Returns: +// Java package name. +std::string FileJavaPackage(const FileDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// Returns: +// Captialized camel case name field name. +std::string CapitalizedFieldName(const FieldDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// Returns: +// Primitive Java type name for the field. +const char* PrimitiveTypeName(const FieldDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// Returns: +// Boes primitive Java type name for the field. +const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor); } // namespace java } // namespace compiler } // namespace protobuf } // namespace google - #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__ diff --git a/src/google/protobuf/compiler/java/java_options.h b/src/google/protobuf/compiler/java/java_options.h index e4e7d5e2..6c29be15 100644 --- a/src/google/protobuf/compiler/java/java_options.h +++ b/src/google/protobuf/compiler/java/java_options.h @@ -68,6 +68,6 @@ struct Options { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__ diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc index 87f687da..644d0685 100644 --- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc +++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc @@ -95,7 +95,7 @@ TEST(JavaPluginTest, PluginTest) { "enum Qux { BLAH = 1; }\n", true)); - google::protobuf::compiler::CommandLineInterface cli; + CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); JavaGenerator java_generator; diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index e6ce69c7..c98c8b3a 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -56,6 +56,14 @@ using internal::WireFormatLite; namespace { +bool EnableJavaPrimitiveExperiment() { +#ifdef PROTOBUF_JAVA_PRIMITIVE_EXPERIMENT + return PROTOBUF_JAVA_PRIMITIVE_EXPERIMENT; +#else // PROTOBUF_JAVA_PRIMITIVE_EXPERIMENT + return false; +#endif // !PROTOBUF_JAVA_PRIMITIVE_EXPERIMENT +} + void SetPrimitiveVariables(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, @@ -63,13 +71,51 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, ClassNameResolver* name_resolver, std::map<string, string>* variables) { SetCommonFieldVariables(descriptor, info, variables); + JavaType javaType = GetJavaType(descriptor); - (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); - (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); + (*variables)["type"] = PrimitiveTypeName(javaType); + (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType); (*variables)["field_type"] = (*variables)["type"]; - (*variables)["field_list_type"] = "java.util.List<" + - (*variables)["boxed_type"] + ">"; - (*variables)["empty_list"] = "java.util.Collections.emptyList()"; + + if (EnableJavaPrimitiveExperiment() && + (javaType == JAVATYPE_BOOLEAN || + javaType == JAVATYPE_DOUBLE || + javaType == JAVATYPE_FLOAT || + javaType == JAVATYPE_INT || + javaType == JAVATYPE_LONG)) { + string capitalized_type = UnderscoresToCamelCase( + PrimitiveTypeName(javaType), /*cap_first_letter=*/true); + (*variables)["field_list_type"] = + "com.google.protobuf.Internal." + capitalized_type + "List"; + (*variables)["empty_list"] = "empty" + capitalized_type + "List()"; + (*variables)["create_list"] = "new" + capitalized_type + "List()"; + (*variables)["mutable_copy_list"] = + "mutableCopy(" + (*variables)["name"] + "_)"; + (*variables)["name_make_immutable"] = + (*variables)["name"] + "_.makeImmutable()"; + (*variables)["repeated_get"] = + (*variables)["name"] + "_.get" + capitalized_type; + (*variables)["repeated_add"] = + (*variables)["name"] + "_.add" + capitalized_type; + (*variables)["repeated_set"] = + (*variables)["name"] + "_.set" + capitalized_type; + } else { + (*variables)["field_list_type"] = + "java.util.List<" + (*variables)["boxed_type"] + ">"; + (*variables)["create_list"] = + "new java.util.ArrayList<" + (*variables)["boxed_type"] + ">()"; + (*variables)["mutable_copy_list"] = "new java.util.ArrayList<" + + (*variables)["boxed_type"] + ">(" + + (*variables)["name"] + "_)"; + (*variables)["empty_list"] = "java.util.Collections.emptyList()"; + (*variables)["name_make_immutable"] = + (*variables)["name"] + "_ = java.util.Collections.unmodifiableList(" + + (*variables)["name"] + "_)"; + (*variables)["repeated_get"] = (*variables)["name"] + "_.get"; + (*variables)["repeated_add"] = (*variables)["name"] + "_.add"; + (*variables)["repeated_set"] = (*variables)["name"] + "_.set"; + } + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ? "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver)); @@ -294,22 +340,21 @@ GenerateMergingCode(io::Printer* printer) const { void ImmutablePrimitiveFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " result.$name$_ = $name$_;\n" - " $set_has_field_bit_to_local$;\n"); if (IsDefaultValueJavaDefault(descriptor_)) { printer->Print(variables_, - "}\n"); + "if ($get_has_field_bit_from_local$) {\n" + " result.$name$_ = $name$_;\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); } else { printer->Print(variables_, - "} else {\n" - " result.$name$_ = $default$;\n" - "}\n"); + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n" + "result.$name$_ = $name$_;\n"); } } else { - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); + printer->Print(variables_, "result.$name$_ = $name$_;\n"); } } @@ -641,7 +686,7 @@ GenerateMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_.get(index);\n" + " return $repeated_get$(index);\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -668,7 +713,7 @@ GenerateBuilderMembers(io::Printer* printer) const { 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" + " $name$_ = $mutable_copy_list$;\n" " $set_mutable_bit_builder$;\n" " }\n" "}\n"); @@ -681,7 +726,8 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, "$deprecation$public java.util.List<$boxed_type$>\n" " ${$get$capitalized_name$List$}$() {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" + " return $get_mutable_bit_builder$ ?\n" + " java.util.Collections.unmodifiableList($name$_) : $name$_;\n" "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); @@ -693,7 +739,7 @@ GenerateBuilderMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n" - " return $name$_.get(index);\n" + " return $repeated_get$(index);\n" "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); @@ -702,7 +748,7 @@ GenerateBuilderMembers(io::Printer* printer) const { " int index, $type$ value) {\n" "$null_check$" " ensure$capitalized_name$IsMutable();\n" - " $name$_.set(index, value);\n" + " $repeated_set$(index, value);\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -712,7 +758,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n" "$null_check$" " ensure$capitalized_name$IsMutable();\n" - " $name$_.add(value);\n" + " $repeated_add$(value);\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -782,7 +828,7 @@ GenerateBuildingCode(io::Printer* printer) const { // list is immutable, we can just reuse it. If not, we make it immutable. printer->Print(variables_, "if ($get_mutable_bit_builder$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $name_make_immutable$;\n" " $clear_mutable_bit_builder$;\n" "}\n" "result.$name$_ = $name$_;\n"); @@ -792,10 +838,10 @@ void RepeatedImmutablePrimitiveFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" + " $name$_ = $create_list$;\n" " $set_mutable_bit_parser$;\n" "}\n" - "$name$_.add(input.read$capitalized_type$());\n"); + "$repeated_add$(input.read$capitalized_type$());\n"); } void RepeatedImmutablePrimitiveFieldGenerator:: @@ -804,11 +850,11 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { "int length = input.readRawVarint32();\n" "int limit = input.pushLimit(length);\n" "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" - " $name$_ = new java.util.ArrayList<$boxed_type$>();\n" + " $name$_ = $create_list$;\n" " $set_mutable_bit_parser$;\n" "}\n" "while (input.getBytesUntilLimit() > 0) {\n" - " $name$_.add(input.read$capitalized_type$());\n" + " $repeated_add$(input.read$capitalized_type$());\n" "}\n" "input.popLimit(limit);\n"); } @@ -817,7 +863,7 @@ void RepeatedImmutablePrimitiveFieldGenerator:: GenerateParsingDoneCode(io::Printer* printer) const { printer->Print(variables_, "if ($get_mutable_bit_parser$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" + " $name_make_immutable$; // C\n" "}\n"); } @@ -833,12 +879,12 @@ GenerateSerializationCode(io::Printer* printer) const { " output.writeUInt32NoTag($name$MemoizedSerializedSize);\n" "}\n" "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$NoTag($name$_.get(i));\n" + " output.write$capitalized_type$NoTag($repeated_get$(i));\n" "}\n"); } else { printer->Print(variables_, "for (int i = 0; i < $name$_.size(); i++) {\n" - " output.write$capitalized_type$($number$, $name$_.get(i));\n" + " output.write$capitalized_type$($number$, $repeated_get$(i));\n" "}\n"); } } @@ -854,7 +900,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "for (int i = 0; i < $name$_.size(); i++) {\n" " dataSize += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$SizeNoTag($name$_.get(i));\n" + " .compute$capitalized_type$SizeNoTag($repeated_get$(i));\n" "}\n"); } else { printer->Print(variables_, diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h index 7ac9bbfb..185a268e 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.h +++ b/src/google/protobuf/compiler/java/java_primitive_field.h @@ -41,26 +41,30 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { public: - explicit ImmutablePrimitiveFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context); ~ImmutablePrimitiveFieldGenerator(); - // implements ImmutableFieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator + // --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -78,11 +82,11 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; const int builderBitIndex_; Context* context_; @@ -95,9 +99,9 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { class ImmutablePrimitiveOneofFieldGenerator : public ImmutablePrimitiveFieldGenerator { public: - ImmutablePrimitiveOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, Context* context); ~ImmutablePrimitiveOneofFieldGenerator(); void GenerateMembers(io::Printer* printer) const; @@ -139,11 +143,11 @@ class RepeatedImmutablePrimitiveFieldGenerator void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; const int builderBitIndex_; Context* context_; @@ -155,6 +159,6 @@ class RepeatedImmutablePrimitiveFieldGenerator } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc index d2ebc567..034a0865 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc @@ -172,15 +172,13 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // =================================================================== -ImmutablePrimitiveFieldLiteGenerator:: -ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, +ImmutablePrimitiveFieldLiteGenerator::ImmutablePrimitiveFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } @@ -191,10 +189,6 @@ int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const { return 1; } -int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - void ImmutablePrimitiveFieldLiteGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { @@ -472,12 +466,11 @@ string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const { // =================================================================== ImmutablePrimitiveOneofFieldLiteGenerator:: -ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutablePrimitiveFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { + ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context) + : ImmutablePrimitiveFieldLiteGenerator(descriptor, messageBitIndex, + context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); @@ -609,14 +602,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { // =================================================================== RepeatedImmutablePrimitiveFieldLiteGenerator:: -RepeatedImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + RepeatedImmutablePrimitiveFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } @@ -628,10 +621,6 @@ int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - void RepeatedImmutablePrimitiveFieldLiteGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h index 93416f0b..6c05521f 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field_lite.h +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h @@ -41,14 +41,16 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -57,13 +59,12 @@ class ImmutablePrimitiveFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: explicit ImmutablePrimitiveFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + const FieldDescriptor* descriptor, int messageBitIndex, Context* context); ~ImmutablePrimitiveFieldLiteGenerator(); - // implements ImmutableFieldLiteGenerator ------------------------------------ + // implements ImmutableFieldLiteGenerator + // ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; @@ -81,13 +82,12 @@ class ImmutablePrimitiveFieldLiteGenerator void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; - const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; @@ -98,9 +98,9 @@ class ImmutablePrimitiveFieldLiteGenerator class ImmutablePrimitiveOneofFieldLiteGenerator : public ImmutablePrimitiveFieldLiteGenerator { public: - ImmutablePrimitiveOneofFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutablePrimitiveOneofFieldLiteGenerator(); void GenerateMembers(io::Printer* printer) const; @@ -120,13 +120,11 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: explicit RepeatedImmutablePrimitiveFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + const FieldDescriptor* descriptor, int messageBitIndex, Context* context); virtual ~RepeatedImmutablePrimitiveFieldLiteGenerator(); // implements ImmutableFieldLiteGenerator ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; @@ -145,13 +143,12 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; - const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; @@ -161,6 +158,6 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc index 988e1942..53a9017d 100644 --- a/src/google/protobuf/compiler/java/java_service.cc +++ b/src/google/protobuf/compiler/java/java_service.cc @@ -84,13 +84,13 @@ void ImmutableServiceGenerator::Generate(io::Printer* printer) { // Generate getDescriptor() and getDescriptorForType(). printer->Print( - "public static final\n" - " com.google.protobuf.Descriptors.ServiceDescriptor\n" - " getDescriptor() {\n" - " return $file$.getDescriptor().getServices().get($index$);\n" - "}\n", - "file", name_resolver_->GetImmutableClassName(descriptor_->file()), - "index", SimpleItoa(descriptor_->index())); + "public static final\n" + " com.google.protobuf.Descriptors.ServiceDescriptor\n" + " getDescriptor() {\n" + " return $file$.getDescriptor().getServices().get($index$);\n" + "}\n", + "file", name_resolver_->GetImmutableClassName(descriptor_->file()), + "index", SimpleItoa(descriptor_->index())); GenerateGetDescriptorForType(printer); // Generate more stuff. diff --git a/src/google/protobuf/compiler/java/java_service.h b/src/google/protobuf/compiler/java/java_service.h index 12b3f942..24b0ccaa 100644 --- a/src/google/protobuf/compiler/java/java_service.h +++ b/src/google/protobuf/compiler/java/java_service.h @@ -40,17 +40,19 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +namespace io { +class Printer; // printer.h } +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -123,7 +125,7 @@ class ImmutableServiceGenerator : public ServiceGenerator { const MethodDescriptor* method); // Return the output type of the method. - string GetOutput(const MethodDescriptor* method); + std::string GetOutput(const MethodDescriptor* method); Context* context_; ClassNameResolver* name_resolver_; @@ -133,6 +135,6 @@ class ImmutableServiceGenerator : public ServiceGenerator { } // namespace java } // namespace compiler } // namespace protobuf +} // namespace google #endif // NET_PROTO2_COMPILER_JAVA_SERVICE_H__ -} // namespace google diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h index 58a31f5d..2f09c3a9 100644 --- a/src/google/protobuf/compiler/java/java_shared_code_generator.h +++ b/src/google/protobuf/compiler/java/java_shared_code_generator.h @@ -44,18 +44,20 @@ namespace google { namespace protobuf { - class FileDescriptor; // descriptor.h - namespace compiler { - class GeneratorContext; // code_generator.h - namespace java { - class ClassNameResolver; // name_resolver.h - } - } - namespace io { - class Printer; // printer.h - } +class FileDescriptor; // descriptor.h +namespace compiler { +class GeneratorContext; // code_generator.h +namespace java { +class ClassNameResolver; // name_resolver.h } +} // namespace compiler +namespace io { +class Printer; // printer.h +} +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { @@ -68,8 +70,8 @@ class SharedCodeGenerator { ~SharedCodeGenerator(); void Generate(GeneratorContext* generator_context, - std::vector<string>* file_list, - std::vector<string>* annotation_file_list); + std::vector<std::string>* file_list, + std::vector<std::string>* annotation_file_list); void GenerateDescriptors(io::Printer* printer); @@ -84,6 +86,6 @@ class SharedCodeGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index b08febc0..2b6e9381 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -405,15 +405,11 @@ GenerateBuildingCode(io::Printer* printer) const { if (SupportFieldPresence(descriptor_->file())) { printer->Print(variables_, "if ($get_has_field_bit_from_local$) {\n" - " result.$name$_ = $name$_;\n" " $set_has_field_bit_to_local$;\n" - "} else {\n" - " result.$name$_ = $default$;\n" "}\n"); - } else { - printer->Print(variables_, - "result.$name$_ = $name$_;\n"); } + printer->Print(variables_, + "result.$name$_ = $name$_;\n"); } void ImmutableStringFieldGenerator:: diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h index 0f7c705b..38fb8365 100644 --- a/src/google/protobuf/compiler/java/java_string_field.h +++ b/src/google/protobuf/compiler/java/java_string_field.h @@ -42,26 +42,29 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { public: - explicit ImmutableStringFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableStringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, Context* context); ~ImmutableStringFieldGenerator(); - // implements ImmutableFieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator + // --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -79,11 +82,11 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; const int builderBitIndex_; Context* context_; @@ -96,9 +99,9 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { class ImmutableStringOneofFieldGenerator : public ImmutableStringFieldGenerator { public: - ImmutableStringOneofFieldGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, int builderBitIndex, + Context* context); ~ImmutableStringOneofFieldGenerator(); private: @@ -138,11 +141,11 @@ class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; const int builderBitIndex_; Context* context_; @@ -154,6 +157,6 @@ class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc index a238c67d..5ce31517 100644 --- a/src/google/protobuf/compiler/java/java_string_field_lite.cc +++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc @@ -119,15 +119,13 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // =================================================================== -ImmutableStringFieldLiteGenerator:: -ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, +ImmutableStringFieldLiteGenerator::ImmutableStringFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } @@ -138,10 +136,6 @@ int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const { return 1; } -int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - // A note about how strings are handled. In the SPEED and CODE_SIZE runtimes, // strings are not stored as java.lang.String in the Message because of two // issues: @@ -403,13 +397,9 @@ string ImmutableStringFieldLiteGenerator::GetBoxedType() const { // =================================================================== -ImmutableStringOneofFieldLiteGenerator:: -ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : ImmutableStringFieldLiteGenerator( - descriptor, messageBitIndex, builderBitIndex, context) { +ImmutableStringOneofFieldLiteGenerator::ImmutableStringOneofFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, Context* context) + : ImmutableStringFieldLiteGenerator(descriptor, messageBitIndex, context) { const OneofGeneratorInfo* info = context->GetOneofGeneratorInfo(descriptor->containing_oneof()); SetCommonOneofVariables(descriptor, info, &variables_); @@ -603,14 +593,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { // =================================================================== RepeatedImmutableStringFieldLiteGenerator:: -RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex, - Context* context) - : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex), context_(context), - name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context) + : descriptor_(descriptor), + messageBitIndex_(messageBitIndex), + context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, &variables_); } @@ -622,10 +612,6 @@ int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const { - return 0; -} - void RepeatedImmutableStringFieldLiteGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h index b7fb6409..89d5c1ae 100644 --- a/src/google/protobuf/compiler/java/java_string_field_lite.h +++ b/src/google/protobuf/compiler/java/java_string_field_lite.h @@ -42,28 +42,30 @@ namespace google { namespace protobuf { - namespace compiler { - namespace java { - class Context; // context.h - class ClassNameResolver; // name_resolver.h - } - } -} +namespace compiler { +namespace java { +class Context; // context.h +class ClassNameResolver; // name_resolver.h +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { namespace java { class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: - explicit ImmutableStringFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + explicit ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + Context* context); ~ImmutableStringFieldLiteGenerator(); - // implements ImmutableFieldLiteGenerator ------------------------------------ + // implements ImmutableFieldLiteGenerator + // ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; @@ -79,13 +81,12 @@ class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; protected: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; - const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; @@ -96,9 +97,8 @@ class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { class ImmutableStringOneofFieldLiteGenerator : public ImmutableStringFieldLiteGenerator { public: - ImmutableStringOneofFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, Context* context); ~ImmutableStringOneofFieldLiteGenerator(); private: @@ -117,13 +117,11 @@ class RepeatedImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { public: explicit RepeatedImmutableStringFieldLiteGenerator( - const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, Context* context); + const FieldDescriptor* descriptor, int messageBitIndex, Context* context); ~RepeatedImmutableStringFieldLiteGenerator(); // implements ImmutableFieldLiteGenerator ------------------------------------ int GetNumBitsForMessage() const; - int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; void GenerateMembers(io::Printer* printer) const; void GenerateBuilderMembers(io::Printer* printer) const; @@ -139,13 +137,12 @@ class RepeatedImmutableStringFieldLiteGenerator void GenerateHashCode(io::Printer* printer) const; - string GetBoxedType() const; + std::string GetBoxedType() const; private: const FieldDescriptor* descriptor_; - std::map<string, string> variables_; + std::map<std::string, std::string> variables_; const int messageBitIndex_; - const int builderBitIndex_; Context* context_; ClassNameResolver* name_resolver_; @@ -155,6 +152,6 @@ class RepeatedImmutableStringFieldLiteGenerator } // namespace java } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc index d25a3668..5779d5e2 100644 --- a/src/google/protobuf/compiler/js/js_generator.cc +++ b/src/google/protobuf/compiler/js/js_generator.cc @@ -42,12 +42,12 @@ #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/stringprintf.h> +#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/compiler/js/well_known_types_embed.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/descriptor.h> -#include <google/protobuf/stubs/strutil.h> namespace google { @@ -220,8 +220,8 @@ string GetNestedMessageName(const Descriptor* descriptor) { if (descriptor == NULL) { return ""; } - string result = - StripPrefixString(descriptor->full_name(), descriptor->file()->package()); + string result = StripPrefixString(descriptor->full_name(), + descriptor->file()->package()); // Add a leading dot if one is not already present. if (!result.empty() && result[0] != '.') { result = "." + result; @@ -439,9 +439,10 @@ string GetMessageId(const Descriptor* desc) { bool IgnoreExtensionField(const FieldDescriptor* field) { // Exclude descriptor extensions from output "to avoid clutter" (from original // codegen). - return field->is_extension() && - field->containing_type()->file()->name() == - "google/protobuf/descriptor.proto"; + if (!field->is_extension()) return false; + const FileDescriptor* file = field->containing_type()->file(); + return file->name() == "net/proto2/proto/descriptor.proto" || + file->name() == "google/protobuf/descriptor.proto"; } @@ -453,19 +454,9 @@ bool IgnoreField(const FieldDescriptor* field) { } -// Used inside Google only -- do not remove. -bool ShouldTreatMapsAsRepeatedFields(const FileDescriptor& descriptor) { - return false; -} - // Do we ignore this message type? -bool IgnoreMessage(const GeneratorOptions& options, const Descriptor* d) { - return d->options().map_entry() && - !ShouldTreatMapsAsRepeatedFields(*d->file()); -} - -bool IsMap(const GeneratorOptions& options, const FieldDescriptor* field) { - return field->is_map() && !ShouldTreatMapsAsRepeatedFields(*field->file()); +bool IgnoreMessage(const Descriptor* d) { + return d->options().map_entry(); } // Does JSPB ignore this entire oneof? True only if all fields are ignored. @@ -490,7 +481,7 @@ string JSIdent(const GeneratorOptions& options, const FieldDescriptor* field, ToUpperCamel(ParseLowerUnderscore(field->name())) : ToLowerCamel(ParseLowerUnderscore(field->name())); } - if (is_map || IsMap(options, field)) { + if (is_map || field->is_map()) { // JSPB-style or proto3-style map. result += "Map"; } else if (!drop_list && field->is_repeated()) { @@ -569,7 +560,8 @@ string JSFieldIndex(const FieldDescriptor* field) { for (int i = 0; i < parent_type->field_count(); i++) { if (parent_type->field(i)->type() == FieldDescriptor::TYPE_GROUP && parent_type->field(i)->message_type() == containing_type) { - return SimpleItoa(field->number() - parent_type->field(i)->number()); + return SimpleItoa(field->number() - + parent_type->field(i)->number()); } } } @@ -781,7 +773,7 @@ bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) { case FieldDescriptor::CPPTYPE_UINT64: // The default value of JSType is JS_NORMAL, which behaves the same as // JS_NUMBER. - return field->options().jstype() == google::protobuf::FieldOptions::JS_STRING; + return field->options().jstype() == FieldOptions::JS_STRING; default: return false; } @@ -804,15 +796,15 @@ string JSFieldDefault(const FieldDescriptor* field) { // The original codegen is in Java, and Java protobufs store unsigned // integer values as signed integer values. In order to exactly match the // output, we need to reinterpret as base-2 signed. Ugh. - return MaybeNumberString( - field, SimpleItoa(static_cast<int32>(field->default_value_uint32()))); + return MaybeNumberString(field, SimpleItoa(static_cast<int32>( + field->default_value_uint32()))); case FieldDescriptor::CPPTYPE_INT64: return MaybeNumberString( field, SimpleItoa(field->default_value_int64())); case FieldDescriptor::CPPTYPE_UINT64: // See above note for uint32 -- reinterpreting as signed. - return MaybeNumberString( - field, SimpleItoa(static_cast<int64>(field->default_value_uint64()))); + return MaybeNumberString(field, SimpleItoa(static_cast<int64>( + field->default_value_uint64()))); case FieldDescriptor::CPPTYPE_ENUM: return SimpleItoa(field->default_value_enum()->number()); case FieldDescriptor::CPPTYPE_BOOL: @@ -1014,11 +1006,11 @@ string JSFieldTypeAnnotation(const GeneratorOptions& options, bool is_setter_argument, bool force_present, bool singular_if_not_packed, - BytesMode bytes_mode = BYTES_DEFAULT) { - GOOGLE_CHECK(!(is_setter_argument && force_present)); + BytesMode bytes_mode = BYTES_DEFAULT, + bool force_singular = false) { string jstype = JSTypeName(options, field, bytes_mode); - if (field->is_repeated() && + if (!force_singular && field->is_repeated() && (field->is_packed() || !singular_if_not_packed)) { if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_DEFAULT) { @@ -1136,7 +1128,7 @@ string JSReturnDoc(const GeneratorOptions& options, bool HasRepeatedFields(const GeneratorOptions& options, const Descriptor* desc) { for (int i = 0; i < desc->field_count(); i++) { - if (desc->field(i)->is_repeated() && !IsMap(options, desc->field(i))) { + if (desc->field(i)->is_repeated() && !desc->field(i)->is_map()) { return true; } } @@ -1174,7 +1166,7 @@ string RepeatedFieldNumberList(const GeneratorOptions& options, const Descriptor* desc) { std::vector<string> numbers; for (int i = 0; i < desc->field_count(); i++) { - if (desc->field(i)->is_repeated() && !IsMap(options, desc->field(i))) { + if (desc->field(i)->is_repeated() && !desc->field(i)->is_map()) { numbers.push_back(JSFieldIndex(desc->field(i))); } } @@ -1260,7 +1252,7 @@ const FieldDescriptor* MapFieldValue(const FieldDescriptor* field) { string FieldDefinition(const GeneratorOptions& options, const FieldDescriptor* field) { - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* key_field = MapFieldKey(field); const FieldDescriptor* value_field = MapFieldValue(field); string key_type = ProtoTypeName(options, key_field); @@ -1352,7 +1344,7 @@ bool HasExtensions(const FileDescriptor* file) { bool HasMap(const GeneratorOptions& options, const Descriptor* desc) { for (int i = 0; i < desc->field_count(); i++) { - if (IsMap(options, desc->field(i))) { + if (desc->field(i)->is_map()) { return true; } } @@ -1618,7 +1610,7 @@ void Generator::FindProvidesForMessage( io::Printer* printer, const Descriptor* desc, std::set<string>* provided) const { - if (IgnoreMessage(options, desc)) { + if (IgnoreMessage(desc)) { return; } @@ -1681,13 +1673,13 @@ void Generator::GenerateProvides(const GeneratorOptions& options, if (options.import_style == GeneratorOptions::kImportCommonJsStrict) { string namespaceObject = *it; // Remove "proto." from the namespace object - GOOGLE_CHECK(namespaceObject.compare(0, 6, "proto.")); + GOOGLE_CHECK_EQ(0, namespaceObject.compare(0, 6, "proto.")); namespaceObject.erase(0, 6); printer->Print("goog.exportSymbol('$name$', null, proto);\n", "name", - namespaceObject); + namespaceObject); } else { printer->Print("goog.exportSymbol('$name$', null, global);\n", "name", - *it); + *it); } } } @@ -1724,7 +1716,7 @@ void Generator::GenerateRequiresForLibrary( for (int i = 0; i < files.size(); i++) { for (int j = 0; j < files[i]->message_type_count(); j++) { const Descriptor* desc = files[i]->message_type(j); - if (!IgnoreMessage(options, desc)) { + if (!IgnoreMessage(desc)) { FindRequiresForMessage(options, desc, &required, &forwards, &have_message); } @@ -1869,7 +1861,7 @@ void Generator::FindRequiresForField(const GeneratorOptions& options, forwards->insert(GetEnumPath(options, field->enum_type())); } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (!IgnoreMessage(options, field->message_type())) { + if (!IgnoreMessage(field->message_type())) { required->insert(GetMessagePath(options, field->message_type())); } } @@ -1907,7 +1899,7 @@ void Generator::GenerateClassesAndEnums(const GeneratorOptions& options, void Generator::GenerateClass(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc) const { - if (IgnoreMessage(options, desc)) { + if (IgnoreMessage(desc)) { return; } @@ -2229,7 +2221,7 @@ void Generator::GenerateClassFieldToObject(const GeneratorOptions& options, printer->Print("$fieldname$: ", "fieldname", JSObjectFieldName(options, field)); - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* value_field = MapFieldValue(field); // If the map values are of a message type, we must provide their static // toObject() method; otherwise we pass undefined for that argument. @@ -2297,7 +2289,7 @@ void Generator::GenerateClassFromObject(const GeneratorOptions& options, " * @return {!$classname$}\n" " */\n" "$classname$.fromObject = function(obj) {\n" - " var f, msg = new $classname$();\n", + " var msg = new $classname$();\n", "classname", GetMessagePath(options, desc)); for (int i = 0; i < desc->field_count(); i++) { @@ -2315,7 +2307,7 @@ void Generator::GenerateClassFieldFromObject( const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* value_field = MapFieldValue(field); if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { // Since the map values are of message type, we have to do some extra work @@ -2427,7 +2419,7 @@ void GenerateBytesWrapper(const GeneratorOptions& options, void Generator::GenerateClassField(const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* key_field = MapFieldKey(field); const FieldDescriptor* value_field = MapFieldValue(field); // Map field: special handling to instantiate the map object on demand. @@ -2707,7 +2699,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, // Generate clearFoo() method for map fields, repeated fields, and other // fields with presence. - if (IsMap(options, field)) { + if (field->is_map()) { printer->Print( "$class$.prototype.$clearername$ = function() {\n" " this.$gettername$().clear();$returnvalue$\n" @@ -2762,7 +2754,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, printer->Print( "/**\n" " * Returns whether this field is set.\n" - " * @return {!boolean}\n" + " * @return {boolean}\n" " */\n" "$class$.prototype.$hasername$ = function() {\n" " return jspb.Message.getField(this, $index$) != null;\n" @@ -2782,7 +2774,7 @@ void Generator::GenerateRepeatedPrimitiveHelperMethods( // clang-format off printer->Print( "/**\n" - " * @param {!$optionaltype$} value\n" + " * @param {$optionaltype$} value\n" " * @param {number=} opt_index$returndoc$\n" " */\n" "$class$.prototype.$addername$ = function(value, opt_index) {\n" @@ -2790,7 +2782,14 @@ void Generator::GenerateRepeatedPrimitiveHelperMethods( "class", GetMessagePath(options, field->containing_type()), "addername", "add" + JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true), - "optionaltype", JSTypeName(options, field, BYTES_DEFAULT), + "optionaltype", + JSFieldTypeAnnotation( + options, field, + /* is_setter_argument = */ false, + /* force_present = */ true, + /* singular_if_not_packed = */ false, + BYTES_DEFAULT, + /* force_singular = */ true), "index", JSFieldIndex(field), "returndoc", JSReturnDoc(options, field)); printer->Annotate("addername", field); @@ -2954,11 +2953,10 @@ void Generator::GenerateClassDeserializeBinaryField( const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { + printer->Print(" case $num$:\n", "num", + SimpleItoa(field->number())); - printer->Print(" case $num$:\n", - "num", SimpleItoa(field->number())); - - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* key_field = MapFieldKey(field); const FieldDescriptor* value_field = MapFieldValue(field); printer->Print( @@ -2988,11 +2986,12 @@ void Generator::GenerateClassDeserializeBinaryField( " var value = new $fieldclass$;\n" " reader.read$msgOrGroup$($grpfield$value," "$fieldclass$.deserializeBinaryFromReader);\n", - "fieldclass", SubmessageTypeRef(options, field), - "msgOrGroup", (field->type() == FieldDescriptor::TYPE_GROUP) ? - "Group" : "Message", - "grpfield", (field->type() == FieldDescriptor::TYPE_GROUP) ? - (SimpleItoa(field->number()) + ", ") : ""); + "fieldclass", SubmessageTypeRef(options, field), "msgOrGroup", + (field->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message", + "grpfield", + (field->type() == FieldDescriptor::TYPE_GROUP) + ? (SimpleItoa(field->number()) + ", ") + : ""); } else { printer->Print( " var value = /** @type {$fieldtype$} */ " @@ -3090,12 +3089,12 @@ void Generator::GenerateClassSerializeBinaryField( " f = message.get$name$($nolazy$);\n", "name", JSGetterName(options, field, BYTES_U8), // No lazy creation for maps containers -- fastpath the empty case. - "nolazy", IsMap(options, field) ? "true" : ""); + "nolazy", field->is_map() ? "true" : ""); } // Print an `if (condition)` statement that evaluates to true if the field // goes on the wire. - if (IsMap(options, field)) { + if (field->is_map()) { printer->Print( " if (f && f.getLength() > 0) {\n"); } else if (field->is_repeated()) { @@ -3148,15 +3147,15 @@ void Generator::GenerateClassSerializeBinaryField( } // Write the field on the wire. - if (IsMap(options, field)) { + if (field->is_map()) { const FieldDescriptor* key_field = MapFieldKey(field); const FieldDescriptor* value_field = MapFieldValue(field); printer->Print( " f.serializeBinary($index$, writer, " - "$keyWriterFn$, $valueWriterFn$", - "index", SimpleItoa(field->number()), - "keyWriterFn", JSBinaryWriterMethodName(options, key_field), - "valueWriterFn", JSBinaryWriterMethodName(options, value_field)); + "$keyWriterFn$, $valueWriterFn$", + "index", SimpleItoa(field->number()), "keyWriterFn", + JSBinaryWriterMethodName(options, key_field), "valueWriterFn", + JSBinaryWriterMethodName(options, value_field)); if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(", $messageType$.serializeBinaryToWriter", @@ -3173,7 +3172,7 @@ void Generator::GenerateClassSerializeBinaryField( "index", SimpleItoa(field->number())); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - !IsMap(options, field)) { + !field->is_map()) { printer->Print( ",\n" " $submsg$.serializeBinaryToWriter\n", @@ -3205,11 +3204,10 @@ void Generator::GenerateEnum(const GeneratorOptions& options, for (int i = 0; i < enumdesc->value_count(); i++) { const EnumValueDescriptor* value = enumdesc->value(i); - printer->Print( - " $name$: $value$$comma$\n", - "name", ToEnumCase(value->name()), - "value", SimpleItoa(value->number()), - "comma", (i == enumdesc->value_count() - 1) ? "" : ","); + printer->Print(" $name$: $value$$comma$\n", "name", + ToEnumCase(value->name()), "value", + SimpleItoa(value->number()), "comma", + (i == enumdesc->value_count() - 1) ? "" : ","); printer->Annotate("name", value); } @@ -3252,13 +3250,15 @@ void Generator::GenerateExtension(const GeneratorOptions& options, "!Object} */ (\n" " $toObject$),\n" " $repeated$);\n", - "index", SimpleItoa(field->number()), - "name", extension_object_name, - "ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? - SubmessageTypeRef(options, field) : string("null")), - "toObject", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? - (SubmessageTypeRef(options, field) + ".toObject") : - string("null")), + "index", SimpleItoa(field->number()), "name", + extension_object_name, "ctor", + (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + ? SubmessageTypeRef(options, field) + : string("null")), + "toObject", + (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + ? (SubmessageTypeRef(options, field) + ".toObject") + : string("null")), "repeated", (field->is_repeated() ? "1" : "0")); printer->Print( @@ -3271,8 +3271,8 @@ void Generator::GenerateExtension(const GeneratorOptions& options, " $binaryMessageDeserializeFn$,\n", "extendName", JSExtensionsObjectName(options, field->file(), field->containing_type()), - "index", SimpleItoa(field->number()), "class", extension_scope, "name", - extension_object_name, "binaryReaderFn", + "index", SimpleItoa(field->number()), "class", extension_scope, + "name", extension_object_name, "binaryReaderFn", JSBinaryReaderMethodName(options, field), "binaryWriterFn", JSBinaryWriterMethodName(options, field), "binaryMessageSerializeFn", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) @@ -3291,10 +3291,9 @@ void Generator::GenerateExtension(const GeneratorOptions& options, "// toObject() will function correctly.\n" "$extendName$[$index$] = $class$.$name$;\n" "\n", - "extendName", JSExtensionsObjectName(options, field->file(), - field->containing_type()), - "index", SimpleItoa(field->number()), - "class", extension_scope, + "extendName", + JSExtensionsObjectName(options, field->file(), field->containing_type()), + "index", SimpleItoa(field->number()), "class", extension_scope, "name", extension_object_name); } @@ -3465,8 +3464,7 @@ void Generator::GenerateFile(const GeneratorOptions& options, printer->Print( "var $alias$ = require('$file$');\n" "goog.object.extend(proto, $alias$);\n", - "alias", ModuleAlias(name), - "file", + "alias", ModuleAlias(name), "file", GetRootPath(file->name(), name) + GetJSFilename(options, name)); } } @@ -3504,12 +3502,13 @@ void Generator::GenerateFile(const GeneratorOptions& options, } // if provided is empty, do not export anything - if (options.import_style == GeneratorOptions::kImportCommonJs && !provided.empty()) { + if (options.import_style == GeneratorOptions::kImportCommonJs && + !provided.empty()) { printer->Print("goog.object.extend(exports, $package$);\n", "package", GetFilePath(options, file)); - } else if(options.import_style == GeneratorOptions::kImportCommonJsStrict) { - printer->Print("goog.object.extend(exports, proto);\n", - "package", GetFilePath(options, file)); + } else if (options.import_style == GeneratorOptions::kImportCommonJsStrict) { + printer->Print("goog.object.extend(exports, proto);\n", "package", + GetFilePath(options, file)); } // Emit well-known type methods. @@ -3667,7 +3666,7 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files, // Generate one output file per input (.proto) file. for (int i = 0; i < files.size(); i++) { - const google::protobuf::FileDescriptor* file = files[i]; + const FileDescriptor* file = files[i]; string filename = options.output_dir + "/" + GetJSFilename(options, file->name()); diff --git a/src/google/protobuf/compiler/js/js_generator.h b/src/google/protobuf/compiler/js/js_generator.h index b50ef7fd..4567b07a 100644 --- a/src/google/protobuf/compiler/js/js_generator.h +++ b/src/google/protobuf/compiler/js/js_generator.h @@ -40,6 +40,8 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { @@ -56,9 +58,9 @@ namespace js { struct GeneratorOptions { // Output path. - string output_dir; + std::string output_dir; // Namespace prefix. - string namespace_prefix; + std::string namespace_prefix; // Enable binary-format support? bool binary; // What style of imports should be used. @@ -84,11 +86,11 @@ struct GeneratorOptions { annotate_code(false) {} bool ParseFromOptions( - const std::vector< std::pair< string, string > >& options, - string* error); + const std::vector< std::pair< std::string, std::string > >& options, + std::string* error); // Returns the file name extension to use for generated code. - string GetFileNameExtension() const { + std::string GetFileNameExtension() const { return import_style == kImportClosure ? extension : "_pb.js"; } @@ -113,11 +115,11 @@ struct GeneratorOptions { bool testonly; // Create a library with name <name>_lib.js rather than a separate .js file // per type? - string library; + std::string library; // Error if there are two types that would generate the same output file? bool error_on_name_conflict; // The extension to use for output file names. - string extension; + std::string extension; // Create a separate output file for each input file? bool one_output_file_per_input_file; // If true, we should build .meta files that contain annotations for @@ -129,15 +131,15 @@ struct GeneratorOptions { // header. If you create your own protocol compiler binary and you want it to // support JavaScript output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT Generator : public CodeGenerator { +class PROTOC_EXPORT Generator : public CodeGenerator { public: Generator() {} virtual ~Generator() {} virtual bool Generate(const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* context, - string* error) const { + std::string* error) const { *error = "Unimplemented Generate() method. Call GenerateAll() instead."; return false; } @@ -145,9 +147,9 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { virtual bool HasGenerateAll() const { return true; } virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files, - const string& parameter, + const std::string& parameter, GeneratorContext* context, - string* error) const; + std::string* error) const; private: void GenerateHeader(const GeneratorOptions& options, @@ -157,28 +159,28 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void FindProvides(const GeneratorOptions& options, io::Printer* printer, const std::vector<const FileDescriptor*>& file, - std::set<string>* provided) const; + std::set<std::string>* provided) const; void FindProvidesForFile(const GeneratorOptions& options, io::Printer* printer, const FileDescriptor* file, - std::set<string>* provided) const; + std::set<std::string>* provided) const; void FindProvidesForMessage(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc, - std::set<string>* provided) const; + std::set<std::string>* provided) const; void FindProvidesForEnum(const GeneratorOptions& options, io::Printer* printer, const EnumDescriptor* enumdesc, - std::set<string>* provided) const; + std::set<std::string>* provided) const; // For extension fields at file scope. void FindProvidesForFields(const GeneratorOptions& options, io::Printer* printer, const std::vector<const FieldDescriptor*>& fields, - std::set<string>* provided) const; + std::set<std::string>* provided) const; // Print the goog.provides() found by the methods above. void GenerateProvides(const GeneratorOptions& options, io::Printer* printer, - std::set<string>* provided) const; + std::set<std::string>* provided) const; // Generate goog.setTestOnly() if indicated. void GenerateTestOnly(const GeneratorOptions& options, @@ -188,34 +190,34 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void GenerateRequiresForLibrary( const GeneratorOptions& options, io::Printer* printer, const std::vector<const FileDescriptor*>& files, - std::set<string>* provided) const; + std::set<std::string>* provided) const; void GenerateRequiresForMessage(const GeneratorOptions& options, io::Printer* printer, const Descriptor* desc, - std::set<string>* provided) const; + std::set<std::string>* provided) const; // For extension fields at file scope. void GenerateRequiresForExtensions( const GeneratorOptions& options, io::Printer* printer, const std::vector<const FieldDescriptor*>& fields, - std::set<string>* provided) const; + std::set<std::string>* provided) const; void GenerateRequiresImpl(const GeneratorOptions& options, - io::Printer* printer, std::set<string>* required, - std::set<string>* forwards, - std::set<string>* provided, bool require_jspb, + io::Printer* printer, std::set<std::string>* required, + std::set<std::string>* forwards, + std::set<std::string>* provided, bool require_jspb, bool require_extension, bool require_map) const; void FindRequiresForMessage(const GeneratorOptions& options, const Descriptor* desc, - std::set<string>* required, - std::set<string>* forwards, + std::set<std::string>* required, + std::set<std::string>* forwards, bool* have_message) const; void FindRequiresForField(const GeneratorOptions& options, const FieldDescriptor* field, - std::set<string>* required, - std::set<string>* forwards) const; + std::set<std::string>* required, + std::set<std::string>* forwards) const; void FindRequiresForExtension(const GeneratorOptions& options, const FieldDescriptor* field, - std::set<string>* required, - std::set<string>* forwards) const; + std::set<std::string>* required, + std::set<std::string>* forwards) const; void GenerateFile(const GeneratorOptions& options, io::Printer* printer, @@ -329,6 +331,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { } // namespace js } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_JS_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/js/well_known_types/any.js b/src/google/protobuf/compiler/js/well_known_types/any.js deleted file mode 100644 index d7ca6e3a..00000000 --- a/src/google/protobuf/compiler/js/well_known_types/any.js +++ /dev/null @@ -1,80 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* This code will be inserted into generated code for - * google/protobuf/any.proto. */ - -/** - * Returns the type name contained in this instance, if any. - * @return {string|undefined} - */ -proto.google.protobuf.Any.prototype.getTypeName = function() { - return this.getTypeUrl().split('/').pop(); -}; - - -/** - * Packs the given message instance into this Any. - * @param {!Uint8Array} serialized The serialized data to pack. - * @param {string} name The type name of this message object. - * @param {string=} opt_typeUrlPrefix the type URL prefix. - */ -proto.google.protobuf.Any.prototype.pack = function(serialized, name, - opt_typeUrlPrefix) { - if (!opt_typeUrlPrefix) { - opt_typeUrlPrefix = 'type.googleapis.com/'; - } - - if (opt_typeUrlPrefix.substr(-1) != '/') { - this.setTypeUrl(opt_typeUrlPrefix + '/' + name); - } else { - this.setTypeUrl(opt_typeUrlPrefix + name); - } - - this.setValue(serialized); -}; - - -/** - * @template T - * Unpacks this Any into the given message object. - * @param {function(Uint8Array):T} deserialize Function that will deserialize - * the binary data properly. - * @param {string} name The expected type name of this message object. - * @return {?T} If the name matched the expected name, returns the deserialized - * object, otherwise returns null. - */ -proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) { - if (this.getTypeName() == name) { - return deserialize(this.getValue_asU8()); - } else { - return null; - } -}; diff --git a/src/google/protobuf/compiler/js/well_known_types/struct.js b/src/google/protobuf/compiler/js/well_known_types/struct.js deleted file mode 100644 index 30e3d02a..00000000 --- a/src/google/protobuf/compiler/js/well_known_types/struct.js +++ /dev/null @@ -1,168 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* This code will be inserted into generated code for - * google/protobuf/struct.proto. */ - -/** - * Typedef representing plain JavaScript values that can go into a - * Struct. - * @typedef {null|number|string|boolean|Array|Object} - */ -proto.google.protobuf.JavaScriptValue; - - -/** - * Converts this Value object to a plain JavaScript value. - * @return {?proto.google.protobuf.JavaScriptValue} a plain JavaScript - * value representing this Struct. - */ -proto.google.protobuf.Value.prototype.toJavaScript = function() { - var kindCase = proto.google.protobuf.Value.KindCase; - switch (this.getKindCase()) { - case kindCase.NULL_VALUE: - return null; - case kindCase.NUMBER_VALUE: - return this.getNumberValue(); - case kindCase.STRING_VALUE: - return this.getStringValue(); - case kindCase.BOOL_VALUE: - return this.getBoolValue(); - case kindCase.STRUCT_VALUE: - return this.getStructValue().toJavaScript(); - case kindCase.LIST_VALUE: - return this.getListValue().toJavaScript(); - default: - throw new Error('Unexpected struct type'); - } -}; - - -/** - * Converts this JavaScript value to a new Value proto. - * @param {!proto.google.protobuf.JavaScriptValue} value The value to - * convert. - * @return {!proto.google.protobuf.Value} The newly constructed value. - */ -proto.google.protobuf.Value.fromJavaScript = function(value) { - var ret = new proto.google.protobuf.Value(); - switch (goog.typeOf(value)) { - case 'string': - ret.setStringValue(/** @type {string} */ (value)); - break; - case 'number': - ret.setNumberValue(/** @type {number} */ (value)); - break; - case 'boolean': - ret.setBoolValue(/** @type {boolean} */ (value)); - break; - case 'null': - ret.setNullValue(proto.google.protobuf.NullValue.NULL_VALUE); - break; - case 'array': - ret.setListValue(proto.google.protobuf.ListValue.fromJavaScript( - /** @type{!Array} */ (value))); - break; - case 'object': - ret.setStructValue(proto.google.protobuf.Struct.fromJavaScript( - /** @type{!Object} */ (value))); - break; - default: - throw new Error('Unexpected struct type.'); - } - - return ret; -}; - - -/** - * Converts this ListValue object to a plain JavaScript array. - * @return {!Array} a plain JavaScript array representing this List. - */ -proto.google.protobuf.ListValue.prototype.toJavaScript = function() { - var ret = []; - var values = this.getValuesList(); - - for (var i = 0; i < values.length; i++) { - ret[i] = values[i].toJavaScript(); - } - - return ret; -}; - - -/** - * Constructs a ListValue protobuf from this plain JavaScript array. - * @param {!Array} array a plain JavaScript array - * @return {proto.google.protobuf.ListValue} a new ListValue object - */ -proto.google.protobuf.ListValue.fromJavaScript = function(array) { - var ret = new proto.google.protobuf.ListValue(); - - for (var i = 0; i < array.length; i++) { - ret.addValues(proto.google.protobuf.Value.fromJavaScript(array[i])); - } - - return ret; -}; - - -/** - * Converts this Struct object to a plain JavaScript object. - * @return {!Object<string, !proto.google.protobuf.JavaScriptValue>} a plain - * JavaScript object representing this Struct. - */ -proto.google.protobuf.Struct.prototype.toJavaScript = function() { - var ret = {}; - - this.getFieldsMap().forEach(function(value, key) { - ret[key] = value.toJavaScript(); - }); - - return ret; -}; - - -/** - * Constructs a Struct protobuf from this plain JavaScript object. - * @param {!Object} obj a plain JavaScript object - * @return {proto.google.protobuf.Struct} a new Struct object - */ -proto.google.protobuf.Struct.fromJavaScript = function(obj) { - var ret = new proto.google.protobuf.Struct(); - var map = ret.getFieldsMap(); - - for (var property in obj) { - var val = obj[property]; - map.set(property, proto.google.protobuf.Value.fromJavaScript(val)); - } - - return ret; -}; diff --git a/src/google/protobuf/compiler/js/well_known_types/timestamp.js b/src/google/protobuf/compiler/js/well_known_types/timestamp.js deleted file mode 100644 index b7e43f19..00000000 --- a/src/google/protobuf/compiler/js/well_known_types/timestamp.js +++ /dev/null @@ -1,53 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/* This code will be inserted into generated code for - * google/protobuf/timestamp.proto. */ - -/** - * Returns a JavaScript 'Date' object corresponding to this Timestamp. - * @return {!Date} - */ -proto.google.protobuf.Timestamp.prototype.toDate = function() { - var seconds = this.getSeconds(); - var nanos = this.getNanos(); - - return new Date((seconds * 1000) + (nanos / 1000000)); -}; - - -/** - * Sets the value of this Timestamp object to be the given Date. - * @param {!Date} value The value to set. - */ -proto.google.protobuf.Timestamp.prototype.fromDate = function(value) { - this.setSeconds(Math.floor(value.getTime() / 1000)); - this.setNanos(value.getMilliseconds() * 1000000); -}; diff --git a/src/google/protobuf/compiler/js/well_known_types_embed.cc b/src/google/protobuf/compiler/js/well_known_types_embed.cc index e5ee5510..c00c60cb 100644 --- a/src/google/protobuf/compiler/js/well_known_types_embed.cc +++ b/src/google/protobuf/compiler/js/well_known_types_embed.cc @@ -1,3 +1,33 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + #include <google/protobuf/compiler/js/well_known_types_embed.h> struct FileToc well_known_types_js[] = { diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index 1db35441..8be2652a 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -30,71 +30,80 @@ // Author: kenton@google.com (Kenton Varda) -#include <google/protobuf/compiler/command_line_interface.h> #include <google/protobuf/compiler/cpp/cpp_generator.h> - -#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP -#include <google/protobuf/compiler/python/python_generator.h> #include <google/protobuf/compiler/java/java_generator.h> -#endif // ! OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP +#include <google/protobuf/compiler/command_line_interface.h> +#include <google/protobuf/compiler/python/python_generator.h> -#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP #include <google/protobuf/compiler/csharp/csharp_generator.h> #include <google/protobuf/compiler/js/js_generator.h> #include <google/protobuf/compiler/objectivec/objectivec_generator.h> #include <google/protobuf/compiler/php/php_generator.h> #include <google/protobuf/compiler/ruby/ruby_generator.h> -#endif // ! OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP -int main(int argc, char* argv[]) { +namespace google { +namespace protobuf { +namespace compiler { - google::protobuf::compiler::CommandLineInterface cli; +int ProtobufMain(int argc, char* argv[]) { + + CommandLineInterface cli; cli.AllowPlugins("protoc-"); // Proto2 C++ - google::protobuf::compiler::cpp::CppGenerator cpp_generator; + cpp::CppGenerator cpp_generator; cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator, "Generate C++ header and source."); -#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP +#ifdef GOOGLE_PROTOBUF_USE_OPENSOURCE_GOOGLE3_RUNTIME + cpp_generator.set_runtime(cpp::CppGenerator::Runtime::kOpensourceGoogle3); +#elif defined(GOOGLE_PROTOBUF_USE_OPENSOURCE_RUNTIME) + cpp_generator.set_runtime(cpp::CppGenerator::Runtime::kOpensource); +#endif + // Proto2 Java - google::protobuf::compiler::java::JavaGenerator java_generator; + java::JavaGenerator java_generator; cli.RegisterGenerator("--java_out", "--java_opt", &java_generator, "Generate Java source file."); -#endif // !OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP -#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP // Proto2 Python - google::protobuf::compiler::python::Generator py_generator; + python::Generator py_generator; cli.RegisterGenerator("--python_out", &py_generator, "Generate Python source file."); // PHP - google::protobuf::compiler::php::Generator php_generator; + php::Generator php_generator; cli.RegisterGenerator("--php_out", &php_generator, "Generate PHP source file."); // Ruby - google::protobuf::compiler::ruby::Generator rb_generator; + ruby::Generator rb_generator; cli.RegisterGenerator("--ruby_out", &rb_generator, "Generate Ruby source file."); // CSharp - google::protobuf::compiler::csharp::Generator csharp_generator; + csharp::Generator csharp_generator; cli.RegisterGenerator("--csharp_out", "--csharp_opt", &csharp_generator, "Generate C# source file."); // Objective C - google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator; + objectivec::ObjectiveCGenerator objc_generator; cli.RegisterGenerator("--objc_out", "--objc_opt", &objc_generator, "Generate Objective C header and source."); // JavaScript - google::protobuf::compiler::js::Generator js_generator; + js::Generator js_generator; cli.RegisterGenerator("--js_out", &js_generator, "Generate JavaScript source."); -#endif // !OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP return cli.Run(argc, argv); } + +} // namespace compiler +} // namespace protobuf +} // namespace google + +int main(int argc, char* argv[]) { + return google::protobuf::compiler::ProtobufMain(argc, argv); +} diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index e150f97d..4bb1d872 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -36,9 +36,9 @@ #include <iostream> #include <memory> #include <vector> +#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/logging.h> #include <google/protobuf/stubs/common.h> @@ -179,7 +179,7 @@ bool MockCodeGenerator::Generate( for (int i = 0; i < file->message_type_count(); i++) { if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) { string command = StripPrefixString(file->message_type(i)->name(), - "MockCodeGenerator_"); + "MockCodeGenerator_"); if (command == "Error") { *error = "Saw message type MockCodeGenerator_Error."; return false; @@ -223,8 +223,8 @@ bool MockCodeGenerator::Generate( if (HasPrefixString(parameter, "insert=")) { std::vector<string> insert_into; - SplitStringUsing(StripPrefixString(parameter, "insert="), - ",", &insert_into); + SplitStringUsing(StripPrefixString(parameter, "insert="), ",", + &insert_into); for (size_t i = 0; i < insert_into.size(); i++) { { diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h index cdd9138c..e6370b34 100644 --- a/src/google/protobuf/compiler/mock_code_generator.h +++ b/src/google/protobuf/compiler/mock_code_generator.h @@ -41,7 +41,9 @@ namespace google { namespace protobuf { class FileDescriptor; } // namespace protobuf +} // namespace google +namespace google { namespace protobuf { namespace compiler { @@ -72,7 +74,7 @@ namespace compiler { // that can later be verified with CheckGeneratedAnnotations. class MockCodeGenerator : public CodeGenerator { public: - MockCodeGenerator(const string& name); + MockCodeGenerator(const std::string& name); virtual ~MockCodeGenerator(); // Expect (via gTest) that a MockCodeGenerator with the given name was called @@ -82,49 +84,49 @@ class MockCodeGenerator : public CodeGenerator { // 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); + static void ExpectGenerated(const std::string& name, + const std::string& parameter, + const std::string& insertions, + const std::string& file, + const std::string& first_message_name, + const std::string& parsed_file_list, + const std::string& output_directory); // Checks that the correct text ranges were annotated by the // MockCodeGenerator_Annotate directive. - static void CheckGeneratedAnnotations(const string& name, - const string& file, - const string& output_directory); + static void CheckGeneratedAnnotations(const std::string& name, + const std::string& file, + const std::string& output_directory); // Get the name of the file which would be written by the given generator. - static string GetOutputFileName(const string& generator_name, + static std::string GetOutputFileName(const std::string& generator_name, const FileDescriptor* file); - static string GetOutputFileName(const string& generator_name, - const string& file); + static std::string GetOutputFileName(const std::string& generator_name, + const std::string& file); // implements CodeGenerator ---------------------------------------- virtual bool Generate(const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* context, - string* error) const; + std::string* error) const; private: - string name_; + std::string name_; - static string GetOutputFileContent(const string& generator_name, - const string& parameter, + static std::string GetOutputFileContent(const std::string& generator_name, + const std::string& parameter, 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); + static std::string GetOutputFileContent(const std::string& generator_name, + const std::string& parameter, + const std::string& file, + const std::string& parsed_file_list, + const std::string& first_message_name); }; } // namespace compiler } // namespace protobuf - } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h index 3e43f732..ac20cfdb 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h @@ -36,6 +36,8 @@ #include <string> #include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { @@ -45,7 +47,7 @@ namespace objectivec { // header. If you create your own protocol compiler binary and you want it to // support ObjectiveC output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { +class PROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { public: ObjectiveCGenerator(); ~ObjectiveCGenerator(); @@ -69,4 +71,7 @@ class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { } // namespace compiler } // namespace protobuf } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index df71c8bb..0afa6fb0 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -38,6 +38,7 @@ #include <iostream> #include <sstream> #include <stdlib.h> +#include <unordered_set> #include <vector> #include <google/protobuf/stubs/hash.h> @@ -79,8 +80,8 @@ Options::Options() { namespace { -hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) { - hash_set<string> result; +std::unordered_set<string> MakeWordsMap(const char* const words[], size_t num_words) { + std::unordered_set<string> result; for (int i = 0; i < num_words; i++) { result.insert(words[i]); } @@ -89,7 +90,7 @@ hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) { const char* const kUpperSegmentsList[] = {"url", "http", "https"}; -hash_set<string> kUpperSegments = +std::unordered_set<string> kUpperSegments = MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList)); bool ascii_isnewline(char c) { @@ -217,7 +218,7 @@ const char* const kReservedWordList[] = { "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord", }; -hash_set<string> kReservedWords = +std::unordered_set<string> kReservedWords = MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList)); string SanitizeNameForObjC(const string& input, diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index 8999aa59..e7f21f28 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -39,6 +39,8 @@ #include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { @@ -53,66 +55,67 @@ struct Options { }; // Escape C++ trigraphs by escaping question marks to "\?". -string LIBPROTOC_EXPORT EscapeTrigraphs(const string& to_escape); +string PROTOC_EXPORT EscapeTrigraphs(const string& to_escape); // Strips ".proto" or ".protodevel" from the end of a filename. -string LIBPROTOC_EXPORT StripProto(const string& filename); +string PROTOC_EXPORT StripProto(const string& filename); // Remove white space from either end of a StringPiece. -void LIBPROTOC_EXPORT StringPieceTrimWhitespace(StringPiece* input); +void PROTOC_EXPORT StringPieceTrimWhitespace(StringPiece* input); // Returns true if the name requires a ns_returns_not_retained attribute applied // to it. -bool LIBPROTOC_EXPORT IsRetainedName(const string& name); +bool PROTOC_EXPORT IsRetainedName(const string& name); // Returns true if the name starts with "init" and will need to have special // handling under ARC. -bool LIBPROTOC_EXPORT IsInitName(const string& name); +bool PROTOC_EXPORT IsInitName(const string& name); // Gets the objc_class_prefix. -string LIBPROTOC_EXPORT FileClassPrefix(const FileDescriptor* file); +string PROTOC_EXPORT FileClassPrefix(const FileDescriptor* file); // Gets the path of the file we're going to generate (sans the .pb.h // extension). The path will be dependent on the objectivec package // declared in the proto package. -string LIBPROTOC_EXPORT FilePath(const FileDescriptor* file); +string PROTOC_EXPORT FilePath(const FileDescriptor* file); // Just like FilePath(), but without the directory part. -string LIBPROTOC_EXPORT FilePathBasename(const FileDescriptor* file); +string PROTOC_EXPORT FilePathBasename(const FileDescriptor* file); // Gets the name of the root class we'll generate in the file. This class // is not meant for external consumption, but instead contains helpers that // the rest of the classes need -string LIBPROTOC_EXPORT FileClassName(const FileDescriptor* file); +string PROTOC_EXPORT FileClassName(const FileDescriptor* file); // These return the fully-qualified class name corresponding to the given // descriptor. -string LIBPROTOC_EXPORT ClassName(const Descriptor* descriptor); -string LIBPROTOC_EXPORT ClassName(const Descriptor* descriptor, string* out_suffix_added); -string LIBPROTOC_EXPORT EnumName(const EnumDescriptor* descriptor); +string PROTOC_EXPORT ClassName(const Descriptor* descriptor); +string PROTOC_EXPORT ClassName(const Descriptor* descriptor, + string* out_suffix_added); +string PROTOC_EXPORT EnumName(const EnumDescriptor* descriptor); // Returns the fully-qualified name of the enum value corresponding to the // the descriptor. -string LIBPROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor); +string PROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor); // Returns the name of the enum value corresponding to the descriptor. -string LIBPROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor); +string PROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor); // Reverse what an enum does. -string LIBPROTOC_EXPORT UnCamelCaseEnumShortName(const string& name); +string PROTOC_EXPORT UnCamelCaseEnumShortName(const string& name); // Returns the name to use for the extension (used as the method off the file's // Root class). -string LIBPROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor); +string PROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor); // Returns the transformed field name. -string LIBPROTOC_EXPORT FieldName(const FieldDescriptor* field); -string LIBPROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field); +string PROTOC_EXPORT FieldName(const FieldDescriptor* field); +string PROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field); // Returns the transformed oneof name. -string LIBPROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor); -string LIBPROTOC_EXPORT OneofName(const OneofDescriptor* descriptor); -string LIBPROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor); +string PROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor); +string PROTOC_EXPORT OneofName(const OneofDescriptor* descriptor); +string PROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor); inline bool HasFieldPresence(const FileDescriptor* file) { return file->syntax() != FileDescriptor::SYNTAX_PROTO3; @@ -127,7 +130,8 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) { } // Reverse of the above. -string LIBPROTOC_EXPORT UnCamelCaseFieldName(const string& name, const FieldDescriptor* field); +string PROTOC_EXPORT UnCamelCaseFieldName(const string& name, + const FieldDescriptor* field); enum ObjectiveCType { OBJECTIVECTYPE_INT32, @@ -175,48 +179,52 @@ string GetOptionalDeprecatedAttribute( } } -string LIBPROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field); +string PROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field); -ObjectiveCType LIBPROTOC_EXPORT GetObjectiveCType(FieldDescriptor::Type field_type); +ObjectiveCType PROTOC_EXPORT +GetObjectiveCType(FieldDescriptor::Type field_type); inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) { return GetObjectiveCType(field->type()); } -bool LIBPROTOC_EXPORT IsPrimitiveType(const FieldDescriptor* field); -bool LIBPROTOC_EXPORT IsReferenceType(const FieldDescriptor* field); +bool PROTOC_EXPORT IsPrimitiveType(const FieldDescriptor* field); +bool PROTOC_EXPORT IsReferenceType(const FieldDescriptor* field); -string LIBPROTOC_EXPORT GPBGenericValueFieldName(const FieldDescriptor* field); -string LIBPROTOC_EXPORT DefaultValue(const FieldDescriptor* field); -bool LIBPROTOC_EXPORT HasNonZeroDefaultValue(const FieldDescriptor* field); +string PROTOC_EXPORT GPBGenericValueFieldName(const FieldDescriptor* field); +string PROTOC_EXPORT DefaultValue(const FieldDescriptor* field); +bool PROTOC_EXPORT HasNonZeroDefaultValue(const FieldDescriptor* field); -string LIBPROTOC_EXPORT BuildFlagsString(const FlagType type, const std::vector<string>& strings); +string PROTOC_EXPORT BuildFlagsString(const FlagType type, + const std::vector<string>& strings); // Builds HeaderDoc/appledoc style comments out of the comments in the .proto // file. -string LIBPROTOC_EXPORT BuildCommentsString(const SourceLocation& location, - bool prefer_single_line); +string PROTOC_EXPORT BuildCommentsString(const SourceLocation& location, + bool prefer_single_line); // The name the commonly used by the library when built as a framework. // This lines up to the name used in the CocoaPod. -extern LIBPROTOC_EXPORT const char* const ProtobufLibraryFrameworkName; +extern PROTOC_EXPORT const char* const ProtobufLibraryFrameworkName; // Returns the CPP symbol name to use as the gate for framework style imports // for the given framework name to use. -string LIBPROTOC_EXPORT ProtobufFrameworkImportSymbol(const string& framework_name); +string PROTOC_EXPORT +ProtobufFrameworkImportSymbol(const string& framework_name); // Checks if the file is one of the proto's bundled with the library. -bool LIBPROTOC_EXPORT IsProtobufLibraryBundledProtoFile(const FileDescriptor* file); +bool PROTOC_EXPORT +IsProtobufLibraryBundledProtoFile(const FileDescriptor* file); // Checks the prefix for the given files and outputs any warnings as needed. If // there are flat out errors, then out_error is filled in with the first error // and the result is false. -bool LIBPROTOC_EXPORT ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files, - const Options& generation_options, - string* out_error); +bool PROTOC_EXPORT +ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files, + const Options& generation_options, string* out_error); // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform // the input into the expected output. -class LIBPROTOC_EXPORT TextFormatDecodeData { +class PROTOC_EXPORT TextFormatDecodeData { public: TextFormatDecodeData(); ~TextFormatDecodeData(); @@ -237,20 +245,20 @@ class LIBPROTOC_EXPORT TextFormatDecodeData { }; // Helper for parsing simple files. -class LIBPROTOC_EXPORT LineConsumer { +class PROTOC_EXPORT LineConsumer { public: LineConsumer(); virtual ~LineConsumer(); virtual bool ConsumeLine(const StringPiece& line, string* out_error) = 0; }; -bool LIBPROTOC_EXPORT ParseSimpleFile( - const string& path, LineConsumer* line_consumer, string* out_error); - +bool PROTOC_EXPORT ParseSimpleFile(const string& path, + LineConsumer* line_consumer, + string* out_error); // Helper class for parsing framework import mappings and generating // import statements. -class LIBPROTOC_EXPORT ImportWriter { +class PROTOC_EXPORT ImportWriter { public: ImportWriter(const string& generate_for_named_framework, const string& named_framework_to_proto_path_mappings_path, @@ -290,4 +298,7 @@ class LIBPROTOC_EXPORT ImportWriter { } // namespace compiler } // namespace protobuf } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ diff --git a/src/google/protobuf/compiler/package_info.h b/src/google/protobuf/compiler/package_info.h index fb6b473e..105ef601 100644 --- a/src/google/protobuf/compiler/package_info.h +++ b/src/google/protobuf/compiler/package_info.h @@ -37,7 +37,6 @@ // documentation generator. namespace google { - namespace protobuf { // Implementation of the Protocol Buffer compiler. diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 5c7047a6..0cec2939 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -35,9 +35,10 @@ // Recursive descent FTW. #include <float.h> -#include <google/protobuf/stubs/hash.h> #include <limits> +#include <unordered_map> +#include <google/protobuf/stubs/hash.h> #include <google/protobuf/stubs/casts.h> #include <google/protobuf/stubs/logging.h> @@ -58,7 +59,7 @@ using internal::WireFormat; namespace { -typedef hash_map<string, FieldDescriptorProto::Type> TypeNameMap; +typedef std::unordered_map<string, FieldDescriptorProto::Type> TypeNameMap; TypeNameMap MakeTypeNameTable() { TypeNameMap result; @@ -336,9 +337,9 @@ void Parser::AddError(const string& error) { // ------------------------------------------------------------------- Parser::LocationRecorder::LocationRecorder(Parser* parser) - : parser_(parser), - source_code_info_(parser->source_code_info_), - location_(parser_->source_code_info_->add_location()) { + : parser_(parser), + source_code_info_(parser->source_code_info_), + location_(parser_->source_code_info_->add_location()) { location_->add_span(parser_->input_->current().line); location_->add_span(parser_->input_->current().column); } @@ -1511,7 +1512,6 @@ bool Parser::ParseExtensions(DescriptorProto* message, range->set_end(end); } while (TryConsume(",")); - if (LookingAt("[")) { int range_number_index = extensions_location.CurrentPathSize(); SourceCodeInfo info; @@ -1525,8 +1525,7 @@ bool Parser::ParseExtensions(DescriptorProto* message, extensions_location, 0 /* we fill this in w/ actual index below */, &info); LocationRecorder location( - index_location, - DescriptorProto::ExtensionRange::kOptionsFieldNumber); + index_location, DescriptorProto::ExtensionRange::kOptionsFieldNumber); DO(Consume("[")); do { @@ -1546,12 +1545,12 @@ bool Parser::ParseExtensions(DescriptorProto* message, for (int i = old_range_size; i < message->extension_range_size(); i++) { for (int j = 0; j < info.location_size(); j++) { if (info.location(j).path_size() == range_number_index + 1) { - // this location's path is up to the extension range index, but doesn't - // include options; so it's redundant with location above + // this location's path is up to the extension range index, but + // doesn't include options; so it's redundant with location above continue; } SourceCodeInfo_Location* dest = source_code_info_->add_location(); - dest->CopyFrom(info.location(j)); + *dest = info.location(j); dest->set_path(range_number_index, i); } } @@ -2277,5 +2276,4 @@ void SourceLocationTable::Clear() { } // namespace compiler } // namespace protobuf - } // namespace google diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h index 5d98e5e1..9ae6c6da 100644 --- a/src/google/protobuf/compiler/parser.h +++ b/src/google/protobuf/compiler/parser.h @@ -45,10 +45,13 @@ #include <google/protobuf/descriptor.h> #include <google/protobuf/repeated_field.h> -namespace google { -namespace protobuf { class Message; } +#include <google/protobuf/port_def.inc> +namespace google { namespace protobuf { + +class Message; + namespace compiler { // Defined in this file. @@ -62,7 +65,7 @@ class SourceLocationTable; // to a FileDescriptorProto. It does not resolve import directives or perform // many other kinds of validation needed to construct a complete // FileDescriptor. -class LIBPROTOBUF_EXPORT Parser { +class PROTOBUF_EXPORT Parser { public: Parser(); ~Parser(); @@ -92,7 +95,7 @@ class LIBPROTOBUF_EXPORT Parser { // Returns the identifier used in the "syntax = " declaration, if one was // seen during the last call to Parse(), or the empty string otherwise. - const string& GetSyntaxIdentifier() { return syntax_identifier_; } + const std::string& GetSyntaxIdentifier() { return syntax_identifier_; } // If set true, input files will be required to begin with a syntax // identifier. Otherwise, files may omit this. If a syntax identifier @@ -162,7 +165,7 @@ class LIBPROTOBUF_EXPORT Parser { // where "text" is the expected token text. bool Consume(const char* text); // Consume a token of type IDENTIFIER and store its text in "output". - bool ConsumeIdentifier(string* output, const char* error); + bool ConsumeIdentifier(std::string* output, const char* error); // Consume an integer and store its value in "output". bool ConsumeInteger(int* output, const char* error); // Consume a signed integer and store its value in "output". @@ -174,7 +177,7 @@ class LIBPROTOBUF_EXPORT Parser { // tokens of either INTEGER or FLOAT type. bool ConsumeNumber(double* output, const char* error); // Consume a string literal and store its (unescaped) value in "output". - bool ConsumeString(string* output, const char* error); + bool ConsumeString(std::string* output, const char* error); // Consume a token representing the end of the statement. Comments between // this token and the next will be harvested for documentation. The given @@ -197,18 +200,18 @@ class LIBPROTOBUF_EXPORT Parser { // Error logging helpers // Invokes error_collector_->AddError(), if error_collector_ is not NULL. - void AddError(int line, int column, const string& error); + void AddError(int line, int column, const std::string& error); // Invokes error_collector_->AddError() with the line and column number // of the current token. - void AddError(const string& error); + void AddError(const std::string& error); // 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 { + class PROTOBUF_EXPORT LocationRecorder { public: // Construct the file's "root" location. LocationRecorder(Parser* parser); @@ -226,7 +229,7 @@ class LIBPROTOBUF_EXPORT Parser { // Creates a recorder that generates locations into given source code info. LocationRecorder(const LocationRecorder& parent, int path1, - SourceCodeInfo* source_code_info); + SourceCodeInfo* source_code_info); ~LocationRecorder(); @@ -263,8 +266,8 @@ class LIBPROTOBUF_EXPORT Parser { // // TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for // why this is const. - void AttachComments(string* leading, string* trailing, - std::vector<string>* detached_comments) const; + void AttachComments(std::string* leading, std::string* trailing, + std::vector<std::string>* detached_comments) const; private: // Indexes of parent and current location in the parent @@ -312,7 +315,7 @@ class LIBPROTOBUF_EXPORT Parser { bool ParsePackage(FileDescriptorProto* file, const LocationRecorder& root_location, const FileDescriptorProto* containing_file); - bool ParseImport(RepeatedPtrField<string>* dependency, + bool ParseImport(RepeatedPtrField<std::string>* dependency, RepeatedField<int32>* public_dependency, RepeatedField<int32>* weak_dependency, const LocationRecorder& root_location, @@ -436,10 +439,10 @@ class LIBPROTOBUF_EXPORT Parser { // Parse a type name and fill in "type" (if it is a primitive) or // "type_name" (if it is not) with the type parsed. bool ParseType(FieldDescriptorProto::Type* type, - string* type_name); + std::string* type_name); // Parse a user-defined type and fill in "type_name" with the name. // If a primitive type is named, it is treated as an error. - bool ParseUserDefinedType(string* type_name); + bool ParseUserDefinedType(std::string* type_name); // Parses field options, i.e. the stuff in square brackets at the end // of a field definition. Also parses default value. @@ -488,7 +491,7 @@ class LIBPROTOBUF_EXPORT Parser { // REQUIRES: LookingAt("{") // When finished successfully, we are looking at the first token past // the ending brace. - bool ParseUninterpretedBlock(string* value); + bool ParseUninterpretedBlock(std::string* value); struct MapField { // Whether the field is a map field. @@ -497,8 +500,8 @@ class LIBPROTOBUF_EXPORT Parser { FieldDescriptorProto::Type key_type; FieldDescriptorProto::Type value_type; // Or the type names string if the types are customized types. - string key_type_name; - string value_type_name; + std::string key_type_name; + std::string value_type_name; MapField() : is_map_field(false) {} }; @@ -523,18 +526,18 @@ class LIBPROTOBUF_EXPORT Parser { bool had_errors_; bool require_syntax_identifier_; bool stop_after_syntax_identifier_; - string syntax_identifier_; + std::string syntax_identifier_; // Leading doc comments for the next declaration. These are not complete // yet; use ConsumeEndOfDeclaration() to get the complete comments. - string upcoming_doc_comments_; + std::string upcoming_doc_comments_; // Detached comments are not connected to any syntax entities. Elements in // this vector are paragraphs of comments separated by empty lines. The // detached comments will be put into the leading_detached_comments field for // the next element (See SourceCodeInfo.Location in descriptor.proto), when // ConsumeEndOfDeclaration() is called. - std::vector<string> upcoming_detached_comments_; + std::vector<std::string> upcoming_detached_comments_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser); }; @@ -547,7 +550,7 @@ class LIBPROTOBUF_EXPORT Parser { // 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 { +class PROTOBUF_EXPORT SourceLocationTable { public: SourceLocationTable(); ~SourceLocationTable(); @@ -578,6 +581,8 @@ class LIBPROTOBUF_EXPORT SourceLocationTable { } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_PARSER_H__ diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index 0725a682..008d97d5 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -39,6 +39,7 @@ #include <google/protobuf/compiler/parser.h> +#include <google/protobuf/test_util2.h> #include <google/protobuf/unittest.pb.h> #include <google/protobuf/unittest_custom_options.pb.h> #include <google/protobuf/io/tokenizer.h> @@ -1746,7 +1747,8 @@ TEST_F(ParserValidationErrorTest, FieldDefaultValueError) { TEST_F(ParserValidationErrorTest, FileOptionNameError) { ExpectHasValidationErrors( "option foo = 5;", - "0:7: Option \"foo\" unknown.\n"); + "0:7: Option \"foo\" unknown. Ensure that your proto definition file " + "imports the proto which defines the option.\n"); } TEST_F(ParserValidationErrorTest, FileOptionValueError) { @@ -1761,7 +1763,8 @@ TEST_F(ParserValidationErrorTest, FieldOptionNameError) { "message Foo {\n" " optional bool bar = 1 [foo=1];\n" "}\n", - "1:25: Option \"foo\" unknown.\n"); + "1:25: Option \"foo\" unknown. Ensure that your proto definition file " + "imports the proto which defines the option.\n"); } TEST_F(ParserValidationErrorTest, FieldOptionValueError) { @@ -1866,7 +1869,7 @@ TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) { // base2.proto: // package baz - // import google/protobuf/descriptor.proto + // import net/proto2/proto/descriptor.proto // message Bar { optional int32 foo = 1; } // extend FileOptions { optional Bar bar = 7672757; } FileDescriptorProto other_file; @@ -1992,7 +1995,8 @@ TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) { // We now have a FileDescriptorProto, but to compare with the expected we // need to link to a FileDecriptor, then output back to a proto. We'll // also need to give it the same name as the original. - parsed.set_name("google/protobuf/unittest.proto"); + parsed.set_name( + TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto")); // We need the imported dependency before we can build our parsed proto const FileDescriptor* public_import = protobuf_unittest_import::PublicImportMessage::descriptor()->file(); diff --git a/src/google/protobuf/compiler/php/php_generator.h b/src/google/protobuf/compiler/php/php_generator.h index b851d9b4..283767ec 100644 --- a/src/google/protobuf/compiler/php/php_generator.h +++ b/src/google/protobuf/compiler/php/php_generator.h @@ -36,12 +36,14 @@ #include <string> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { namespace php { -class LIBPROTOC_EXPORT Generator +class PROTOC_EXPORT Generator : public google::protobuf::compiler::CodeGenerator { virtual bool Generate( const FileDescriptor* file, @@ -53,11 +55,11 @@ class LIBPROTOC_EXPORT Generator // To skip reserved keywords in php, some generated classname are prefixed. // Other code generators may need following API to figure out the actual // classname. -LIBPROTOC_EXPORT std::string GeneratedClassName( +PROTOC_EXPORT std::string GeneratedClassName( const google::protobuf::Descriptor* desc); -LIBPROTOC_EXPORT std::string GeneratedClassName( +PROTOC_EXPORT std::string GeneratedClassName( const google::protobuf::EnumDescriptor* desc); -LIBPROTOC_EXPORT std::string GeneratedClassName( +PROTOC_EXPORT std::string GeneratedClassName( const google::protobuf::ServiceDescriptor* desc); } // namespace php @@ -65,4 +67,6 @@ LIBPROTOC_EXPORT std::string GeneratedClassName( } // namespace protobuf } // namespace google +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h index d2793a9f..48db3c1c 100644 --- a/src/google/protobuf/compiler/plugin.h +++ b/src/google/protobuf/compiler/plugin.h @@ -64,7 +64,8 @@ #include <string> -#include <google/protobuf/stubs/common.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { @@ -74,17 +75,20 @@ class CodeGeneratorRequest; class CodeGeneratorResponse; // Implements main() for a protoc plugin exposing the given code generator. -LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator); +PROTOC_EXPORT int PluginMain(int argc, char* argv[], + const CodeGenerator* generator); // Generates code using the given code generator. Returns true if the code // generation is successful. If the code geneartion fails, error_msg may be // populated to describe the failure cause. bool GenerateCode(const CodeGeneratorRequest& request, const CodeGenerator& generator, CodeGeneratorResponse* response, - string* error_msg); + std::string* error_msg); } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 20aa82c7..234be0dd 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -6,54 +6,42 @@ #include <algorithm> #include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/port.h> #include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/extension_set.h> #include <google/protobuf/wire_format_lite_inl.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/generated_message_reflection.h> #include <google/protobuf/reflection_ops.h> #include <google/protobuf/wire_format.h> -// This is a temporary google only hack -#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS -#include "third_party/protobuf/version.h" -#endif // @@protoc_insertion_point(includes) +#include <google/protobuf/port_def.inc> -namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto { -extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_CodeGeneratorResponse_File; -extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Version; -} // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto -namespace protobuf_google_2fprotobuf_2fdescriptor_2eproto { -extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fdescriptor_2eproto ::google::protobuf::internal::SCCInfo<6> scc_info_FileDescriptorProto; -} // namespace protobuf_google_2fprotobuf_2fdescriptor_2eproto +extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto; +extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto; +extern PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto ::google::protobuf::internal::SCCInfo<6> scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto; namespace google { namespace protobuf { namespace compiler { class VersionDefaultTypeInternal { public: - ::google::protobuf::internal::ExplicitlyConstructed<Version> - _instance; + ::google::protobuf::internal::ExplicitlyConstructed<Version> _instance; } _Version_default_instance_; class CodeGeneratorRequestDefaultTypeInternal { public: - ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorRequest> - _instance; + ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorRequest> _instance; } _CodeGeneratorRequest_default_instance_; class CodeGeneratorResponse_FileDefaultTypeInternal { public: - ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse_File> - _instance; + ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse_File> _instance; } _CodeGeneratorResponse_File_default_instance_; class CodeGeneratorResponseDefaultTypeInternal { public: - ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse> - _instance; + ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse> _instance; } _CodeGeneratorResponse_default_instance_; } // namespace compiler } // namespace protobuf } // namespace google -namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto { -static void InitDefaultsVersion() { +static void InitDefaultsVersion_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { GOOGLE_PROTOBUF_VERIFY_VERSION; { @@ -64,10 +52,10 @@ static void InitDefaultsVersion() { ::google::protobuf::compiler::Version::InitAsDefaultInstance(); } -LIBPROTOC_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_Version = - {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsVersion}, {}}; +PROTOC_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto = + {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsVersion_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {}}; -static void InitDefaultsCodeGeneratorRequest() { +static void InitDefaultsCodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { GOOGLE_PROTOBUF_VERIFY_VERSION; { @@ -78,12 +66,12 @@ static void InitDefaultsCodeGeneratorRequest() { ::google::protobuf::compiler::CodeGeneratorRequest::InitAsDefaultInstance(); } -LIBPROTOC_EXPORT ::google::protobuf::internal::SCCInfo<2> scc_info_CodeGeneratorRequest = - {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsCodeGeneratorRequest}, { - &protobuf_google_2fprotobuf_2fdescriptor_2eproto::scc_info_FileDescriptorProto.base, - &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_Version.base,}}; +PROTOC_EXPORT ::google::protobuf::internal::SCCInfo<2> scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto = + {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsCodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, { + &scc_info_FileDescriptorProto_google_2fprotobuf_2fdescriptor_2eproto.base, + &scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,}}; -static void InitDefaultsCodeGeneratorResponse_File() { +static void InitDefaultsCodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { GOOGLE_PROTOBUF_VERIFY_VERSION; { @@ -94,10 +82,10 @@ static void InitDefaultsCodeGeneratorResponse_File() { ::google::protobuf::compiler::CodeGeneratorResponse_File::InitAsDefaultInstance(); } -LIBPROTOC_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_CodeGeneratorResponse_File = - {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsCodeGeneratorResponse_File}, {}}; +PROTOC_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto = + {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsCodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, {}}; -static void InitDefaultsCodeGeneratorResponse() { +static void InitDefaultsCodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { GOOGLE_PROTOBUF_VERIFY_VERSION; { @@ -108,68 +96,70 @@ static void InitDefaultsCodeGeneratorResponse() { ::google::protobuf::compiler::CodeGeneratorResponse::InitAsDefaultInstance(); } -LIBPROTOC_EXPORT ::google::protobuf::internal::SCCInfo<1> scc_info_CodeGeneratorResponse = - {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsCodeGeneratorResponse}, { - &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorResponse_File.base,}}; +PROTOC_EXPORT ::google::protobuf::internal::SCCInfo<1> scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto = + {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsCodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto}, { + &scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base,}}; -void InitDefaults() { - ::google::protobuf::internal::InitSCC(&scc_info_Version.base); - ::google::protobuf::internal::InitSCC(&scc_info_CodeGeneratorRequest.base); - ::google::protobuf::internal::InitSCC(&scc_info_CodeGeneratorResponse_File.base); - ::google::protobuf::internal::InitSCC(&scc_info_CodeGeneratorResponse.base); +void InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { + ::google::protobuf::internal::InitSCC(&scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); + ::google::protobuf::internal::InitSCC(&scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); + ::google::protobuf::internal::InitSCC(&scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); + ::google::protobuf::internal::InitSCC(&scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); } -::google::protobuf::Metadata file_level_metadata[4]; +::google::protobuf::Metadata file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[4]; +constexpr ::google::protobuf::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr; +constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr; -const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, _internal_metadata_), +const ::google::protobuf::uint32 TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, major_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, minor_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, patch_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::Version, suffix_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, major_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, minor_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, patch_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::Version, suffix_), 1, 2, 3, 0, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, file_to_generate_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, parameter_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, proto_file_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, compiler_version_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, file_to_generate_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, parameter_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, proto_file_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorRequest, compiler_version_), ~0u, 0, ~0u, 1, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, name_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, insertion_point_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, content_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, name_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, insertion_point_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse_File, content_), 0, 1, 2, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _has_bits_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _internal_metadata_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _has_bits_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ ~0u, // no _weak_field_map_ - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, error_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, file_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, error_), + PROTOBUF_FIELD_OFFSET(::google::protobuf::compiler::CodeGeneratorResponse, file_), 0, ~0u, }; -static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { +static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { { 0, 9, sizeof(::google::protobuf::compiler::Version)}, { 13, 22, sizeof(::google::protobuf::compiler::CodeGeneratorRequest)}, { 26, 34, sizeof(::google::protobuf::compiler::CodeGeneratorResponse_File)}, @@ -183,62 +173,44 @@ static ::google::protobuf::Message const * const file_default_instances[] = { reinterpret_cast<const ::google::protobuf::Message*>(&::google::protobuf::compiler::_CodeGeneratorResponse_default_instance_), }; -static void protobuf_AssignDescriptors() { - AddDescriptors(); - AssignDescriptors( - "google/protobuf/compiler/plugin.proto", schemas, file_default_instances, TableStruct::offsets, - file_level_metadata, NULL, NULL); -} - -static void protobuf_AssignDescriptorsOnce() { - static ::google::protobuf::internal::once_flag once; - ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors); -} - -void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD; -void protobuf_RegisterTypes(const ::std::string&) { - protobuf_AssignDescriptorsOnce(); - ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 4); -} - -static void AddDescriptorsImpl() { - InitDefaults(); - static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - "\n%google/protobuf/compiler/plugin.proto\022" - "\030google.protobuf.compiler\032 google/protob" - "uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030" - "\001 \001(\005\022\r\n\005minor\030\002 \001(\005\022\r\n\005patch\030\003 \001(\005\022\016\n\006s" - "uffix\030\004 \001(\t\"\272\001\n\024CodeGeneratorRequest\022\030\n\020" - "file_to_generate\030\001 \003(\t\022\021\n\tparameter\030\002 \001(" - "\t\0228\n\nproto_file\030\017 \003(\0132$.google.protobuf." - "FileDescriptorProto\022;\n\020compiler_version\030" - "\003 \001(\0132!.google.protobuf.compiler.Version" - "\"\252\001\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001(" - "\t\022B\n\004file\030\017 \003(\01324.google.protobuf.compil" - "er.CodeGeneratorResponse.File\032>\n\004File\022\014\n" - "\004name\030\001 \001(\t\022\027\n\017insertion_point\030\002 \001(\t\022\017\n\007" - "content\030\017 \001(\tBg\n\034com.google.protobuf.com" - "pilerB\014PluginProtosZ9github.com/golang/p" - "rotobuf/protoc-gen-go/plugin;plugin_go" +::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto = { + {}, AddDescriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto", schemas, + file_default_instances, TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, 4, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, +}; + +::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto = { + false, InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto, + "\n%google/protobuf/compiler/plugin.proto\022" + "\030google.protobuf.compiler\032 google/protob" + "uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030" + "\001 \001(\005\022\r\n\005minor\030\002 \001(\005\022\r\n\005patch\030\003 \001(\005\022\016\n\006s" + "uffix\030\004 \001(\t\"\272\001\n\024CodeGeneratorRequest\022\030\n\020" + "file_to_generate\030\001 \003(\t\022\021\n\tparameter\030\002 \001(" + "\t\0228\n\nproto_file\030\017 \003(\0132$.google.protobuf." + "FileDescriptorProto\022;\n\020compiler_version\030" + "\003 \001(\0132!.google.protobuf.compiler.Version" + "\"\252\001\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001(" + "\t\022B\n\004file\030\017 \003(\01324.google.protobuf.compil" + "er.CodeGeneratorResponse.File\032>\n\004File\022\014\n" + "\004name\030\001 \001(\t\022\027\n\017insertion_point\030\002 \001(\t\022\017\n\007" + "content\030\017 \001(\tBg\n\034com.google.protobuf.com" + "pilerB\014PluginProtosZ9github.com/golang/p" + "rotobuf/protoc-gen-go/plugin;plugin_go" +, + "google/protobuf/compiler/plugin.proto", &assign_descriptors_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto, 638, +}; + +void AddDescriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { + static constexpr ::google::protobuf::internal::InitFunc deps[1] = + { + ::AddDescriptors_google_2fprotobuf_2fdescriptor_2eproto, }; - ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( - descriptor, 638); - ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( - "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes); - ::protobuf_google_2fprotobuf_2fdescriptor_2eproto::AddDescriptors(); + ::google::protobuf::internal::AddDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto, deps, 1); } -void AddDescriptors() { - static ::google::protobuf::internal::once_flag once; - ::google::protobuf::internal::call_once(once, AddDescriptorsImpl); -} -// Force AddDescriptors() to be called at dynamic initialization time. -struct StaticDescriptorInitializer { - StaticDescriptorInitializer() { - AddDescriptors(); - } -} static_descriptor_initializer; -} // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto +// Force running AddDescriptors() at dynamic initialization time. +static bool dynamic_init_dummy_google_2fprotobuf_2fcompiler_2fplugin_2eproto = []() { AddDescriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); return true; }(); namespace google { namespace protobuf { namespace compiler { @@ -247,6 +219,22 @@ namespace compiler { void Version::InitAsDefaultInstance() { } +class Version::HasBitSetters { + public: + static void set_has_major(Version* msg) { + msg->_has_bits_[0] |= 0x00000002u; + } + static void set_has_minor(Version* msg) { + msg->_has_bits_[0] |= 0x00000004u; + } + static void set_has_patch(Version* msg) { + msg->_has_bits_[0] |= 0x00000008u; + } + static void set_has_suffix(Version* msg) { + msg->_has_bits_[0] |= 0x00000001u; + } +}; + #if !defined(_MSC_VER) || _MSC_VER >= 1900 const int Version::kMajorFieldNumber; const int Version::kMinorFieldNumber; @@ -256,8 +244,6 @@ const int Version::kSuffixFieldNumber; Version::Version() : ::google::protobuf::Message(), _internal_metadata_(NULL) { - ::google::protobuf::internal::InitSCC( - &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_Version.base); SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.compiler.Version) } @@ -277,6 +263,8 @@ Version::Version(const Version& from) } void Version::SharedCtor() { + ::google::protobuf::internal::InitSCC( + &scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); suffix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(&major_, 0, static_cast<size_t>( reinterpret_cast<char*>(&patch_) - @@ -295,13 +283,8 @@ void Version::SharedDtor() { void Version::SetCachedSize(int size) const { _cached_size_.Set(size); } -const ::google::protobuf::Descriptor* Version::descriptor() { - ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - const Version& Version::default_instance() { - ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_Version.base); + ::google::protobuf::internal::InitSCC(&::scc_info_Version_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); return *internal_default_instance(); } @@ -316,7 +299,7 @@ void Version::Clear() { if (cached_has_bits & 0x00000001u) { suffix_.ClearNonDefaultToEmptyNoArena(); } - if (cached_has_bits & 14u) { + if (cached_has_bits & 0x0000000eu) { ::memset(&major_, 0, static_cast<size_t>( reinterpret_cast<char*>(&patch_) - reinterpret_cast<char*>(&major_)) + sizeof(patch_)); @@ -325,9 +308,92 @@ void Version::Clear() { _internal_metadata_.Clear(); } +#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +const char* Version::_InternalParse(const char* begin, const char* end, void* object, + ::google::protobuf::internal::ParseContext* ctx) { + auto msg = static_cast<Version*>(object); + ::google::protobuf::uint32 size; (void)size; + int depth; (void)depth; + ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end; + auto ptr = begin; + while (ptr < end) { + ::google::protobuf::uint32 tag; + ptr = Varint::Parse32Inline(ptr, &tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + switch (tag >> 3) { + // optional int32 major = 1; + case 1: { + if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual; + ::google::protobuf::uint64 val; + ptr = Varint::Parse64(ptr, &val); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ::google::protobuf::int32 value = val; + msg->set_major(value); + break; + } + // optional int32 minor = 2; + case 2: { + if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual; + ::google::protobuf::uint64 val; + ptr = Varint::Parse64(ptr, &val); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ::google::protobuf::int32 value = val; + msg->set_minor(value); + break; + } + // optional int32 patch = 3; + case 3: { + if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual; + ::google::protobuf::uint64 val; + ptr = Varint::Parse64(ptr, &val); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ::google::protobuf::int32 value = val; + msg->set_patch(value); + break; + } + // optional string suffix = 4; + case 4: { + if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual; + ptr = Varint::Parse32Inline(ptr, &size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.Version.suffix"); + parser_till_end = ::google::protobuf::internal::StringParserUTF8Verify; + ::std::string* str = msg->mutable_suffix(); + str->clear(); + object = str; + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + if (size) ptr = parser_till_end(ptr, newend, object, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend); + break; + } + default: { + handle_unusual: (void)&&handle_unusual; + if ((tag & 7) == 4 || tag == 0) { + bool ok = ctx->ValidEndGroup(tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ok); + return ptr; + } + auto res = UnknownFieldParse(tag, {_InternalParse, msg}, + ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx); + ptr = res.first; + if (res.second) return ptr; + } + } // switch + } // while + return ptr; +len_delim_till_end: (void)&&len_delim_till_end; + return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg}, + {parser_till_end, object}, size); +group_continues: (void)&&group_continues; + GOOGLE_DCHECK(ptr >= end); + ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth); + return ptr; +} +#else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER bool Version::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.compiler.Version) for (;;) { @@ -337,9 +403,8 @@ bool Version::MergePartialFromCodedStream( switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional int32 major = 1; case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { - set_has_major(); + if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) { + HasBitSetters::set_has_major(this); DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &major_))); @@ -351,9 +416,8 @@ bool Version::MergePartialFromCodedStream( // optional int32 minor = 2; case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { - set_has_minor(); + if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) { + HasBitSetters::set_has_minor(this); DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &minor_))); @@ -365,9 +429,8 @@ bool Version::MergePartialFromCodedStream( // optional int32 patch = 3; case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) { - set_has_patch(); + if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) { + HasBitSetters::set_has_patch(this); DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &patch_))); @@ -379,8 +442,7 @@ bool Version::MergePartialFromCodedStream( // optional string suffix = 4; case 4: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) { + if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_suffix())); ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( @@ -412,6 +474,7 @@ failure: return false; #undef DO_ } +#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER void Version::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { @@ -503,30 +566,35 @@ size_t Version::ByteSizeLong() const { ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( _internal_metadata_.unknown_fields()); } - if (_has_bits_[0 / 32] & 15u) { + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x0000000fu) { // optional string suffix = 4; - if (has_suffix()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->suffix()); } // optional int32 major = 1; - if (has_major()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::Int32Size( this->major()); } // optional int32 minor = 2; - if (has_minor()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::Int32Size( this->minor()); } // optional int32 patch = 3; - if (has_patch()) { + if (cached_has_bits & 0x00000008u) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::Int32Size( this->patch()); @@ -542,7 +610,7 @@ void Version::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.Version) GOOGLE_DCHECK_NE(&from, this); const Version* source = - ::google::protobuf::internal::DynamicCastToGenerated<const Version>( + ::google::protobuf::DynamicCastToGenerated<Version>( &from); if (source == NULL) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.Version) @@ -561,9 +629,9 @@ void Version::MergeFrom(const Version& from) { (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 15u) { + if (cached_has_bits & 0x0000000fu) { if (cached_has_bits & 0x00000001u) { - set_has_suffix(); + _has_bits_[0] |= 0x00000001u; suffix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.suffix_); } if (cached_has_bits & 0x00000002u) { @@ -603,18 +671,18 @@ void Version::Swap(Version* other) { } void Version::InternalSwap(Version* other) { using std::swap; + _internal_metadata_.Swap(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); suffix_.Swap(&other->suffix_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); swap(major_, other->major_); swap(minor_, other->minor_); swap(patch_, other->patch_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); } ::google::protobuf::Metadata Version::GetMetadata() const { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages]; + ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto); + return ::file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[kIndexInFileMessages]; } @@ -624,6 +692,21 @@ void CodeGeneratorRequest::InitAsDefaultInstance() { ::google::protobuf::compiler::_CodeGeneratorRequest_default_instance_._instance.get_mutable()->compiler_version_ = const_cast< ::google::protobuf::compiler::Version*>( ::google::protobuf::compiler::Version::internal_default_instance()); } +class CodeGeneratorRequest::HasBitSetters { + public: + static void set_has_parameter(CodeGeneratorRequest* msg) { + msg->_has_bits_[0] |= 0x00000001u; + } + static const ::google::protobuf::compiler::Version& compiler_version(const CodeGeneratorRequest* msg); + static void set_has_compiler_version(CodeGeneratorRequest* msg) { + msg->_has_bits_[0] |= 0x00000002u; + } +}; + +const ::google::protobuf::compiler::Version& +CodeGeneratorRequest::HasBitSetters::compiler_version(const CodeGeneratorRequest* msg) { + return *msg->compiler_version_; +} void CodeGeneratorRequest::clear_proto_file() { proto_file_.Clear(); } @@ -636,8 +719,6 @@ const int CodeGeneratorRequest::kCompilerVersionFieldNumber; CodeGeneratorRequest::CodeGeneratorRequest() : ::google::protobuf::Message(), _internal_metadata_(NULL) { - ::google::protobuf::internal::InitSCC( - &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorRequest.base); SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest) } @@ -661,6 +742,8 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from) } void CodeGeneratorRequest::SharedCtor() { + ::google::protobuf::internal::InitSCC( + &scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); parameter_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); compiler_version_ = NULL; } @@ -678,13 +761,8 @@ void CodeGeneratorRequest::SharedDtor() { void CodeGeneratorRequest::SetCachedSize(int size) const { _cached_size_.Set(size); } -const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() { - ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() { - ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorRequest.base); + ::google::protobuf::internal::InitSCC(&::scc_info_CodeGeneratorRequest_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); return *internal_default_instance(); } @@ -698,7 +776,7 @@ void CodeGeneratorRequest::Clear() { file_to_generate_.Clear(); proto_file_.Clear(); cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { parameter_.ClearNonDefaultToEmptyNoArena(); } @@ -711,9 +789,114 @@ void CodeGeneratorRequest::Clear() { _internal_metadata_.Clear(); } +#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +const char* CodeGeneratorRequest::_InternalParse(const char* begin, const char* end, void* object, + ::google::protobuf::internal::ParseContext* ctx) { + auto msg = static_cast<CodeGeneratorRequest*>(object); + ::google::protobuf::uint32 size; (void)size; + int depth; (void)depth; + ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end; + auto ptr = begin; + while (ptr < end) { + ::google::protobuf::uint32 tag; + ptr = Varint::Parse32Inline(ptr, &tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + switch (tag >> 3) { + // repeated string file_to_generate = 1; + case 1: { + if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual; + do { + ptr = Varint::Parse32Inline(ptr, &size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorRequest.file_to_generate"); + parser_till_end = ::google::protobuf::internal::StringParserUTF8Verify; + ::std::string* str = msg->add_file_to_generate(); + str->clear(); + object = str; + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + if (size) ptr = parser_till_end(ptr, newend, object, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend); + if (ptr >= end) break; + } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 10 && (ptr += 1)); + break; + } + // optional string parameter = 2; + case 2: { + if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual; + ptr = Varint::Parse32Inline(ptr, &size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorRequest.parameter"); + parser_till_end = ::google::protobuf::internal::StringParserUTF8Verify; + ::std::string* str = msg->mutable_parameter(); + str->clear(); + object = str; + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + if (size) ptr = parser_till_end(ptr, newend, object, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend); + break; + } + // optional .google.protobuf.compiler.Version compiler_version = 3; + case 3: { + if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual; + ptr = Varint::Parse32Inline(ptr, &size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + parser_till_end = ::google::protobuf::compiler::Version::_InternalParse; + object = msg->mutable_compiler_version(); + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + bool ok = ctx->ParseExactRange({parser_till_end, object}, + ptr, newend); + GOOGLE_PROTOBUF_PARSER_ASSERT(ok); + ptr = newend; + break; + } + // repeated .google.protobuf.FileDescriptorProto proto_file = 15; + case 15: { + if (static_cast<::google::protobuf::uint8>(tag) != 122) goto handle_unusual; + do { + ptr = Varint::Parse32Inline(ptr, &size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + parser_till_end = ::google::protobuf::FileDescriptorProto::_InternalParse; + object = msg->add_proto_file(); + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + bool ok = ctx->ParseExactRange({parser_till_end, object}, + ptr, newend); + GOOGLE_PROTOBUF_PARSER_ASSERT(ok); + ptr = newend; + if (ptr >= end) break; + } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 122 && (ptr += 1)); + break; + } + default: { + handle_unusual: (void)&&handle_unusual; + if ((tag & 7) == 4 || tag == 0) { + bool ok = ctx->ValidEndGroup(tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ok); + return ptr; + } + auto res = UnknownFieldParse(tag, {_InternalParse, msg}, + ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx); + ptr = res.first; + if (res.second) return ptr; + } + } // switch + } // while + return ptr; +len_delim_till_end: (void)&&len_delim_till_end; + return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg}, + {parser_till_end, object}, size); +group_continues: (void)&&group_continues; + GOOGLE_DCHECK(ptr >= end); + ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth); + return ptr; +} +#else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER bool CodeGeneratorRequest::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorRequest) for (;;) { @@ -723,8 +906,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated string file_to_generate = 1; case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { + if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->add_file_to_generate())); ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( @@ -740,8 +922,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( // optional string parameter = 2; case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { + if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_parameter())); ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( @@ -756,8 +937,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( // optional .google.protobuf.compiler.Version compiler_version = 3; case 3: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { + if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) { DO_(::google::protobuf::internal::WireFormatLite::ReadMessage( input, mutable_compiler_version())); } else { @@ -768,8 +948,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( // repeated .google.protobuf.FileDescriptorProto proto_file = 15; case 15: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) { + if (static_cast< ::google::protobuf::uint8>(tag) == (122 & 0xFF)) { DO_(::google::protobuf::internal::WireFormatLite::ReadMessage( input, add_proto_file())); } else { @@ -797,6 +976,7 @@ failure: return false; #undef DO_ } +#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER void CodeGeneratorRequest::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { @@ -828,7 +1008,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes( // optional .google.protobuf.compiler.Version compiler_version = 3; if (cached_has_bits & 0x00000002u) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( - 3, this->_internal_compiler_version(), output); + 3, HasBitSetters::compiler_version(this), output); } // repeated .google.protobuf.FileDescriptorProto proto_file = 15; @@ -880,7 +1060,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes( if (cached_has_bits & 0x00000002u) { target = ::google::protobuf::internal::WireFormatLite:: InternalWriteMessageToArray( - 3, this->_internal_compiler_version(), deterministic, target); + 3, HasBitSetters::compiler_version(this), deterministic, target); } // repeated .google.protobuf.FileDescriptorProto proto_file = 15; @@ -908,6 +1088,10 @@ size_t CodeGeneratorRequest::ByteSizeLong() const { ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( _internal_metadata_.unknown_fields()); } + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated string file_to_generate = 1; total_size += 1 * ::google::protobuf::internal::FromIntSize(this->file_to_generate_size()); @@ -927,16 +1111,17 @@ size_t CodeGeneratorRequest::ByteSizeLong() const { } } - if (_has_bits_[0 / 32] & 3u) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000003u) { // optional string parameter = 2; - if (has_parameter()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->parameter()); } // optional .google.protobuf.compiler.Version compiler_version = 3; - if (has_compiler_version()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::MessageSize( *compiler_version_); @@ -952,7 +1137,7 @@ void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest) GOOGLE_DCHECK_NE(&from, this); const CodeGeneratorRequest* source = - ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>( + ::google::protobuf::DynamicCastToGenerated<CodeGeneratorRequest>( &from); if (source == NULL) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorRequest) @@ -973,9 +1158,9 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) { file_to_generate_.MergeFrom(from.file_to_generate_); proto_file_.MergeFrom(from.proto_file_); cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 3u) { + if (cached_has_bits & 0x00000003u) { if (cached_has_bits & 0x00000001u) { - set_has_parameter(); + _has_bits_[0] |= 0x00000001u; parameter_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.parameter_); } if (cached_has_bits & 0x00000002u) { @@ -1009,18 +1194,18 @@ void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) { } void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) { using std::swap; + _internal_metadata_.Swap(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); file_to_generate_.InternalSwap(CastToBase(&other->file_to_generate_)); CastToBase(&proto_file_)->InternalSwap(CastToBase(&other->proto_file_)); parameter_.Swap(&other->parameter_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); swap(compiler_version_, other->compiler_version_); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); } ::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages]; + ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto); + return ::file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[kIndexInFileMessages]; } @@ -1028,6 +1213,19 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) { void CodeGeneratorResponse_File::InitAsDefaultInstance() { } +class CodeGeneratorResponse_File::HasBitSetters { + public: + static void set_has_name(CodeGeneratorResponse_File* msg) { + msg->_has_bits_[0] |= 0x00000001u; + } + static void set_has_insertion_point(CodeGeneratorResponse_File* msg) { + msg->_has_bits_[0] |= 0x00000002u; + } + static void set_has_content(CodeGeneratorResponse_File* msg) { + msg->_has_bits_[0] |= 0x00000004u; + } +}; + #if !defined(_MSC_VER) || _MSC_VER >= 1900 const int CodeGeneratorResponse_File::kNameFieldNumber; const int CodeGeneratorResponse_File::kInsertionPointFieldNumber; @@ -1036,8 +1234,6 @@ const int CodeGeneratorResponse_File::kContentFieldNumber; CodeGeneratorResponse_File::CodeGeneratorResponse_File() : ::google::protobuf::Message(), _internal_metadata_(NULL) { - ::google::protobuf::internal::InitSCC( - &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorResponse_File.base); SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } @@ -1062,6 +1258,8 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon } void CodeGeneratorResponse_File::SharedCtor() { + ::google::protobuf::internal::InitSCC( + &scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); insertion_point_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); content_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -1081,13 +1279,8 @@ void CodeGeneratorResponse_File::SharedDtor() { void CodeGeneratorResponse_File::SetCachedSize(int size) const { _cached_size_.Set(size); } -const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() { - ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() { - ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorResponse_File.base); + ::google::protobuf::internal::InitSCC(&::scc_info_CodeGeneratorResponse_File_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); return *internal_default_instance(); } @@ -1099,7 +1292,7 @@ void CodeGeneratorResponse_File::Clear() { (void) cached_has_bits; cached_has_bits = _has_bits_[0]; - if (cached_has_bits & 7u) { + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { name_.ClearNonDefaultToEmptyNoArena(); } @@ -1114,9 +1307,94 @@ void CodeGeneratorResponse_File::Clear() { _internal_metadata_.Clear(); } +#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +const char* CodeGeneratorResponse_File::_InternalParse(const char* begin, const char* end, void* object, + ::google::protobuf::internal::ParseContext* ctx) { + auto msg = static_cast<CodeGeneratorResponse_File*>(object); + ::google::protobuf::uint32 size; (void)size; + int depth; (void)depth; + ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end; + auto ptr = begin; + while (ptr < end) { + ::google::protobuf::uint32 tag; + ptr = Varint::Parse32Inline(ptr, &tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + switch (tag >> 3) { + // optional string name = 1; + case 1: { + if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual; + ptr = Varint::Parse32Inline(ptr, &size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorResponse.File.name"); + parser_till_end = ::google::protobuf::internal::StringParserUTF8Verify; + ::std::string* str = msg->mutable_name(); + str->clear(); + object = str; + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + if (size) ptr = parser_till_end(ptr, newend, object, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend); + break; + } + // optional string insertion_point = 2; + case 2: { + if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual; + ptr = Varint::Parse32Inline(ptr, &size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point"); + parser_till_end = ::google::protobuf::internal::StringParserUTF8Verify; + ::std::string* str = msg->mutable_insertion_point(); + str->clear(); + object = str; + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + if (size) ptr = parser_till_end(ptr, newend, object, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend); + break; + } + // optional string content = 15; + case 15: { + if (static_cast<::google::protobuf::uint8>(tag) != 122) goto handle_unusual; + ptr = Varint::Parse32Inline(ptr, &size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorResponse.File.content"); + parser_till_end = ::google::protobuf::internal::StringParserUTF8Verify; + ::std::string* str = msg->mutable_content(); + str->clear(); + object = str; + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + if (size) ptr = parser_till_end(ptr, newend, object, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend); + break; + } + default: { + handle_unusual: (void)&&handle_unusual; + if ((tag & 7) == 4 || tag == 0) { + bool ok = ctx->ValidEndGroup(tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ok); + return ptr; + } + auto res = UnknownFieldParse(tag, {_InternalParse, msg}, + ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx); + ptr = res.first; + if (res.second) return ptr; + } + } // switch + } // while + return ptr; +len_delim_till_end: (void)&&len_delim_till_end; + return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg}, + {parser_till_end, object}, size); +group_continues: (void)&&group_continues; + GOOGLE_DCHECK(ptr >= end); + ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth); + return ptr; +} +#else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER bool CodeGeneratorResponse_File::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse.File) for (;;) { @@ -1126,8 +1404,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream( switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { + if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( @@ -1142,8 +1419,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream( // optional string insertion_point = 2; case 2: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { + if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_insertion_point())); ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( @@ -1158,8 +1434,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream( // optional string content = 15; case 15: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) { + if (static_cast< ::google::protobuf::uint8>(tag) == (122 & 0xFF)) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_content())); ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( @@ -1191,6 +1466,7 @@ failure: return false; #undef DO_ } +#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER void CodeGeneratorResponse_File::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { @@ -1294,23 +1570,28 @@ size_t CodeGeneratorResponse_File::ByteSizeLong() const { ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( _internal_metadata_.unknown_fields()); } - if (_has_bits_[0 / 32] & 7u) { + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000007u) { // optional string name = 1; - if (has_name()) { + if (cached_has_bits & 0x00000001u) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->name()); } // optional string insertion_point = 2; - if (has_insertion_point()) { + if (cached_has_bits & 0x00000002u) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->insertion_point()); } // optional string content = 15; - if (has_content()) { + if (cached_has_bits & 0x00000004u) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->content()); @@ -1326,7 +1607,7 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) GOOGLE_DCHECK_NE(&from, this); const CodeGeneratorResponse_File* source = - ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>( + ::google::protobuf::DynamicCastToGenerated<CodeGeneratorResponse_File>( &from); if (source == NULL) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse.File) @@ -1345,17 +1626,17 @@ void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& fro (void) cached_has_bits; cached_has_bits = from._has_bits_[0]; - if (cached_has_bits & 7u) { + if (cached_has_bits & 0x00000007u) { if (cached_has_bits & 0x00000001u) { - set_has_name(); + _has_bits_[0] |= 0x00000001u; name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); } if (cached_has_bits & 0x00000002u) { - set_has_insertion_point(); + _has_bits_[0] |= 0x00000002u; insertion_point_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.insertion_point_); } if (cached_has_bits & 0x00000004u) { - set_has_content(); + _has_bits_[0] |= 0x00000004u; content_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.content_); } } @@ -1385,19 +1666,19 @@ void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) { } void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) { using std::swap; + _internal_metadata_.Swap(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); name_.Swap(&other->name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); insertion_point_.Swap(&other->insertion_point_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); content_.Swap(&other->content_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); } ::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages]; + ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto); + return ::file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[kIndexInFileMessages]; } @@ -1405,6 +1686,13 @@ void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) void CodeGeneratorResponse::InitAsDefaultInstance() { } +class CodeGeneratorResponse::HasBitSetters { + public: + static void set_has_error(CodeGeneratorResponse* msg) { + msg->_has_bits_[0] |= 0x00000001u; + } +}; + #if !defined(_MSC_VER) || _MSC_VER >= 1900 const int CodeGeneratorResponse::kErrorFieldNumber; const int CodeGeneratorResponse::kFileFieldNumber; @@ -1412,8 +1700,6 @@ const int CodeGeneratorResponse::kFileFieldNumber; CodeGeneratorResponse::CodeGeneratorResponse() : ::google::protobuf::Message(), _internal_metadata_(NULL) { - ::google::protobuf::internal::InitSCC( - &protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorResponse.base); SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse) } @@ -1431,6 +1717,8 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from) } void CodeGeneratorResponse::SharedCtor() { + ::google::protobuf::internal::InitSCC( + &scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); error_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1446,13 +1734,8 @@ void CodeGeneratorResponse::SharedDtor() { void CodeGeneratorResponse::SetCachedSize(int size) const { _cached_size_.Set(size); } -const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() { - ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; -} - const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() { - ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::scc_info_CodeGeneratorResponse.base); + ::google::protobuf::internal::InitSCC(&::scc_info_CodeGeneratorResponse_google_2fprotobuf_2fcompiler_2fplugin_2eproto.base); return *internal_default_instance(); } @@ -1472,9 +1755,80 @@ void CodeGeneratorResponse::Clear() { _internal_metadata_.Clear(); } +#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +const char* CodeGeneratorResponse::_InternalParse(const char* begin, const char* end, void* object, + ::google::protobuf::internal::ParseContext* ctx) { + auto msg = static_cast<CodeGeneratorResponse*>(object); + ::google::protobuf::uint32 size; (void)size; + int depth; (void)depth; + ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end; + auto ptr = begin; + while (ptr < end) { + ::google::protobuf::uint32 tag; + ptr = Varint::Parse32Inline(ptr, &tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + switch (tag >> 3) { + // optional string error = 1; + case 1: { + if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual; + ptr = Varint::Parse32Inline(ptr, &size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + ctx->extra_parse_data().SetFieldName("google.protobuf.compiler.CodeGeneratorResponse.error"); + parser_till_end = ::google::protobuf::internal::StringParserUTF8Verify; + ::std::string* str = msg->mutable_error(); + str->clear(); + object = str; + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + if (size) ptr = parser_till_end(ptr, newend, object, ctx); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr == newend); + break; + } + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + case 15: { + if (static_cast<::google::protobuf::uint8>(tag) != 122) goto handle_unusual; + do { + ptr = Varint::Parse32Inline(ptr, &size); + GOOGLE_PROTOBUF_PARSER_ASSERT(ptr); + parser_till_end = ::google::protobuf::compiler::CodeGeneratorResponse_File::_InternalParse; + object = msg->add_file(); + if (size > end - ptr) goto len_delim_till_end; + auto newend = ptr + size; + bool ok = ctx->ParseExactRange({parser_till_end, object}, + ptr, newend); + GOOGLE_PROTOBUF_PARSER_ASSERT(ok); + ptr = newend; + if (ptr >= end) break; + } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 122 && (ptr += 1)); + break; + } + default: { + handle_unusual: (void)&&handle_unusual; + if ((tag & 7) == 4 || tag == 0) { + bool ok = ctx->ValidEndGroup(tag); + GOOGLE_PROTOBUF_PARSER_ASSERT(ok); + return ptr; + } + auto res = UnknownFieldParse(tag, {_InternalParse, msg}, + ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx); + ptr = res.first; + if (res.second) return ptr; + } + } // switch + } // while + return ptr; +len_delim_till_end: (void)&&len_delim_till_end; + return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg}, + {parser_till_end, object}, size); +group_continues: (void)&&group_continues; + GOOGLE_DCHECK(ptr >= end); + ctx->StoreGroup({_InternalParse, msg}, {parser_till_end, object}, depth); + return ptr; +} +#else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER bool CodeGeneratorResponse::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure +#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse) for (;;) { @@ -1484,8 +1838,7 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream( switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string error = 1; case 1: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { + if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_error())); ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( @@ -1500,8 +1853,7 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream( // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; case 15: { - if (static_cast< ::google::protobuf::uint8>(tag) == - static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) { + if (static_cast< ::google::protobuf::uint8>(tag) == (122 & 0xFF)) { DO_(::google::protobuf::internal::WireFormatLite::ReadMessage( input, add_file())); } else { @@ -1529,6 +1881,7 @@ failure: return false; #undef DO_ } +#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER void CodeGeneratorResponse::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { @@ -1607,6 +1960,10 @@ size_t CodeGeneratorResponse::ByteSizeLong() const { ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( _internal_metadata_.unknown_fields()); } + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; { unsigned int count = static_cast<unsigned int>(this->file_size()); @@ -1619,7 +1976,8 @@ size_t CodeGeneratorResponse::ByteSizeLong() const { } // optional string error = 1; - if (has_error()) { + cached_has_bits = _has_bits_[0]; + if (cached_has_bits & 0x00000001u) { total_size += 1 + ::google::protobuf::internal::WireFormatLite::StringSize( this->error()); @@ -1634,7 +1992,7 @@ void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse) GOOGLE_DCHECK_NE(&from, this); const CodeGeneratorResponse* source = - ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>( + ::google::protobuf::DynamicCastToGenerated<CodeGeneratorResponse>( &from); if (source == NULL) { // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.CodeGeneratorResponse) @@ -1654,7 +2012,7 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) { file_.MergeFrom(from.file_); if (from.has_error()) { - set_has_error(); + _has_bits_[0] |= 0x00000001u; error_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.error_); } } @@ -1683,16 +2041,16 @@ void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) { } void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { using std::swap; + _internal_metadata_.Swap(&other->_internal_metadata_); + swap(_has_bits_[0], other->_has_bits_[0]); CastToBase(&file_)->InternalSwap(CastToBase(&other->file_)); error_.Swap(&other->error_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); - swap(_has_bits_[0], other->_has_bits_[0]); - _internal_metadata_.Swap(&other->_internal_metadata_); } ::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const { - protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::protobuf_AssignDescriptorsOnce(); - return ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::file_level_metadata[kIndexInFileMessages]; + ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto); + return ::file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[kIndexInFileMessages]; } @@ -1702,19 +2060,20 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { } // namespace google namespace google { namespace protobuf { -template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::Version* Arena::CreateMaybeMessage< ::google::protobuf::compiler::Version >(Arena* arena) { +template<> PROTOBUF_NOINLINE ::google::protobuf::compiler::Version* Arena::CreateMaybeMessage< ::google::protobuf::compiler::Version >(Arena* arena) { return Arena::CreateInternal< ::google::protobuf::compiler::Version >(arena); } -template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage< ::google::protobuf::compiler::CodeGeneratorRequest >(Arena* arena) { +template<> PROTOBUF_NOINLINE ::google::protobuf::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage< ::google::protobuf::compiler::CodeGeneratorRequest >(Arena* arena) { return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorRequest >(arena); } -template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage< ::google::protobuf::compiler::CodeGeneratorResponse_File >(Arena* arena) { +template<> PROTOBUF_NOINLINE ::google::protobuf::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage< ::google::protobuf::compiler::CodeGeneratorResponse_File >(Arena* arena) { return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorResponse_File >(arena); } -template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage< ::google::protobuf::compiler::CodeGeneratorResponse >(Arena* arena) { +template<> PROTOBUF_NOINLINE ::google::protobuf::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage< ::google::protobuf::compiler::CodeGeneratorResponse >(Arena* arena) { return Arena::CreateInternal< ::google::protobuf::compiler::CodeGeneratorResponse >(arena); } } // namespace protobuf } // namespace google // @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index d5b70a88..187587ca 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -4,21 +4,22 @@ #ifndef PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto #define PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto +#include <limits> #include <string> -#include <google/protobuf/stubs/common.h> - -#if GOOGLE_PROTOBUF_VERSION < 3006000 +#include <google/protobuf/port_def.inc> +#if PROTOBUF_VERSION < 3006001 #error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update +#error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif -#if 3006000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#if 3006001 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is -#error incompatible with your Protocol Buffer headers. Please +#error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif +#include <google/protobuf/port_undef.inc> #include <google/protobuf/io/coded_stream.h> #include <google/protobuf/arena.h> #include <google/protobuf/arenastring.h> @@ -32,7 +33,8 @@ #include <google/protobuf/unknown_field_set.h> #include <google/protobuf/descriptor.pb.h> // @@protoc_insertion_point(includes) -#define PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto LIBPROTOC_EXPORT +#include <google/protobuf/port_def.inc> +#define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto PROTOC_EXPORT #ifdef major #undef major #endif @@ -40,42 +42,39 @@ #undef minor #endif -namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto { // Internal implementation detail -- do not use these members. -struct LIBPROTOC_EXPORT TableStruct { - static const ::google::protobuf::internal::ParseTableField entries[]; - static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; - static const ::google::protobuf::internal::ParseTable schema[4]; +struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto { + static const ::google::protobuf::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::google::protobuf::internal::AuxillaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::google::protobuf::internal::ParseTable schema[4] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); static const ::google::protobuf::internal::FieldMetadata field_metadata[]; static const ::google::protobuf::internal::SerializationTable serialization_table[]; static const ::google::protobuf::uint32 offsets[]; }; -void LIBPROTOC_EXPORT AddDescriptors(); -} // namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto +void PROTOC_EXPORT AddDescriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); namespace google { namespace protobuf { namespace compiler { class CodeGeneratorRequest; class CodeGeneratorRequestDefaultTypeInternal; -LIBPROTOC_EXPORT extern CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_; +PROTOC_EXPORT extern CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_; class CodeGeneratorResponse; class CodeGeneratorResponseDefaultTypeInternal; -LIBPROTOC_EXPORT extern CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_; +PROTOC_EXPORT extern CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_; class CodeGeneratorResponse_File; class CodeGeneratorResponse_FileDefaultTypeInternal; -LIBPROTOC_EXPORT extern CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_; +PROTOC_EXPORT extern CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_; class Version; class VersionDefaultTypeInternal; -LIBPROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_; +PROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_; } // namespace compiler -} // namespace protobuf -} // namespace google -namespace google { -namespace protobuf { -template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage<::google::protobuf::compiler::CodeGeneratorRequest>(Arena*); -template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage<::google::protobuf::compiler::CodeGeneratorResponse>(Arena*); -template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage<::google::protobuf::compiler::CodeGeneratorResponse_File>(Arena*); -template<> LIBPROTOC_EXPORT ::google::protobuf::compiler::Version* Arena::CreateMaybeMessage<::google::protobuf::compiler::Version>(Arena*); +template<> PROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage<::google::protobuf::compiler::CodeGeneratorRequest>(Arena*); +template<> PROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage<::google::protobuf::compiler::CodeGeneratorResponse>(Arena*); +template<> PROTOC_EXPORT ::google::protobuf::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage<::google::protobuf::compiler::CodeGeneratorResponse_File>(Arena*); +template<> PROTOC_EXPORT ::google::protobuf::compiler::Version* Arena::CreateMaybeMessage<::google::protobuf::compiler::Version>(Arena*); } // namespace protobuf } // namespace google namespace google { @@ -84,7 +83,7 @@ namespace compiler { // =================================================================== -class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ { +class PROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ { public: Version(); virtual ~Version(); @@ -117,7 +116,9 @@ class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_ return _internal_metadata_.mutable_unknown_fields(); } - static const ::google::protobuf::Descriptor* descriptor(); + static const ::google::protobuf::Descriptor* descriptor() { + return default_instance().GetDescriptor(); + } static const Version& default_instance(); static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY @@ -150,8 +151,13 @@ class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_ bool IsInitialized() const final; size_t ByteSizeLong() const final; + #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx); + ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; } + #else bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) final; + #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER void SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const final; ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( @@ -216,14 +222,7 @@ class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_ // @@protoc_insertion_point(class_scope:google.protobuf.compiler.Version) private: - void set_has_major(); - void clear_has_major(); - void set_has_minor(); - void clear_has_minor(); - void set_has_patch(); - void clear_has_patch(); - void set_has_suffix(); - void clear_has_suffix(); + class HasBitSetters; ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::internal::HasBits<1> _has_bits_; @@ -232,11 +231,11 @@ class LIBPROTOC_EXPORT Version : public ::google::protobuf::Message /* @@protoc_ ::google::protobuf::int32 major_; ::google::protobuf::int32 minor_; ::google::protobuf::int32 patch_; - friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ { +class PROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ { public: CodeGeneratorRequest(); virtual ~CodeGeneratorRequest(); @@ -269,7 +268,9 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message return _internal_metadata_.mutable_unknown_fields(); } - static const ::google::protobuf::Descriptor* descriptor(); + static const ::google::protobuf::Descriptor* descriptor() { + return default_instance().GetDescriptor(); + } static const CodeGeneratorRequest& default_instance(); static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY @@ -302,8 +303,13 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message bool IsInitialized() const final; size_t ByteSizeLong() const final; + #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx); + ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; } + #else bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) final; + #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER void SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const final; ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( @@ -349,8 +355,8 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message #endif void add_file_to_generate(const char* value); void add_file_to_generate(const char* value, size_t size); - const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const; - ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate(); + const ::google::protobuf::RepeatedPtrField<::std::string>& file_to_generate() const; + ::google::protobuf::RepeatedPtrField<::std::string>* mutable_file_to_generate(); // repeated .google.protobuf.FileDescriptorProto proto_file = 15; int proto_file_size() const; @@ -383,9 +389,6 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message bool has_compiler_version() const; void clear_compiler_version(); static const int kCompilerVersionFieldNumber = 3; - private: - const ::google::protobuf::compiler::Version& _internal_compiler_version() const; - public: const ::google::protobuf::compiler::Version& compiler_version() const; ::google::protobuf::compiler::Version* release_compiler_version(); ::google::protobuf::compiler::Version* mutable_compiler_version(); @@ -393,23 +396,20 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) private: - void set_has_parameter(); - void clear_has_parameter(); - void set_has_compiler_version(); - void clear_has_compiler_version(); + class HasBitSetters; ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::internal::HasBits<1> _has_bits_; mutable ::google::protobuf::internal::CachedSize _cached_size_; - ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_; + ::google::protobuf::RepeatedPtrField<::std::string> file_to_generate_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_; ::google::protobuf::internal::ArenaStringPtr parameter_; ::google::protobuf::compiler::Version* compiler_version_; - friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ { +class PROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ { public: CodeGeneratorResponse_File(); virtual ~CodeGeneratorResponse_File(); @@ -442,7 +442,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M return _internal_metadata_.mutable_unknown_fields(); } - static const ::google::protobuf::Descriptor* descriptor(); + static const ::google::protobuf::Descriptor* descriptor() { + return default_instance().GetDescriptor(); + } static const CodeGeneratorResponse_File& default_instance(); static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY @@ -475,8 +477,13 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M bool IsInitialized() const final; size_t ByteSizeLong() const final; + #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx); + ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; } + #else bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) final; + #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER void SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const final; ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( @@ -550,12 +557,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) private: - void set_has_name(); - void clear_has_name(); - void set_has_insertion_point(); - void clear_has_insertion_point(); - void set_has_content(); - void clear_has_content(); + class HasBitSetters; ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::internal::HasBits<1> _has_bits_; @@ -563,11 +565,11 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M ::google::protobuf::internal::ArenaStringPtr name_; ::google::protobuf::internal::ArenaStringPtr insertion_point_; ::google::protobuf::internal::ArenaStringPtr content_; - friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; // ------------------------------------------------------------------- -class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ { +class PROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ { public: CodeGeneratorResponse(); virtual ~CodeGeneratorResponse(); @@ -600,7 +602,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag return _internal_metadata_.mutable_unknown_fields(); } - static const ::google::protobuf::Descriptor* descriptor(); + static const ::google::protobuf::Descriptor* descriptor() { + return default_instance().GetDescriptor(); + } static const CodeGeneratorResponse& default_instance(); static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY @@ -633,8 +637,13 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag bool IsInitialized() const final; size_t ByteSizeLong() const final; + #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx); + ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; } + #else bool MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) final; + #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER void SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const final; ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( @@ -692,15 +701,14 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) private: - void set_has_error(); - void clear_has_error(); + class HasBitSetters; ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; ::google::protobuf::internal::HasBits<1> _has_bits_; mutable ::google::protobuf::internal::CachedSize _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_; ::google::protobuf::internal::ArenaStringPtr error_; - friend struct ::protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto::TableStruct; + friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; // =================================================================== @@ -717,22 +725,16 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag inline bool Version::has_major() const { return (_has_bits_[0] & 0x00000002u) != 0; } -inline void Version::set_has_major() { - _has_bits_[0] |= 0x00000002u; -} -inline void Version::clear_has_major() { - _has_bits_[0] &= ~0x00000002u; -} inline void Version::clear_major() { major_ = 0; - clear_has_major(); + _has_bits_[0] &= ~0x00000002u; } inline ::google::protobuf::int32 Version::major() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.major) return major_; } inline void Version::set_major(::google::protobuf::int32 value) { - set_has_major(); + _has_bits_[0] |= 0x00000002u; major_ = value; // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.major) } @@ -741,22 +743,16 @@ inline void Version::set_major(::google::protobuf::int32 value) { inline bool Version::has_minor() const { return (_has_bits_[0] & 0x00000004u) != 0; } -inline void Version::set_has_minor() { - _has_bits_[0] |= 0x00000004u; -} -inline void Version::clear_has_minor() { - _has_bits_[0] &= ~0x00000004u; -} inline void Version::clear_minor() { minor_ = 0; - clear_has_minor(); + _has_bits_[0] &= ~0x00000004u; } inline ::google::protobuf::int32 Version::minor() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.minor) return minor_; } inline void Version::set_minor(::google::protobuf::int32 value) { - set_has_minor(); + _has_bits_[0] |= 0x00000004u; minor_ = value; // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.minor) } @@ -765,22 +761,16 @@ inline void Version::set_minor(::google::protobuf::int32 value) { inline bool Version::has_patch() const { return (_has_bits_[0] & 0x00000008u) != 0; } -inline void Version::set_has_patch() { - _has_bits_[0] |= 0x00000008u; -} -inline void Version::clear_has_patch() { - _has_bits_[0] &= ~0x00000008u; -} inline void Version::clear_patch() { patch_ = 0; - clear_has_patch(); + _has_bits_[0] &= ~0x00000008u; } inline ::google::protobuf::int32 Version::patch() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.patch) return patch_; } inline void Version::set_patch(::google::protobuf::int32 value) { - set_has_patch(); + _has_bits_[0] |= 0x00000008u; patch_ = value; // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.patch) } @@ -789,28 +779,22 @@ inline void Version::set_patch(::google::protobuf::int32 value) { inline bool Version::has_suffix() const { return (_has_bits_[0] & 0x00000001u) != 0; } -inline void Version::set_has_suffix() { - _has_bits_[0] |= 0x00000001u; -} -inline void Version::clear_has_suffix() { - _has_bits_[0] &= ~0x00000001u; -} inline void Version::clear_suffix() { suffix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_suffix(); + _has_bits_[0] &= ~0x00000001u; } inline const ::std::string& Version::suffix() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.suffix) return suffix_.GetNoArena(); } inline void Version::set_suffix(const ::std::string& value) { - set_has_suffix(); + _has_bits_[0] |= 0x00000001u; suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.suffix) } #if LANG_CXX11 inline void Version::set_suffix(::std::string&& value) { - set_has_suffix(); + _has_bits_[0] |= 0x00000001u; suffix_.SetNoArena( &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.Version.suffix) @@ -818,18 +802,18 @@ inline void Version::set_suffix(::std::string&& value) { #endif inline void Version::set_suffix(const char* value) { GOOGLE_DCHECK(value != NULL); - set_has_suffix(); + _has_bits_[0] |= 0x00000001u; suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.Version.suffix) } inline void Version::set_suffix(const char* value, size_t size) { - set_has_suffix(); + _has_bits_[0] |= 0x00000001u; suffix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(reinterpret_cast<const char*>(value), size)); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.Version.suffix) } inline ::std::string* Version::mutable_suffix() { - set_has_suffix(); + _has_bits_[0] |= 0x00000001u; // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.Version.suffix) return suffix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -838,14 +822,14 @@ inline ::std::string* Version::release_suffix() { if (!has_suffix()) { return NULL; } - clear_has_suffix(); + _has_bits_[0] &= ~0x00000001u; return suffix_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline void Version::set_allocated_suffix(::std::string* suffix) { if (suffix != NULL) { - set_has_suffix(); + _has_bits_[0] |= 0x00000001u; } else { - clear_has_suffix(); + _has_bits_[0] &= ~0x00000001u; } suffix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), suffix); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.Version.suffix) @@ -913,12 +897,12 @@ inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size); // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } -inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +inline const ::google::protobuf::RepeatedPtrField<::std::string>& CodeGeneratorRequest::file_to_generate() const { // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_; } -inline ::google::protobuf::RepeatedPtrField< ::std::string>* +inline ::google::protobuf::RepeatedPtrField<::std::string>* CodeGeneratorRequest::mutable_file_to_generate() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return &file_to_generate_; @@ -928,28 +912,22 @@ CodeGeneratorRequest::mutable_file_to_generate() { inline bool CodeGeneratorRequest::has_parameter() const { return (_has_bits_[0] & 0x00000001u) != 0; } -inline void CodeGeneratorRequest::set_has_parameter() { - _has_bits_[0] |= 0x00000001u; -} -inline void CodeGeneratorRequest::clear_has_parameter() { - _has_bits_[0] &= ~0x00000001u; -} inline void CodeGeneratorRequest::clear_parameter() { parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_parameter(); + _has_bits_[0] &= ~0x00000001u; } inline const ::std::string& CodeGeneratorRequest::parameter() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter) return parameter_.GetNoArena(); } inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) { - set_has_parameter(); + _has_bits_[0] |= 0x00000001u; parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter) } #if LANG_CXX11 inline void CodeGeneratorRequest::set_parameter(::std::string&& value) { - set_has_parameter(); + _has_bits_[0] |= 0x00000001u; parameter_.SetNoArena( &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorRequest.parameter) @@ -957,18 +935,18 @@ inline void CodeGeneratorRequest::set_parameter(::std::string&& value) { #endif inline void CodeGeneratorRequest::set_parameter(const char* value) { GOOGLE_DCHECK(value != NULL); - set_has_parameter(); + _has_bits_[0] |= 0x00000001u; parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { - set_has_parameter(); + _has_bits_[0] |= 0x00000001u; parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(reinterpret_cast<const char*>(value), size)); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline ::std::string* CodeGeneratorRequest::mutable_parameter() { - set_has_parameter(); + _has_bits_[0] |= 0x00000001u; // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter) return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -977,14 +955,14 @@ inline ::std::string* CodeGeneratorRequest::release_parameter() { if (!has_parameter()) { return NULL; } - clear_has_parameter(); + _has_bits_[0] &= ~0x00000001u; return parameter_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) { if (parameter != NULL) { - set_has_parameter(); + _has_bits_[0] |= 0x00000001u; } else { - clear_has_parameter(); + _has_bits_[0] &= ~0x00000001u; } parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter) @@ -1021,18 +999,9 @@ CodeGeneratorRequest::proto_file() const { inline bool CodeGeneratorRequest::has_compiler_version() const { return (_has_bits_[0] & 0x00000002u) != 0; } -inline void CodeGeneratorRequest::set_has_compiler_version() { - _has_bits_[0] |= 0x00000002u; -} -inline void CodeGeneratorRequest::clear_has_compiler_version() { - _has_bits_[0] &= ~0x00000002u; -} inline void CodeGeneratorRequest::clear_compiler_version() { if (compiler_version_ != NULL) compiler_version_->Clear(); - clear_has_compiler_version(); -} -inline const ::google::protobuf::compiler::Version& CodeGeneratorRequest::_internal_compiler_version() const { - return *compiler_version_; + _has_bits_[0] &= ~0x00000002u; } inline const ::google::protobuf::compiler::Version& CodeGeneratorRequest::compiler_version() const { const ::google::protobuf::compiler::Version* p = compiler_version_; @@ -1042,13 +1011,13 @@ inline const ::google::protobuf::compiler::Version& CodeGeneratorRequest::compil } inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::release_compiler_version() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) - clear_has_compiler_version(); + _has_bits_[0] &= ~0x00000002u; ::google::protobuf::compiler::Version* temp = compiler_version_; compiler_version_ = NULL; return temp; } inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() { - set_has_compiler_version(); + _has_bits_[0] |= 0x00000002u; if (compiler_version_ == NULL) { auto* p = CreateMaybeMessage<::google::protobuf::compiler::Version>(GetArenaNoVirtual()); compiler_version_ = p; @@ -1067,9 +1036,9 @@ inline void CodeGeneratorRequest::set_allocated_compiler_version(::google::proto compiler_version = ::google::protobuf::internal::GetOwnedMessage( message_arena, compiler_version, submessage_arena); } - set_has_compiler_version(); + _has_bits_[0] |= 0x00000002u; } else { - clear_has_compiler_version(); + _has_bits_[0] &= ~0x00000002u; } compiler_version_ = compiler_version; // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.compiler_version) @@ -1083,28 +1052,22 @@ inline void CodeGeneratorRequest::set_allocated_compiler_version(::google::proto inline bool CodeGeneratorResponse_File::has_name() const { 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() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; } inline const ::std::string& CodeGeneratorResponse_File::name() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name) return name_.GetNoArena(); } inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) { - set_has_name(); + _has_bits_[0] |= 0x00000001u; name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name) } #if LANG_CXX11 inline void CodeGeneratorResponse_File::set_name(::std::string&& value) { - set_has_name(); + _has_bits_[0] |= 0x00000001u; name_.SetNoArena( &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.name) @@ -1112,18 +1075,18 @@ inline void CodeGeneratorResponse_File::set_name(::std::string&& value) { #endif inline void CodeGeneratorResponse_File::set_name(const char* value) { GOOGLE_DCHECK(value != NULL); - set_has_name(); + _has_bits_[0] |= 0x00000001u; name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { - set_has_name(); + _has_bits_[0] |= 0x00000001u; name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(reinterpret_cast<const char*>(value), size)); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline ::std::string* CodeGeneratorResponse_File::mutable_name() { - set_has_name(); + _has_bits_[0] |= 0x00000001u; // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name) return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1132,14 +1095,14 @@ inline ::std::string* CodeGeneratorResponse_File::release_name() { if (!has_name()) { return NULL; } - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; return name_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) { if (name != NULL) { - set_has_name(); + _has_bits_[0] |= 0x00000001u; } else { - clear_has_name(); + _has_bits_[0] &= ~0x00000001u; } name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name) @@ -1149,28 +1112,22 @@ inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) inline bool CodeGeneratorResponse_File::has_insertion_point() const { 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() { insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_insertion_point(); + _has_bits_[0] &= ~0x00000002u; } inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) return insertion_point_.GetNoArena(); } inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) { - set_has_insertion_point(); + _has_bits_[0] |= 0x00000002u; insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } #if LANG_CXX11 inline void CodeGeneratorResponse_File::set_insertion_point(::std::string&& value) { - set_has_insertion_point(); + _has_bits_[0] |= 0x00000002u; insertion_point_.SetNoArena( &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) @@ -1178,18 +1135,18 @@ inline void CodeGeneratorResponse_File::set_insertion_point(::std::string&& valu #endif inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) { GOOGLE_DCHECK(value != NULL); - set_has_insertion_point(); + _has_bits_[0] |= 0x00000002u; insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { - set_has_insertion_point(); + _has_bits_[0] |= 0x00000002u; insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(reinterpret_cast<const char*>(value), size)); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { - set_has_insertion_point(); + _has_bits_[0] |= 0x00000002u; // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1198,14 +1155,14 @@ inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() { if (!has_insertion_point()) { return NULL; } - clear_has_insertion_point(); + _has_bits_[0] &= ~0x00000002u; return insertion_point_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) { if (insertion_point != NULL) { - set_has_insertion_point(); + _has_bits_[0] |= 0x00000002u; } else { - clear_has_insertion_point(); + _has_bits_[0] &= ~0x00000002u; } insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) @@ -1215,28 +1172,22 @@ inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::str inline bool CodeGeneratorResponse_File::has_content() const { 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() { content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_content(); + _has_bits_[0] &= ~0x00000004u; } inline const ::std::string& CodeGeneratorResponse_File::content() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content) return content_.GetNoArena(); } inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) { - set_has_content(); + _has_bits_[0] |= 0x00000004u; content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content) } #if LANG_CXX11 inline void CodeGeneratorResponse_File::set_content(::std::string&& value) { - set_has_content(); + _has_bits_[0] |= 0x00000004u; content_.SetNoArena( &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.content) @@ -1244,18 +1195,18 @@ inline void CodeGeneratorResponse_File::set_content(::std::string&& value) { #endif inline void CodeGeneratorResponse_File::set_content(const char* value) { GOOGLE_DCHECK(value != NULL); - set_has_content(); + _has_bits_[0] |= 0x00000004u; content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { - set_has_content(); + _has_bits_[0] |= 0x00000004u; content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(reinterpret_cast<const char*>(value), size)); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline ::std::string* CodeGeneratorResponse_File::mutable_content() { - set_has_content(); + _has_bits_[0] |= 0x00000004u; // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content) return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1264,14 +1215,14 @@ inline ::std::string* CodeGeneratorResponse_File::release_content() { if (!has_content()) { return NULL; } - clear_has_content(); + _has_bits_[0] &= ~0x00000004u; return content_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) { if (content != NULL) { - set_has_content(); + _has_bits_[0] |= 0x00000004u; } else { - clear_has_content(); + _has_bits_[0] &= ~0x00000004u; } content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) @@ -1285,28 +1236,22 @@ inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* con inline bool CodeGeneratorResponse::has_error() const { 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() { error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_error(); + _has_bits_[0] &= ~0x00000001u; } inline const ::std::string& CodeGeneratorResponse::error() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error) return error_.GetNoArena(); } inline void CodeGeneratorResponse::set_error(const ::std::string& value) { - set_has_error(); + _has_bits_[0] |= 0x00000001u; error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error) } #if LANG_CXX11 inline void CodeGeneratorResponse::set_error(::std::string&& value) { - set_has_error(); + _has_bits_[0] |= 0x00000001u; error_.SetNoArena( &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.error) @@ -1314,18 +1259,18 @@ inline void CodeGeneratorResponse::set_error(::std::string&& value) { #endif inline void CodeGeneratorResponse::set_error(const char* value) { GOOGLE_DCHECK(value != NULL); - set_has_error(); + _has_bits_[0] |= 0x00000001u; error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error) } inline void CodeGeneratorResponse::set_error(const char* value, size_t size) { - set_has_error(); + _has_bits_[0] |= 0x00000001u; error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(reinterpret_cast<const char*>(value), size)); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error) } inline ::std::string* CodeGeneratorResponse::mutable_error() { - set_has_error(); + _has_bits_[0] |= 0x00000001u; // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error) return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } @@ -1334,14 +1279,14 @@ inline ::std::string* CodeGeneratorResponse::release_error() { if (!has_error()) { return NULL; } - clear_has_error(); + _has_bits_[0] &= ~0x00000001u; return error_.ReleaseNonDefaultNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) { if (error != NULL) { - set_has_error(); + _has_bits_[0] |= 0x00000001u; } else { - clear_has_error(); + _has_bits_[0] &= ~0x00000001u; } error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error); // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error) @@ -1395,4 +1340,5 @@ CodeGeneratorResponse::file() const { // @@protoc_insertion_point(global_scope) +#include <google/protobuf/port_undef.inc> #endif // PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index 01f28b37..6dc61ec1 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -45,7 +45,6 @@ // directly. #include <algorithm> -#include <google/protobuf/stubs/hash.h> #include <limits> #include <map> #include <memory> @@ -73,11 +72,6 @@ namespace python { namespace { -// Reimplemented here because we can't bring in -// absl/strings/string_view_utils.h because it needs C++11. -bool StrStartsWith(StringPiece sp, StringPiece x) { - return sp.size() >= x.size() && sp.substr(0, x.size()) == x; -} bool StrEndsWith(StringPiece sp, StringPiece x) { return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x; } @@ -103,7 +97,7 @@ string ModuleName(const string& filename) { // Returns the alias we assign to the module of the given .proto filename // when importing. See testPackageInitializationImport in -// google/protobuf/python/reflection_test.py +// net/proto2/python/internal/reflection_test.py // to see why we need the alias. string ModuleAlias(const string& filename) { string module_name = ModuleName(filename); @@ -424,7 +418,7 @@ void Generator::PrintFileDescriptor() const { printer_->Print(m, file_descriptor_template); printer_->Indent(); printer_->Print( -//##!PY25 "serialized_pb=b'$value$'\n", + //##!PY25 "serialized_pb=b'$value$'\n", "serialized_pb=_b('$value$')\n", //##PY25 "value", strings::CHexEscape(file_descriptor_serialized_)); if (file_->dependency_count() != 0) { @@ -476,9 +470,9 @@ void Generator::PrintTopLevelEnums() const { } for (int i = 0; i < top_level_enum_values.size(); ++i) { - printer_->Print("$name$ = $value$\n", - "name", top_level_enum_values[i].first, - "value", SimpleItoa(top_level_enum_values[i].second)); + printer_->Print("$name$ = $value$\n", "name", + top_level_enum_values[i].first, "value", + SimpleItoa(top_level_enum_values[i].second)); } printer_->Print("\n"); } @@ -550,9 +544,9 @@ void Generator::PrintTopLevelExtensions() const { const FieldDescriptor& extension_field = *file_->extension(i); string constant_name = extension_field.name() + "_FIELD_NUMBER"; UpperString(&constant_name); - printer_->Print("$constant_name$ = $number$\n", - "constant_name", constant_name, - "number", SimpleItoa(extension_field.number())); + printer_->Print("$constant_name$ = $number$\n", "constant_name", + constant_name, "number", + SimpleItoa(extension_field.number())); printer_->Print("$name$ = ", "name", extension_field.name()); PrintFieldDescriptor(extension_field, is_extension); printer_->Print("\n"); @@ -745,9 +739,9 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { for (int i = 0; i < message_descriptor.extension_range_count(); ++i) { const Descriptor::ExtensionRange* range = message_descriptor.extension_range(i); - printer_->Print("($start$, $end$), ", - "start", SimpleItoa(range->start), - "end", SimpleItoa(range->end)); + printer_->Print("($start$, $end$), ", "start", + SimpleItoa(range->start), "end", + SimpleItoa(range->end)); } printer_->Print("],\n"); printer_->Print("oneofs=[\n"); @@ -1184,7 +1178,8 @@ void Generator::PrintExtensionsInDescriptor( } bool Generator::GeneratingDescriptorProto() const { - return file_->name() == "google/protobuf/descriptor.proto"; + return file_->name() == "net/proto2/proto/descriptor.proto" || + file_->name() == "google/protobuf/descriptor.proto"; } // Returns the unique Python module-level identifier given to a descriptor. @@ -1260,10 +1255,11 @@ void Generator::PrintSerializedPbInterval( int offset = file_descriptor_serialized_.find(sp); GOOGLE_CHECK_GE(offset, 0); - printer_->Print("serialized_start=$serialized_start$,\n" - "serialized_end=$serialized_end$,\n", - "serialized_start", SimpleItoa(offset), - "serialized_end", SimpleItoa(offset + sp.size())); + printer_->Print( + "serialized_start=$serialized_start$,\n" + "serialized_end=$serialized_end$,\n", + "serialized_start", SimpleItoa(offset), "serialized_end", + SimpleItoa(offset + sp.size())); } namespace { diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h index 8e4050de..c21c36da 100644 --- a/src/google/protobuf/compiler/python/python_generator.h +++ b/src/google/protobuf/compiler/python/python_generator.h @@ -38,8 +38,8 @@ #include <string> #include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/stubs/mutex.h> -#include <google/protobuf/stubs/common.h> + +#include <google/protobuf/port_def.inc> namespace google { namespace protobuf { @@ -60,16 +60,16 @@ namespace python { // If you create your own protocol compiler binary and you want it to support // Python output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT Generator : public CodeGenerator { +class PROTOC_EXPORT Generator : public CodeGenerator { public: Generator(); virtual ~Generator(); // CodeGenerator methods. virtual bool Generate(const FileDescriptor* file, - const string& parameter, + const std::string& parameter, GeneratorContext* generator_context, - string* error) const; + std::string* error) const; private: void PrintImports() const; @@ -86,7 +86,7 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintFieldDescriptorsInDescriptor( const Descriptor& message_descriptor, bool is_extension, - const string& list_variable_name, + const std::string& list_variable_name, int (Descriptor::*CountFn)() const, const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const; void PrintFieldsInDescriptor(const Descriptor& message_descriptor) const; @@ -96,11 +96,11 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintNestedDescriptors(const Descriptor& containing_descriptor) const; void PrintMessages() const; - void PrintMessage(const Descriptor& message_descriptor, const string& prefix, - std::vector<string>* to_register) const; + void PrintMessage(const Descriptor& message_descriptor, const std::string& prefix, + std::vector<std::string>* to_register) const; void PrintNestedMessages(const Descriptor& containing_descriptor, - const string& prefix, - std::vector<string>* to_register) const; + const std::string& prefix, + std::vector<std::string>* to_register) const; void FixForeignFieldsInDescriptors() const; void FixForeignFieldsInDescriptor( @@ -108,14 +108,14 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { const Descriptor* containing_descriptor) const; void FixForeignFieldsInField(const Descriptor* containing_type, const FieldDescriptor& field, - const string& python_dict_name) const; + const std::string& python_dict_name) const; void AddMessageToFileDescriptor(const Descriptor& descriptor) const; void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const; void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const; void AddServiceToFileDescriptor(const ServiceDescriptor& descriptor) const; - string FieldReferencingExpression(const Descriptor* containing_type, + std::string FieldReferencingExpression(const Descriptor* containing_type, const FieldDescriptor& field, - const string& python_dict_name) const; + const std::string& python_dict_name) const; template <typename DescriptorT> void FixContainingTypeInDescriptor( const DescriptorT& descriptor, @@ -135,13 +135,13 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { const ServiceDescriptor& descriptor) const; void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const; - string OptionsValue(const string& serialized_options) const; + std::string OptionsValue(const std::string& serialized_options) const; bool GeneratingDescriptorProto() const; template <typename DescriptorT> - string ModuleLevelDescriptorName(const DescriptorT& descriptor) const; - string ModuleLevelMessageName(const Descriptor& descriptor) const; - string ModuleLevelServiceDescriptorName( + std::string ModuleLevelDescriptorName(const DescriptorT& descriptor) const; + std::string ModuleLevelMessageName(const Descriptor& descriptor) const; + std::string ModuleLevelServiceDescriptorName( const ServiceDescriptor& descriptor) const; template <typename DescriptorT, typename DescriptorProtoT> @@ -155,13 +155,13 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void FixOptionsForMessage(const Descriptor& descriptor) const; void CopyPublicDependenciesAliases( - const string& copy_from, const FileDescriptor* file) const; + const std::string& copy_from, const FileDescriptor* file) const; // Very coarse-grained lock to ensure that Generate() is reentrant. // Guards file_, printer_ and file_descriptor_serialized_. mutable Mutex mutex_; mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_. - mutable string file_descriptor_serialized_; + mutable std::string file_descriptor_serialized_; mutable io::Printer* printer_; // Set in Generate(). Under mutex_. GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator); @@ -170,6 +170,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { } // namespace python } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc index 2f096808..d19d11f0 100644 --- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc +++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc @@ -90,7 +90,7 @@ TEST(PythonPluginTest, PluginTest) { "}\n", true)); - google::protobuf::compiler::CommandLineInterface cli; + compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); python::Generator python_generator; @@ -133,7 +133,7 @@ TEST(PythonPluginTest, ImportTest) { "message Message2 {}\n", true)); - google::protobuf::compiler::CommandLineInterface cli; + compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); python::Generator python_generator; cli.RegisterGenerator("--python_out", &python_generator, ""); diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h index 8c1dfa26..521697fb 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.h +++ b/src/google/protobuf/compiler/ruby/ruby_generator.h @@ -37,6 +37,8 @@ #include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { namespace compiler { @@ -46,7 +48,7 @@ namespace ruby { // If you create your own protocol compiler binary and you want it to support // Ruby output, you can do so by registering an instance of this // CodeGenerator with the CommandLineInterface in your main() function. -class LIBPROTOC_EXPORT Generator +class PROTOC_EXPORT Generator : public google::protobuf::compiler::CodeGenerator { virtual bool Generate( const FileDescriptor* file, @@ -60,5 +62,7 @@ class LIBPROTOC_EXPORT Generator } // namespace protobuf } // namespace google +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index 984d6b89..2e9b2e12 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -90,12 +90,12 @@ TEST(RubyGeneratorTest, Proto3GeneratorTest) { // Load the generated output and compare to the expected result. string output; - GOOGLE_CHECK_OK(File::GetContents( + GOOGLE_CHECK_OK(File::GetContentsAsText( TestTempDir() + "/ruby_generated_code_pb.rb", &output, true)); string expected_output; - GOOGLE_CHECK_OK(File::GetContents( + GOOGLE_CHECK_OK(File::GetContentsAsText( ruby_tests + "/ruby_generated_code_pb.rb", &expected_output, true)); diff --git a/src/google/protobuf/compiler/scc.cc b/src/google/protobuf/compiler/scc.cc new file mode 100644 index 00000000..bbdabbfc --- /dev/null +++ b/src/google/protobuf/compiler/scc.cc @@ -0,0 +1,111 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include <google/protobuf/compiler/scc.h> + +#include <google/protobuf/stubs/logging.h> +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/descriptor.h> + +namespace google { +namespace protobuf { +namespace compiler { + +SCCAnalyzer::NodeData SCCAnalyzer::DFS(const Descriptor* descriptor) { + // Must not have visited already. + GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0); + + // Mark visited by inserting in map. + NodeData& result = cache_[descriptor]; + // Initialize data structures. + result.index = result.lowlink = index_++; + stack_.push_back(descriptor); + + // Recurse the fields / nodes in graph + for (int i = 0; i < descriptor->field_count(); i++) { + const Descriptor* child = descriptor->field(i)->message_type(); + if (child) { + if (cache_.count(child) == 0) { + // unexplored node + NodeData child_data = DFS(child); + result.lowlink = std::min(result.lowlink, child_data.lowlink); + } else { + NodeData child_data = cache_[child]; + if (child_data.scc == nullptr) { + // Still in the stack_ so we found a back edge + result.lowlink = std::min(result.lowlink, child_data.index); + } + } + } + } + if (result.index == result.lowlink) { + // This is the root of a strongly connected component + SCC* scc = CreateSCC(); + while (true) { + const Descriptor* scc_desc = stack_.back(); + scc->descriptors.push_back(scc_desc); + // Remove from stack + stack_.pop_back(); + cache_[scc_desc].scc = scc; + + if (scc_desc == descriptor) break; + } + + // The order of descriptors is random and depends how this SCC was + // discovered. In-order to ensure maximum stability we sort it by name. + std::sort(scc->descriptors.begin(), scc->descriptors.end(), + [](const Descriptor* a, const Descriptor* b) { + return a->full_name() < b->full_name(); + }); + AddChildren(scc); + } + return result; +} + +void SCCAnalyzer::AddChildren(SCC* scc) { + std::set<const SCC*> seen; + for (int i = 0; i < scc->descriptors.size(); i++) { + const Descriptor* descriptor = scc->descriptors[i]; + for (int j = 0; j < descriptor->field_count(); j++) { + const Descriptor* child_msg = descriptor->field(j)->message_type(); + if (child_msg) { + const SCC* child = GetSCC(child_msg); + if (child == scc) continue; + if (seen.insert(child).second) { + scc->children.push_back(child); + } + } + } + } +} + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/scc.h b/src/google/protobuf/compiler/scc.h new file mode 100644 index 00000000..c8cf77d6 --- /dev/null +++ b/src/google/protobuf/compiler/scc.h @@ -0,0 +1,99 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_SCC_H__ +#define GOOGLE_PROTOBUF_COMPILER_SCC_H__ + +#include <map> + +#include <google/protobuf/descriptor.h> + +#include <google/protobuf/port_def.inc> + +namespace google { +namespace protobuf { +namespace compiler { + +// Description of each strongly connected component. Note that the order +// of both the descriptors in this SCC and the order of children is +// deterministic. +struct SCC { + std::vector<const Descriptor*> descriptors; + std::vector<const SCC*> children; + + const Descriptor* GetRepresentative() const { return descriptors[0]; } +}; + +// This class is used for analyzing the SCC for each message, to ensure linear +// instead of quadratic performance, if we do this per message we would get +// O(V*(V+E)). +class PROTOC_EXPORT SCCAnalyzer { + public: + explicit SCCAnalyzer() : index_(0) {} + + const SCC* GetSCC(const Descriptor* descriptor) { + if (cache_.count(descriptor)) return cache_[descriptor].scc; + return DFS(descriptor).scc; + } + + private: + struct NodeData { + const SCC* scc; // if null it means its still on the stack + int index; + int lowlink; + }; + + std::map<const Descriptor*, NodeData> cache_; + std::vector<const Descriptor*> stack_; + int index_; + std::vector<std::unique_ptr<SCC>> garbage_bin_; + + SCC* CreateSCC() { + garbage_bin_.emplace_back(new SCC()); + return garbage_bin_.back().get(); + } + + // Tarjan's Strongly Connected Components algo + NodeData DFS(const Descriptor* descriptor); + + // Add the SCC's that are children of this SCC to its children. + void AddChildren(SCC* scc); + + // This is necessary for compiler bug in msvc2015. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SCCAnalyzer); +}; + +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include <google/protobuf/port_undef.inc> + +#endif // GOOGLE_PROTOBUF_COMPILER_SCC_H__ diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index 2e5a89ac..5bd3d435 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -124,14 +124,15 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { << Win32ErrorMessage(GetLastError()); } - // CreateProcess() mutates its second parameter. WTF? - char* name_copy = portable_strdup(program.c_str()); + // Invoking cmd.exe allows for '.bat' files from the path as well as '.exe'. + // Using a malloc'ed string because CreateProcess() can mutate its second parameter. (WTF). + char *command_line = portable_strdup(("cmd.exe /c \"" + program + "\"").c_str()); // Create the process. PROCESS_INFORMATION process_info; if (CreateProcessA((search_mode == SEARCH_PATH) ? NULL : program.c_str(), - (search_mode == SEARCH_PATH) ? name_copy : NULL, + (search_mode == SEARCH_PATH) ? command_line : NULL, NULL, // process security attributes NULL, // thread security attributes TRUE, // inherit handles? @@ -152,7 +153,7 @@ void Subprocess::Start(const string& program, SearchMode search_mode) { CloseHandleOrDie(stdin_pipe_read); CloseHandleOrDie(stdout_pipe_write); - free(name_copy); + free(command_line); } bool Subprocess::Communicate(const Message& input, Message* output, diff --git a/src/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h index 9d980b06..977abff7 100644 --- a/src/google/protobuf/compiler/subprocess.h +++ b/src/google/protobuf/compiler/subprocess.h @@ -44,6 +44,8 @@ #include <string> +#include <google/protobuf/port_def.inc> + namespace google { namespace protobuf { @@ -52,7 +54,7 @@ class Message; namespace compiler { // Utility class for launching sub-processes. -class LIBPROTOC_EXPORT Subprocess { +class PROTOC_EXPORT Subprocess { public: Subprocess(); ~Subprocess(); @@ -64,19 +66,19 @@ class LIBPROTOC_EXPORT Subprocess { // Start the subprocess. Currently we don't provide a way to specify // arguments as protoc plugins don't have any. - void Start(const string& program, SearchMode search_mode); + void Start(const std::string& program, SearchMode search_mode); // Serialize the input message and pipe it to the subprocess's stdin, then // close the pipe. Meanwhile, read from the subprocess's stdout and parse // the data into *output. All this is done carefully to avoid deadlocks. // Returns true if successful. On any sort of error, returns false and sets // *error to a description of the problem. - bool Communicate(const Message& input, Message* output, string* error); + bool Communicate(const Message& input, Message* output, std::string* error); #ifdef _WIN32 // Given an error code, returns a human-readable error message. This is // defined here so that CommandLineInterface can share it. - static string Win32ErrorMessage(DWORD error_code); + static std::string Win32ErrorMessage(DWORD error_code); #endif private: @@ -102,6 +104,8 @@ class LIBPROTOC_EXPORT Subprocess { } // namespace compiler } // namespace protobuf - } // namespace google + +#include <google/protobuf/port_undef.inc> + #endif // GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__ diff --git a/src/google/protobuf/compiler/test_plugin.cc b/src/google/protobuf/compiler/test_plugin.cc index c676ce8c..4b758764 100644 --- a/src/google/protobuf/compiler/test_plugin.cc +++ b/src/google/protobuf/compiler/test_plugin.cc @@ -38,13 +38,24 @@ #include <google/protobuf/compiler/plugin.h> #include <google/protobuf/compiler/mock_code_generator.h> +namespace google { +namespace protobuf { +namespace compiler { + +int ProtobufMain(int argc, char* argv[]) { + MockCodeGenerator generator("test_plugin"); + return PluginMain(argc, argv, &generator); +} + +} // namespace compiler +} // namespace protobuf +} // namespace google + int main(int argc, char* argv[]) { #ifdef _MSC_VER // Don't print a silly message or stick a modal dialog box in my face, // please. _set_abort_behavior(0, ~0); #endif // !_MSC_VER - - google::protobuf::compiler::MockCodeGenerator generator("test_plugin"); - return google::protobuf::compiler::PluginMain(argc, argv, &generator); + return google::protobuf::compiler::ProtobufMain(argc, argv); } diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h index 03db4d57..a99bb78c 100644 --- a/src/google/protobuf/compiler/zip_writer.h +++ b/src/google/protobuf/compiler/zip_writer.h @@ -73,12 +73,12 @@ class ZipWriter { ZipWriter(io::ZeroCopyOutputStream* raw_output); ~ZipWriter(); - bool Write(const string& filename, const string& contents); + bool Write(const std::string& filename, const std::string& contents); bool WriteDirectory(); private: struct FileInfo { - string name; + std::string name; uint32 offset; uint32 size; uint32 crc32; |