diff options
author | nechda <[email protected]> | 2024-08-29 23:50:27 +0300 |
---|---|---|
committer | nechda <[email protected]> | 2024-08-30 00:05:25 +0300 |
commit | e10d6638f07a82edae3ea8197b9f5c0affcc07ea (patch) | |
tree | 571c38cec05813766a1ad290c9d51ce7ace52919 /contrib/libs/protoc/src/google/protobuf | |
parent | e79b38f2bbbf78d295d1901d2a79f898022d5224 (diff) |
Update cpp-protobuf to 22.5
Привет!\
Этот PR переключат cpp & python библиотеки protobuf на версию 22.5
Если у вас возникли проблемы после влития этого PR:
1. Если начали падать канон тесты, то проведите их переканонизацию
2. Прочитайте <https://wiki.yandex-team.ru/users/nechda/obnovlenie-cpp-protobuf-22.5/> страничку с основными изменениями
3. Если страничка в вики не помогла, то пишите в [DEVTOOLSSUPPORT](https://st.yandex-team.ru/DEVTOOLSSUPPORT)
7fecade616c20a841b9e9af7b7998bdfc8d2807d
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf')
209 files changed, 20719 insertions, 18322 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/code_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/code_generator.cc index f714df372ae..21291b6b29f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/code_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/code_generator.cc @@ -32,13 +32,17 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/code_generator.h> +#include "google/protobuf/compiler/code_generator.h" -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/plugin.pb.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/stubs/strutil.h> +#include <utility> + +#include "google/protobuf/compiler/plugin.pb.h" +#include "google/protobuf/descriptor.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/strip.h" namespace google { namespace protobuf { @@ -62,7 +66,7 @@ bool CodeGenerator::GenerateAll(const std::vector<const FileDescriptor*>& files, "description."; } if (error && !error->empty()) { - *error = file->name() + ": " + *error; + *error = y_absl::StrCat(file->name(), ": ", *error); break; } if (!succeeded) { @@ -81,7 +85,7 @@ io::ZeroCopyOutputStream* GeneratorContext::OpenForAppend( io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert( const TProtoStringType& filename, const TProtoStringType& insertion_point) { - GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion."; + Y_ABSL_LOG(FATAL) << "This GeneratorContext does not support insertion."; return nullptr; // make compiler happy } @@ -93,7 +97,7 @@ io::ZeroCopyOutputStream* GeneratorContext::OpenForInsertWithGeneratedCodeInfo( void GeneratorContext::ListParsedFiles( std::vector<const FileDescriptor*>* output) { - GOOGLE_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles"; + Y_ABSL_LOG(FATAL) << "This GeneratorContext does not support ListParsedFiles"; } void GeneratorContext::GetCompilerVersion(Version* version) const { @@ -105,30 +109,28 @@ void GeneratorContext::GetCompilerVersion(Version* version) const { // Parses a set of comma-delimited name/value pairs. void ParseGeneratorParameter( - const TProtoStringType& text, + y_absl::string_view text, std::vector<std::pair<TProtoStringType, TProtoStringType> >* output) { - std::vector<TProtoStringType> parts = Split(text, ",", true); - - for (int i = 0; i < parts.size(); i++) { - TProtoStringType::size_type equals_pos = parts[i].find_first_of('='); - std::pair<TProtoStringType, TProtoStringType> value; - if (equals_pos == TProtoStringType::npos) { - value.first = parts[i]; - value.second = ""; + std::vector<y_absl::string_view> parts = + y_absl::StrSplit(text, ',', y_absl::SkipEmpty()); + + for (y_absl::string_view part : parts) { + auto equals_pos = part.find_first_of('='); + if (equals_pos == y_absl::string_view::npos) { + output->emplace_back(part, ""); } else { - value.first = parts[i].substr(0, equals_pos); - value.second = parts[i].substr(equals_pos + 1); + output->emplace_back(part.substr(0, equals_pos), + part.substr(equals_pos + 1)); } - output->push_back(value); } } // Strips ".proto" or ".protodevel" from the end of a filename. -TProtoStringType StripProto(const TProtoStringType& filename) { - if (HasSuffixString(filename, ".protodevel")) { - return StripSuffixString(filename, ".protodevel"); +TProtoStringType StripProto(y_absl::string_view filename) { + if (y_absl::EndsWith(filename, ".protodevel")) { + return TProtoStringType(y_absl::StripSuffix(filename, ".protodevel")); } else { - return StripSuffixString(filename, ".proto"); + return TProtoStringType(y_absl::StripSuffix(filename, ".proto")); } } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/code_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/code_generator.h index 2bbd80d650f..f0b5650a792 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/code_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/code_generator.h @@ -41,10 +41,12 @@ #include <string> #include <utility> #include <vector> -#include <google/protobuf/stubs/common.h> + +#include "y_absl/strings/string_view.h" +#include "google/protobuf/port.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -69,7 +71,9 @@ class GeneratorContext; // be registered with CommandLineInterface to support various languages. class PROTOC_EXPORT CodeGenerator { public: - inline CodeGenerator() {} + CodeGenerator() {} + CodeGenerator(const CodeGenerator&) = delete; + CodeGenerator& operator=(const CodeGenerator&) = delete; virtual ~CodeGenerator(); // Generates code for the given proto file, generating one or more files in @@ -120,9 +124,6 @@ class PROTOC_EXPORT CodeGenerator { // version of the library. When protobufs does a api breaking change, the // method can be removed. virtual bool HasGenerateAll() const { return true; } - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator); }; // CodeGenerators generate one or more files in a given directory. This @@ -131,8 +132,10 @@ class PROTOC_EXPORT CodeGenerator { // runs. class PROTOC_EXPORT GeneratorContext { public: - inline GeneratorContext() { + GeneratorContext() { } + GeneratorContext(const GeneratorContext&) = delete; + GeneratorContext& operator=(const GeneratorContext&) = delete; virtual ~GeneratorContext(); // Opens the given file, truncating it if it exists, and returns a @@ -177,9 +180,6 @@ class PROTOC_EXPORT GeneratorContext { // this GeneratorContext. virtual void GetCompilerVersion(Version* version) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext); }; // The type GeneratorContext was once called OutputDirectory. This typedef @@ -193,15 +193,15 @@ typedef GeneratorContext OutputDirectory; // parses to the pairs: // ("foo", "bar"), ("baz", ""), ("moo", "corge") PROTOC_EXPORT void ParseGeneratorParameter( - const TProtoStringType&, std::vector<std::pair<TProtoStringType, TProtoStringType> >*); + y_absl::string_view, std::vector<std::pair<TProtoStringType, TProtoStringType> >*); // Strips ".proto" or ".protodevel" from the end of a filename. -PROTOC_EXPORT TProtoStringType StripProto(const TProtoStringType& filename); +PROTOC_EXPORT TProtoStringType StripProto(y_absl::string_view filename); } // namespace compiler } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/command_line_interface.cc b/contrib/libs/protoc/src/google/protobuf/compiler/command_line_interface.cc index 3de6dc2f6d6..4568848cd11 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/command_line_interface.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/command_line_interface.cc @@ -32,11 +32,15 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/command_line_interface.h> +#include "google/protobuf/compiler/command_line_interface.h" -#include <google/protobuf/stubs/platform_macros.h> +#include "y_absl/container/btree_set.h" +#include "y_absl/container/flat_hash_map.h" + +#include "google/protobuf/stubs/platform_macros.h" #include <stdio.h> +#include <stdlib.h> #include <sys/types.h> #ifdef major #undef major @@ -58,6 +62,9 @@ #include <limits.h> // For PATH_MAX #include <memory> +#include <string> +#include <utility> +#include <vector> #if defined(__APPLE__) #include <mach-o/dyld.h> @@ -65,29 +72,32 @@ #include <sys/sysctl.h> #endif -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/compiler/subprocess.h> -#include <google/protobuf/compiler/plugin.pb.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/stringprintf.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/importer.h> -#include <google/protobuf/compiler/zip_writer.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/dynamic_message.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/io_win32.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/text_format.h> -#include <google/protobuf/stubs/map_util.h> -#include <google/protobuf/stubs/stl_util.h> +#include "google/protobuf/stubs/common.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "google/protobuf/compiler/subprocess.h" +#include "google/protobuf/compiler/plugin.pb.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/importer.h" +#include "google/protobuf/compiler/zip_writer.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/dynamic_message.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/io/io_win32.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream_impl.h" +#include "google/protobuf/text_format.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -132,7 +142,7 @@ void SetFdToTextMode(int fd) { #ifdef _WIN32 if (setmode(fd, _O_TEXT) == -1) { // This should never happen, I think. - GOOGLE_LOG(WARNING) << "setmode(" << fd << ", _O_TEXT): " << strerror(errno); + Y_ABSL_LOG(WARNING) << "setmode(" << fd << ", _O_TEXT): " << strerror(errno); } #endif // (Text and binary are the same on non-Windows platforms.) @@ -142,7 +152,8 @@ void SetFdToBinaryMode(int fd) { #ifdef _WIN32 if (setmode(fd, _O_BINARY) == -1) { // This should never happen, I think. - GOOGLE_LOG(WARNING) << "setmode(" << fd << ", _O_BINARY): " << strerror(errno); + Y_ABSL_LOG(WARNING) << "setmode(" << fd + << ", _O_BINARY): " << strerror(errno); } #endif // (Text and binary are the same on non-Windows platforms.) @@ -174,7 +185,7 @@ bool TryCreateParentDirectory(const TProtoStringType& prefix, // Recursively create parent directories to the output file. // On Windows, both '/' and '\' are valid path separators. std::vector<TProtoStringType> parts = - Split(filename, "/\\", true); + y_absl::StrSplit(filename, y_absl::ByAnyChar("/\\"), y_absl::SkipEmpty()); TProtoStringType path_so_far = prefix; for (int i = 0; i < parts.size() - 1; i++) { path_so_far += parts[i]; @@ -227,9 +238,10 @@ bool GetProtocAbsolutePath(TProtoStringType* path) { // Whether a path is where google/protobuf/descriptor.proto and other well-known // type protos are installed. -bool IsInstalledProtoPath(const TProtoStringType& path) { +bool IsInstalledProtoPath(y_absl::string_view path) { // Checking the descriptor.proto file should be good enough. - TProtoStringType file_path = path + "/google/protobuf/descriptor.proto"; + TProtoStringType file_path = + y_absl::StrCat(path, "/google/protobuf/descriptor.proto"); return access(file_path.c_str(), F_OK) != -1; } @@ -240,25 +252,26 @@ void AddDefaultProtoPaths( // TODO(xiaofeng): The code currently only checks relative paths of where // the protoc binary is installed. We probably should make it handle more // cases than that. - TProtoStringType path; - if (!GetProtocAbsolutePath(&path)) { + TProtoStringType path_str; + if (!GetProtocAbsolutePath(&path_str)) { return; } + y_absl::string_view path(path_str); // Strip the binary name. size_t pos = path.find_last_of("/\\"); - if (pos == TProtoStringType::npos || pos == 0) { + if (pos == path.npos || pos == 0) { return; } path = path.substr(0, pos); // Check the binary's directory. if (IsInstalledProtoPath(path)) { - paths->push_back(std::pair<TProtoStringType, TProtoStringType>("", path)); + paths->emplace_back("", path); return; } // Check if there is an include subdirectory. - if (IsInstalledProtoPath(path + "/include")) { - paths->push_back( - std::pair<TProtoStringType, TProtoStringType>("", path + "/include")); + TProtoStringType include_path = y_absl::StrCat(path, "/include"); + if (IsInstalledProtoPath(include_path)) { + paths->emplace_back("", std::move(include_path)); return; } // Check if the upper level directory has an "include" subdirectory. @@ -267,18 +280,19 @@ void AddDefaultProtoPaths( return; } path = path.substr(0, pos); - if (IsInstalledProtoPath(path + "/include")) { - paths->push_back( - std::pair<TProtoStringType, TProtoStringType>("", path + "/include")); + include_path = y_absl::StrCat(path, "/include"); + if (IsInstalledProtoPath(include_path)) { + paths->emplace_back("", std::move(include_path)); return; } } -TProtoStringType PluginName(const TProtoStringType& plugin_prefix, - const TProtoStringType& directive) { +TProtoStringType PluginName(y_absl::string_view plugin_prefix, + y_absl::string_view directive) { // Assuming the directive starts with "--" and ends with "_out" or "_opt", // strip the "--" and "_out/_opt" and add the plugin prefix. - return plugin_prefix + "gen-" + directive.substr(2, directive.size() - 6); + return y_absl::StrCat(plugin_prefix, "gen-", + directive.substr(2, directive.size() - 6)); } } // namespace @@ -297,37 +311,37 @@ class CommandLineInterface::ErrorPrinter ~ErrorPrinter() override {} // implements MultiFileErrorCollector ------------------------------ - void AddError(const TProtoStringType& filename, int line, int column, - const TProtoStringType& message) override { + void RecordError(y_absl::string_view filename, int line, int column, + y_absl::string_view message) override { found_errors_ = true; AddErrorOrWarning(filename, line, column, message, "error", std::cerr); } - void AddWarning(const TProtoStringType& filename, int line, int column, - const TProtoStringType& message) override { + void RecordWarning(y_absl::string_view filename, int line, int column, + y_absl::string_view message) override { found_warnings_ = true; AddErrorOrWarning(filename, line, column, message, "warning", std::clog); } // implements io::ErrorCollector ----------------------------------- - void AddError(int line, int column, const TProtoStringType& message) override { - AddError("input", line, column, message); + void RecordError(int line, int column, y_absl::string_view message) override { + RecordError("input", line, column, message); } - void AddWarning(int line, int column, const TProtoStringType& message) override { + void RecordWarning(int line, int column, y_absl::string_view message) override { AddErrorOrWarning("input", line, column, message, "warning", std::clog); } // implements DescriptorPool::ErrorCollector------------------------- - void AddError(const TProtoStringType& filename, const TProtoStringType& element_name, - const Message* descriptor, ErrorLocation location, - const TProtoStringType& message) override { + void RecordError(y_absl::string_view filename, y_absl::string_view element_name, + const Message* descriptor, ErrorLocation location, + y_absl::string_view message) override { AddErrorOrWarning(filename, -1, -1, message, "error", std::cerr); } - void AddWarning(const TProtoStringType& filename, const TProtoStringType& element_name, - const Message* descriptor, ErrorLocation location, - const TProtoStringType& message) override { + void RecordWarning(y_absl::string_view filename, y_absl::string_view element_name, + const Message* descriptor, ErrorLocation location, + y_absl::string_view message) override { AddErrorOrWarning(filename, -1, -1, message, "warning", std::clog); } @@ -336,12 +350,15 @@ class CommandLineInterface::ErrorPrinter bool FoundWarnings() const { return found_warnings_; } private: - void AddErrorOrWarning(const TProtoStringType& filename, int line, int column, - const TProtoStringType& message, const TProtoStringType& type, + void AddErrorOrWarning(y_absl::string_view filename, int line, int column, + y_absl::string_view message, y_absl::string_view type, std::ostream& out) { - // Print full path when running under MSVS TProtoStringType dfile; - if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && + if ( +#ifndef PROTOBUF_OPENSOURCE + // Print full path when running under MSVS + format_ == CommandLineInterface::ERROR_FORMAT_MSVS && +#endif // !PROTOBUF_OPENSOURCE tree_ != nullptr && tree_->VirtualFileToDiskFile(filename, &dfile)) { out << dfile; } else { @@ -398,7 +415,6 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { // Get name of all output files. void GetOutputFilenames(std::vector<TProtoStringType>* output_filenames); - // implements GeneratorContext -------------------------------------- io::ZeroCopyOutputStream* Open(const TProtoStringType& filename) override; io::ZeroCopyOutputStream* OpenForAppend(const TProtoStringType& filename) override; @@ -417,7 +433,7 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { // The files_ field maps from path keys to file content values. It's a map // instead of an unordered_map so that files are written in order (good when // writing zips). - std::map<TProtoStringType, TProtoStringType> files_; + y_absl::btree_map<TProtoStringType, TProtoStringType> files_; const std::vector<const FileDescriptor*>& parsed_files_; bool had_error_; }; @@ -708,7 +724,7 @@ void CommandLineInterface::MemoryOutputStream::InsertShiftedInfo( void CommandLineInterface::MemoryOutputStream::UpdateMetadata( const TProtoStringType& insertion_content, size_t insertion_offset, size_t insertion_length, size_t indent_length) { - auto it = directory_->files_.find(filename_ + ".pb.meta"); + auto it = directory_->files_.find(y_absl::StrCat(filename_, ".pb.meta")); if (it == directory_->files_.end() && info_to_insert_.annotation().empty()) { // No metadata was recorded for this file. return; @@ -738,7 +754,8 @@ void CommandLineInterface::MemoryOutputStream::UpdateMetadata( } else { // Create a new file to store the new metadata in info_to_insert_. encoded_data = - &directory_->files_.insert({filename_ + ".pb.meta", ""}).first->second; + &directory_->files_.try_emplace(y_absl::StrCat(filename_, ".pb.meta"), "") + .first->second; } GeneratedCodeInfo new_metadata; bool crossed_offset = false; @@ -795,96 +812,95 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { } it->second.swap(data_); - } else { - // This was an OpenForInsert(). + return; + } + // This was an OpenForInsert(). - // If the data doesn't end with a clean line break, add one. - if (!data_.empty() && data_[data_.size() - 1] != '\n') { - data_.push_back('\n'); - } + // If the data doesn't end with a clean line break, add one. + if (!data_.empty() && data_[data_.size() - 1] != '\n') { + data_.push_back('\n'); + } - // Find the file we are going to insert into. - if (!already_present) { - std::cerr << filename_ - << ": Tried to insert into file that doesn't exist." - << std::endl; - directory_->had_error_ = true; - return; - } - TProtoStringType* target = &it->second; + // Find the file we are going to insert into. + if (!already_present) { + std::cerr << filename_ << ": Tried to insert into file that doesn't exist." + << std::endl; + directory_->had_error_ = true; + return; + } + TProtoStringType* target = &it->second; - // Find the insertion point. - TProtoStringType magic_string = - strings::Substitute("@@protoc_insertion_point($0)", insertion_point_); - TProtoStringType::size_type pos = target->find(magic_string); + // Find the insertion point. + TProtoStringType magic_string = + y_absl::Substitute("@@protoc_insertion_point($0)", insertion_point_); + TProtoStringType::size_type pos = target->find(magic_string); - if (pos == TProtoStringType::npos) { - std::cerr << filename_ << ": insertion point \"" << insertion_point_ - << "\" not found." << std::endl; - directory_->had_error_ = true; - return; - } + if (pos == TProtoStringType::npos) { + std::cerr << filename_ << ": insertion point \"" << insertion_point_ + << "\" not found." << std::endl; + directory_->had_error_ = true; + return; + } - if ((pos > 3) && (target->substr(pos - 3, 2) == "/*")) { - // Support for inline "/* @@protoc_insertion_point() */" - pos = pos - 3; + if ((pos > 3) && (target->substr(pos - 3, 2) == "/*")) { + // Support for inline "/* @@protoc_insertion_point() */" + pos = pos - 3; + } else { + // Seek backwards to the beginning of the line, which is where we will + // insert the data. Note that this has the effect of pushing the + // insertion point down, so the data is inserted before it. This is + // intentional because it means that multiple insertions at the same point + // will end up in the expected order in the final output. + pos = target->find_last_of('\n', pos); + if (pos == TProtoStringType::npos) { + // Insertion point is on the first line. + pos = 0; } else { - // Seek backwards to the beginning of the line, which is where we will - // insert the data. Note that this has the effect of pushing the - // insertion point down, so the data is inserted before it. This is - // intentional because it means that multiple insertions at the same point - // will end up in the expected order in the final output. - pos = target->find_last_of('\n', pos); - if (pos == TProtoStringType::npos) { - // Insertion point is on the first line. - pos = 0; - } else { - // Advance to character after '\n'. - ++pos; - } + // Advance to character after '\n'. + ++pos; } + } - // Extract indent. - TProtoStringType indent_(*target, pos, - target->find_first_not_of(" \t", pos) - pos); + // Extract indent. + TProtoStringType indent_(*target, pos, + target->find_first_not_of(" \t", pos) - pos); - if (indent_.empty()) { - // No indent. This makes things easier. - target->insert(pos, data_); - UpdateMetadata(data_, pos, data_.size(), 0); - } else { - // Calculate how much space we need. - int indent_size = 0; - for (int i = 0; i < data_.size(); i++) { - if (data_[i] == '\n') indent_size += indent_.size(); - } + if (indent_.empty()) { + // No indent. This makes things easier. + target->insert(pos, data_); + UpdateMetadata(data_, pos, data_.size(), 0); + return; + } + // Calculate how much space we need. + int indent_size = 0; + for (int i = 0; i < data_.size(); i++) { + if (data_[i] == '\n') indent_size += indent_.size(); + } - // Make a hole for it. - target->insert(pos, data_.size() + indent_size, '\0'); - - // Now copy in the data. - TProtoStringType::size_type data_pos = 0; - char* target_ptr = ::google::protobuf::string_as_array(target) + pos; - while (data_pos < data_.size()) { - // Copy indent. - memcpy(target_ptr, indent_.data(), indent_.size()); - target_ptr += indent_.size(); - - // Copy line from data_. - // We already guaranteed that data_ ends with a newline (above), so this - // search can't fail. - TProtoStringType::size_type line_length = - data_.find_first_of('\n', data_pos) + 1 - data_pos; - memcpy(target_ptr, data_.data() + data_pos, line_length); - target_ptr += line_length; - data_pos += line_length; - } - UpdateMetadata(data_, pos, data_.size() + indent_size, indent_.size()); + // Make a hole for it. + target->insert(pos, data_.size() + indent_size, '\0'); - GOOGLE_CHECK_EQ(target_ptr, - ::google::protobuf::string_as_array(target) + pos + data_.size() + indent_size); - } + // Now copy in the data. + TProtoStringType::size_type data_pos = 0; + char* target_ptr = &(*target)[pos]; + while (data_pos < data_.size()) { + // Copy indent. + memcpy(target_ptr, indent_.data(), indent_.size()); + target_ptr += indent_.size(); + + // Copy line from data_. + // We already guaranteed that data_ ends with a newline (above), so this + // search can't fail. + TProtoStringType::size_type line_length = + data_.find_first_of('\n', data_pos) + 1 - data_pos; + memcpy(target_ptr, data_.data() + data_pos, line_length); + target_ptr += line_length; + data_pos += line_length; } + + Y_ABSL_CHECK_EQ(target_ptr, &(*target)[pos] + data_.size() + indent_size); + + UpdateMetadata(data_, pos, data_.size() + indent_size, indent_.size()); } // =================================================================== @@ -954,6 +970,77 @@ bool ContainsProto3Optional(const FileDescriptor* file) { return false; } +template <typename Visitor> +struct VisitImpl { + Visitor visitor; + void Visit(const FieldDescriptor* descriptor) { visitor(descriptor); } + + void Visit(const EnumDescriptor* descriptor) { visitor(descriptor); } + + void Visit(const Descriptor* descriptor) { + visitor(descriptor); + + for (int i = 0; i < descriptor->enum_type_count(); i++) { + Visit(descriptor->enum_type(i)); + } + + for (int i = 0; i < descriptor->field_count(); i++) { + Visit(descriptor->field(i)); + } + + for (int i = 0; i < descriptor->nested_type_count(); i++) { + Visit(descriptor->nested_type(i)); + } + + for (int i = 0; i < descriptor->extension_count(); i++) { + Visit(descriptor->extension(i)); + } + } + + void Visit(const std::vector<const FileDescriptor*>& descriptors) { + for (auto* descriptor : descriptors) { + visitor(descriptor); + for (int i = 0; i < descriptor->message_type_count(); i++) { + Visit(descriptor->message_type(i)); + } + for (int i = 0; i < descriptor->enum_type_count(); i++) { + Visit(descriptor->enum_type(i)); + } + for (int i = 0; i < descriptor->extension_count(); i++) { + Visit(descriptor->extension(i)); + } + } + } +}; + +// Visit every node in the descriptors calling `visitor(node)`. +// The visitor does not need to handle all possible node types. Types that are +// not visitable via `visitor` will be ignored. +// Disclaimer: this is not fully implemented yet to visit _every_ node. +// VisitImpl might need to be updated where needs arise. +template <typename Visitor> +void VisitDescriptors(const std::vector<const FileDescriptor*>& descriptors, + Visitor visitor) { + // Provide a fallback to ignore all the nodes that are not interesting to the + // input visitor. + struct VisitorImpl : Visitor { + explicit VisitorImpl(Visitor visitor) : Visitor(visitor) {} + using Visitor::operator(); + // Honeypot to ignore all inputs that Visitor does not take. + void operator()(const void*) const {} + }; + + VisitImpl<VisitorImpl>{VisitorImpl(visitor)}.Visit(descriptors); +} + +bool HasReservedFieldNumber(const FieldDescriptor* field) { + if (field->number() >= FieldDescriptor::kFirstReservedNumber && + field->number() <= FieldDescriptor::kLastReservedNumber) { + return true; + } + return false; +} + } // namespace namespace { @@ -963,6 +1050,7 @@ PopulateSingleSimpleDescriptorDatabase(const TProtoStringType& descriptor_set_na int CommandLineInterface::Run(int argc, const char* const argv[]) { Clear(); + switch (ParseArguments(argc, argv)) { case PARSE_ARGUMENT_DONE_AND_EXIT: return 0; @@ -1046,6 +1134,38 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { return 1; } + bool validation_error = false; // Defer exiting so we log more warnings. + + VisitDescriptors(parsed_files, [&](const FieldDescriptor* field) { + if (HasReservedFieldNumber(field)) { + const char* error_link = nullptr; + validation_error = true; + TProtoStringType error; + if (field->number() >= FieldDescriptor::kFirstReservedNumber && + field->number() <= FieldDescriptor::kLastReservedNumber) { + error = y_absl::Substitute( + "Field numbers $0 through $1 are reserved " + "for the protocol buffer library implementation.", + FieldDescriptor::kFirstReservedNumber, + FieldDescriptor::kLastReservedNumber); + } else { + error = y_absl::Substitute( + "Field number $0 is reserved for specific purposes.", + field->number()); + } + if (error_link) { + y_absl::StrAppend(&error, "(See ", error_link, ")"); + } + static_cast<DescriptorPool::ErrorCollector*>(error_collector.get()) + ->RecordError(field->file()->name(), field->full_name(), nullptr, + DescriptorPool::ErrorCollector::NUMBER, error); + } + }); + + + if (validation_error) { + return 1; + } // We construct a separate GeneratorContext for each output location. Note // that two code generators may output to the same location, in which case @@ -1056,9 +1176,9 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { if (mode_ == MODE_COMPILE) { for (int i = 0; i < output_directives_.size(); i++) { TProtoStringType output_location = output_directives_[i].output_location; - if (!HasSuffixString(output_location, ".zip") && - !HasSuffixString(output_location, ".jar") && - !HasSuffixString(output_location, ".srcjar")) { + if (!y_absl::EndsWith(output_location, ".zip") && + !y_absl::EndsWith(output_location, ".jar") && + !y_absl::EndsWith(output_location, ".srcjar")) { AddTrailingSlash(&output_location); } @@ -1066,7 +1186,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { if (!generator) { // First time we've seen this output location. - generator.reset(new GeneratorContextImpl(parsed_files)); + generator = std::make_unique<GeneratorContextImpl>(parsed_files); } if (!GenerateOutput(parsed_files, output_directives_[i], @@ -1076,16 +1196,15 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } - // Write all output to disk. for (const auto& pair : output_directories) { const TProtoStringType& location = pair.first; GeneratorContextImpl* directory = pair.second.get(); - if (HasSuffixString(location, "/")) { + if (y_absl::EndsWith(location, "/")) { if (!directory->WriteAllToDisk(location)) { return 1; } } else { - if (HasSuffixString(location, ".jar")) { + if (y_absl::EndsWith(location, ".jar")) { directory->AddJarManifest(); } @@ -1096,7 +1215,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } if (!dependency_out_name_.empty()) { - GOOGLE_DCHECK(disk_source_tree.get()); + Y_ABSL_DCHECK(disk_source_tree.get()); if (!GenerateDependencyManifestFile(parsed_files, output_directories, disk_source_tree.get())) { return 1; @@ -1116,7 +1235,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { FileDescriptorProto file; file.set_name("empty_message.proto"); file.add_message_type()->set_name("EmptyMessage"); - GOOGLE_CHECK(pool.BuildFile(file) != nullptr); + Y_ABSL_CHECK(pool.BuildFile(file) != nullptr); codec_type_ = "EmptyMessage"; if (!EncodeOrDecode(&pool)) { return 1; @@ -1144,14 +1263,14 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } break; case PRINT_NONE: - GOOGLE_LOG(ERROR) << "If the code reaches here, it usually means a bug of " - "flag parsing in the CommandLineInterface."; + Y_ABSL_LOG(ERROR) + << "If the code reaches here, it usually means a bug of " + "flag parsing in the CommandLineInterface."; return 1; // Do not add a default case. } } - return 0; } @@ -1276,6 +1395,7 @@ bool CommandLineInterface::ParseInputFiles( } parsed_files->push_back(parsed_file); + // Enforce --disallow_services. if (disallow_services_ && parsed_file->service_count() > 0) { std::cerr << parsed_file->name() @@ -1295,9 +1415,9 @@ bool CommandLineInterface::ParseInputFiles( direct_dependencies_.end()) { indirect_imports = true; std::cerr << parsed_file->name() << ": " - << StringReplace(direct_dependencies_violation_msg_, "%s", - parsed_file->dependency(i)->name(), - true /* replace_all */) + << y_absl::StrReplaceAll( + direct_dependencies_violation_msg_, + {{"%s", parsed_file->dependency(i)->name()}}) << std::endl; } } @@ -1486,19 +1606,15 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( // Make sure each plugin option has a matching plugin output. bool foundUnknownPluginOption = false; - for (std::map<TProtoStringType, TProtoStringType>::const_iterator i = - plugin_parameters_.begin(); - i != plugin_parameters_.end(); ++i) { - if (plugins_.find(i->first) != plugins_.end()) { + for (const auto& kv : plugin_parameters_) { + if (plugins_.find(kv.first) != plugins_.end()) { continue; } bool foundImplicitPlugin = false; - for (std::vector<OutputDirective>::const_iterator j = - output_directives_.begin(); - j != output_directives_.end(); ++j) { - if (j->generator == nullptr) { - TProtoStringType plugin_name = PluginName(plugin_prefix_, j->name); - if (plugin_name == i->first) { + for (const auto& d : output_directives_) { + if (d.generator == nullptr) { + TProtoStringType plugin_name = PluginName(plugin_prefix_, d.name); + if (plugin_name == kv.first) { foundImplicitPlugin = true; break; } @@ -1507,7 +1623,7 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( if (!foundImplicitPlugin) { std::cerr << "Unknown flag: " // strip prefix + "gen-" and add back "_opt" - << "--" + i->first.substr(plugin_prefix_.size() + 4) + "_opt" + << "--" << kv.first.substr(plugin_prefix_.size() + 4) << "_opt" << std::endl; foundUnknownPluginOption = true; } @@ -1552,7 +1668,7 @@ CommandLineInterface::ParseArgumentStatus CommandLineInterface::ParseArguments( input_files_.empty() && descriptor_set_in_names_.empty(); break; default: - GOOGLE_LOG(FATAL) << "Unexpected mode: " << mode_; + Y_ABSL_LOG(FATAL) << "Unexpected mode: " << mode_; } if (missing_proto_definitions) { std::cerr << "Missing input file." << std::endl; @@ -1686,8 +1802,7 @@ CommandLineInterface::InterpretArgument(const TProtoStringType& name, })) { case google::protobuf::io::win32::ExpandWildcardsResult::kSuccess: break; - case google::protobuf::io::win32::ExpandWildcardsResult:: - kErrorNoMatchingFile: + case google::protobuf::io::win32::ExpandWildcardsResult::kErrorNoMatchingFile: // Path does not exist, is not a file, or it's longer than MAX_PATH and // long path handling is disabled. std::cerr << "Invalid file name pattern or missing input file \"" @@ -1708,9 +1823,9 @@ CommandLineInterface::InterpretArgument(const TProtoStringType& name, // Java's -classpath (and some other languages) delimits path components // with colons. Let's accept that syntax too just to make things more // intuitive. - std::vector<TProtoStringType> parts = Split( - value, CommandLineInterface::kPathSeparator, - true); + std::vector<TProtoStringType> parts = y_absl::StrSplit( + value, y_absl::ByAnyChar(CommandLineInterface::kPathSeparator), + y_absl::SkipEmpty()); for (int i = 0; i < parts.size(); i++) { TProtoStringType virtual_path; @@ -1764,8 +1879,8 @@ CommandLineInterface::InterpretArgument(const TProtoStringType& name, direct_dependencies_explicitly_set_ = true; std::vector<TProtoStringType> direct = - Split(value, ":", true); - GOOGLE_DCHECK(direct_dependencies_.empty()); + y_absl::StrSplit(value, ":", y_absl::SkipEmpty()); + Y_ABSL_DCHECK(direct_dependencies_.empty()); direct_dependencies_.insert(direct.begin(), direct.end()); } else if (name == "--direct_dependencies_violation_msg") { @@ -1790,9 +1905,9 @@ CommandLineInterface::InterpretArgument(const TProtoStringType& name, return PARSE_ARGUMENT_FAIL; } - descriptor_set_in_names_ = Split( - value, CommandLineInterface::kPathSeparator, - true); + descriptor_set_in_names_ = y_absl::StrSplit( + value, y_absl::ByAnyChar(CommandLineInterface::kPathSeparator), + y_absl::SkipEmpty()); } else if (name == "-o" || name == "--descriptor_set_out") { if (!descriptor_set_out_name_.empty()) { @@ -1850,7 +1965,7 @@ CommandLineInterface::InterpretArgument(const TProtoStringType& name, if (!version_info_.empty()) { std::cout << version_info_ << std::endl; } - std::cout << "libprotoc " << internal::VersionString(PROTOBUF_VERSION) + std::cout << "libprotoc " << internal::ProtocVersionString(PROTOBUF_VERSION) << PROTOBUF_VERSION_SUFFIX << std::endl; return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. @@ -1979,14 +2094,30 @@ CommandLineInterface::InterpretArgument(const TProtoStringType& name, } mode_ = MODE_PRINT; print_mode_ = PRINT_FREE_FIELDS; + } else if (name == "--enable_codegen_trace") { + // We use environment variables here so that subprocesses see this setting + // when we spawn them. + // + // Setting environment variables is more-or-less asking for a data race, + // because C got this wrong and did not mandate synchronization. + // In practice, this code path is "only" in the main thread of protoc, and + // it is common knowledge that touching setenv in a library is asking for + // life-ruining bugs *anyways*. As such, there is a reasonable probability + // that there isn't another thread kicking environment variables at this + // moment. + +#ifdef _WIN32 + ::_putenv(y_absl::StrCat(io::Printer::kProtocCodegenTrace, "=yes").c_str()); +#else + ::setenv(io::Printer::kProtocCodegenTrace.data(), "yes", 0); +#endif } else { // Some other flag. Look it up in the generators list. - const GeneratorInfo* generator_info = - FindOrNull(generators_by_flag_name_, name); + const GeneratorInfo* generator_info = FindGeneratorByFlag(name); if (generator_info == nullptr && - (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) { + (plugin_prefix_.empty() || !y_absl::EndsWith(name, "_out"))) { // Check if it's a generator option flag. - generator_info = FindOrNull(generators_by_option_name_, name); + generator_info = FindGeneratorByOption(name); if (generator_info != nullptr) { TProtoStringType* parameters = &generator_parameters_[generator_info->flag_name]; @@ -1994,7 +2125,7 @@ CommandLineInterface::InterpretArgument(const TProtoStringType& name, parameters->append(","); } parameters->append(value); - } else if (HasPrefixString(name, "--") && HasSuffixString(name, "_opt")) { + } else if (y_absl::StartsWith(name, "--") && y_absl::EndsWith(name, "_opt")) { TProtoStringType* parameters = &plugin_parameters_[PluginName(plugin_prefix_, name)]; if (!parameters->empty()) { @@ -2109,7 +2240,10 @@ Parse PROTO_FILES and generate output based on the options given: defined in the given proto files. Groups share the same field number space with the parent message. Extension ranges are counted as - occupied fields numbers.)"; + occupied fields numbers. + --enable_codegen_trace Enables tracing which parts of protoc are + responsible for what codegen output. Not supported + by all backends or on all platforms.)"; if (!plugin_prefix_.empty()) { std::cout << R"( --plugin=EXECUTABLE Specifies a plugin executable to use. @@ -2122,16 +2256,15 @@ Parse PROTO_FILES and generate output based on the options given: the executable's own name differs.)"; } - for (GeneratorMap::iterator iter = generators_by_flag_name_.begin(); - iter != generators_by_flag_name_.end(); ++iter) { + for (const auto& kv : generators_by_flag_name_) { // FIXME(kenton): If the text is long enough it will wrap, which is ugly, // but fixing this nicely (e.g. splitting on spaces) is probably more // trouble than it's worth. std::cout << std::endl - << " " << iter->first << "=OUT_DIR " - << TProtoStringType(19 - iter->first.size(), + << " " << kv.first << "=OUT_DIR " + << TProtoStringType(19 - kv.first.size(), ' ') // Spaces for alignment. - << iter->second.help_text; + << kv.second.help_text; } std::cout << R"( @<filename> Read options and filenames from file. If a @@ -2163,7 +2296,8 @@ bool CommandLineInterface::EnforceProto3OptionalSupport( << codegen_name << " hasn't been updated to support optional fields in " "proto3. Please ask the owner of this code generator to " - "support proto3 optional."; + "support proto3 optional." + << std::endl; return false; } } @@ -2179,8 +2313,8 @@ bool CommandLineInterface::GenerateOutput( TProtoStringType error; if (output_directive.generator == nullptr) { // This is a plugin. - GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") && - HasSuffixString(output_directive.name, "_out")) + Y_ABSL_CHECK(y_absl::StartsWith(output_directive.name, "--") && + y_absl::EndsWith(output_directive.name, "_out")) << "Bad name for plugin generator: " << output_directive.name; TProtoStringType plugin_name = PluginName(plugin_prefix_, output_directive.name); @@ -2228,7 +2362,7 @@ bool CommandLineInterface::GenerateDependencyManifestFile( DiskSourceTree* source_tree) { FileDescriptorSet file_set; - std::set<const FileDescriptor*> already_seen; + y_absl::flat_hash_set<const FileDescriptor*> already_seen; for (int i = 0; i < parsed_files.size(); i++) { GetTransitiveDependencies(parsed_files[i], false, false, &already_seen, file_set.mutable_file()); @@ -2268,7 +2402,7 @@ bool CommandLineInterface::GenerateDependencyManifestFile( io::Printer printer(&out, '$'); for (int i = 0; i < output_filenames.size(); i++) { - printer.Print(output_filenames[i].c_str()); + printer.Print(output_filenames[i]); if (i == output_filenames.size() - 1) { printer.Print(":"); } else { @@ -2309,7 +2443,7 @@ bool CommandLineInterface::GeneratePluginOutput( } - std::set<const FileDescriptor*> already_seen; + y_absl::flat_hash_set<const FileDescriptor*> already_seen; for (int i = 0; i < parsed_files.size(); i++) { request.add_file_to_generate(parsed_files[i]->name()); GetTransitiveDependencies(parsed_files[i], @@ -2336,7 +2470,7 @@ bool CommandLineInterface::GeneratePluginOutput( TProtoStringType communicate_error; if (!subprocess.Communicate(request, &response, &communicate_error)) { - *error = strings::Substitute("$0: $1", plugin_name, communicate_error); + *error = y_absl::Substitute("$0: $1", plugin_name, communicate_error); return false; } @@ -2363,7 +2497,7 @@ bool CommandLineInterface::GeneratePluginOutput( current_output.reset(); current_output.reset(generator_context->Open(output_file.name())); } else if (current_output == nullptr) { - *error = strings::Substitute( + *error = y_absl::Substitute( "$0: First file chunk returned by plugin did not specify a file " "name.", plugin_name); @@ -2482,13 +2616,13 @@ bool CommandLineInterface::WriteDescriptorSet( const std::vector<const FileDescriptor*>& parsed_files) { FileDescriptorSet file_set; - std::set<const FileDescriptor*> already_seen; + y_absl::flat_hash_set<const FileDescriptor*> already_seen; if (!imports_in_descriptor_set_) { // Since we don't want to output transitive dependencies, but we do want // things to be in dependency order, add all dependencies that aren't in // parsed_files to already_seen. This will short circuit the recursion // in GetTransitiveDependencies. - std::set<const FileDescriptor*> to_output; + y_absl::flat_hash_set<const FileDescriptor*> to_output; to_output.insert(parsed_files.begin(), parsed_files.end()); for (int i = 0; i < parsed_files.size(); i++) { const FileDescriptor* file = parsed_files[i]; @@ -2546,7 +2680,7 @@ bool CommandLineInterface::WriteDescriptorSet( void CommandLineInterface::GetTransitiveDependencies( const FileDescriptor* file, bool include_json_name, bool include_source_code_info, - std::set<const FileDescriptor*>* already_seen, + y_absl::flat_hash_set<const FileDescriptor*>* already_seen, RepeatedPtrField<FileDescriptorProto>* output) { if (!already_seen->insert(file).second) { // Already saw this file. Skip. @@ -2570,6 +2704,20 @@ void CommandLineInterface::GetTransitiveDependencies( } } +const CommandLineInterface::GeneratorInfo* +CommandLineInterface::FindGeneratorByFlag(const TProtoStringType& name) const { + auto it = generators_by_flag_name_.find(name); + if (it == generators_by_flag_name_.end()) return nullptr; + return &it->second; +} + +const CommandLineInterface::GeneratorInfo* +CommandLineInterface::FindGeneratorByOption(const TProtoStringType& option) const { + auto it = generators_by_option_name_.find(option); + if (it == generators_by_option_name_.end()) return nullptr; + return &it->second; +} + namespace { // Utility function for PrintFreeFieldNumbers. @@ -2605,9 +2753,9 @@ namespace { // order of the nested messages is also preserved. typedef std::pair<int, int> FieldRange; void GatherOccupiedFieldRanges( - const Descriptor* descriptor, std::set<FieldRange>* ranges, + const Descriptor* descriptor, y_absl::btree_set<FieldRange>* ranges, std::vector<const Descriptor*>* nested_messages) { - std::set<const Descriptor*> groups; + y_absl::flat_hash_set<const Descriptor*> groups; for (int i = 0; i < descriptor->field_count(); ++i) { const FieldDescriptor* fd = descriptor->field(i); ranges->insert(FieldRange(fd->number(), fd->number() + 1)); @@ -2639,30 +2787,29 @@ void GatherOccupiedFieldRanges( // Actually prints the formatted free field numbers for given message name and // occupied ranges. void FormatFreeFieldNumbers(const TProtoStringType& name, - const std::set<FieldRange>& ranges) { + const y_absl::btree_set<FieldRange>& ranges) { TProtoStringType output; - StringAppendF(&output, "%-35s free:", name.c_str()); + y_absl::StrAppendFormat(&output, "%-35s free:", name.c_str()); int next_free_number = 1; - for (std::set<FieldRange>::const_iterator i = ranges.begin(); - i != ranges.end(); ++i) { + for (const auto& range : ranges) { // This happens when groups re-use parent field numbers, in which // case we skip the FieldRange entirely. - if (next_free_number >= i->second) continue; + if (next_free_number >= range.second) continue; - if (next_free_number < i->first) { - if (next_free_number + 1 == i->first) { + if (next_free_number < range.first) { + if (next_free_number + 1 == range.first) { // Singleton - StringAppendF(&output, " %d", next_free_number); + y_absl::StrAppendFormat(&output, " %d", next_free_number); } else { // Range - StringAppendF(&output, " %d-%d", next_free_number, - i->first - 1); + y_absl::StrAppendFormat(&output, " %d-%d", next_free_number, + range.first - 1); } } - next_free_number = i->second; + next_free_number = range.second; } if (next_free_number <= FieldDescriptor::kMaxNumber) { - StringAppendF(&output, " %d-INF", next_free_number); + y_absl::StrAppendFormat(&output, " %d-INF", next_free_number); } std::cout << output << std::endl; } @@ -2670,7 +2817,7 @@ void FormatFreeFieldNumbers(const TProtoStringType& name, } // namespace void CommandLineInterface::PrintFreeFieldNumbers(const Descriptor* descriptor) { - std::set<FieldRange> ranges; + y_absl::btree_set<FieldRange> ranges; std::vector<const Descriptor*> nested_messages; GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages); diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/command_line_interface.h b/contrib/libs/protoc/src/google/protobuf/compiler/command_line_interface.h index a2a3dffe4b2..054efd0dbc9 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/command_line_interface.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/command_line_interface.h @@ -39,19 +39,20 @@ #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ #include <cstdint> -#include <map> +#include <functional> #include <memory> -#include <set> #include <string> -#include <unordered_map> -#include <unordered_set> #include <utility> #include <vector> -#include <google/protobuf/stubs/common.h> +#include "y_absl/container/btree_map.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/port.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -115,6 +116,8 @@ class PROTOC_EXPORT CommandLineInterface { static const char* const kPathSeparator; CommandLineInterface(); + CommandLineInterface(const CommandLineInterface&) = delete; + CommandLineInterface& operator=(const CommandLineInterface&) = delete; ~CommandLineInterface(); // Register a code generator for a language. @@ -212,8 +215,8 @@ class PROTOC_EXPORT CommandLineInterface { class ErrorPrinter; class GeneratorContextImpl; class MemoryOutputStream; - typedef std::unordered_map<TProtoStringType, std::unique_ptr<GeneratorContextImpl>> - GeneratorContextMap; + using GeneratorContextMap = + y_absl::flat_hash_map<TProtoStringType, std::unique_ptr<GeneratorContextImpl>>; // Clear state from previous Run(). void Clear(); @@ -318,7 +321,7 @@ class PROTOC_EXPORT CommandLineInterface { static void GetTransitiveDependencies( const FileDescriptor* file, bool include_json_name, bool include_source_code_info, - std::set<const FileDescriptor*>* already_seen, + y_absl::flat_hash_set<const FileDescriptor*>* already_seen, RepeatedPtrField<FileDescriptorProto>* output); // Implements the --print_free_field_numbers. This function prints free field @@ -352,16 +355,19 @@ class PROTOC_EXPORT CommandLineInterface { CodeGenerator* generator; TProtoStringType help_text; }; - typedef std::map<TProtoStringType, GeneratorInfo> GeneratorMap; - GeneratorMap generators_by_flag_name_; - GeneratorMap generators_by_option_name_; + + const GeneratorInfo* FindGeneratorByFlag(const TProtoStringType& name) const; + const GeneratorInfo* FindGeneratorByOption(const TProtoStringType& option) const; + + y_absl::btree_map<TProtoStringType, GeneratorInfo> generators_by_flag_name_; + y_absl::flat_hash_map<TProtoStringType, GeneratorInfo> 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<TProtoStringType, TProtoStringType> generator_parameters_; + y_absl::flat_hash_map<TProtoStringType, TProtoStringType> generator_parameters_; // Similar to generator_parameters_, but stores the parameters for plugins. - std::map<TProtoStringType, TProtoStringType> plugin_parameters_; + y_absl::flat_hash_map<TProtoStringType, TProtoStringType> plugin_parameters_; // See AllowPlugins(). If this is empty, plugins aren't allowed. TProtoStringType plugin_prefix_; @@ -369,7 +375,7 @@ class PROTOC_EXPORT CommandLineInterface { // 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<TProtoStringType, TProtoStringType> plugins_; + y_absl::flat_hash_map<TProtoStringType, TProtoStringType> plugins_; // Stuff parsed from command line. enum Mode { @@ -403,13 +409,13 @@ class PROTOC_EXPORT CommandLineInterface { // True if we should treat warnings as errors that fail the compilation. bool fatal_warnings_ = false; - std::vector<std::pair<TProtoStringType, TProtoStringType> > + std::vector<std::pair<TProtoStringType, TProtoStringType>> proto_path_; // Search path for proto files. std::vector<TProtoStringType> 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<TProtoStringType> direct_dependencies_; + y_absl::flat_hash_set<TProtoStringType> direct_dependencies_; bool direct_dependencies_explicitly_set_ = false; // If there's a violation of depend-on-what-you-import, this string will be @@ -456,14 +462,12 @@ class PROTOC_EXPORT CommandLineInterface { // When using --encode, this will be passed to SetSerializationDeterministic. bool deterministic_output_ = false; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface); }; } // namespace compiler } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.cc index 91d0b9442b7..917cc761288 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.cc @@ -32,26 +32,49 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/cpp/enum.h> +#include "google/protobuf/compiler/cpp/enum.h" +#include <algorithm> #include <cstdint> #include <limits> -#include <map> - -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/compiler/cpp/names.h> +#include <string> +#include <utility> +#include <vector> + +#include "google/protobuf/descriptor.h" +#include "y_absl/container/btree_map.h" +#include "y_absl/container/btree_set.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/names.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { - namespace { -// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value -// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the -// generation of the GOOGLE_ARRAYSIZE constant. +using Sub = ::google::protobuf::io::Printer::Sub; + +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> EnumVars( + const EnumDescriptor* enum_, const Options& options, + const EnumValueDescriptor* min, const EnumValueDescriptor* max) { + auto classname = ClassName(enum_, false); + return { + {"Enum", enum_->name()}, + {"Enum_", ResolveKeyword(enum_->name())}, + {"Msg_Enum", classname}, + {"::Msg_Enum", QualifiedClassName(enum_, options)}, + {"Msg_Enum_", + enum_->containing_type() == nullptr ? "" : y_absl::StrCat(classname, "_")}, + {"kMin", y_absl::StrCat(min->number())}, + {"kMax", y_absl::StrCat(max->number())}, + }; +} + +// The ARRAYSIZE constant is the max enum value plus 1. If the max enum value +// is kint32max, ARRAYSIZE will overflow. In such cases we should omit the +// generation of the ARRAYSIZE constant. bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { arc_i32 max_value = descriptor->value(0)->number(); for (int i = 0; i < descriptor->value_count(); i++) { @@ -61,251 +84,323 @@ bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { } return max_value != std::numeric_limits<arc_i32>::max(); } - -// Returns the number of unique numeric enum values. This is less than -// descriptor->value_count() when there are aliased values. -int CountUniqueValues(const EnumDescriptor* descriptor) { - std::set<int> values; - for (int i = 0; i < descriptor->value_count(); ++i) { - values.insert(descriptor->value(i)->number()); +} // namespace +EnumGenerator::ValueLimits EnumGenerator::ValueLimits::FromEnum( + const EnumDescriptor* descriptor) { + const EnumValueDescriptor* min_desc = descriptor->value(0); + const EnumValueDescriptor* max_desc = descriptor->value(0); + + for (int i = 1; i < descriptor->value_count(); ++i) { + if (descriptor->value(i)->number() < min_desc->number()) { + min_desc = descriptor->value(i); + } + if (descriptor->value(i)->number() > max_desc->number()) { + max_desc = descriptor->value(i); + } } - return values.size(); -} -} // namespace + return EnumGenerator::ValueLimits{min_desc, max_desc}; +} EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, - const std::map<TProtoStringType, TProtoStringType>& vars, const Options& options) - : descriptor_(descriptor), - classname_(ClassName(descriptor, false)), + : enum_(descriptor), options_(options), generate_array_size_(ShouldGenerateArraySize(descriptor)), - variables_(vars) { - variables_["classname"] = classname_; - variables_["classtype"] = QualifiedClassName(descriptor_, options); - variables_["short_name"] = descriptor_->name(); - variables_["nested_name"] = descriptor_->name(); - variables_["resolved_name"] = ResolveKeyword(descriptor_->name()); - variables_["prefix"] = - (descriptor_->containing_type() == nullptr) ? "" : classname_ + "_"; + has_reflection_(HasDescriptorMethods(enum_->file(), options_)), + limits_(ValueLimits::FromEnum(enum_)) { + // The conditions here for what is "sparse" are not rigorously + // chosen. + size_t values_range = static_cast<size_t>(limits_.max->number()) - + static_cast<size_t>(limits_.min->number()); + size_t total_values = static_cast<size_t>(enum_->value_count()); + should_cache_ = has_reflection_ && + (values_range < 16u || values_range < total_values * 2u); } -EnumGenerator::~EnumGenerator() {} - -void EnumGenerator::GenerateDefinition(io::Printer* printer) { - Formatter format(printer, variables_); - format("enum ${1$$classname$$}$ : int {\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++) { - 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. - format_value.Set("number", Int32ToString(descriptor_->value(i)->number())); - format_value.Set("deprecation", - DeprecatedAttribute(options_, 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); - } - if (descriptor_->value(i)->number() > max_value->number()) { - max_value = descriptor_->value(i); - } - } - - if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { - // For new enum semantics: generate min and max sentinel values equal to - // INT32_MIN and INT32_MAX - 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()"); - } - - format.Outdent(); - format("\n};\n"); - - format( - "$dllexport_decl $bool $classname$_IsValid(int value);\n" - "constexpr $classname$ ${1$$prefix$$short_name$_MIN$}$ = " - "$prefix$$2$;\n" - "constexpr $classname$ ${1$$prefix$$short_name$_MAX$}$ = " - "$prefix$$3$;\n", - descriptor_, EnumValueName(min_value), EnumValueName(max_value)); +void EnumGenerator::GenerateDefinition(io::Printer* p) { + auto v1 = p->WithVars(EnumVars(enum_, options_, limits_.min, limits_.max)); + + auto v2 = p->WithVars({ + Sub("Msg_Enum_Enum_MIN", + y_absl::StrCat(p->LookupVar("Msg_Enum_"), enum_->name(), "_MIN")) + .AnnotatedAs(enum_), + Sub("Msg_Enum_Enum_MAX", + y_absl::StrCat(p->LookupVar("Msg_Enum_"), enum_->name(), "_MAX")) + .AnnotatedAs(enum_), + }); + p->Emit( + { + {"values", + [&] { + for (int i = 0; i < enum_->value_count(); ++i) { + const auto* value = enum_->value(i); + p->Emit( + { + Sub("Msg_Enum_VALUE", + y_absl::StrCat(p->LookupVar("Msg_Enum_"), + EnumValueName(value))) + .AnnotatedAs(value), + {"kNumber", Int32ToString(value->number())}, + {"DEPRECATED", value->options().deprecated() + ? "PROTOBUF_DEPRECATED_ENUM" + : ""}, + }, + R"cc( + $Msg_Enum_VALUE$$ DEPRECATED$ = $kNumber$, + )cc"); + } + }}, + // Only emit annotations for the $Msg_Enum$ used in the `enum` + // definition. + Sub("Msg_Enum_annotated", p->LookupVar("Msg_Enum")) + .AnnotatedAs(enum_), + {"open_enum_sentinels", + [&] { + if (enum_->is_closed()) { + return; + } + + // For open enum semantics: generate min and max sentinel values + // equal to INT32_MIN and INT32_MAX + p->Emit({{"Msg_Enum_Msg_Enum_", + y_absl::StrCat(p->LookupVar("Msg_Enum"), "_", + p->LookupVar("Msg_Enum_"))}}, + R"cc( + $Msg_Enum_Msg_Enum_$INT_MIN_SENTINEL_DO_NOT_USE_ = + std::numeric_limits<::arc_i32>::min(), + $Msg_Enum_Msg_Enum_$INT_MAX_SENTINEL_DO_NOT_USE_ = + std::numeric_limits<::arc_i32>::max(), + )cc"); + }}, + }, + R"cc( + enum $Msg_Enum_annotated$ : int { + $values$, + $open_enum_sentinels$, + }; + + $dllexport_decl $bool $Msg_Enum$_IsValid(int value); + constexpr $Msg_Enum$ $Msg_Enum_Enum_MIN$ = static_cast<$Msg_Enum$>($kMin$); + constexpr $Msg_Enum$ $Msg_Enum_Enum_MAX$ = static_cast<$Msg_Enum$>($kMax$); + )cc"); if (generate_array_size_) { - format( - "constexpr int ${1$$prefix$$short_name$_ARRAYSIZE$}$ = " - "$prefix$$short_name$_MAX + 1;\n\n", - descriptor_); + p->Emit({Sub("Msg_Enum_Enum_ARRAYSIZE", + y_absl::StrCat(p->LookupVar("Msg_Enum_"), enum_->name(), + "_ARRAYSIZE")) + .AnnotatedAs(enum_)}, + R"cc( + constexpr int $Msg_Enum_Enum_ARRAYSIZE$ = $kMax$ + 1; + )cc"); } - if (HasDescriptorMethods(descriptor_->file(), options_)) { - format( - "$dllexport_decl $const ::$proto_ns$::EnumDescriptor* " - "$classname$_descriptor();\n"); + if (has_reflection_) { + p->Emit(R"cc( + $dllexport_decl $const ::$proto_ns$::EnumDescriptor* + $Msg_Enum$_descriptor(); + )cc"); + } else { + p->Emit(R"cc( + const TProtoStringType& $Msg_Enum$_Name($Msg_Enum$ value); + )cc"); } - // The _Name and _Parse functions. The lite implementation is table-based, so - // we make sure to keep the tables hidden in the .cc file. - if (!HasDescriptorMethods(descriptor_->file(), options_)) { - format("const TProtoStringType& $classname$_Name($classname$ value);\n"); - } - // The _Name() function accepts the enum type itself but also any integral - // type. - format( - "template<typename T>\n" - "inline const TProtoStringType& $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"); - if (HasDescriptorMethods(descriptor_->file(), options_)) { - format( - " return ::$proto_ns$::internal::NameOfEnum(\n" - " $classname$_descriptor(), enum_t_value);\n"); + // There are three possible implementations of $Enum$_Name() and + // $Msg_Enum$_Parse(), depending on whether we are using a dense enum name + // cache or not, and whether or not we have reflection. Very little code is + // shared between the three, so it is split into three Emit() calls. + + // Can't use WithVars here, since callbacks can only be passed to Emit() + // directly. Because this includes $Enum$, it must be a callback. + auto write_assert = [&] { + p->Emit(R"cc( + static_assert(std::is_same<T, $Msg_Enum$>::value || + std::is_integral<T>::value, + "Incorrect type passed to $Enum$_Name()."); + )cc"); + }; + + if (should_cache_ || !has_reflection_) { + p->Emit({{"static_assert", write_assert}}, R"cc( + template <typename T> + const TProtoStringType& $Msg_Enum$_Name(T value) { + $static_assert$; + return $Msg_Enum$_Name(static_cast<$Msg_Enum$>(value)); + } + )cc"); + if (should_cache_) { + // Using the NameOfEnum routine can be slow, so we create a small + // cache of pointers to the TProtoStringType objects that reflection + // stores internally. This cache is a simple contiguous array of + // pointers, so if the enum values are sparse, it's not worth it. + p->Emit(R"cc( + template <> + inline const TProtoStringType& $Msg_Enum$_Name($Msg_Enum$ value) { + return ::$proto_ns$::internal::NameOfDenseEnum<$Msg_Enum$_descriptor, + $kMin$, $kMax$>( + static_cast<int>(value)); + } + )cc"); + } else { + p->Emit(R"cc( + const TProtoStringType& $Msg_Enum$_Name($Msg_Enum$ value); + )cc"); + } } else { - format( - " return $classname$_Name(static_cast<$classname$>(enum_t_value));\n"); + p->Emit({{"static_assert", write_assert}}, R"cc( + template <typename T> + const TProtoStringType& $Msg_Enum$_Name(T value) { + $static_assert$; + return ::$proto_ns$::internal::NameOfEnum($Msg_Enum$_descriptor(), value); + } + )cc"); } - format("}\n"); - - if (HasDescriptorMethods(descriptor_->file(), options_)) { - format( - "inline bool $classname$_Parse(\n" - " ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* " - "value) " - "{\n" - " return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n" - " $classname$_descriptor(), name, value);\n" - "}\n"); + + if (has_reflection_) { + p->Emit(R"cc( + inline bool $Msg_Enum$_Parse(y_absl::string_view name, $Msg_Enum$* value) { + return ::$proto_ns$::internal::ParseNamedEnum<$Msg_Enum$>( + $Msg_Enum$_descriptor(), name, value); + } + )cc"); } else { - format( - "bool $classname$_Parse(\n" - " ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* " - "value);\n"); + p->Emit(R"cc( + bool $Msg_Enum$_Parse(y_absl::string_view name, $Msg_Enum$* value); + )cc"); } } -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_)) { - format( - "template <>\n" - "inline const EnumDescriptor* GetEnumDescriptor< $classtype$>() {\n" - " return $classtype$_descriptor();\n" - "}\n"); +void EnumGenerator::GenerateGetEnumDescriptorSpecializations(io::Printer* p) { + auto v = p->WithVars(EnumVars(enum_, options_, limits_.min, limits_.max)); + + p->Emit(R"cc( + template <> + struct is_proto_enum<$::Msg_Enum$> : std::true_type {}; + )cc"); + if (!has_reflection_) { + return; } + p->Emit(R"cc( + template <> + inline const EnumDescriptor* GetEnumDescriptor<$::Msg_Enum$>() { + return $::Msg_Enum$_descriptor(); + } + )cc"); } -void EnumGenerator::GenerateSymbolImports(io::Printer* printer) const { - Formatter format(printer, variables_); - format("typedef $classname$ $resolved_name$;\n"); - - for (int j = 0; j < descriptor_->value_count(); j++) { - TProtoStringType deprecated_attr = - DeprecatedAttribute(options_, descriptor_->value(j)); - format( - "$1$static constexpr $resolved_name$ ${2$$3$$}$ =\n" - " $classname$_$3$;\n", - deprecated_attr, descriptor_->value(j), - EnumValueName(descriptor_->value(j))); +void EnumGenerator::GenerateSymbolImports(io::Printer* p) const { + auto v = p->WithVars(EnumVars(enum_, options_, limits_.min, limits_.max)); + + p->Emit({Sub("Enum_", p->LookupVar("Enum_")).AnnotatedAs(enum_)}, R"cc( + using $Enum_$ = $Msg_Enum$; + )cc"); + + for (int j = 0; j < enum_->value_count(); ++j) { + const auto* value = enum_->value(j); + p->Emit( + { + Sub("VALUE", EnumValueName(enum_->value(j))).AnnotatedAs(value), + {"DEPRECATED", + value->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM" : ""}, + }, + R"cc( + $DEPRECATED $static constexpr $Enum_$ $VALUE$ = $Msg_Enum$_$VALUE$; + )cc"); } - format( - "static inline bool $nested_name$_IsValid(int value) {\n" - " return $classname$_IsValid(value);\n" - "}\n" - "static constexpr $resolved_name$ ${1$$nested_name$_MIN$}$ =\n" - " $classname$_$nested_name$_MIN;\n" - "static constexpr $resolved_name$ ${1$$nested_name$_MAX$}$ =\n" - " $classname$_$nested_name$_MAX;\n", - descriptor_); + p->Emit( + { + Sub("Enum_MIN", y_absl::StrCat(enum_->name(), "_MIN")) + .AnnotatedAs(enum_), + Sub("Enum_MAX", y_absl::StrCat(enum_->name(), "_MAX")) + .AnnotatedAs(enum_), + }, + R"cc( + static inline bool $Enum$_IsValid(int value) { + return $Msg_Enum$_IsValid(value); + } + static constexpr $Enum_$ $Enum_MIN$ = $Msg_Enum$_$Enum$_MIN; + static constexpr $Enum_$ $Enum_MAX$ = $Msg_Enum$_$Enum$_MAX; + )cc"); + if (generate_array_size_) { - format( - "static constexpr int ${1$$nested_name$_ARRAYSIZE$}$ =\n" - " $classname$_$nested_name$_ARRAYSIZE;\n", - descriptor_); + p->Emit( + { + Sub("Enum_ARRAYSIZE", y_absl::StrCat(enum_->name(), "_ARRAYSIZE")) + .AnnotatedAs(enum_), + }, + R"cc( + static constexpr int $Enum_ARRAYSIZE$ = $Msg_Enum$_$Enum$_ARRAYSIZE; + )cc"); } - if (HasDescriptorMethods(descriptor_->file(), options_)) { - format( - "static inline const ::$proto_ns$::EnumDescriptor*\n" - "$nested_name$_descriptor() {\n" - " return $classname$_descriptor();\n" - "}\n"); + if (has_reflection_) { + p->Emit(R"cc( + static inline const ::$proto_ns$::EnumDescriptor* $Enum$_descriptor() { + return $Msg_Enum$_descriptor(); + } + )cc"); } - format( - "template<typename T>\n" - "static inline const TProtoStringType& $nested_name$_Name(T enum_t_value) {\n" - " static_assert(::std::is_same<T, $resolved_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(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,\n" - " $resolved_name$* value) {\n" - " return $classname$_Parse(name, value);\n" - "}\n"); + p->Emit(R"cc( + template <typename T> + static inline const TProtoStringType& $Enum$_Name(T value) { + return $Msg_Enum$_Name(value); + } + static inline bool $Enum$_Parse(y_absl::string_view name, $Enum_$* value) { + return $Msg_Enum$_Parse(name, value); + } + )cc"); } -void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) { - Formatter format(printer, variables_); - if (HasDescriptorMethods(descriptor_->file(), options_)) { - format( - "const ::$proto_ns$::EnumDescriptor* $classname$_descriptor() {\n" - " ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n" - " return $file_level_enum_descriptors$[$1$];\n" - "}\n", - idx); - } - - 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 - // numbers, then printing a case statement for each element. - - std::set<int> numbers; - for (int j = 0; j < descriptor_->value_count(); j++) { - const EnumValueDescriptor* value = descriptor_->value(j); - numbers.insert(value->number()); - } +void EnumGenerator::GenerateMethods(int idx, io::Printer* p) { + auto v = p->WithVars(EnumVars(enum_, options_, limits_.min, limits_.max)); - for (std::set<int>::iterator iter = numbers.begin(); iter != numbers.end(); - ++iter) { - format(" case $1$:\n", Int32ToString(*iter)); + if (has_reflection_) { + p->Emit({{"idx", idx}}, R"cc( + const ::$proto_ns$::EnumDescriptor* $Msg_Enum$_descriptor() { + ::$proto_ns$::internal::AssignDescriptors(&$desc_table$); + return $file_level_enum_descriptors$[$idx$]; + } + )cc"); } - format( - " return true;\n" - " default:\n" - " return false;\n" - " }\n" - "}\n" - "\n"); - - if (!HasDescriptorMethods(descriptor_->file(), options_)) { + p->Emit({{"cases", + [&] { + // Multiple values may have the same number. Make sure we only + // cover each number once by first constructing a set containing + // all valid numbers, then printing a case statement for each + // element. + + std::vector<int> numbers; + numbers.reserve(enum_->value_count()); + for (int i = 0; i < enum_->value_count(); ++i) { + numbers.push_back(enum_->value(i)->number()); + } + // Sort and deduplicate `numbers`. + y_absl::c_sort(numbers); + numbers.erase(std::unique(numbers.begin(), numbers.end()), + numbers.end()); + + for (int n : numbers) { + p->Emit({{"n", n}}, R"cc( + case $n$: + )cc"); + } + }}}, + R"( + bool $Msg_Enum$_IsValid(int value) { + switch (value) { + $cases$; + return true; + default: + return false; + } + } + )"); + + if (!has_reflection_) { // In lite mode (where descriptors are unavailable), we generate separate // tables for mapping between enum names and numbers. The _entries table // contains the bulk of the data and is sorted by name, while @@ -319,119 +414,168 @@ void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) { // numerical value. In cases where there are multiple names for the same // number, we treat the first name appearing in the .proto file as the // canonical one. - std::map<TProtoStringType, int> name_to_number; - std::map<int, TProtoStringType> number_to_canonical_name; - for (int i = 0; i < descriptor_->value_count(); i++) { - const EnumValueDescriptor* value = descriptor_->value(i); + + y_absl::btree_map<TProtoStringType, int> name_to_number; + y_absl::flat_hash_map<int, TProtoStringType> number_to_canonical_name; + for (int i = 0; i < enum_->value_count(); ++i) { + const auto* value = enum_->value(i); name_to_number.emplace(value->name(), value->number()); + // The same number may appear with multiple names, so we use emplace() to // let the first name win. number_to_canonical_name.emplace(value->number(), value->name()); } - format( - "static ::$proto_ns$::internal::ExplicitlyConstructed<TProtoStringType> " - "$classname$_strings[$1$] = {};\n\n", - CountUniqueValues(descriptor_)); - - // We concatenate all the names for a given enum into one big string - // literal. If instead we store an array of string literals, the linker - // seems to put all enum strings for a given .proto file in the same - // section, which hinders its ability to strip out unused strings. - format("static const char $classname$_names[] ="); - for (const auto& p : name_to_number) { - format("\n \"$1$\"", p.first); + // Build the offset table for the strings table. + struct Offset { + int number; + size_t index, byte_offset, len; + }; + std::vector<Offset> offsets; + size_t index = 0; + size_t offset = 0; + for (const auto& e : name_to_number) { + offsets.push_back(Offset{e.second, index, offset, e.first.size()}); + ++index; + offset += e.first.size(); } - format(";\n\n"); - - format( - "static const ::$proto_ns$::internal::EnumEntry $classname$_entries[] " - "= {\n"); - int i = 0; - std::map<int, int> number_to_index; - int data_index = 0; - for (const auto& p : name_to_number) { - format(" { {$classname$_names + $1$, $2$}, $3$ },\n", data_index, - p.first.size(), p.second); - if (number_to_canonical_name[p.second] == p.first) { - number_to_index.emplace(p.second, i); - } - ++i; - data_index += p.first.size(); - } - - format( - "};\n" - "\n" - "static const int $classname$_entries_by_number[] = {\n"); - for (const auto& p : number_to_index) { - format(" $1$, // $2$ -> $3$\n", p.second, p.first, - number_to_canonical_name[p.first]); - } - format( - "};\n" - "\n"); - - format( - "const TProtoStringType& $classname$_Name(\n" - " $classname$ value) {\n" - " static const bool dummy =\n" - " ::$proto_ns$::internal::InitializeEnumStrings(\n" - " $classname$_entries,\n" - " $classname$_entries_by_number,\n" - " $1$, $classname$_strings);\n" - " (void) dummy;\n" - " int idx = ::$proto_ns$::internal::LookUpEnumName(\n" - " $classname$_entries,\n" - " $classname$_entries_by_number,\n" - " $1$, value);\n" - " return idx == -1 ? ::$proto_ns$::internal::GetEmptyString() :\n" - " $classname$_strings[idx].get();\n" - "}\n", - CountUniqueValues(descriptor_)); - format( - "bool $classname$_Parse(\n" - " ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* " - "value) " - "{\n" - " int int_value;\n" - " bool success = ::$proto_ns$::internal::LookUpEnumValue(\n" - " $classname$_entries, $1$, name, &int_value);\n" - " if (success) {\n" - " *value = static_cast<$classname$>(int_value);\n" - " }\n" - " return success;\n" - "}\n", - descriptor_->value_count()); + y_absl::c_sort(offsets, [](const auto& a, const auto& b) { + return a.byte_offset < b.byte_offset; + }); + + std::vector<Offset> offsets_by_number = offsets; + y_absl::c_sort(offsets_by_number, [](const auto& a, const auto& b) { + return a.number < b.number; + }); + + offsets_by_number.erase( + std::unique( + offsets_by_number.begin(), offsets_by_number.end(), + [](const auto& a, const auto& b) { return a.number == b.number; }), + offsets_by_number.end()); + + p->Emit( + { + {"num_unique", number_to_canonical_name.size()}, + {"num_declared", enum_->value_count()}, + {"names", + // We concatenate all the names for a given enum into one big + // string literal. If instead we store an array of string + // literals, the linker seems to put all enum strings for a given + // .proto file in the same section, which hinders its ability to + // strip out unused strings. + [&] { + for (const auto& e : name_to_number) { + p->Emit({{"name", e.first}}, R"cc( + "$name$" + )cc"); + } + }}, + {"entries", + [&] { + for (const auto& offset : offsets) { + p->Emit({{"number", offset.number}, + {"offset", offset.byte_offset}, + {"len", offset.len}}, + R"cc( + {{&$Msg_Enum$_names[$offset$], $len$}, $number$}, + )cc"); + } + }}, + {"entries_by_number", + [&] { + for (const auto& offset : offsets_by_number) { + p->Emit({{"number", offset.number}, + {"index", offset.index}, + {"name", number_to_canonical_name[offset.number]}}, + R"cc( + $index$, // $number$ -> $name$ + )cc"); + } + }}, + }, + R"cc( + static ::$proto_ns$::internal::ExplicitlyConstructed<TProtoStringType> + $Msg_Enum$_strings[$num_unique$] = {}; + + static const char $Msg_Enum$_names[] = { + $names$, + }; + + static const ::$proto_ns$::internal::EnumEntry $Msg_Enum$_entries[] = + { + $entries$, + }; + + static const int $Msg_Enum$_entries_by_number[] = { + $entries_by_number$, + }; + + const TProtoStringType& $Msg_Enum$_Name($Msg_Enum$ value) { + static const bool kDummy = + ::$proto_ns$::internal::InitializeEnumStrings( + $Msg_Enum$_entries, $Msg_Enum$_entries_by_number, + $num_unique$, $Msg_Enum$_strings); + (void)kDummy; + + int idx = ::$proto_ns$::internal::LookUpEnumName( + $Msg_Enum$_entries, $Msg_Enum$_entries_by_number, $num_unique$, + value); + return idx == -1 ? ::$proto_ns$::internal::GetEmptyString() + : $Msg_Enum$_strings[idx].get(); + } + + bool $Msg_Enum$_Parse(y_absl::string_view name, $Msg_Enum$* value) { + int int_value; + bool success = ::$proto_ns$::internal::LookUpEnumValue( + $Msg_Enum$_entries, $num_declared$, name, &int_value); + if (success) { + *value = static_cast<$Msg_Enum$>(int_value); + } + return success; + } + )cc"); } - if (descriptor_->containing_type() != nullptr) { - TProtoStringType parent = ClassName(descriptor_->containing_type(), false); + if (enum_->containing_type() != nullptr) { // Before C++17, we must define the static constants which were // declared in the header, to give the linker a place to put them. // But MSVC++ pre-2015 and post-2017 (version 15.5+) insists that we not. - format( - "#if (__cplusplus < 201703) && " - "(!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))\n"); - - for (int i = 0; i < descriptor_->value_count(); i++) { - format("constexpr $classname$ $1$::$2$;\n", parent, - EnumValueName(descriptor_->value(i))); - } - format( - "constexpr $classname$ $1$::$nested_name$_MIN;\n" - "constexpr $classname$ $1$::$nested_name$_MAX;\n", - parent); - if (generate_array_size_) { - format("constexpr int $1$::$nested_name$_ARRAYSIZE;\n", parent); - } - - format( - "#endif // (__cplusplus < 201703) && " - "(!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))\n"); + p->Emit( + { + {"Msg_", ClassName(enum_->containing_type(), false)}, + {"constexpr_storage", + [&] { + for (int i = 0; i < enum_->value_count(); i++) { + p->Emit({{"VALUE", EnumValueName(enum_->value(i))}}, + R"cc( + constexpr $Msg_Enum$ $Msg_$::$VALUE$; + )cc"); + } + }}, + {"array_size", + [&] { + if (generate_array_size_) { + p->Emit(R"cc( + constexpr int $Msg_$::$Enum$_ARRAYSIZE; + )cc"); + } + }}, + }, + R"( + #if (__cplusplus < 201703) && \ + (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) + + $constexpr_storage$; + constexpr $Msg_Enum$ $Msg_$::$Enum$_MIN; + constexpr $Msg_Enum$ $Msg_$::$Enum$_MAX; + $array_size$; + + #endif // (__cplusplus < 201703) && + // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) + )"); } } - } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.h index 550f43b1ed4..58a62f5533a 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.h @@ -35,67 +35,64 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__ -#include <map> -#include <set> #include <string> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/cpp/options.h> - -namespace google { -namespace protobuf { -namespace io { -class Printer; // printer.h -} -} // namespace protobuf -} // namespace google +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { - class EnumGenerator { public: - // See generator.cc for the meaning of dllexport_decl. - EnumGenerator(const EnumDescriptor* descriptor, - const std::map<TProtoStringType, TProtoStringType>& vars, - const Options& options); - ~EnumGenerator(); + EnumGenerator(const EnumDescriptor* descriptor, const Options& options); + + EnumGenerator(const EnumGenerator&) = delete; + EnumGenerator& operator=(const EnumGenerator&) = delete; + + ~EnumGenerator() = default; // 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. - void GenerateDefinition(io::Printer* printer); + void GenerateDefinition(io::Printer* p); // Generate specialization of GetEnumDescriptor<MyEnum>(). // Precondition: in ::google::protobuf namespace. - void GenerateGetEnumDescriptorSpecializations(io::Printer* printer); + void GenerateGetEnumDescriptorSpecializations(io::Printer* p); // For enums nested within a message, generate code to import all the enum's // 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) const; + void GenerateSymbolImports(io::Printer* p) const; // Source file stuff. // Generate non-inline methods related to the enum, such as IsValidValue(). // Goes in the .cc file. EnumDescriptors are stored in an array, idx is // the index in this array that corresponds with this enum. - void GenerateMethods(int idx, io::Printer* printer); + void GenerateMethods(int idx, io::Printer* p); private: - const EnumDescriptor* descriptor_; - const TProtoStringType classname_; - const Options& options_; - // whether to generate the *_ARRAYSIZE constant. - const bool generate_array_size_; + friend class FileGenerator; - std::map<TProtoStringType, TProtoStringType> variables_; + struct ValueLimits { + const EnumValueDescriptor* min; + const EnumValueDescriptor* max; - friend class FileGenerator; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); + static ValueLimits FromEnum(const EnumDescriptor* descriptor); + }; + + const EnumDescriptor* enum_; + Options options_; + + bool generate_array_size_; + bool should_cache_; + bool has_reflection_; + ValueLimits limits_; }; } // namespace cpp diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.cc deleted file mode 100644 index dc8dc524815..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.cc +++ /dev/null @@ -1,451 +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: [email protected] (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <google/protobuf/compiler/cpp/enum_field.h> - -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/cpp/field.h> -#include <google/protobuf/compiler/cpp/helpers.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace cpp { - -namespace { - -void SetEnumVariables(const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables, - const Options& options) { - SetCommonFieldVariables(descriptor, variables, options); - const EnumValueDescriptor* default_value = descriptor->default_value_enum(); - (*variables)["type"] = QualifiedClassName(descriptor->enum_type(), options); - (*variables)["default"] = Int32ToString(default_value->number()); - (*variables)["full_name"] = descriptor->full_name(); - (*variables)["cached_byte_size_name"] = MakeVarintCachedSizeName(descriptor); - bool cold = ShouldSplit(descriptor, options); - (*variables)["cached_byte_size_field"] = - MakeVarintCachedSizeFieldName(descriptor, cold); -} - -} // namespace - -// =================================================================== - -EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : FieldGenerator(descriptor, options) { - SetEnumVariables(descriptor, &variables_, options); -} - -EnumFieldGenerator::~EnumFieldGenerator() {} - -void EnumFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { - Formatter format(printer, variables_); - format("int $name$_;\n"); -} - -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" - "private:\n" - "$type$ ${1$_internal_$name$$}$() const;\n" - "void ${1$_internal_set_$name$$}$($type$ value);\n" - "public:\n", - descriptor_); -} - -void EnumFieldGenerator::GenerateInlineAccessorDefinitions( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "inline $type$ $classname$::_internal_$name$() const {\n" - " return static_cast< $type$ >($field$);\n" - "}\n" - "inline $type$ $classname$::$name$() const {\n" - "$annotate_get$" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return _internal_$name$();\n" - "}\n" - "inline void $classname$::_internal_set_$name$($type$ value) {\n"); - if (!HasPreservingUnknownEnumSemantics(descriptor_)) { - format(" assert($type$_IsValid(value));\n"); - } - format( - " $set_hasbit$\n" - " $field$ = value;\n" - "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" - "$maybe_prepare_split_message$" - " _internal_set_$name$(value);\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); -} - -void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$ = $default$;\n"); -} - -void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const { - Formatter format(printer, variables_); - format("_this->_internal_set_$name$(from._internal_$name$());\n"); -} - -void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { - Formatter format(printer, variables_); - format("swap($field$, other->$field$);\n"); -} - -void EnumFieldGenerator::GenerateCopyConstructorCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("_this->$field$ = from.$field$;\n"); -} - -void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "target = stream->EnsureSpace(target);\n" - "target = ::_pbi::WireFormatLite::WriteEnumToArray(\n" - " $number$, this->_internal_$name$(), target);\n"); -} - -void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "total_size += $tag_size$ +\n" - " ::_pbi::WireFormatLite::EnumSize(this->_internal_$name$());\n"); -} - -void EnumFieldGenerator::GenerateConstexprAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("/*decltype($field$)*/$default$"); -} - -void EnumFieldGenerator::GenerateAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - if (ShouldSplit(descriptor_, options_)) { - format("decltype(Impl_::Split::$name$_){$default$}"); - return; - } - format("decltype($field$){$default$}"); -} - -void EnumFieldGenerator::GenerateCopyAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("decltype($field$){}"); -} - -// =================================================================== - -EnumOneofFieldGenerator::EnumOneofFieldGenerator( - const FieldDescriptor* descriptor, const Options& options) - : EnumFieldGenerator(descriptor, options) { - SetCommonOneofFieldVariables(descriptor, &variables_); -} - -EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {} - -void EnumOneofFieldGenerator::GenerateInlineAccessorDefinitions( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "inline $type$ $classname$::_internal_$name$() const {\n" - " if (_internal_has_$name$()) {\n" - " return static_cast< $type$ >($field$);\n" - " }\n" - " return static_cast< $type$ >($default$);\n" - "}\n" - "inline $type$ $classname$::$name$() const {\n" - "$annotate_get$" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return _internal_$name$();\n" - "}\n" - "inline void $classname$::_internal_set_$name$($type$ value) {\n"); - if (!HasPreservingUnknownEnumSemantics(descriptor_)) { - format(" assert($type$_IsValid(value));\n"); - } - format( - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " }\n" - " $field$ = value;\n" - "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" - " _internal_set_$name$(value);\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); -} - -void EnumOneofFieldGenerator::GenerateClearingCode(io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$ = $default$;\n"); -} - -void EnumOneofFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { - // Don't print any swapping code. Swapping the union will swap this field. -} - -void EnumOneofFieldGenerator::GenerateConstructorCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$ns$::_$classname$_default_instance_.$field$ = $default$;\n"); -} - -// =================================================================== - -RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( - const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(descriptor, options) { - SetEnumVariables(descriptor, &variables_, options); -} - -RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} - -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_)) { - format("mutable std::atomic<int> $cached_byte_size_name$;\n"); - } -} - -void RepeatedEnumFieldGenerator::GenerateAccessorDeclarations( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "private:\n" - "$type$ ${1$_internal_$name$$}$(int index) const;\n" - "void ${1$_internal_add_$name$$}$($type$ value);\n" - "::$proto_ns$::RepeatedField<int>* " - "${1$_internal_mutable_$name$$}$();\n" - "public:\n" - "$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$::_internal_$name$(int index) const {\n" - " return static_cast< $type$ >($field$.Get(index));\n" - "}\n" - "inline $type$ $classname$::$name$(int index) const {\n" - "$annotate_get$" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return _internal_$name$(index);\n" - "}\n" - "inline void $classname$::set_$name$(int index, $type$ value) {\n"); - if (!HasPreservingUnknownEnumSemantics(descriptor_)) { - format(" assert($type$_IsValid(value));\n"); - } - format( - " $field$.Set(index, value);\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "inline void $classname$::_internal_add_$name$($type$ value) {\n"); - if (!HasPreservingUnknownEnumSemantics(descriptor_)) { - format(" assert($type$_IsValid(value));\n"); - } - format( - " $field$.Add(value);\n" - "}\n" - "inline void $classname$::add_$name$($type$ value) {\n" - " _internal_add_$name$(value);\n" - "$annotate_add$" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "inline const ::$proto_ns$::RepeatedField<int>&\n" - "$classname$::$name$() const {\n" - "$annotate_list$" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $field$;\n" - "}\n" - "inline ::$proto_ns$::RepeatedField<int>*\n" - "$classname$::_internal_mutable_$name$() {\n" - " return &$field$;\n" - "}\n" - "inline ::$proto_ns$::RepeatedField<int>*\n" - "$classname$::mutable_$name$() {\n" - "$annotate_mutable_list$" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return _internal_mutable_$name$();\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator::GenerateClearingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$.Clear();\n"); -} - -void RepeatedEnumFieldGenerator::GenerateMergingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("_this->$field$.MergeFrom(from.$field$);\n"); -} - -void RepeatedEnumFieldGenerator::GenerateSwappingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$.InternalSwap(&other->$field$);\n"); -} - -void RepeatedEnumFieldGenerator::GenerateConstructorCode( - io::Printer* printer) const { - // Not needed for repeated fields. -} - -void RepeatedEnumFieldGenerator::GenerateDestructorCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$.~RepeatedField();\n"); -} - -void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const { - Formatter format(printer, variables_); - if (descriptor_->is_packed()) { - // Write the tag and the size. - format( - "{\n" - " int byte_size = " - "$cached_byte_size_field$.load(std::memory_order_relaxed);\n" - " if (byte_size > 0) {\n" - " target = stream->WriteEnumPacked(\n" - " $number$, $field$, byte_size, target);\n" - " }\n" - "}\n"); - } else { - format( - "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n" - " target = stream->EnsureSpace(target);\n" - " target = ::_pbi::WireFormatLite::WriteEnumToArray(\n" - " $number$, this->_internal_$name$(i), target);\n" - "}\n"); - } -} - -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->_internal_$name$_size());"); - format.Indent(); - format( - "for (unsigned int i = 0; i < count; i++) {\n" - " data_size += ::_pbi::WireFormatLite::EnumSize(\n" - " this->_internal_$name$(static_cast<int>(i)));\n" - "}\n"); - - if (descriptor_->is_packed()) { - format( - "if (data_size > 0) {\n" - " total_size += $tag_size$ +\n" - " " - "::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n" - "}\n" - "int cached_size = ::_pbi::ToCachedSize(data_size);\n" - "$cached_byte_size_field$.store(cached_size,\n" - " std::memory_order_relaxed);\n" - "total_size += data_size;\n"); - } else { - format("total_size += ($tag_size$UL * count) + data_size;\n"); - } - format.Outdent(); - format("}\n"); -} - -void RepeatedEnumFieldGenerator::GenerateConstexprAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("/*decltype($field$)*/{}"); - if (descriptor_->is_packed() && - HasGeneratedMethods(descriptor_->file(), options_)) { - format("\n, /*decltype($cached_byte_size_field$)*/{0}"); - } -} - -void RepeatedEnumFieldGenerator::GenerateAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("decltype($field$){arena}"); - if (descriptor_->is_packed() && - HasGeneratedMethods(descriptor_->file(), options_)) { - // std::atomic has no copy constructor, which prevents explicit aggregate - // initialization pre-C++17. - format("\n, /*decltype($cached_byte_size_field$)*/{0}"); - } -} - -void RepeatedEnumFieldGenerator::GenerateCopyAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("decltype($field$){from.$field$}"); - if (descriptor_->is_packed() && - HasGeneratedMethods(descriptor_->file(), options_)) { - // std::atomic has no copy constructor. - format("\n, /*decltype($cached_byte_size_field$)*/{0}"); - } -} - -} // namespace cpp -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.h deleted file mode 100644 index 61bae855cd6..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.h +++ /dev/null @@ -1,125 +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: [email protected] (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__ - -#include <map> -#include <string> - -#include <google/protobuf/compiler/cpp/field.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace cpp { - -class EnumFieldGenerator : public FieldGenerator { - public: - EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options); - ~EnumFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GeneratePrivateMembers(io::Printer* printer) const override; - void GenerateAccessorDeclarations(io::Printer* printer) const override; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateMergingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override {} - void GenerateCopyConstructorCode(io::Printer* printer) const override; - void GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const override; - void GenerateByteSize(io::Printer* printer) const override; - void GenerateConstexprAggregateInitializer( - io::Printer* printer) const override; - void GenerateAggregateInitializer(io::Printer* printer) const override; - void GenerateCopyAggregateInitializer(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); -}; - -class EnumOneofFieldGenerator : public EnumFieldGenerator { - public: - EnumOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~EnumOneofFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator); -}; - -class RepeatedEnumFieldGenerator : public FieldGenerator { - public: - RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~RepeatedEnumFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GeneratePrivateMembers(io::Printer* printer) const override; - void GenerateAccessorDeclarations(io::Printer* printer) const override; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateMergingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override; - void GenerateCopyConstructorCode(io::Printer* /*printer*/) const override { - GOOGLE_CHECK(!ShouldSplit(descriptor_, options_)); - } - void GenerateDestructorCode(io::Printer* printer) const override; - void GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const override; - void GenerateByteSize(io::Printer* printer) const override; - void GenerateConstexprAggregateInitializer( - io::Printer* printer) const override; - void GenerateAggregateInitializer(io::Printer* printer) const override; - void GenerateCopyAggregateInitializer(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); -}; - -} // namespace cpp -} // namespace compiler -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.cc index ed85f75960a..60ef25c1356 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.cc @@ -32,14 +32,13 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/cpp/extension.h> +#include "google/protobuf/compiler/cpp/extension.h" -#include <map> - -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_replace.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -77,7 +76,6 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, type_traits_.append(" >"); break; } - SetCommonVars(options, &variables_); SetCommonMessageDataVariables(descriptor_->containing_type(), &variables_); variables_["extendee"] = QualifiedClassName(descriptor_->containing_type(), options_); @@ -86,14 +84,18 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, variables_["name"] = ResolveKeyword(name); variables_["constant_name"] = FieldConstantName(descriptor_); variables_["field_type"] = - StrCat(static_cast<int>(descriptor_->type())); + y_absl::StrCat(static_cast<int>(descriptor_->type())); variables_["packed"] = descriptor_->is_packed() ? "true" : "false"; - TProtoStringType scope = - IsScoped() ? ClassName(descriptor_->extension_scope(), false) + "::" : ""; + TProtoStringType scope; + if (IsScoped()) { + scope = + y_absl::StrCat(ClassName(descriptor_->extension_scope(), false), "::"); + } + variables_["scope"] = scope; variables_["scoped_name"] = ExtensionName(descriptor_); - variables_["number"] = StrCat(descriptor_->number()); + variables_["number"] = y_absl::StrCat(descriptor_->number()); bool add_verify_fn = // Only verify msgs. @@ -104,7 +106,7 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, variables_["verify_fn"] = add_verify_fn - ? StrCat("&", FieldMessageTypeName(descriptor_, options_), + ? y_absl::StrCat("&", FieldMessageTypeName(descriptor_, options_), "::InternalVerify") : "nullptr"; } @@ -125,7 +127,7 @@ void ExtensionGenerator::GenerateDeclaration(io::Printer* printer) const { if (!IsScoped()) { qualifier = "extern"; if (!options_.dllexport_decl.empty()) { - qualifier = options_.dllexport_decl + " " + qualifier; + qualifier = y_absl::StrCat(options_.dllexport_decl, " ", qualifier); } } else { qualifier = "static"; @@ -159,14 +161,15 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) { // it in the header which would be annoying for other reasons. So we // replace :: with _ in the name and declare it as a global. default_str = - StringReplace(variables_["scoped_name"], "::", "_", true) + "_default"; + y_absl::StrReplaceAll(variables_["scoped_name"], {{"::", "_"}}) + + "_default"; format("const TProtoStringType $1$($2$);\n", default_str, DefaultValue(options_, descriptor_)); } else if (descriptor_->message_type()) { // We have to initialize the default instance for extensions at registration // time. - default_str = - FieldMessageTypeName(descriptor_, options_) + "::default_instance()"; + default_str = y_absl::StrCat(FieldMessageTypeName(descriptor_, options_), + "::default_instance()"); } else { default_str = DefaultValue(options_, descriptor_); } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.h index b94b178868a..e93473dbab1 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.h @@ -35,11 +35,11 @@ #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/options.h> +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -66,6 +66,8 @@ class ExtensionGenerator { explicit ExtensionGenerator(const FieldDescriptor* descriptor, const Options& options, MessageSCCAnalyzer* scc_analyzer); + ExtensionGenerator(const ExtensionGenerator&) = delete; + ExtensionGenerator& operator=(const ExtensionGenerator&) = delete; ~ExtensionGenerator(); // Header stuff. @@ -82,9 +84,7 @@ class ExtensionGenerator { Options options_; MessageSCCAnalyzer* scc_analyzer_; - std::map<TProtoStringType, TProtoStringType> variables_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; }; } // namespace cpp diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.cc index d5359b6d247..361c039cc52 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.cc @@ -32,276 +32,89 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/cpp/field.h> +#include "google/protobuf/compiler/cpp/field.h" #include <cstdint> #include <memory> #include <string> - -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/compiler/cpp/primitive_field.h> -#include <google/protobuf/compiler/cpp/string_field.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/compiler/cpp/enum_field.h> -#include <google/protobuf/compiler/cpp/map_field.h> -#include <google/protobuf/compiler/cpp/message_field.h> -#include <google/protobuf/descriptor.pb.h> +#include <vector> + +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/types/optional.h" +#include "google/protobuf/compiler/cpp/field_generators/generators.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/compiler/cpp/tracker.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { - -using internal::WireFormat; - -namespace { - -void MaySetAnnotationVariable(const Options& options, - StringPiece annotation_name, - StringPiece substitute_template_prefix, - StringPiece prepared_template, - int field_index, StringPiece access_type, - std::map<TProtoStringType, TProtoStringType>* variables) { - if (options.field_listener_options.forbidden_field_listener_events.count( - TProtoStringType(annotation_name))) - return; - (*variables)[StrCat("annotate_", annotation_name)] = strings::Substitute( - StrCat(substitute_template_prefix, prepared_template, ");\n"), - field_index, access_type); -} - -TProtoStringType GenerateTemplateForOneofString(const FieldDescriptor* descriptor, - StringPiece proto_ns, - StringPiece field_member) { - TProtoStringType field_name = google::protobuf::compiler::cpp::FieldName(descriptor); - TProtoStringType field_pointer = - descriptor->options().ctype() == google::protobuf::FieldOptions::STRING - ? "$0.UnsafeGetPointer()" - : "$0"; - - if (descriptor->default_value_string().empty()) { - return strings::Substitute(StrCat("_internal_has_", field_name, "() ? ", - field_pointer, ": nullptr"), - field_member); - } - - if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING_PIECE) { - return strings::Substitute(StrCat("_internal_has_", field_name, "() ? ", - field_pointer, ": nullptr"), - field_member); - } - - TProtoStringType default_value_pointer = - descriptor->options().ctype() == google::protobuf::FieldOptions::STRING - ? "&$1.get()" - : "&$1"; - return strings::Substitute( - StrCat("_internal_has_", field_name, "() ? ", field_pointer, " : ", - default_value_pointer), - field_member, MakeDefaultFieldName(descriptor)); -} - -TProtoStringType GenerateTemplateForSingleString(const FieldDescriptor* descriptor, - StringPiece field_member) { - if (descriptor->default_value_string().empty()) { - return StrCat("&", field_member); - } - - if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING) { - return strings::Substitute( - "$0.IsDefault() ? &$1.get() : $0.UnsafeGetPointer()", field_member, - MakeDefaultFieldName(descriptor)); - } - - return StrCat("&", field_member); -} - -} // namespace - -void AddAccessorAnnotations(const FieldDescriptor* descriptor, - const Options& options, - std::map<TProtoStringType, TProtoStringType>* variables) { - // Can be expanded to include more specific calls, for example, for arena or - // clear calls. - static constexpr const char* kAccessorsAnnotations[] = { - "annotate_add", "annotate_get", "annotate_has", - "annotate_list", "annotate_mutable", "annotate_mutable_list", - "annotate_release", "annotate_set", "annotate_size", - "annotate_clear", "annotate_add_mutable", +using ::google::protobuf::internal::WireFormat; +using Sub = ::google::protobuf::io::Printer::Sub; + +std::vector<Sub> FieldVars(const FieldDescriptor* field, const Options& opts) { + bool split = ShouldSplit(field, opts); + std::vector<Sub> vars = { + // This will eventually be renamed to "field", once the existing "field" + // variable is replaced with "field_" everywhere. + {"name", FieldName(field)}, + + {"index", field->index()}, + {"number", field->number()}, + {"pkg.Msg.field", field->full_name()}, + + {"field_", FieldMemberName(field, split)}, + {"DeclaredType", DeclaredTypeMethodName(field->type())}, + {"kTagBytes", WireFormat::TagSize(field->number(), field->type())}, + Sub("PrepareSplitMessageForWrite", + split ? "PrepareSplitMessageForWrite();" : "") + .WithSuffix(";"), + Sub("DEPRECATED", DeprecatedAttribute(opts, field)).WithSuffix(" "), + + // 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. + {"{", ""}, + {"}", ""}, + + // Old-style names. + {"field", FieldMemberName(field, split)}, + {"maybe_prepare_split_message", + split ? "PrepareSplitMessageForWrite();" : ""}, + {"declared_type", DeclaredTypeMethodName(field->type())}, + {"classname", ClassName(FieldScope(field), false)}, + {"ns", Namespace(field, opts)}, + {"tag_size", WireFormat::TagSize(field->number(), field->type())}, + {"deprecated_attr", DeprecatedAttribute(opts, field)}, }; - for (size_t i = 0; i < GOOGLE_ARRAYSIZE(kAccessorsAnnotations); ++i) { - (*variables)[kAccessorsAnnotations[i]] = ""; - } - if (options.annotate_accessor) { - for (size_t i = 0; i < GOOGLE_ARRAYSIZE(kAccessorsAnnotations); ++i) { - (*variables)[kAccessorsAnnotations[i]] = StrCat( - " ", FieldName(descriptor), "_AccessedNoStrip = true;\n"); - } - } - if (!options.field_listener_options.inject_field_listener_events) { - return; - } - if (descriptor->file()->options().optimize_for() == - google::protobuf::FileOptions::LITE_RUNTIME) { - return; - } - TProtoStringType field_member = (*variables)["field"]; - const google::protobuf::OneofDescriptor* oneof_member = - descriptor->real_containing_oneof(); - const TProtoStringType proto_ns = (*variables)["proto_ns"]; - const TProtoStringType substitute_template_prefix = - StrCat(" ", (*variables)["tracker"], ".$1<$0>(this, "); - TProtoStringType prepared_template; - - // Flat template is needed if the prepared one is introspecting the values - // inside the returned values, for example, for repeated fields and maps. - TProtoStringType prepared_flat_template; - TProtoStringType prepared_add_template; - // TODO(b/190614678): Support fields with type Message or Map. - if (descriptor->is_repeated() && !descriptor->is_map()) { - if (descriptor->type() != FieldDescriptor::TYPE_MESSAGE && - descriptor->type() != FieldDescriptor::TYPE_GROUP) { - prepared_template = strings::Substitute("&$0.Get(index)", field_member); - prepared_add_template = - strings::Substitute("&$0.Get($0.size() - 1)", field_member); - } else { - prepared_template = "nullptr"; - prepared_add_template = "nullptr"; - } - } else if (descriptor->is_map()) { - prepared_template = "nullptr"; - } else if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE && - !IsExplicitLazy(descriptor)) { - prepared_template = "nullptr"; - } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { - if (oneof_member) { - prepared_template = GenerateTemplateForOneofString( - descriptor, (*variables)["proto_ns"], field_member); - } else { - prepared_template = - GenerateTemplateForSingleString(descriptor, field_member); - } - } else { - prepared_template = StrCat("&", field_member); - } - if (descriptor->is_repeated() && !descriptor->is_map() && - descriptor->type() != FieldDescriptor::TYPE_MESSAGE && - descriptor->type() != FieldDescriptor::TYPE_GROUP) { - prepared_flat_template = StrCat("&", field_member); - } else { - prepared_flat_template = prepared_template; - } - MaySetAnnotationVariable(options, "get", substitute_template_prefix, - prepared_template, descriptor->index(), "OnGet", - variables); - MaySetAnnotationVariable(options, "set", substitute_template_prefix, - prepared_template, descriptor->index(), "OnSet", - variables); - MaySetAnnotationVariable(options, "has", substitute_template_prefix, - prepared_template, descriptor->index(), "OnHas", - variables); - MaySetAnnotationVariable(options, "mutable", substitute_template_prefix, - prepared_template, descriptor->index(), "OnMutable", - variables); - MaySetAnnotationVariable(options, "release", substitute_template_prefix, - prepared_template, descriptor->index(), "OnRelease", - variables); - MaySetAnnotationVariable(options, "clear", substitute_template_prefix, - prepared_flat_template, descriptor->index(), - "OnClear", variables); - MaySetAnnotationVariable(options, "size", substitute_template_prefix, - prepared_flat_template, descriptor->index(), - "OnSize", variables); - MaySetAnnotationVariable(options, "list", substitute_template_prefix, - prepared_flat_template, descriptor->index(), - "OnList", variables); - MaySetAnnotationVariable(options, "mutable_list", substitute_template_prefix, - prepared_flat_template, descriptor->index(), - "OnMutableList", variables); - MaySetAnnotationVariable(options, "add", substitute_template_prefix, - prepared_add_template, descriptor->index(), "OnAdd", - variables); - MaySetAnnotationVariable(options, "add_mutable", substitute_template_prefix, - prepared_add_template, descriptor->index(), - "OnAddMutable", variables); -} - -void SetCommonFieldVariables(const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables, - const Options& options) { - SetCommonVars(options, variables); - SetCommonMessageDataVariables(descriptor->containing_type(), variables); - - (*variables)["ns"] = Namespace(descriptor, options); - (*variables)["name"] = FieldName(descriptor); - (*variables)["index"] = StrCat(descriptor->index()); - (*variables)["number"] = StrCat(descriptor->number()); - (*variables)["classname"] = ClassName(FieldScope(descriptor), false); - (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); - bool split = ShouldSplit(descriptor, options); - (*variables)["field"] = FieldMemberName(descriptor, split); - - (*variables)["tag_size"] = StrCat( - WireFormat::TagSize(descriptor->number(), descriptor->type())); - (*variables)["deprecated_attr"] = DeprecatedAttribute(options, descriptor); - - (*variables)["set_hasbit"] = ""; - (*variables)["clear_hasbit"] = ""; - (*variables)["maybe_prepare_split_message"] = - split ? " PrepareSplitMessageForWrite();\n" : ""; - - AddAccessorAnnotations(descriptor, options, variables); - - // 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. - (*variables)["{"] = ""; - (*variables)["}"] = ""; -} - -void FieldGenerator::SetHasBitIndex(arc_i32 has_bit_index) { - if (!HasHasbit(descriptor_)) { - GOOGLE_CHECK_EQ(has_bit_index, -1); - return; + if (const auto* oneof = field->containing_oneof()) { + auto field_name = UnderscoresToCamelCase(field->name(), true); + + vars.push_back({"oneof_name", oneof->name()}); + vars.push_back({"field_name", field_name}); + vars.push_back({"oneof_index", oneof->index()}); + vars.push_back({"has_field", y_absl::StrFormat("%s_case() == k%s", + oneof->name(), field_name)}); + vars.push_back( + {"not_has_field", + y_absl::StrFormat("%s_case() != k%s", oneof->name(), field_name)}); } - variables_["set_hasbit"] = StrCat( - variables_["has_bits"], "[", has_bit_index / 32, "] |= 0x", - strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;"); - variables_["clear_hasbit"] = StrCat( - variables_["has_bits"], "[", has_bit_index / 32, "] &= ~0x", - strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;"); -} -void FieldGenerator::SetInlinedStringIndex(arc_i32 inlined_string_index) { - if (!IsStringInlined(descriptor_, options_)) { - GOOGLE_CHECK_EQ(inlined_string_index, -1); - return; - } - // The first bit is the tracking bit for on demand registering ArenaDtor. - GOOGLE_CHECK_GT(inlined_string_index, 0) - << "_inlined_string_donated_'s bit 0 is reserved for arena dtor tracking"; - variables_["inlined_string_donated"] = StrCat( - "(", variables_["inlined_string_donated_array"], "[", - inlined_string_index / 32, "] & 0x", - strings::Hex(1u << (inlined_string_index % 32), strings::ZERO_PAD_8), - "u) != 0;"); - variables_["donating_states_word"] = - StrCat(variables_["inlined_string_donated_array"], "[", - inlined_string_index / 32, "]"); - variables_["mask_for_undonate"] = StrCat( - "~0x", strings::Hex(1u << (inlined_string_index % 32), strings::ZERO_PAD_8), - "u"); + return vars; } -void FieldGenerator::GenerateAggregateInitializer(io::Printer* printer) const { - Formatter format(printer, variables_); +void FieldGeneratorBase::GenerateAggregateInitializer(io::Printer* p) const { + Formatter format(p, variables_); if (ShouldSplit(descriptor_, options_)) { format("decltype(Impl_::Split::$name$_){arena}"); return; @@ -309,110 +122,159 @@ void FieldGenerator::GenerateAggregateInitializer(io::Printer* printer) const { format("decltype($field$){arena}"); } -void FieldGenerator::GenerateConstexprAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); +void FieldGeneratorBase::GenerateConstexprAggregateInitializer( + io::Printer* p) const { + Formatter format(p, variables_); format("/*decltype($field$)*/{}"); } -void FieldGenerator::GenerateCopyAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); +void FieldGeneratorBase::GenerateCopyAggregateInitializer( + io::Printer* p) const { + Formatter format(p, variables_); format("decltype($field$){from.$field$}"); } -void FieldGenerator::GenerateCopyConstructorCode(io::Printer* printer) const { +void FieldGeneratorBase::GenerateCopyConstructorCode(io::Printer* p) const { if (ShouldSplit(descriptor_, options_)) { // There is no copy constructor for the `Split` struct, so we need to copy // the value here. - Formatter format(printer, variables_); + Formatter format(p, variables_); format("$field$ = from.$field$;\n"); } } -void SetCommonOneofFieldVariables( - const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables) { - const TProtoStringType prefix = descriptor->containing_oneof()->name() + "_."; - (*variables)["oneof_name"] = descriptor->containing_oneof()->name(); -} - -FieldGenerator::~FieldGenerator() {} +void FieldGeneratorBase::GenerateIfHasField(io::Printer* p) const { + Y_ABSL_CHECK(internal::cpp::HasHasbit(descriptor_)); -FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, - const Options& options, - MessageSCCAnalyzer* scc_analyzer) - : descriptor_(descriptor), field_generators_(descriptor->field_count()) { - // Construct all the FieldGenerators. - for (int i = 0; i < descriptor->field_count(); i++) { - field_generators_[i].reset( - MakeGenerator(descriptor->field(i), options, scc_analyzer)); - } + Formatter format(p); + format("if (($has_hasbit$) != 0) {\n"); } -FieldGenerator* FieldGeneratorMap::MakeGoogleInternalGenerator( - const FieldDescriptor* field, const Options& options, - MessageSCCAnalyzer* scc_analyzer) { - - return nullptr; -} +namespace { +std::unique_ptr<FieldGeneratorBase> MakeGenerator(const FieldDescriptor* field, + const Options& options, + MessageSCCAnalyzer* scc) { -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_map()) { + return MakeMapGenerator(field, options, scc); } - if (field->is_repeated()) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: - if (field->is_map()) { - return new MapFieldGenerator(field, options, scc_analyzer); - } else { - return new RepeatedMessageFieldGenerator(field, options, - scc_analyzer); - } - case FieldDescriptor::CPPTYPE_STRING: - return new RepeatedStringFieldGenerator(field, options); - case FieldDescriptor::CPPTYPE_ENUM: - return new RepeatedEnumFieldGenerator(field, options); - default: - return new RepeatedPrimitiveFieldGenerator(field, options); - } - } else if (field->real_containing_oneof()) { - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_MESSAGE: - return new MessageOneofFieldGenerator(field, options, scc_analyzer); - case FieldDescriptor::CPPTYPE_STRING: - return new StringOneofFieldGenerator(field, options); - case FieldDescriptor::CPPTYPE_ENUM: - return new EnumOneofFieldGenerator(field, options); - default: - return new PrimitiveOneofFieldGenerator(field, options); - } - } else { - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_MESSAGE: - return new MessageFieldGenerator(field, options, scc_analyzer); + return MakeRepeatedMessageGenerator(field, options, scc); case FieldDescriptor::CPPTYPE_STRING: - return new StringFieldGenerator(field, options); + return MakeRepeatedStringGenerator(field, options, scc); case FieldDescriptor::CPPTYPE_ENUM: - return new EnumFieldGenerator(field, options); + return MakeRepeatedEnumGenerator(field, options, scc); default: - return new PrimitiveFieldGenerator(field, options); + return MakeRepeatedPrimitiveGenerator(field, options, scc); } } + + if (field->real_containing_oneof() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + return MakeOneofMessageGenerator(field, options, scc); + } + + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_MESSAGE: + return MakeSinguarMessageGenerator(field, options, scc); + case FieldDescriptor::CPPTYPE_STRING: + return MakeSinguarStringGenerator(field, options, scc); + case FieldDescriptor::CPPTYPE_ENUM: + return MakeSinguarEnumGenerator(field, options, scc); + default: + return MakeSinguarPrimitiveGenerator(field, options, scc); + } } -FieldGeneratorMap::~FieldGeneratorMap() {} +void HasBitVars(const FieldDescriptor* field, const Options& opts, + y_absl::optional<arc_ui32> idx, std::vector<Sub>& vars) { + if (!idx.has_value()) { + vars.emplace_back("set_hasbit", ""); + vars.emplace_back("clear_hasbit", ""); + return; + } + + Y_ABSL_CHECK(internal::cpp::HasHasbit(field)); + + arc_i32 index = *idx / 32; + TProtoStringType mask = y_absl::StrFormat("0x%08xu", 1u << (*idx % 32)); -const FieldGenerator& FieldGeneratorMap::get( - const FieldDescriptor* field) const { - GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); - return *field_generators_[field->index()]; + y_absl::string_view has_bits = IsMapEntryMessage(field->containing_type()) + ? "_has_bits_" + : "_impl_._has_bits_"; + + auto has = y_absl::StrFormat("%s[%d] & %s", has_bits, index, mask); + auto set = y_absl::StrFormat("%s[%d] |= %s;", has_bits, index, mask); + auto clr = y_absl::StrFormat("%s[%d] &= ~%s;", has_bits, index, mask); + + vars.emplace_back("has_hasbit", has); + vars.emplace_back(Sub("set_hasbit", set).WithSuffix(";")); + vars.emplace_back(Sub("clear_hasbit", clr).WithSuffix(";")); +} + +void InlinedStringVars(const FieldDescriptor* field, const Options& opts, + y_absl::optional<arc_ui32> idx, std::vector<Sub>& vars) { + if (!IsStringInlined(field, opts)) { + Y_ABSL_CHECK(!idx.has_value()); + return; + } + + // The first bit is the tracking bit for on demand registering ArenaDtor. + Y_ABSL_CHECK_GT(*idx, 0) + << "_inlined_string_donated_'s bit 0 is reserved for arena dtor tracking"; + + arc_i32 index = *idx / 32; + TProtoStringType mask = y_absl::StrFormat("0x%08xu", 1u << (*idx % 32)); + + y_absl::string_view array = IsMapEntryMessage(field->containing_type()) + ? "_inlined_string_donated_" + : "_impl_._inlined_string_donated_"; + + vars.emplace_back("inlined_string_donated", + y_absl::StrFormat("(%s[%d] & %s) != 0;", array, index, mask)); + vars.emplace_back("donating_states_word", + y_absl::StrFormat("%s[%d]", array, index)); + vars.emplace_back("mask_for_undonate", y_absl::StrFormat("~%s", mask)); +} +} // namespace + +FieldGenerator::FieldGenerator(const FieldDescriptor* field, + const Options& options, + MessageSCCAnalyzer* scc_analyzer, + y_absl::optional<arc_ui32> hasbit_index, + y_absl::optional<arc_ui32> inlined_string_index) + : impl_(MakeGenerator(field, options, scc_analyzer)), + field_vars_(FieldVars(field, options)), + tracker_vars_(MakeTrackerCalls(field, options)), + per_generator_vars_(impl_->MakeVars()) { + HasBitVars(field, options, hasbit_index, field_vars_); + InlinedStringVars(field, options, inlined_string_index, field_vars_); +} + +void FieldGeneratorTable::Build( + const Options& options, MessageSCCAnalyzer* scc, + y_absl::Span<const arc_i32> has_bit_indices, + y_absl::Span<const arc_i32> inlined_string_indices) { + // Construct all the FieldGenerators. + fields_.reserve(descriptor_->field_count()); + for (const auto* field : internal::FieldRange(descriptor_)) { + y_absl::optional<arc_ui32> has_bit_index; + if (!has_bit_indices.empty() && has_bit_indices[field->index()] >= 0) { + has_bit_index = static_cast<arc_ui32>(has_bit_indices[field->index()]); + } + + y_absl::optional<arc_ui32> inlined_string_index; + if (!inlined_string_indices.empty() && + inlined_string_indices[field->index()] >= 0) { + inlined_string_index = + static_cast<arc_ui32>(inlined_string_indices[field->index()]); + } + + fields_.push_back(FieldGenerator(field, options, scc, has_bit_index, + inlined_string_index)); + } } } // namespace cpp diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.h index 95eb96f499d..0d00011ff74 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.h @@ -36,232 +36,384 @@ #define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ #include <cstdint> -#include <map> #include <memory> #include <string> +#include <tuple> +#include <vector> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/compiler/cpp/options.h> - -namespace google { -namespace protobuf { -namespace io { -class Printer; // printer.h -} -} // namespace protobuf -} // namespace google +#include "google/protobuf/descriptor.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { -// Helper function: set variables in the map that are the same for all -// field code generators. -// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size', -// 'deprecation']. -void SetCommonFieldVariables(const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables, - const Options& options); +// Customization points for each field codegen type. See FieldGenerator to +// see how each of these functions is used. +// +// TODO(b/245791219): Make every function except the dtor in this generator +// non-pure-virtual. A generator with no implementation should be able to +// automatically not contribute any code to the message it is part of, as a +// matter of clean composability. +class FieldGeneratorBase { + public: + FieldGeneratorBase(const FieldDescriptor* descriptor, const Options& options) + : descriptor_(descriptor), options_(options) {} + + FieldGeneratorBase(const FieldGeneratorBase&) = delete; + FieldGeneratorBase& operator=(const FieldGeneratorBase&) = delete; + + virtual ~FieldGeneratorBase() = 0; + + virtual std::vector<io::Printer::Sub> MakeVars() const { return {}; } + + virtual void GeneratePrivateMembers(io::Printer* p) const = 0; + + virtual void GenerateStaticMembers(io::Printer* p) const {} + + virtual void GenerateAccessorDeclarations(io::Printer* p) const = 0; + + virtual void GenerateInlineAccessorDefinitions(io::Printer* p) const = 0; + + virtual void GenerateNonInlineAccessorDefinitions(io::Printer* p) const {} + + virtual void GenerateInternalAccessorDefinitions(io::Printer* p) const {} + + virtual void GenerateInternalAccessorDeclarations(io::Printer* p) const {} + + virtual void GenerateClearingCode(io::Printer* p) const = 0; + + virtual void GenerateMessageClearingCode(io::Printer* p) const { + GenerateClearingCode(p); + } + + virtual void GenerateMergingCode(io::Printer* p) const = 0; + + virtual void GenerateCopyConstructorCode(io::Printer* p) const; + + virtual void GenerateSwappingCode(io::Printer* p) const = 0; + + virtual void GenerateConstructorCode(io::Printer* p) const = 0; + + virtual void GenerateDestructorCode(io::Printer* p) const {} + + virtual void GenerateArenaDestructorCode(io::Printer* p) const { + Y_ABSL_CHECK(NeedsArenaDestructor() == ArenaDtorNeeds::kNone) + << descriptor_->cpp_type_name(); + } + + virtual void GenerateAggregateInitializer(io::Printer* p) const; + + virtual void GenerateConstexprAggregateInitializer(io::Printer* p) const; + + virtual void GenerateCopyAggregateInitializer(io::Printer* p) const; + + virtual void GenerateSerializeWithCachedSizesToArray( + io::Printer* p) const = 0; + + virtual void GenerateByteSize(io::Printer* p) const = 0; -void SetCommonOneofFieldVariables( - const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables); + virtual void GenerateIsInitialized(io::Printer* p) const {} + + virtual void GenerateIfHasField(io::Printer* p) const; + + virtual bool IsInlined() const { return false; } + + virtual ArenaDtorNeeds NeedsArenaDestructor() const { + return ArenaDtorNeeds::kNone; + } + + protected: + // TODO(b/245791219): Remove these members and make this a pure interface. + const FieldDescriptor* descriptor_; + const Options& options_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; +}; + +inline FieldGeneratorBase::~FieldGeneratorBase() = default; class FieldGenerator { + private: + // This function must be defined here so that the inline definitions below + // can see it, which is required because it has deduced return type. + auto PushVarsForCall(io::Printer* p) const { + // NOTE: we use a struct here because: + // * We want to ensure that order of evaluation below is well-defined, + // which {...} guarantees but (...) does not. + // * We do not require C++17 as of writing and therefore cannot use + // std::tuple with CTAD. + // * std::make_tuple uses (...), not {...}. + struct Vars { + decltype(p->WithVars(field_vars_)) cleanup1; + decltype(p->WithVars(tracker_vars_)) cleanup2; + decltype(p->WithVars(per_generator_vars_)) cleanup3; + }; + + return Vars{p->WithVars(field_vars_), p->WithVars(tracker_vars_), + p->WithVars(per_generator_vars_)}; + } + public: - explicit FieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : descriptor_(descriptor), options_(options) {} - virtual ~FieldGenerator(); - virtual void GenerateSerializeWithCachedSizes( - io::Printer* printer) const final{}; - // Generate lines of code declaring members fields of the message class - // needed to represent this field. These are placed inside the message - // class. - virtual void GeneratePrivateMembers(io::Printer* printer) const = 0; - - // Generate static default variable for this field. These are placed inside - // the message class. Most field types don't need this, so the default - // implementation is empty. - virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {} - - // Generate prototypes for all of the accessor functions related to this - // field. These are placed inside the class definition. - virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0; - - // Generate inline definitions of accessor functions for this field. - // These are placed inside the header after all class definitions. - virtual void GenerateInlineAccessorDefinitions( - io::Printer* printer) const = 0; - - // Generate definitions of accessors that aren't inlined. These are - // placed somewhere in the .cc file. - // Most field types don't need this, so the default implementation is empty. - 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. + FieldGenerator(const FieldGenerator&) = delete; + FieldGenerator& operator=(const FieldGenerator&) = delete; + FieldGenerator(FieldGenerator&&) = default; + FieldGenerator& operator=(FieldGenerator&&) = default; + + // Prints private members needed to represent this field. // - // Since most field types can re-use GenerateClearingCode, this method is - // not pure virtual. - virtual void GenerateMessageClearingCode(io::Printer* printer) const { - GenerateClearingCode(printer); + // These are placed inside the class definition. + void GeneratePrivateMembers(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GeneratePrivateMembers(p); } - // Generate lines of code (statements, not declarations) which merges the - // contents of the field from the current message to the target message, - // which is stored in the generated code variable "from". + // Prints static members needed to represent this field. + // + // These are placed inside the class definition. + void GenerateStaticMembers(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateStaticMembers(p); + } + + // Generates declarations for all of the accessor functions related to this + // field. + // + // These are placed inside the class definition. + void GenerateAccessorDeclarations(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateAccessorDeclarations(p); + } + + // Generates inline definitions of accessor functions for this field. + // + // These are placed in namespace scope in the header after all class + // definitions. + void GenerateInlineAccessorDefinitions(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateInlineAccessorDefinitions(p); + } + + // Generates definitions of accessors that aren't inlined. + // + // These are placed in namespace scope in the .cc file. + void GenerateNonInlineAccessorDefinitions(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateNonInlineAccessorDefinitions(p); + } + + // Generates declarations of accessors that are for internal purposes only. + void GenerateInternalAccessorDefinitions(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateInternalAccessorDefinitions(p); + } + + // Generates definitions of accessors that are for internal purposes only. + void GenerateInternalAccessorDeclarations(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateInternalAccessorDeclarations(p); + } + + // Generates statements which clear the field. + // + // This is used to define the clear_$name$() method. + void GenerateClearingCode(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateClearingCode(p); + } + + // Generates statements 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. + void GenerateMessageClearingCode(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateMessageClearingCode(p); + } + + // Generates statements which merge the contents of the field from the current + // message to the target message, which is stored in the generated code + // variable `from`. + // // This is used to fill in the MergeFrom method for the whole message. + // // Details of this usage can be found in message.cc under the // GenerateMergeFrom method. - virtual void GenerateMergingCode(io::Printer* printer) const = 0; + void GenerateMergingCode(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateMergingCode(p); + } // Generates a copy constructor - virtual void GenerateCopyConstructorCode(io::Printer* printer) const; + // + // TODO(b/245791219): Document this properly. + void GenerateCopyConstructorCode(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateCopyConstructorCode(p); + } - // Generate lines of code (statements, not declarations) which swaps - // this field and the corresponding field of another message, which - // is stored in the generated code variable "other". This is used to - // define the Swap method. Details of usage can be found in + // Generates statements which swap this field and the corresponding field of + // another message, which is stored in the generated code variable `other`. + // + // This is used to define the Swap method. Details of usage can be found in // message.cc under the GenerateSwap method. - virtual void GenerateSwappingCode(io::Printer* printer) const = 0; - - // Generate initialization code for private members declared by - // GeneratePrivateMembers(). These go into the message class's SharedCtor() - // method, invoked by each of the generated constructors. - virtual void GenerateConstructorCode(io::Printer* printer) const = 0; + void GenerateSwappingCode(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateSwappingCode(p); + } - // Generate initialization code for private members in the cold struct. - virtual void GenerateCreateSplitMessageCode(io::Printer* printer) const {} + // Generates initialization code for private members declared by + // GeneratePrivateMembers(). + // + // These go into the message class's SharedCtor() method, invoked by each of + // the generated constructors. + void GenerateConstructorCode(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateConstructorCode(p); + } - // Generate any code that needs to go in the class's SharedDtor() method, + // Generates any code that needs to go in the class's SharedDtor() method, // invoked by the destructor. - // Most field types don't need this, so the default implementation is empty. - virtual void GenerateDestructorCode(io::Printer* /*printer*/) const {} - - // 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(). - virtual void GenerateArenaDestructorCode(io::Printer* printer) const { - GOOGLE_CHECK(NeedsArenaDestructor() == ArenaDtorNeeds::kNone) - << descriptor_->cpp_type_name(); + void GenerateDestructorCode(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateDestructorCode(p); } - // Generate initialization code for private members declared by - // GeneratePrivateMembers(). These go into the SharedCtor's - // aggregate initialization of the _impl_ struct and must follow the syntax - // (e.g. `decltype($field$){$default$}`). Does not include `:` or `,` - // separators. Default values should be specified here when possible. + // Generates a manual destructor invocation for use when the message is on an + // arena. // - // Note: We use `decltype($field$)` for both explicit construction and the - // fact that it's self-documenting. Pre-C++17, copy elision isn't guaranteed + // The code that this method generates will be executed inside a + // shared-for-the-whole-message-class method registered with OwnDestructor(). + void GenerateArenaDestructorCode(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateArenaDestructorCode(p); + } + + // Generates initialization code for private members declared by + // GeneratePrivateMembers(). + // + // These go into the SharedCtor's aggregate initialization of the _impl_ + // struct and must follow the syntax `decltype($field$){$default$}`. + // Does not include `:` or `,` separators. Default values should be specified + // here when possible. + // + // NOTE: We use `decltype($field$)` for both explicit construction and the + // fact that it's self-documenting. Pre-C++17, copy elision isn't guaranteed // in aggregate initialization so a valid copy/move constructor must exist - // (even though it's not used). Because of this, we need to comment out the + // (even though it's not used). Because of this, we need to comment out the // decltype and fallback to implicit construction. - virtual void GenerateAggregateInitializer(io::Printer* printer) const; - - // Generate constinit initialization code for private members declared by - // GeneratePrivateMembers(). These go into the constexpr constructor's - // aggregate initialization of the _impl_ struct and must follow the syntax - // (e.g. `/*decltype($field$)*/{}`, see above). Does not - // include `:` or `,` separators. - virtual void GenerateConstexprAggregateInitializer( - io::Printer* printer) const; - - // Generate copy initialization code for private members declared by - // GeneratePrivateMembers(). These go into the copy constructor's - // aggregate initialization of the _impl_ struct and must follow the syntax - // (e.g. `decltype($field$){from.$field$}`, see above). Does not - // include `:` or `,` separators. - virtual void GenerateCopyAggregateInitializer(io::Printer* printer) const; - - // Generate lines to serialize this field directly to the array "target", - // which are placed within the message's SerializeWithCachedSizesToArray() - // method. This must also advance "target" past the written bytes. - virtual void GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const = 0; + void GenerateAggregateInitializer(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateAggregateInitializer(p); + } + + // Generates constinit initialization code for private members declared by + // GeneratePrivateMembers(). + // + // These go into the constexpr constructor's aggregate initialization of the + // _impl_ struct and must follow the syntax `/*decltype($field$)*/{}` (see + // above). Does not include `:` or `,` separators. + void GenerateConstexprAggregateInitializer(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateConstexprAggregateInitializer(p); + } + + // Generates copy initialization code for private members declared by + // GeneratePrivateMembers(). + // + // These go into the copy constructor's aggregate initialization of the _impl_ + // struct and must follow the syntax `decltype($field$){from.$field$}` (see + // above). Does not include `:` or `,` separators. + void GenerateCopyAggregateInitializer(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateCopyAggregateInitializer(p); + } + + // Generates statements to serialize this field directly to the array + // `target`, which are placed within the message's + // SerializeWithCachedSizesToArray() method. + // + // This must also advance `target` past the written bytes. + void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateSerializeWithCachedSizesToArray(p); + } - // Generate lines to compute the serialized size of this field, which + // Generates statements to compute the serialized size of this field, which // are placed in the message's ByteSize() method. - virtual void GenerateByteSize(io::Printer* printer) const = 0; + void GenerateByteSize(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateByteSize(p); + } // Generates lines to call IsInitialized() for eligible message fields. Non // message fields won't need to override this function. - virtual void GenerateIsInitialized(io::Printer* printer) const {} - - virtual bool IsInlined() const { return false; } + void GenerateIsInitialized(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateIsInitialized(p); + } - virtual ArenaDtorNeeds NeedsArenaDestructor() const { - return ArenaDtorNeeds::kNone; + // TODO(b/245791219): Document this properly. + void GenerateIfHasField(io::Printer* p) const { + auto vars = PushVarsForCall(p); + impl_->GenerateIfHasField(p); } - void SetHasBitIndex(arc_i32 has_bit_index); - void SetInlinedStringIndex(arc_i32 inlined_string_index); + // TODO(b/245791219): Document this properly. + bool IsInlined() const { return impl_->IsInlined(); } - protected: - const FieldDescriptor* descriptor_; - const Options& options_; - std::map<TProtoStringType, TProtoStringType> variables_; + // TODO(b/245791219): Document this properly. + ArenaDtorNeeds NeedsArenaDestructor() const { + return impl_->NeedsArenaDestructor(); + } private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); + friend class FieldGeneratorTable; + FieldGenerator(const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer, + y_absl::optional<arc_ui32> hasbit_index, + y_absl::optional<arc_ui32> inlined_string_index); + + std::unique_ptr<FieldGeneratorBase> impl_; + std::vector<io::Printer::Sub> field_vars_; + std::vector<io::Printer::Sub> tracker_vars_; + std::vector<io::Printer::Sub> per_generator_vars_; }; -// Convenience class which constructs FieldGenerators for a Descriptor. -class FieldGeneratorMap { +// Convenience class which constructs FieldGeneratorBases for a Descriptor. +class FieldGeneratorTable { public: - FieldGeneratorMap(const Descriptor* descriptor, const Options& options, - MessageSCCAnalyzer* scc_analyzer); - ~FieldGeneratorMap(); + explicit FieldGeneratorTable(const Descriptor* descriptor) + : descriptor_(descriptor) {} - const FieldGenerator& get(const FieldDescriptor* field) const; + FieldGeneratorTable(const FieldGeneratorTable&) = delete; + FieldGeneratorTable& operator=(const FieldGeneratorTable&) = delete; - 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]); - } - } + void Build(const Options& options, MessageSCCAnalyzer* scc_analyzer, + y_absl::Span<const arc_i32> has_bit_indices, + y_absl::Span<const arc_i32> inlined_string_indices); - void SetInlinedStringIndices(const std::vector<int>& inlined_string_indices) { - for (int i = 0; i < descriptor_->field_count(); ++i) { - field_generators_[i]->SetInlinedStringIndex(inlined_string_indices[i]); - } + const FieldGenerator& get(const FieldDescriptor* field) const { + Y_ABSL_CHECK_EQ(field->containing_type(), descriptor_); + return fields_[field->index()]; } private: const Descriptor* descriptor_; - 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, - MessageSCCAnalyzer* scc_analyzer); - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); + std::vector<FieldGenerator> fields_; }; +// Returns variables common to all fields. +// +// TODO(b/245791219): Make this function .cc-private. +std::vector<io::Printer::Sub> FieldVars(const FieldDescriptor* field, + const Options& opts); } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc new file mode 100644 index 00000000000..0ee76cb710e --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc @@ -0,0 +1,471 @@ +// 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: [email protected] (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <memory> +#include <string> +#include <tuple> +#include <vector> + +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/memory/memory.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/cpp/field.h" +#include "google/protobuf/compiler/cpp/field_generators/generators.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/descriptor.pb.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { +namespace { +using Sub = ::google::protobuf::io::Printer::Sub; + +std::vector<Sub> Vars(const FieldDescriptor* field, const Options& opts) { + const EnumValueDescriptor* default_value = field->default_value_enum(); + bool split = ShouldSplit(field, opts); + bool is_open = internal::cpp::HasPreservingUnknownEnumSemantics(field); + auto enum_name = QualifiedClassName(field->enum_type(), opts); + return { + {"Enum", enum_name}, + {"kDefault", Int32ToString(default_value->number())}, + Sub("assert_valid", + is_open ? "" + : y_absl::Substitute("assert($0_IsValid(value));", enum_name)) + .WithSuffix(";"), + + {"cached_size_name", MakeVarintCachedSizeName(field)}, + {"cached_size_", MakeVarintCachedSizeFieldName(field, split)}, + }; +} + +class SingularEnum : public FieldGeneratorBase { + public: + SingularEnum(const FieldDescriptor* field, const Options& opts) + : FieldGeneratorBase(field, opts), + field_(field), + opts_(&opts), + is_oneof_(field->real_containing_oneof() != nullptr) {} + ~SingularEnum() override = default; + + std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); } + + void GeneratePrivateMembers(io::Printer* p) const override { + p->Emit(R"cc( + int $name$_; + )cc"); + } + + void GenerateClearingCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$ = $kDefault$; + )cc"); + } + + void GenerateMergingCode(io::Printer* p) const override { + p->Emit(R"cc( + _this->_internal_set_$name$(from._internal_$name$()); + )cc"); + } + + void GenerateSwappingCode(io::Printer* p) const override { + if (is_oneof_) return; + + p->Emit(R"cc( + swap($field_$, other->$field_$); + )cc"); + } + + void GenerateConstructorCode(io::Printer* p) const override { + if (!is_oneof_) return; + p->Emit(R"cc( + $ns$::_$Msg$_default_instance_.$field_$ = $kDefault$; + )cc"); + } + + void GenerateCopyConstructorCode(io::Printer* p) const override { + p->Emit(R"cc( + _this->$field_$ = from.$field_$; + )cc"); + } + + void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override { + p->Emit(R"cc( + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + $number$, this->_internal_$name$(), target); + )cc"); + } + + void GenerateByteSize(io::Printer* p) const override { + p->Emit(R"cc( + total_size += $kTagBytes$ + + ::_pbi::WireFormatLite::EnumSize(this->_internal_$name$()); + )cc"); + } + + void GenerateConstexprAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + /*decltype($field_$)*/ $kDefault$ + )cc"); + } + + void GenerateAggregateInitializer(io::Printer* p) const override { + if (ShouldSplit(descriptor_, options_)) { + p->Emit(R"cc( + decltype(Impl_::Split::$name$_) { $kDefault$ } + )cc"); + return; + } + + p->Emit(R"cc( + decltype($field_$) { $kDefault$ } + )cc"); + } + + void GenerateCopyAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + decltype($field_$) {} + )cc"); + } + + void GenerateAccessorDeclarations(io::Printer* p) const override; + void GenerateInlineAccessorDefinitions(io::Printer* p) const override; + + private: + const FieldDescriptor* field_; + const Options* opts_; + bool is_oneof_; +}; + +void SingularEnum::GenerateAccessorDeclarations(io::Printer* p) const { + auto v = p->WithVars( + AnnotatedAccessors(field_, {"", "set_", "_internal_", "_internal_set_"})); + p->Emit(R"cc( + $DEPRECATED$ $Enum$ $name$() const; + $DEPRECATED$ void $set_name$($Enum$ value); + + private: + $Enum$ $_internal_name$() const; + void $_internal_set_name$($Enum$ value); + + public: + )cc"); +} + +void SingularEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { + p->Emit(R"cc( + inline $Enum$ $Msg$::$name$() const { + $annotate_get$; + // @@protoc_insertion_point(field_get:$pkg.Msg.field$) + return _internal_$name$(); + } + inline void $Msg$::set_$name$($Enum$ value) { + $maybe_prepare_split_message$ _internal_set_$name$(value); + $annotate_set$; + // @@protoc_insertion_point(field_set:$pkg.Msg.field$) + } + )cc"); + + if (is_oneof_) { + p->Emit(R"cc( + inline $Enum$ $Msg$::_internal_$name$() const { + if ($has_field$) { + return static_cast<$Enum$>($field_$); + } + return static_cast<$Enum$>($kDefault$); + } + inline void $Msg$::_internal_set_$name$($Enum$ value) { + $assert_valid$; + if ($not_has_field$) { + clear_$oneof_name$(); + set_has_$name$(); + } + $field_$ = value; + } + )cc"); + } else { + p->Emit(R"cc( + inline $Enum$ $Msg$::_internal_$name$() const { + return static_cast<$Enum$>($field_$); + } + inline void $Msg$::_internal_set_$name$($Enum$ value) { + $assert_valid$; + $set_hasbit$; + $field_$ = value; + } + )cc"); + } +} + +class RepeatedEnum : public FieldGeneratorBase { + public: + RepeatedEnum(const FieldDescriptor* field, const Options& opts) + : FieldGeneratorBase(field, opts), + field_(field), + opts_(&opts), + has_cached_size_(field_->is_packed() && + HasGeneratedMethods(field_->file(), opts)) {} + ~RepeatedEnum() override = default; + + std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); } + + void GeneratePrivateMembers(io::Printer* p) const override { + p->Emit(R"cc( + $pb$::RepeatedField<int> $name$_; + )cc"); + + if (has_cached_size_) { + p->Emit(R"cc( + mutable $pbi$::CachedSize $cached_size_name$; + )cc"); + } + } + + void GenerateClearingCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$.Clear(); + )cc"); + } + + void GenerateMergingCode(io::Printer* p) const override { + p->Emit(R"cc( + _this->$field_$.MergeFrom(from.$field_$); + )cc"); + } + + void GenerateSwappingCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$.InternalSwap(&other->$field_$); + )cc"); + } + + void GenerateDestructorCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$.~RepeatedField(); + )cc"); + } + + void GenerateConstexprAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + /*decltype($field_$)*/ {} + )cc"); + if (has_cached_size_) { + p->Emit(R"cc( + , /*decltype($cached_size_$)*/ { 0 } + )cc"); + } + } + + void GenerateAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + decltype($field_$) { arena } + )cc"); + if (has_cached_size_) { + // std::atomic has no copy constructor, which prevents explicit aggregate + // initialization pre-C++17. + p->Emit(R"cc( + , /*decltype($cached_size_$)*/ { 0 } + )cc"); + } + } + + void GenerateCopyAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + decltype($field_$) { from.$field_$ })cc"); + if (has_cached_size_) { + // std::atomic has no copy constructor. + p->Emit(R"cc( + , /*decltype($cached_size_$)*/ { 0 } + )cc"); + } + } + + void GenerateCopyConstructorCode(io::Printer* p) const override { + Y_ABSL_CHECK(!ShouldSplit(field_, *opts_)); + } + + void GenerateConstructorCode(io::Printer* p) const override {} + + void GenerateAccessorDeclarations(io::Printer* p) const override; + void GenerateInlineAccessorDefinitions(io::Printer* p) const override; + void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override; + void GenerateByteSize(io::Printer* p) const override; + + private: + const FieldDescriptor* field_; + const Options* opts_; + bool has_cached_size_; +}; + +void RepeatedEnum::GenerateAccessorDeclarations(io::Printer* p) const { + auto v = p->WithVars( + AnnotatedAccessors(field_, {"", "set_", "add_", "mutable_", "_internal_", + "_internal_add_", "_internal_mutable_"})); + + p->Emit(R"cc( + public: + $DEPRECATED$ $Enum$ $name$(int index) const; + $DEPRECATED$ void $set_name$(int index, $Enum$ value); + $DEPRECATED$ void $add_name$($Enum$ value); + $DEPRECATED$ const $pb$::RepeatedField<int>& $name$() const; + $DEPRECATED$ $pb$::RepeatedField<int>* $mutable_name$(); + + private: + $Enum$ $_internal_name$(int index) const; + void $_internal_add_name$($Enum$ value); + $pb$::RepeatedField<int>* $_internal_mutable_name$(); + + public: + )cc"); +} + +void RepeatedEnum::GenerateInlineAccessorDefinitions(io::Printer* p) const { + p->Emit(R"cc( + inline $Enum$ $Msg$::$name$(int index) const { + $annotate_get$; + // @@protoc_insertion_point(field_get:$pkg.Msg.field$) + return _internal_$name$(index); + } + inline void $Msg$::set_$name$(int index, $Enum$ value) { + $assert_valid$; + $field_$.Set(index, value); + $annotate_set$ + // @@protoc_insertion_point(field_set:$pkg.Msg.field$) + } + inline void $Msg$::add_$name$($Enum$ value) { + _internal_add_$name$(value); + $annotate_add$ + // @@protoc_insertion_point(field_add:$pkg.Msg.field$) + } + inline const $pb$::RepeatedField<int>& $Msg$::$name$() const { + $annotate_list$; + // @@protoc_insertion_point(field_list:$pkg.Msg.field$) + return $field_$; + } + inline $pb$::RepeatedField<int>* $Msg$::mutable_$name$() { + $annotate_mutable_list$; + // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$) + return _internal_mutable_$name$(); + } + inline $Enum$ $Msg$::_internal_$name$(int index) const { + return static_cast<$Enum$>($field_$.Get(index)); + } + inline void $Msg$::_internal_add_$name$($Enum$ value) { + $assert_valid$; + $field_$.Add(value); + } + inline $pb$::RepeatedField<int>* $Msg$::_internal_mutable_$name$() { + return &$field_$; + } + )cc"); +} + +void RepeatedEnum::GenerateSerializeWithCachedSizesToArray( + io::Printer* p) const { + if (field_->is_packed()) { + p->Emit(R"cc( + { + int byte_size = $cached_size_$.Get(); + if (byte_size > 0) { + target = stream->WriteEnumPacked($number$, $field_$, byte_size, target); + } + } + )cc"); + return; + } + p->Emit(R"cc( + for (int i = 0, n = this->_internal_$name$_size(); i < n; ++i) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + $number$, this->_internal_$name$(i), target); + } + )cc"); +} + +void RepeatedEnum::GenerateByteSize(io::Printer* p) const { + p->Emit( + { + {"add_to_size", + [&] { + if (!field_->is_packed()) { + p->Emit(R"cc( + total_size += std::size_t{$kTagBytes$} * count; + )cc"); + return; + } + + p->Emit(R"cc( + if (data_size > 0) { + total_size += $kTagBytes$; + total_size += ::_pbi::WireFormatLite::Int32Size( + static_cast<arc_i32>(data_size)); + } + $cached_size_$.Set(::_pbi::ToCachedSize(data_size)); + )cc"); + }}, + }, + R"cc( + { + std::size_t data_size = 0; + auto count = static_cast<std::size_t>(this->_internal_$name$_size()); + + for (std::size_t i = 0; i < count; ++i) { + data_size += ::_pbi::WireFormatLite::EnumSize( + this->_internal_$name$(static_cast<int>(i))); + } + total_size += data_size; + $add_to_size$; + } + )cc"); +} +} // namespace + +std::unique_ptr<FieldGeneratorBase> MakeSinguarEnumGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc) { + return y_absl::make_unique<SingularEnum>(desc, options); +} + +std::unique_ptr<FieldGeneratorBase> MakeRepeatedEnumGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc) { + return y_absl::make_unique<RepeatedEnum>(desc, options); +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/generators.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/generators.h new file mode 100644 index 00000000000..c9accc56e71 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/generators.h @@ -0,0 +1,98 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_GENERATORS_GENERATORS_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_GENERATORS_GENERATORS_H__ + +#include <memory> + +#include "google/protobuf/compiler/cpp/field.h" +#include "google/protobuf/compiler/cpp/helpers.h" + +// The functions in this file construct FieldGeneratorBase objects for +// generating different "codegen types" of fields. The logic for selecting the +// correct choice of generator lives in compiler/cpp/field.cc; this is merely +// the API that file uses for constructing generators. +// +// Functions are of the form `Make<card><kind>Generator()`, where <card> is +// `Singular`, `Repeated`, or `Oneof`, and <kind> is the field type, plus +// `MakeMapGenerator()`, since map fields are always repeated message fields. +// +// The returned pointers are never null. + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { +std::unique_ptr<FieldGeneratorBase> MakeSinguarPrimitiveGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc); + +std::unique_ptr<FieldGeneratorBase> MakeRepeatedPrimitiveGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc); + +std::unique_ptr<FieldGeneratorBase> MakeSinguarEnumGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc); + +std::unique_ptr<FieldGeneratorBase> MakeRepeatedEnumGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc); + +std::unique_ptr<FieldGeneratorBase> MakeSinguarStringGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc); + +std::unique_ptr<FieldGeneratorBase> MakeRepeatedStringGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc); + +std::unique_ptr<FieldGeneratorBase> MakeSinguarMessageGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc); + +std::unique_ptr<FieldGeneratorBase> MakeRepeatedMessageGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc); + +std::unique_ptr<FieldGeneratorBase> MakeOneofMessageGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc); + +std::unique_ptr<FieldGeneratorBase> MakeMapGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc); +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_GENERATORS_GENERATORS_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/map_field.cc index ba363f5267b..2fe5484ab4b 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/map_field.cc @@ -28,28 +28,26 @@ // (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/cpp/map_field.h> - -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/cpp/helpers.h> +#include <memory> +#include <string> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/cpp/field_generators/generators.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/wire_format.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { - -bool IsProto3Field(const FieldDescriptor* field_descriptor) { - const FileDescriptor* file_descriptor = field_descriptor->file(); - return file_descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3; -} - -void SetMessageVariables(const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables, - const Options& options) { - SetCommonFieldVariables(descriptor, variables, options); +namespace { +void SetMessageVariables( + const FieldDescriptor* descriptor, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables, + const Options& options) { (*variables)["type"] = ClassName(descriptor->message_type(), false); (*variables)["full_name"] = descriptor->full_name(); @@ -66,13 +64,13 @@ void SetMessageVariables(const FieldDescriptor* descriptor, default: (*variables)["val_cpp"] = PrimitiveTypeName(options, val->cpp_type()); } - (*variables)["key_wire_type"] = - "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); - (*variables)["val_wire_type"] = - "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); + (*variables)["key_wire_type"] = y_absl::StrCat( + "TYPE_", y_absl::AsciiStrToUpper(DeclaredTypeMethodName(key->type()))); + (*variables)["val_wire_type"] = y_absl::StrCat( + "TYPE_", y_absl::AsciiStrToUpper(DeclaredTypeMethodName(val->type()))); (*variables)["map_classname"] = ClassName(descriptor->message_type(), false); - (*variables)["number"] = StrCat(descriptor->number()); - (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor)); + (*variables)["number"] = y_absl::StrCat(descriptor->number()); + (*variables)["tag"] = y_absl::StrCat(internal::WireFormat::MakeTag(descriptor)); if (HasDescriptorMethods(descriptor->file(), options)) { (*variables)["lite"] = ""; @@ -81,17 +79,46 @@ void SetMessageVariables(const FieldDescriptor* descriptor, } } +class MapFieldGenerator : public FieldGeneratorBase { + public: + MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options, + MessageSCCAnalyzer* scc_analyzer); + ~MapFieldGenerator() override = default; + + // implements FieldGeneratorBase --------------------------------------- + void GeneratePrivateMembers(io::Printer* printer) const override; + void GenerateAccessorDeclarations(io::Printer* printer) const override; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; + void GenerateClearingCode(io::Printer* printer) const override; + void GenerateMergingCode(io::Printer* printer) const override; + void GenerateSwappingCode(io::Printer* printer) const override; + void GenerateConstructorCode(io::Printer* printer) const override {} + void GenerateCopyConstructorCode(io::Printer* printer) const override; + void GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const override; + void GenerateByteSize(io::Printer* printer) const override; + void GenerateIsInitialized(io::Printer* printer) const override; + void GenerateConstexprAggregateInitializer( + io::Printer* printer) const override; + void GenerateCopyAggregateInitializer(io::Printer* printer) const override; + void GenerateAggregateInitializer(io::Printer* printer) const override; + void GenerateDestructorCode(io::Printer* printer) const override; + void GenerateArenaDestructorCode(io::Printer* printer) const override; + ArenaDtorNeeds NeedsArenaDestructor() const override; + + private: + bool has_required_fields_; +}; + MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options, MessageSCCAnalyzer* scc_analyzer) - : FieldGenerator(descriptor, options), + : FieldGeneratorBase(descriptor, options), has_required_fields_( scc_analyzer->HasRequiredFields(descriptor->message_type())) { SetMessageVariables(descriptor, &variables_, options); } -MapFieldGenerator::~MapFieldGenerator() {} - void MapFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { Formatter format(printer, variables_); format( @@ -303,8 +330,6 @@ void MapFieldGenerator::GenerateAggregateInitializer( } void MapFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); if (ShouldSplit(descriptor_, options_)) { format("$cached_split_ptr$->$name$_.Destruct();\n"); @@ -331,6 +356,13 @@ ArenaDtorNeeds MapFieldGenerator::NeedsArenaDestructor() const { ? ArenaDtorNeeds::kRequired : ArenaDtorNeeds::kNone; } +} // namespace + +std::unique_ptr<FieldGeneratorBase> MakeMapGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc) { + return std::make_unique<MapFieldGenerator>(desc, options, scc); +} } // namespace cpp } // namespace compiler diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/message_field.cc index 9a91fd91720..49e86d936bf 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/message_field.cc @@ -32,52 +32,63 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/cpp/message_field.h> - -#include <google/protobuf/io/printer.h> -#include <google/protobuf/compiler/cpp/field.h> -#include <google/protobuf/compiler/cpp/helpers.h> - -#include <google/protobuf/stubs/strutil.h> +#include <memory> +#include <string> +#include <tuple> + +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/memory/memory.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/cpp/field.h" +#include "google/protobuf/compiler/cpp/field_generators/generators.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { - namespace { -TProtoStringType ReinterpretCast(const TProtoStringType& type, - const TProtoStringType& expression, +TProtoStringType ReinterpretCast(y_absl::string_view type, + y_absl::string_view expression, bool implicit_weak_field) { if (implicit_weak_field) { - return "reinterpret_cast< " + type + " >(" + expression + ")"; + return y_absl::StrCat("reinterpret_cast< ", type, " >(", expression, ")"); } else { - return expression; + return TProtoStringType(expression); } } -void SetMessageVariables(const FieldDescriptor* descriptor, - const Options& options, bool implicit_weak, - std::map<TProtoStringType, TProtoStringType>* variables) { - SetCommonFieldVariables(descriptor, variables, options); +void SetMessageVariables( + const FieldDescriptor* descriptor, const Options& options, + bool implicit_weak, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { + bool split = ShouldSplit(descriptor, options); + TProtoStringType field_name = FieldMemberName(descriptor, split); + (*variables)["type"] = FieldMessageTypeName(descriptor, options); - (*variables)["casted_member"] = ReinterpretCast( - (*variables)["type"] + "*", (*variables)["field"], implicit_weak); - (*variables)["casted_member_const"] = - ReinterpretCast("const " + (*variables)["type"] + "&", - "*" + (*variables)["field"], implicit_weak); + variables->insert( + {"casted_member", ReinterpretCast(y_absl::StrCat((*variables)["type"], "*"), + field_name, implicit_weak)}); + variables->insert( + {"casted_member_const", + ReinterpretCast(y_absl::StrCat("const ", (*variables)["type"], "&"), + y_absl::StrCat("*", field_name), implicit_weak)}); (*variables)["type_default_instance"] = QualifiedDefaultInstanceName(descriptor->message_type(), options); (*variables)["type_default_instance_ptr"] = ReinterpretCast( "const ::PROTOBUF_NAMESPACE_ID::MessageLite*", QualifiedDefaultInstancePtr(descriptor->message_type(), options), implicit_weak); - (*variables)["type_reference_function"] = - implicit_weak ? (" ::" + (*variables)["proto_ns"] + - "::internal::StrongReference(reinterpret_cast<const " + - (*variables)["type"] + "&>(\n" + - (*variables)["type_default_instance"] + "));\n") - : ""; + variables->insert( + {"type_reference_function", + implicit_weak + ? y_absl::StrCat(" ::", ProtobufNamespace(options), + "::internal::StrongReference(reinterpret_cast<const ", + (*variables)["type"], "&>(\n", + (*variables)["type_default_instance"], "));\n") + : ""}); // NOTE: Escaped here to unblock proto1->proto2 migration. // TODO(liujisi): Extend this to apply for other conflicting methods. (*variables)["release_name"] = @@ -85,14 +96,92 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["full_name"] = descriptor->full_name(); } -} // namespace +class MessageFieldGenerator : public FieldGeneratorBase { + public: + MessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options, + MessageSCCAnalyzer* scc_analyzer); + ~MessageFieldGenerator() override = default; + + void GeneratePrivateMembers(io::Printer* printer) const override; + void GenerateAccessorDeclarations(io::Printer* printer) const override; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; + void GenerateNonInlineAccessorDefinitions( + io::Printer* printer) const override; + void GenerateInternalAccessorDeclarations( + io::Printer* printer) const override; + void GenerateInternalAccessorDefinitions(io::Printer* printer) const override; + void GenerateClearingCode(io::Printer* printer) const override; + void GenerateMessageClearingCode(io::Printer* printer) const override; + void GenerateMergingCode(io::Printer* printer) const override; + void GenerateSwappingCode(io::Printer* printer) const override; + void GenerateDestructorCode(io::Printer* printer) const override; + void GenerateConstructorCode(io::Printer* printer) const override {} + void GenerateCopyConstructorCode(io::Printer* printer) const override; + void GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const override; + void GenerateByteSize(io::Printer* printer) const override; + void GenerateIsInitialized(io::Printer* printer) const override; + void GenerateConstexprAggregateInitializer( + io::Printer* printer) const override; + void GenerateAggregateInitializer(io::Printer* printer) const override; + void GenerateCopyAggregateInitializer(io::Printer* printer) const override; + + protected: + bool implicit_weak_field_; + bool has_required_fields_; +}; + +class MessageOneofFieldGenerator : public MessageFieldGenerator { + public: + MessageOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options, + MessageSCCAnalyzer* scc_analyzer); + ~MessageOneofFieldGenerator() override = default; + + void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; + void GenerateNonInlineAccessorDefinitions( + io::Printer* printer) const override; + void GenerateClearingCode(io::Printer* printer) const override; + void GenerateMessageClearingCode(io::Printer* printer) const override; + void GenerateSwappingCode(io::Printer* printer) const override; + void GenerateDestructorCode(io::Printer* printer) const override; + void GenerateConstructorCode(io::Printer* printer) const override; + void GenerateIsInitialized(io::Printer* printer) const override; +}; + +class RepeatedMessageFieldGenerator : public FieldGeneratorBase { + public: + RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, + const Options& options, + MessageSCCAnalyzer* scc_analyzer); + ~RepeatedMessageFieldGenerator() override = default; + + void GeneratePrivateMembers(io::Printer* printer) const override; + void GenerateAccessorDeclarations(io::Printer* printer) const override; + void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; + void GenerateClearingCode(io::Printer* printer) const override; + void GenerateMergingCode(io::Printer* printer) const override; + void GenerateSwappingCode(io::Printer* printer) const override; + void GenerateConstructorCode(io::Printer* printer) const override; + void GenerateCopyConstructorCode(io::Printer* printer) const override {} + void GenerateDestructorCode(io::Printer* printer) const override; + void GenerateSerializeWithCachedSizesToArray( + io::Printer* printer) const override; + void GenerateByteSize(io::Printer* printer) const override; + void GenerateIsInitialized(io::Printer* printer) const override; + + private: + bool implicit_weak_field_; + bool has_required_fields_; +}; // =================================================================== MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, const Options& options, MessageSCCAnalyzer* scc_analyzer) - : FieldGenerator(descriptor, options), + : FieldGeneratorBase(descriptor, options), implicit_weak_field_( IsImplicitWeakField(descriptor, options, scc_analyzer)), has_required_fields_( @@ -100,8 +189,6 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_); } -MessageFieldGenerator::~MessageFieldGenerator() {} - void MessageFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { Formatter format(printer, variables_); if (implicit_weak_field_) { @@ -114,41 +201,21 @@ void MessageFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { void MessageFieldGenerator::GenerateAccessorDeclarations( io::Printer* printer) const { Formatter format(printer, variables_); - if (IsFieldStripped(descriptor_, options_)) { - format( - "$deprecated_attr$const $type$& ${1$$name$$}$() const { " - "__builtin_trap(); }\n" - "PROTOBUF_NODISCARD $deprecated_attr$$type$* " - "${1$$release_name$$}$() { " - "__builtin_trap(); }\n" - "$deprecated_attr$$type$* ${1$mutable_$name$$}$() { " - "__builtin_trap(); }\n" - "$deprecated_attr$void ${1$set_allocated_$name$$}$" - "($type$* $name$) { __builtin_trap(); }\n" - "$deprecated_attr$void " - "${1$unsafe_arena_set_allocated_$name$$}$(\n" - " $type$* $name$) { __builtin_trap(); }\n" - "$deprecated_attr$$type$* ${1$unsafe_arena_release_$name$$}$() { " - "__builtin_trap(); }\n", - descriptor_); - return; - } format( "$deprecated_attr$const $type$& ${1$$name$$}$() const;\n" "PROTOBUF_NODISCARD $deprecated_attr$$type$* " - "${1$$release_name$$}$();\n" - "$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n" + "${1$$release_name$$}$();\n", + descriptor_); + format("$deprecated_attr$$type$* ${1$mutable_$name$$}$();\n", + std::make_tuple(descriptor_, GeneratedCodeInfo::Annotation::ALIAS)); + format( "$deprecated_attr$void ${1$set_allocated_$name$$}$" - "($type$* $name$);\n", + "($type$* $name$);\n" + "private:\n" + "const $type$& ${1$_internal_$name$$}$() const;\n" + "$type$* ${1$_internal_mutable_$name$$}$();\n" + "public:\n", descriptor_); - if (!IsFieldStripped(descriptor_, options_)) { - format( - "private:\n" - "const $type$& ${1$_internal_$name$$}$() const;\n" - "$type$* ${1$_internal_mutable_$name$$}$();\n" - "public:\n", - descriptor_); - } format( "$deprecated_attr$void " "${1$unsafe_arena_set_allocated_$name$$}$(\n" @@ -191,12 +258,15 @@ void MessageFieldGenerator::GenerateInlineAccessorDefinitions( } else { format(" $field$ = $name$;\n"); } + if (internal::cpp::HasHasbit(descriptor_)) { + format( + " if ($name$) {\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" + " }\n"); + } format( - " if ($name$) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" "$annotate_set$" " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" ":$full_name$)\n" @@ -343,14 +413,14 @@ void MessageFieldGenerator::GenerateInternalAccessorDefinitions( format( "::$proto_ns$::MessageLite*\n" "$classname$::_Internal::mutable_$name$($classname$* msg) {\n"); - if (HasHasbit(descriptor_)) { + if (internal::cpp::HasHasbit(descriptor_)) { format(" msg->$set_hasbit$\n"); } if (descriptor_->real_containing_oneof() == nullptr) { format(" if (msg->$field$ == nullptr) {\n"); } else { format( - " if (!msg->_internal_has_$name$()) {\n" + " if (msg->$not_has_field$) {\n" " msg->clear_$oneof_name$();\n" " msg->set_has_$name$();\n"); } @@ -373,10 +443,8 @@ void MessageFieldGenerator::GenerateInternalAccessorDefinitions( } void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); - if (!HasHasbit(descriptor_)) { + if (!internal::cpp::HasHasbit(descriptor_)) { // If we don't have has-bits, message presence is indicated only by ptr != // nullptr. Thus on clear, we need to delete the object. format( @@ -391,10 +459,8 @@ void MessageFieldGenerator::GenerateClearingCode(io::Printer* printer) const { void MessageFieldGenerator::GenerateMessageClearingCode( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); - if (!HasHasbit(descriptor_)) { + if (!internal::cpp::HasHasbit(descriptor_)) { // If we don't have has-bits, message presence is indicated only by ptr != // nullptr. Thus on clear, we need to delete the object. format( @@ -410,8 +476,6 @@ void MessageFieldGenerator::GenerateMessageClearingCode( } void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); if (implicit_weak_field_) { format( @@ -425,15 +489,11 @@ void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) const { } void MessageFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); format("swap($field$, other->$field$);\n"); } void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); if (options_.opensource_runtime) { // TODO(gerbens) Remove this when we don't need to destruct default @@ -450,21 +510,26 @@ void MessageFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { format("delete $field$;\n"); } +using internal::cpp::HasHasbit; + void MessageFieldGenerator::GenerateCopyConstructorCode( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); - format( - "if (from._internal_has_$name$()) {\n" - " _this->$field$ = new $type$(*from.$field$);\n" - "}\n"); + if (HasHasbit(descriptor_)) { + format( + "if ((from.$has_hasbit$) != 0) {\n" + " _this->$field$ = new $type$(*from.$field$);\n" + "}\n"); + } else { + format( + "if (from._internal_has_$name$()) {\n" + " _this->$field$ = new $type$(*from.$field$);\n" + "}\n"); + } } void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { format( @@ -481,8 +546,6 @@ void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray( } void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); format( "total_size += $tag_size$ +\n" @@ -491,15 +554,20 @@ void MessageFieldGenerator::GenerateByteSize(io::Printer* printer) const { } void MessageFieldGenerator::GenerateIsInitialized(io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - if (!has_required_fields_) return; Formatter format(printer, variables_); - format( - "if (_internal_has_$name$()) {\n" - " if (!$field$->IsInitialized()) return false;\n" - "}\n"); + if (HasHasbit(descriptor_)) { + format( + "if (($has_hasbit$) != 0) {\n" + " if (!$field$->IsInitialized()) return false;\n" + "}\n"); + } else { + format( + "if (_internal_has_$name$()) {\n" + " if (!$field$->IsInitialized()) return false;\n" + "}\n"); + } } void MessageFieldGenerator::GenerateConstexprAggregateInitializer( @@ -530,11 +598,8 @@ MessageOneofFieldGenerator::MessageOneofFieldGenerator( const FieldDescriptor* descriptor, const Options& options, MessageSCCAnalyzer* scc_analyzer) : MessageFieldGenerator(descriptor, options, scc_analyzer) { - SetCommonOneofFieldVariables(descriptor, &variables_); } -MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} - void MessageOneofFieldGenerator::GenerateNonInlineAccessorDefinitions( io::Printer* printer) const { Formatter format(printer, variables_); @@ -577,7 +642,7 @@ void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions( "$annotate_release$" " // @@protoc_insertion_point(field_release:$full_name$)\n" "$type_reference_function$" - " if (_internal_has_$name$()) {\n" + " if ($has_field$) {\n" " clear_has_$oneof_name$();\n" " $type$* temp = $casted_member$;\n" " if (GetArenaForAllocation() != nullptr) {\n" @@ -593,7 +658,7 @@ void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions( format( "inline const $type$& $classname$::_internal_$name$() const {\n" "$type_reference_function$" - " return _internal_has_$name$()\n" + " return $has_field$\n" " ? $casted_member_const$\n" " : reinterpret_cast< $type$&>($type_default_instance$);\n" "}\n" @@ -607,7 +672,7 @@ void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions( " // @@protoc_insertion_point(field_unsafe_arena_release" ":$full_name$)\n" "$type_reference_function$" - " if (_internal_has_$name$()) {\n" + " if ($has_field$) {\n" " clear_has_$oneof_name$();\n" " $type$* temp = $casted_member$;\n" " $field$ = nullptr;\n" @@ -639,7 +704,7 @@ void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions( "}\n" "inline $type$* $classname$::_internal_mutable_$name$() {\n" "$type_reference_function$" - " if (!_internal_has_$name$()) {\n" + " if ($not_has_field$) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n"); if (implicit_weak_field_) { @@ -666,8 +731,6 @@ void MessageOneofFieldGenerator::GenerateInlineAccessorDefinitions( void MessageOneofFieldGenerator::GenerateClearingCode( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); format( "if (GetArenaForAllocation() == nullptr) {\n" @@ -703,7 +766,7 @@ void MessageOneofFieldGenerator::GenerateIsInitialized( Formatter format(printer, variables_); format( - "if (_internal_has_$name$()) {\n" + "if ($has_field$) {\n" " if (!$field$->IsInitialized()) return false;\n" "}\n"); } @@ -713,7 +776,7 @@ void MessageOneofFieldGenerator::GenerateIsInitialized( RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( const FieldDescriptor* descriptor, const Options& options, MessageSCCAnalyzer* scc_analyzer) - : FieldGenerator(descriptor, options), + : FieldGeneratorBase(descriptor, options), implicit_weak_field_( IsImplicitWeakField(descriptor, options, scc_analyzer)), has_required_fields_( @@ -721,8 +784,6 @@ RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( SetMessageVariables(descriptor, options, implicit_weak_field_, &variables_); } -RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} - void RepeatedMessageFieldGenerator::GeneratePrivateMembers( io::Printer* printer) const { Formatter format(printer, variables_); @@ -736,34 +797,18 @@ void RepeatedMessageFieldGenerator::GeneratePrivateMembers( void RepeatedMessageFieldGenerator::GenerateAccessorDeclarations( io::Printer* printer) const { Formatter format(printer, variables_); - if (IsFieldStripped(descriptor_, options_)) { - format( - "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index) { " - "__builtin_trap(); }\n" - "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n" - " ${1$mutable_$name$$}$() { __builtin_trap(); }\n" - "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const { " - "__builtin_trap(); }\n" - "$deprecated_attr$$type$* ${1$add_$name$$}$() { " - "__builtin_trap(); }\n" - "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField< $type$ >&\n" - " ${1$$name$$}$() const { __builtin_trap(); }\n", - descriptor_); - return; - } + format("$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index);\n", + std::make_tuple(descriptor_, GeneratedCodeInfo::Annotation::ALIAS)); format( - "$deprecated_attr$$type$* ${1$mutable_$name$$}$(int index);\n" "$deprecated_attr$::$proto_ns$::RepeatedPtrField< $type$ >*\n" " ${1$mutable_$name$$}$();\n", + std::make_tuple(descriptor_, GeneratedCodeInfo::Annotation::ALIAS)); + format( + "private:\n" + "const $type$& ${1$_internal_$name$$}$(int index) const;\n" + "$type$* ${1$_internal_add_$name$$}$();\n" + "public:\n", descriptor_); - if (!IsFieldStripped(descriptor_, options_)) { - format( - "private:\n" - "const $type$& ${1$_internal_$name$$}$(int index) const;\n" - "$type$* ${1$_internal_add_$name$$}$();\n" - "public:\n", - descriptor_); - } format( "$deprecated_attr$const $type$& ${1$$name$$}$(int index) const;\n" "$deprecated_attr$$type$* ${1$add_$name$$}$();\n" @@ -837,24 +882,18 @@ void RepeatedMessageFieldGenerator::GenerateInlineAccessorDefinitions( void RepeatedMessageFieldGenerator::GenerateClearingCode( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); format("$field$.Clear();\n"); } void RepeatedMessageFieldGenerator::GenerateMergingCode( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); format("_this->$field$.MergeFrom(from.$field$);\n"); } void RepeatedMessageFieldGenerator::GenerateSwappingCode( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); format("$field$.InternalSwap(&other->$field$);\n"); } @@ -866,8 +905,6 @@ void RepeatedMessageFieldGenerator::GenerateConstructorCode( void RepeatedMessageFieldGenerator::GenerateDestructorCode( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); if (implicit_weak_field_) { format("$field$.~WeakRepeatedPtrField();\n"); @@ -878,8 +915,6 @@ void RepeatedMessageFieldGenerator::GenerateDestructorCode( void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); if (implicit_weak_field_) { format( @@ -923,8 +958,6 @@ void RepeatedMessageFieldGenerator::GenerateSerializeWithCachedSizesToArray( void RepeatedMessageFieldGenerator::GenerateByteSize( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - Formatter format(printer, variables_); format( "total_size += $tag_size$UL * this->_internal_$name$_size();\n" @@ -936,8 +969,6 @@ void RepeatedMessageFieldGenerator::GenerateByteSize( void RepeatedMessageFieldGenerator::GenerateIsInitialized( io::Printer* printer) const { - GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_)); - if (!has_required_fields_) return; Formatter format(printer, variables_); @@ -951,6 +982,25 @@ void RepeatedMessageFieldGenerator::GenerateIsInitialized( " return false;\n"); } } +} // namespace + +std::unique_ptr<FieldGeneratorBase> MakeSinguarMessageGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc) { + return y_absl::make_unique<MessageFieldGenerator>(desc, options, scc); +} + +std::unique_ptr<FieldGeneratorBase> MakeRepeatedMessageGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc) { + return y_absl::make_unique<RepeatedMessageFieldGenerator>(desc, options, scc); +} + +std::unique_ptr<FieldGeneratorBase> MakeOneofMessageGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc) { + return y_absl::make_unique<MessageOneofFieldGenerator>(desc, options, scc); +} } // namespace cpp } // namespace compiler diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc new file mode 100644 index 00000000000..9b5659fc023 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc @@ -0,0 +1,582 @@ +// 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: [email protected] (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <memory> +#include <string> +#include <tuple> +#include <vector> + +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/memory/memory.h" +#include "y_absl/types/optional.h" +#include "google/protobuf/compiler/cpp/field_generators/generators.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { +namespace { +using ::google::protobuf::internal::WireFormat; +using ::google::protobuf::internal::WireFormatLite; +using Sub = ::google::protobuf::io::Printer::Sub; +using Annotation = ::google::protobuf::GeneratedCodeInfo::Annotation; + +// For encodings with fixed sizes, returns that size in bytes. +y_absl::optional<size_t> FixedSize(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_ENUM: + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + return y_absl::nullopt; + + case FieldDescriptor::TYPE_FIXED32: + return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64: + return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: + return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: + return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT: + return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE: + return WireFormatLite::kDoubleSize; + case FieldDescriptor::TYPE_BOOL: + return WireFormatLite::kBoolSize; + + // No default because we want the compiler to complain if any new + // types are added. + } + + Y_ABSL_LOG(FATAL) << "Can't get here."; + return y_absl::nullopt; +} + +std::vector<Sub> Vars(const FieldDescriptor* field, const Options& options) { + bool cold = ShouldSplit(field, options); + return { + {"Type", PrimitiveTypeName(options, field->cpp_type())}, + {"kDefault", DefaultValue(options, field)}, + {"_field_cached_byte_size_", MakeVarintCachedSizeFieldName(field, cold)}, + }; +} + +class SingularPrimitive final : public FieldGeneratorBase { + public: + SingularPrimitive(const FieldDescriptor* field, const Options& opts) + : FieldGeneratorBase(field, opts), + field_(field), + opts_(&opts), + is_oneof_(field_->real_containing_oneof() != nullptr) {} + ~SingularPrimitive() override = default; + + std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); } + + void GeneratePrivateMembers(io::Printer* p) const override { + p->Emit(R"cc( + $Type$ $name$_; + )cc"); + } + + void GenerateClearingCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$ = $kDefault$; + )cc"); + } + + void GenerateMergingCode(io::Printer* p) const override { + p->Emit(R"cc( + _this->_internal_set_$name$(from._internal_$name$()); + )cc"); + } + + void GenerateSwappingCode(io::Printer* p) const override { + if (is_oneof_) { + // Don't print any swapping code. Swapping the union will swap this field. + return; + } + + p->Emit(R"cc( + //~ A `using std::swap;` is already present in this function. + swap($field_$, other->$field_$); + )cc"); + } + + void GenerateConstructorCode(io::Printer* p) const override { + if (!is_oneof_) { + return; + } + + p->Emit(R"cc( + $pkg$::_$Msg$_default_instance_.$field_$ = $kDefault$; + )cc"); + } + + void GenerateCopyConstructorCode(io::Printer* p) const override { + p->Emit(R"cc( + _this->$field_$ = from.$field_$; + )cc"); + } + + void GenerateConstexprAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + /*decltype($field_$)*/ $kDefault$ + )cc"); + } + + void GenerateAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + decltype($field_$) { $kDefault$ } + )cc"); + } + + void GenerateCopyAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + decltype($field_$) {} + )cc"); + } + + void GenerateAccessorDeclarations(io::Printer* p) const override; + void GenerateInlineAccessorDefinitions(io::Printer* p) const override; + void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override; + void GenerateByteSize(io::Printer* p) const override; + + private: + const FieldDescriptor* field_; + const Options* opts_; + bool is_oneof_; +}; + +void SingularPrimitive::GenerateAccessorDeclarations(io::Printer* p) const { + p->Emit( + { + Sub("name", p->LookupVar("name")).AnnotatedAs(field_), + Sub("set_name", y_absl::StrCat("set_", p->LookupVar("name"))) + .AnnotatedAs(field_), + Sub("_internal_name", + y_absl::StrCat("_internal_", p->LookupVar("name"))) + .AnnotatedAs(field_), + Sub("_internal_set_name", + y_absl::StrCat("_internal_set_", p->LookupVar("name"))) + .AnnotatedAs(field_), + }, + R"cc( + $DEPRECATED$ $Type$ $name$() const; + $DEPRECATED$ void $set_name$($Type$ value); + + private: + $Type$ $_internal_name$() const; + void $_internal_set_name$($Type$ value); + + public: + )cc"); +} + +void SingularPrimitive::GenerateInlineAccessorDefinitions( + io::Printer* p) const { + p->Emit(R"cc( + inline $Type$ $Msg$::$name$() const { + $annotate_get$; + // @@protoc_insertion_point(field_get:$pkg.Msg.field$) + return _internal_$name$(); + } + inline void $Msg$::set_$name$($Type$ value) { + $PrepareSplitMessageForWrite$; + _internal_set_$name$(value); + $annotate_set$; + // @@protoc_insertion_point(field_set:$pkg.Msg.field$) + } + )cc"); + + if (is_oneof_) { + p->Emit(R"cc( + inline $Type$ $Msg$::_internal_$name$() const { + if ($has_field$) { + return $field_$; + } + return $kDefault$; + } + inline void $Msg$::_internal_set_$name$($Type$ value) { + if ($not_has_field$) { + clear_$oneof_name$(); + set_has_$name$(); + } + $field_$ = value; + } + )cc"); + } else { + p->Emit(R"cc( + inline $Type$ $Msg$::_internal_$name$() const { + return $field_$; + } + inline void $Msg$::_internal_set_$name$($Type$ value) { + $set_hasbit$; + $field_$ = value; + } + )cc"); + } +} + +void SingularPrimitive::GenerateSerializeWithCachedSizesToArray( + io::Printer* p) const { + p->Emit(R"cc( + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::Write$DeclaredType$ToArray( + $number$, this->_internal_$name$(), target); + )cc"); +} + +void SingularPrimitive::GenerateByteSize(io::Printer* p) const { + size_t tag_size = WireFormat::TagSize(field_->number(), field_->type()); + + auto fixed_size = FixedSize(field_->type()); + if (fixed_size.has_value()) { + p->Emit({{"kFixedBytes", tag_size + *fixed_size}}, R"cc( + total_size += $kFixedBytes$; + )cc"); + return; + } + + // Adding one is very common and it turns out it can be done for + // free inside of WireFormatLite, so we can save an instruction here. + if (tag_size == 1) { + p->Emit(R"cc( + total_size += ::_pbi::WireFormatLite::$DeclaredType$SizePlusOne( + this->_internal_$name$()); + )cc"); + return; + } + + p->Emit(R"cc( + total_size += $kTagBytes$ + ::_pbi::WireFormatLite::$DeclaredType$Size( + this->_internal_$name$()); + )cc"); +} + +class RepeatedPrimitive final : public FieldGeneratorBase { + public: + RepeatedPrimitive(const FieldDescriptor* field, const Options& opts) + : FieldGeneratorBase(field, opts), field_(field), opts_(&opts) {} + ~RepeatedPrimitive() override = default; + + std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); } + + void GenerateClearingCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$.Clear(); + )cc"); + } + + void GenerateMergingCode(io::Printer* p) const override { + p->Emit(R"cc( + _this->$field_$.MergeFrom(from.$field_$); + )cc"); + } + + void GenerateSwappingCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$.InternalSwap(&other->$field_$); + )cc"); + } + + void GenerateDestructorCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$.~RepeatedField(); + )cc"); + } + + void GenerateConstructorCode(io::Printer* p) const override {} + + void GenerateCopyConstructorCode(io::Printer* p) const override { + Y_ABSL_CHECK(!ShouldSplit(field_, *opts_)); + } + + void GenerateConstexprAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + /*decltype($field_$)*/ {} + )cc"); + InitCachedSize(p); + } + + void GenerateAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + decltype($field_$) { arena } + )cc"); + InitCachedSize(p); + } + + void GenerateCopyAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + decltype($field_$) { from.$field_$ } + )cc"); + InitCachedSize(p); + } + + void GeneratePrivateMembers(io::Printer* p) const override; + void GenerateAccessorDeclarations(io::Printer* p) const override; + void GenerateInlineAccessorDefinitions(io::Printer* p) const override; + void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override; + void GenerateByteSize(io::Printer* p) const override; + + private: + bool HasCachedSize() const { + bool is_packed_varint = + field_->is_packed() && !FixedSize(field_->type()).has_value(); + return is_packed_varint && HasGeneratedMethods(field_->file(), *opts_); + } + + void InitCachedSize(io::Printer* p) const { + if (!HasCachedSize()) return; + // std::atomic has no move constructor, which prevents explicit aggregate + // initialization pre-C++17. + p->Emit(R"( + ,/* $_field_cached_byte_size_$ = */ { 0 } + )"); + } + + const FieldDescriptor* field_; + const Options* opts_; +}; + +void RepeatedPrimitive::GeneratePrivateMembers(io::Printer* p) const { + p->Emit(R"cc( + $pb$::RepeatedField<$Type$> $name$_; + )cc"); + + if (HasCachedSize()) { + p->Emit({{"_cached_size_", MakeVarintCachedSizeName(field_)}}, + R"cc( + mutable $pbi$::CachedSize $_cached_size_$; + )cc"); + } +} + +void RepeatedPrimitive::GenerateAccessorDeclarations(io::Printer* p) const { + p->Emit( + { + Sub("name", p->LookupVar("name")).AnnotatedAs(field_), + Sub("set_name", y_absl::StrCat("set_", p->LookupVar("name"))) + .AnnotatedAs(field_), + Sub("add_name", y_absl::StrCat("add_", p->LookupVar("name"))) + .AnnotatedAs(field_), + Sub("mutable_name", y_absl::StrCat("mutable_", p->LookupVar("name"))) + .AnnotatedAs(field_), + + Sub("_internal_name", + y_absl::StrCat("_internal_", p->LookupVar("name"))) + .AnnotatedAs(field_), + Sub("_internal_add_name", + y_absl::StrCat("_internal_add_", p->LookupVar("name"))) + .AnnotatedAs(field_), + Sub("_internal_mutable_name", + y_absl::StrCat("_internal_mutable_", p->LookupVar("name"))) + .AnnotatedAs(field_), + }, + R"cc( + $DEPRECATED$ $Type$ $name$(int index) const; + $DEPRECATED$ void $set_name$(int index, $Type$ value); + $DEPRECATED$ void $add_name$($Type$ value); + $DEPRECATED$ const $pb$::RepeatedField<$Type$>& $name$() const; + $DEPRECATED$ $pb$::RepeatedField<$Type$>* $mutable_name$(); + + private: + $Type$ $_internal_name$(int index) const; + void $_internal_add_name$($Type$ value); + const $pb$::RepeatedField<$Type$>& $_internal_name$() const; + $pb$::RepeatedField<$Type$>* $_internal_mutable_name$(); + + public: + )cc"); +} + +void RepeatedPrimitive::GenerateInlineAccessorDefinitions( + io::Printer* p) const { + p->Emit(R"cc( + inline $Type$ $Msg$::$name$(int index) const { + $annotate_get$; + // @@protoc_insertion_point(field_get:$pkg.Msg.field$) + return _internal_$name$(index); + } + inline void $Msg$::set_$name$(int index, $Type$ value) { + $annotate_set$; + $field_$.Set(index, value); + // @@protoc_insertion_point(field_set:$pkg.Msg.field$) + } + inline void $Msg$::add_$name$($Type$ value) { + _internal_add_$name$(value); + $annotate_add$; + // @@protoc_insertion_point(field_add:$pkg.Msg.field$) + } + inline const $pb$::RepeatedField<$Type$>& $Msg$::$name$() const { + $annotate_list$; + // @@protoc_insertion_point(field_list:$pkg.Msg.field$) + return _internal_$name$(); + } + inline $pb$::RepeatedField<$Type$>* $Msg$::mutable_$name$() { + $annotate_mutable_list$; + // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$) + return _internal_mutable_$name$(); + } + + inline $Type$ $Msg$::_internal_$name$(int index) const { + return $field_$.Get(index); + } + inline void $Msg$::_internal_add_$name$($Type$ value) { $field_$.Add(value); } + inline const $pb$::RepeatedField<$Type$>& $Msg$::_internal_$name$() const { + return $field_$; + } + inline $pb$::RepeatedField<$Type$>* $Msg$::_internal_mutable_$name$() { + return &$field_$; + } + )cc"); +} + +void RepeatedPrimitive::GenerateSerializeWithCachedSizesToArray( + io::Printer* p) const { + if (!field_->is_packed()) { + p->Emit(R"cc( + for (int i = 0, n = this->_internal_$name$_size(); i < n; ++i) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::Write$DeclaredType$ToArray( + $number$, this->_internal_$name$(i), target); + } + )cc"); + return; + } + + if (FixedSize(field_->type()).has_value()) { + p->Emit(R"cc( + if (this->_internal_$name$_size() > 0) { + target = stream->WriteFixedPacked($number$, _internal_$name$(), target); + } + )cc"); + return; + } + + p->Emit(R"cc( + { + int byte_size = $_field_cached_byte_size_$.Get(); + if (byte_size > 0) { + target = stream->Write$DeclaredType$Packed($number$, _internal_$name$(), + byte_size, target); + } + } + )cc"); +} + +void RepeatedPrimitive::GenerateByteSize(io::Printer* p) const { + p->Emit( + { + Sub{"data_size", + [&] { + auto fixed_size = FixedSize(descriptor_->type()); + if (fixed_size.has_value()) { + p->Emit({{"kFixed", *fixed_size}}, R"cc( + std::size_t{$kFixed$} * + ::_pbi::FromIntSize(this->_internal_$name$_size()) + )cc"); + } else { + p->Emit(R"cc( + ::_pbi::WireFormatLite::$DeclaredType$Size(this->$field_$) + )cc"); + } + }} // Here and below, we need to disable the default ;-chomping + // that closure substitutions do. + .WithSuffix(""), + {"maybe_cache_data_size", + [&] { + if (!HasCachedSize()) return; + p->Emit(R"cc( + $_field_cached_byte_size_$.Set(::_pbi::ToCachedSize(data_size)); + )cc"); + }}, + Sub{"tag_size", + [&] { + if (field_->is_packed()) { + p->Emit(R"cc( + data_size == 0 + ? 0 + : $kTagBytes$ + ::_pbi::WireFormatLite::Int32Size( + static_cast<arc_i32>(data_size)) + )cc"); + } else { + p->Emit(R"cc( + std::size_t{$kTagBytes$} * + ::_pbi::FromIntSize(this->_internal_$name$_size()); + )cc"); + } + }} + .WithSuffix(""), + }, + R"cc( + { + std::size_t data_size = $data_size$; + $maybe_cache_data_size$; + std::size_t tag_size = $tag_size$; + total_size += tag_size + data_size; + } + )cc"); +} +} // namespace + +std::unique_ptr<FieldGeneratorBase> MakeSinguarPrimitiveGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc) { + return y_absl::make_unique<SingularPrimitive>(desc, options); +} + +std::unique_ptr<FieldGeneratorBase> MakeRepeatedPrimitiveGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc) { + return y_absl::make_unique<RepeatedPrimitive>(desc, options); +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/string_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/string_field.cc new file mode 100644 index 00000000000..11b5b83ea66 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/string_field.cc @@ -0,0 +1,922 @@ +// 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: [email protected] (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <memory> +#include <string> +#include <vector> + +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/memory/memory.h" +#include "google/protobuf/compiler/cpp/field.h" +#include "google/protobuf/compiler/cpp/field_generators/generators.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { +namespace { +using ::google::protobuf::internal::cpp::HasHasbit; +using ::google::protobuf::io::AnnotationCollector; +using Sub = ::google::protobuf::io::Printer::Sub; + +std::vector<Sub> Vars(const FieldDescriptor* field, const Options& opts) { + auto trivial_default = + y_absl::StrCat("::", ProtobufNamespace(opts), + "::internal::GetEmptyStringAlreadyInited()"); + auto lazy_var = + y_absl::StrCat(QualifiedClassName(field->containing_type(), opts), + "::", MakeDefaultFieldName(field)); + + bool empty_default = field->default_value_string().empty(); + bool is_bytes = field->type() == FieldDescriptor::TYPE_BYTES; + + return { + {"kDefault", DefaultValue(opts, field)}, + {"kDefaultLen", field->default_value_string().size()}, + {"default_variable_name", MakeDefaultName(field)}, + {"default_variable_field", MakeDefaultFieldName(field)}, + + {"kDefaultStr", + !empty_default ? y_absl::StrCat(lazy_var, ".get()") : trivial_default}, + {"kDefaultValue", + !empty_default ? "nullptr" : y_absl::StrCat("&", trivial_default)}, + + {"lazy_var", lazy_var}, + Sub{"lazy_args", !empty_default ? y_absl::StrCat(lazy_var, ",") : ""} + .WithSuffix(","), + + {"byte", is_bytes ? "void" : "char"}, + {"Set", is_bytes ? "SetBytes" : "Set"}, + }; +} + +class SingularString : public FieldGeneratorBase { + public: + SingularString(const FieldDescriptor* field, const Options& opts) + : FieldGeneratorBase(field, opts), + field_(field), + opts_(&opts), + is_oneof_(field->real_containing_oneof() != nullptr), + inlined_(IsStringInlined(field, opts)) {} + ~SingularString() override = default; + + std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); } + + bool IsInlined() const override { return inlined_; } + + ArenaDtorNeeds NeedsArenaDestructor() const override { + return inlined_ ? ArenaDtorNeeds::kOnDemand : ArenaDtorNeeds::kNone; + } + + void GeneratePrivateMembers(io::Printer* p) const override { + // Skips the automatic destruction if inlined; rather calls it explicitly if + // allocating arena is null. + p->Emit({{"Str", inlined_ ? "InlinedStringField" : "ArenaStringPtr"}}, R"cc( + $pbi$::$Str$ $name$_; + )cc"); + } + + void GenerateMergingCode(io::Printer* p) const override { + p->Emit(R"cc( + _this->_internal_set_$name$(from._internal_$name$()); + )cc"); + } + + void GenerateArenaDestructorCode(io::Printer* p) const override { + if (!inlined_) return; + + p->Emit(R"cc( + if (!_this->_internal_$name$_donated()) { + _this->$field_$.~InlinedStringField(); + } + )cc"); + } + + void GenerateNonInlineAccessorDefinitions(io::Printer* p) const override { + if (EmptyDefault()) return; + p->Emit(R"cc( + /*static*/ const ::_pbi::LazyString $Msg$::$default_variable_field${ + {{$kDefault$, $kDefaultLen$}}, + {nullptr}, + }; + )cc"); + } + + void GenerateByteSize(io::Printer* p) const override { + p->Emit(R"cc( + total_size += $kTagBytes$ + $pbi$::WireFormatLite::$DeclaredType$Size( + this->_internal_$name$()); + )cc"); + } + + void GenerateCopyAggregateInitializer(io::Printer* p) const override { + p->Emit(R"cc( + decltype($field_$) {} + )cc"); + } + + void GenerateStaticMembers(io::Printer* p) const override; + void GenerateAccessorDeclarations(io::Printer* p) const override; + void GenerateInlineAccessorDefinitions(io::Printer* p) const override; + void GenerateClearingCode(io::Printer* p) const override; + void GenerateMessageClearingCode(io::Printer* p) const override; + void GenerateSwappingCode(io::Printer* p) const override; + void GenerateConstructorCode(io::Printer* p) const override; + void GenerateCopyConstructorCode(io::Printer* p) const override; + void GenerateDestructorCode(io::Printer* p) const override; + void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override; + void GenerateConstexprAggregateInitializer(io::Printer* p) const override; + void GenerateAggregateInitializer(io::Printer* p) const override; + + private: + bool EmptyDefault() const { return field_->default_value_string().empty(); } + void ReleaseImpl(io::Printer* p) const; + void SetAllocatedImpl(io::Printer* p) const; + + const FieldDescriptor* field_; + const Options* opts_; + bool is_oneof_; + bool inlined_; +}; + +void SingularString::GenerateStaticMembers(io::Printer* p) const { + if (!EmptyDefault()) { + p->Emit(R"cc( + static const $pbi$::LazyString $default_variable_name$; + )cc"); + } + if (inlined_) { + // `_init_inline_xxx` is used for initializing default instances. + p->Emit(R"cc( + static std::true_type _init_inline_$name$_; + )cc"); + } +} + +void SingularString::GenerateAccessorDeclarations(io::Printer* p) const { + // If we're using SingularString 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. + // We aren't releasing Cord because it has too many Google-specific + // dependencies and we aren't releasing StringPiece because it's hardly + // useful outside of Google and because it would get confusing to have + // multiple instances of the StringPiece class in different libraries (PCRE + // already includes it for their C++ bindings, which came from Google). + // + // In any case, we make all the accessors private while still actually + // using a string to represent the field internally. This way, we can + // guarantee that if we do ever implement the ctype, it won't break any + // existing users who might be -- for whatever reason -- already using .proto + // files that applied the ctype. The field can still be accessed via the + // reflection interface since the reflection interface is independent of + // the string's underlying representation. + bool unknown_ctype = + field_->options().ctype() != EffectiveStringCType(field_, options_); + + if (unknown_ctype) { + p->Emit(R"cc( + private: // Hidden due to unknown ctype option. + )cc"); + } + + auto vars = AnnotatedAccessors(field_, {"", "set_allocated_"}); + vars.push_back(Sub{ + "release_name", + SafeFunctionName(field_->containing_type(), field_, "release_"), + } + .AnnotatedAs(field_)); + auto v1 = p->WithVars(vars); + auto v2 = p->WithVars( + AnnotatedAccessors(field_, {"set_"}, AnnotationCollector::kSet)); + auto v3 = p->WithVars( + AnnotatedAccessors(field_, {"mutable_"}, AnnotationCollector::kAlias)); + + p->Emit( + {{"donated", + [&] { + if (!inlined_) return; + p->Emit(R"cc( + inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() const; + )cc"); + }}}, + R"cc( + $DEPRECATED$ const TProtoStringType& $name$() const; + //~ Using `Arg_ = const TProtoStringType&` will make the type of `arg` + //~ default to `const TProtoStringType&`, due to reference collapse. This is + //~ necessary because there are a handful of users that rely on this + //~ default. + template <typename Arg_ = const TProtoStringType&, typename... Args_> + $DEPRECATED$ void $set_name$(Arg_&& arg, Args_... args); + $DEPRECATED$ TProtoStringType* $mutable_name$(); + PROTOBUF_NODISCARD $DEPRECATED$ TProtoStringType* $release_name$(); + $DEPRECATED$ void $set_allocated_name$(TProtoStringType* ptr); + + private: + const TProtoStringType& _internal_$name$() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_$name$( + const TProtoStringType& value); + TProtoStringType* _internal_mutable_$name$(); + $donated$; + + public: + )cc"); +} + +void UpdateHasbitSet(io::Printer* p, bool is_oneof) { + if (!is_oneof) { + p->Emit(R"cc( + $set_hasbit$; + )cc"); + return; + } + + p->Emit(R"cc( + if ($not_has_field$) { + clear_$oneof_name$(); + + set_has_$name$(); + $field_$.InitDefault(); + } + )cc"); +} + +void ArgsForSetter(io::Printer* p, bool inlined) { + if (!inlined) { + p->Emit("GetArenaForAllocation()"); + return; + } + p->Emit( + "GetArenaForAllocation(), _internal_$name$_donated(), " + "&$donating_states_word$, $mask_for_undonate$, this"); +} + +void SingularString::ReleaseImpl(io::Printer* p) const { + if (is_oneof_) { + p->Emit(R"cc( + if ($not_has_field$) { + return nullptr; + } + clear_has_$oneof_name$(); + return $field_$.Release(); + )cc"); + return; + } + + if (!HasHasbit(field_)) { + p->Emit(R"cc( + return $field_$.Release(); + )cc"); + return; + } + + if (inlined_) { + p->Emit(R"cc( + if (($has_hasbit$) == 0) { + return nullptr; + } + $clear_hasbit$; + + return $field_$.Release(GetArenaForAllocation(), _internal_$name$_donated()); + )cc"); + return; + } + + p->Emit(R"cc( + if (($has_hasbit$) == 0) { + return nullptr; + } + $clear_hasbit$; + )cc"); + + if (!EmptyDefault()) { + p->Emit(R"cc( + return $field_$.Release(); + )cc"); + return; + } + + p->Emit(R"cc( + auto* released = $field_$.Release(); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + $field_$.Set("", $set_args$); +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return released; + )cc"); +} + +void SingularString::SetAllocatedImpl(io::Printer* p) const { + if (is_oneof_) { + p->Emit(R"cc( + if (has_$oneof_name$()) { + clear_$oneof_name$(); + } + if (value != nullptr) { + set_has_$name$(); + $field_$.InitAllocated(value, GetArenaForAllocation()); + } + )cc"); + return; + } + + if (HasHasbit(field_)) { + p->Emit(R"cc( + if (value != nullptr) { + $set_hasbit$ + } else { + $clear_hasbit$ + } + )cc"); + } + + if (inlined_) { + // Currently, string fields with default value can't be inlined. + p->Emit(R"cc( + $field_$.SetAllocated(nullptr, value, $set_args$); + )cc"); + return; + } + + p->Emit(R"cc( + $field_$.SetAllocated(value, $set_args$); + )cc"); + + if (EmptyDefault()) { + p->Emit(R"cc( +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if ($field_$.IsDefault()) { + $field_$.Set("", $set_args$); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + )cc"); + } +} + +void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const { + p->Emit( + { + {"if_IsDefault", + [&] { + if (EmptyDefault() || is_oneof_) return; + p->Emit(R"cc( + if ($field_$.IsDefault()) { + return $default_variable_field$.get(); + } + )cc"); + }}, + {"update_hasbit", [&] { UpdateHasbitSet(p, is_oneof_); }}, + {"set_args", [&] { ArgsForSetter(p, inlined_); }}, + {"check_hasbit", + [&] { + if (!is_oneof_) return; + p->Emit(R"cc( + if ($not_has_field$) { + return $kDefaultStr$; + } + )cc"); + }}, + {"release_name", + SafeFunctionName(field_->containing_type(), field_, "release_")}, + {"release_impl", [&] { ReleaseImpl(p); }}, + {"set_allocated_impl", [&] { SetAllocatedImpl(p); }}, + }, + R"cc( + inline const TProtoStringType& $Msg$::$name$() const { + $annotate_get$; + // @@protoc_insertion_point(field_get:$pkg.Msg.field$) + $if_IsDefault$; + return _internal_$name$(); + } + template <typename Arg_, typename... Args_> + inline PROTOBUF_ALWAYS_INLINE void $Msg$::set_$name$(Arg_&& arg, + Args_... args) { + $PrepareSplitMessageForWrite$; + $update_hasbit$; + $field_$.$Set$(static_cast<Arg_&&>(arg), args..., $set_args$); + $annotate_set$; + // @@protoc_insertion_point(field_set:$pkg.Msg.field$) + } + inline TProtoStringType* $Msg$::mutable_$name$() { + $PrepareSplitMessageForWrite$; + TProtoStringType* _s = _internal_mutable_$name$(); + $annotate_mutable$; + // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$) + return _s; + } + inline const TProtoStringType& $Msg$::_internal_$name$() const { + $check_hasbit$; + return $field_$.Get(); + } + inline void $Msg$::_internal_set_$name$(const TProtoStringType& value) { + $update_hasbit$; + //~ Don't use $Set$ here; we always want the TProtoStringType variant + //~ regardless of whether this is a `bytes` field. + $field_$.Set(value, $set_args$); + } + inline TProtoStringType* $Msg$::_internal_mutable_$name$() { + $update_hasbit$; + return $field_$.Mutable($lazy_args$, $set_args$); + } + inline TProtoStringType* $Msg$::$release_name$() { + $annotate_release$; + $PrepareSplitMessageForWrite$; + // @@protoc_insertion_point(field_release:$pkg.Msg.field$) + $release_impl$; + } + inline void $Msg$::set_allocated_$name$(TProtoStringType* value) { + $PrepareSplitMessageForWrite$; + $set_allocated_impl$; + $annotate_set$; + // @@protoc_insertion_point(field_set_allocated:$pkg.Msg.field$) + } + )cc"); + + if (inlined_) { + p->Emit(R"cc( + inline bool $Msg$::_internal_$name$_donated() const { + return $inlined_string_donated$; + } + )cc"); + } +} + +void SingularString::GenerateClearingCode(io::Printer* p) const { + if (is_oneof_) { + p->Emit(R"cc( + $field_$.Destroy(); + )cc"); + return; + } + + if (EmptyDefault()) { + p->Emit(R"cc( + $field_$.ClearToEmpty(); + )cc"); + return; + } + + Y_ABSL_DCHECK(!inlined_); + p->Emit(R"cc( + $field_$.ClearToDefault($lazy_var$, GetArenaForAllocation()); + )cc"); +} + +void SingularString::GenerateMessageClearingCode(io::Printer* p) const { + if (is_oneof_) { + p->Emit(R"cc( + $field_$.Destroy(); + )cc"); + return; + } + + // 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 + // (given that the below methods are inlined one-liners)! + + // If we have a hasbit, then the Clear() method of the protocol buffer + // will have checked that this field is set. If so, we can avoid redundant + // checks against the default variable. + + if (inlined_ && HasHasbit(field_)) { + // Calling mutable_$name$() gives us a string reference and sets the has bit + // for $name$ (in proto2). We may get here when the string field is inlined + // but the string's contents have not been changed by the user, so we cannot + // make an assertion about the contents of the string and could never make + // an assertion about the string instance. + // + // For non-inlined strings, we distinguish from non-default by comparing + // instances, rather than contents. + p->Emit(R"cc( + $DCHK$(!$field_$.IsDefault()); + )cc"); + } + + if (!EmptyDefault()) { + // 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. + p->Emit(R"cc( + $field_$.ClearToDefault($lazy_var$, GetArenaForAllocation()); + )cc"); + return; + } + + p->Emit({{"Clear", + HasHasbit(field_) ? "ClearNonDefaultToEmpty" : "ClearToEmpty"}}, + R"cc( + $field_$.$Clear$(); + )cc"); +} + +void SingularString::GenerateSwappingCode(io::Printer* p) const { + if (is_oneof_) { + // Don't print any swapping code. Swapping the union will swap this field. + return; + } + + if (!inlined_) { + p->Emit(R"cc( + ::_pbi::ArenaStringPtr::InternalSwap(&$field_$, lhs_arena, + &other->$field_$, rhs_arena); + )cc"); + return; + } + + p->Emit(R"cc( + { + bool lhs_dtor_registered = ($inlined_string_donated_array$[0] & 1) == 0; + bool rhs_dtor_registered = + (other->$inlined_string_donated_array$[0] & 1) == 0; + ::_pbi::InlinedStringField::InternalSwap( + &$field_$, lhs_arena, lhs_dtor_registered, this, &other->$field_$, + rhs_arena, rhs_dtor_registered, other); + } + )cc"); +} + +void SingularString::GenerateConstructorCode(io::Printer* p) const { + if ((inlined_ && EmptyDefault()) || is_oneof_) return; + Y_ABSL_DCHECK(!inlined_); + + p->Emit(R"cc( + $field_$.InitDefault(); + )cc"); + + if (IsString(field_, *opts_) && EmptyDefault()) { + p->Emit(R"cc( +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + $field_$.Set("", GetArenaForAllocation()); +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + )cc"); + } +} + +void SingularString::GenerateCopyConstructorCode(io::Printer* p) const { + GenerateConstructorCode(p); + + if (inlined_) { + p->Emit(R"cc( + new (&_this->$field_$)::_pbi::InlinedStringField; + )cc"); + } + + p->Emit( + {{"hazzer", + [&] { + if (HasHasbit(field_)) { + p->Emit(R"cc((from.$has_hasbit$) != 0)cc"); + } else { + p->Emit(R"cc(!from._internal_$name$().empty())cc"); + } + }}, + {"set_args", + [&] { + if (!inlined_) { + p->Emit("_this->GetArenaForAllocation()"); + } else { + p->Emit( + "_this->GetArenaForAllocation(), " + "_this->_internal_$name$_donated(), " + "&_this->$donating_states_word$, $mask_for_undonate$, _this"); + } + }}}, + R"cc( + if ($hazzer$) { + _this->$field_$.Set(from._internal_$name$(), $set_args$); + } + )cc"); +} + +void SingularString::GenerateDestructorCode(io::Printer* p) const { + if (inlined_) { + // Explicitly calls ~InlinedStringField as its automatic call is disabled. + // Destructor has been implicitly skipped as a union. + Y_ABSL_DCHECK(!ShouldSplit(field_, *opts_)); + p->Emit(R"cc( + $field_$.~InlinedStringField(); + )cc"); + return; + } + + if (ShouldSplit(field_, *opts_)) { + p->Emit(R"cc( + $cached_split_ptr$->$name$_.Destroy(); + )cc"); + return; + } + + p->Emit(R"cc( + $field_$.Destroy(); + )cc"); +} + +void SingularString::GenerateSerializeWithCachedSizesToArray( + io::Printer* p) const { + p->Emit({{"utf8_check", + [&] { + GenerateUtf8CheckCodeForString(p, field_, options_, false, + "_s.data(), " + "static_cast<int>(_s.length()),"); + }}}, + R"cc( + const TProtoStringType& _s = this->_internal_$name$(); + $utf8_check$; + target = stream->Write$DeclaredType$MaybeAliased($number$, _s, target); + )cc"); +} + +void SingularString::GenerateConstexprAggregateInitializer( + io::Printer* p) const { + if (inlined_) { + p->Emit(R"cc( + /*decltype($field_$)*/ { nullptr, false } + )cc"); + return; + } + + p->Emit(R"cc( + /*decltype($field_$)*/ { + &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {} + } + )cc"); +} + +void SingularString::GenerateAggregateInitializer(io::Printer* p) const { + if (ShouldSplit(field_, options_)) { + Y_ABSL_CHECK(!inlined_); + p->Emit(R"cc( + decltype(Impl_::Split::$name$_) {} + )cc"); + return; + } + + if (!inlined_) { + p->Emit(R"cc( + decltype($field_$) {} + )cc"); + } else { + p->Emit(R"cc( + decltype($field_$) { arena } + )cc"); + } +} + +class RepeatedString : public FieldGeneratorBase { + public: + RepeatedString(const FieldDescriptor* field, const Options& opts) + : FieldGeneratorBase(field, opts), field_(field), opts_(&opts) {} + ~RepeatedString() override = default; + + std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); } + + void GeneratePrivateMembers(io::Printer* p) const override { + p->Emit(R"cc( + $pb$::RepeatedPtrField<TProtoStringType> $name$_; + )cc"); + } + + void GenerateClearingCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$.Clear(); + )cc"); + } + + void GenerateMergingCode(io::Printer* p) const override { + p->Emit(R"cc( + _this->$field_$.MergeFrom(from.$field_$); + )cc"); + } + + void GenerateSwappingCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$.InternalSwap(&other->$field_$); + )cc"); + } + + void GenerateDestructorCode(io::Printer* p) const override { + p->Emit(R"cc( + $field_$.~RepeatedPtrField(); + )cc"); + } + + void GenerateConstructorCode(io::Printer* p) const override {} + + void GenerateCopyConstructorCode(io::Printer* p) const override { + Y_ABSL_CHECK(!ShouldSplit(field_, options_)); + } + + void GenerateByteSize(io::Printer* p) const override { + p->Emit(R"cc( + total_size += $kTagBytes$ * $pbi$::FromIntSize($field_$.size()); + for (int i = 0, n = $field_$.size(); i < n; ++i) { + total_size += $pbi$::WireFormatLite::$DeclaredType$Size($field_$.Get(i)); + } + )cc"); + } + + void GenerateAccessorDeclarations(io::Printer* p) const override; + void GenerateInlineAccessorDefinitions(io::Printer* p) const override; + void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override; + + private: + const FieldDescriptor* field_; + const Options* opts_; +}; + +void RepeatedString::GenerateAccessorDeclarations(io::Printer* p) const { + bool unknown_ctype = + field_->options().ctype() != EffectiveStringCType(field_, options_); + + if (unknown_ctype) { + p->Emit(R"cc( + private: // Hidden due to unknown ctype option. + )cc"); + } + + auto v1 = p->WithVars( + AnnotatedAccessors(field_, {"", "_internal_", "_internal_add_"})); + auto v2 = p->WithVars( + AnnotatedAccessors(field_, {"set_", "add_"}, AnnotationCollector::kSet)); + auto v3 = p->WithVars( + AnnotatedAccessors(field_, {"mutable_"}, AnnotationCollector::kAlias)); + + p->Emit(R"cc( + $DEPRECATED$ const TProtoStringType& $name$(int index) const; + $DEPRECATED$ TProtoStringType* $mutable_name$(int index); + $DEPRECATED$ void $set_name$(int index, const TProtoStringType& value); + $DEPRECATED$ void $set_name$(int index, TProtoStringType&& value); + $DEPRECATED$ void $set_name$(int index, const char* value); + $DEPRECATED$ void $set_name$(int index, const $byte$* value, std::size_t size); + $DEPRECATED$ TProtoStringType* $add_name$(); + $DEPRECATED$ void $add_name$(const TProtoStringType& value); + $DEPRECATED$ void $add_name$(TProtoStringType&& value); + $DEPRECATED$ void $add_name$(const char* value); + $DEPRECATED$ void $add_name$(const $byte$* value, std::size_t size); + $DEPRECATED$ const $pb$::RepeatedPtrField<TProtoStringType>& $name$() const; + $DEPRECATED$ $pb$::RepeatedPtrField<TProtoStringType>* $mutable_name$(); + + private: + const TProtoStringType& $_internal_name$(int index) const; + TProtoStringType* $_internal_add_name$(); + + public: + )cc"); +} + +void RepeatedString::GenerateInlineAccessorDefinitions(io::Printer* p) const { + p->Emit({{"Get", opts_->safe_boundary_check ? "InternalCheckedGet" : "Get"}, + {"get_args", + [&] { + if (!opts_->safe_boundary_check) { + p->Emit("index"); + return; + } + + p->Emit(R"cc(index, $pbi$::GetEmptyStringAlreadyInited())cc"); + }}}, + R"cc( + inline TProtoStringType* $Msg$::add_$name$() { + TProtoStringType* _s = _internal_add_$name$(); + $annotate_add_mutable$; + // @@protoc_insertion_point(field_add_mutable:$pkg.Msg.field$) + return _s; + } + inline const TProtoStringType& $Msg$::_internal_$name$(int index) const { + return $field_$.$Get$($get_args$); + } + inline const TProtoStringType& $Msg$::$name$(int index) const { + $annotate_get$; + // @@protoc_insertion_point(field_get:$pkg.Msg.field$) + return _internal_$name$(index); + } + inline TProtoStringType* $Msg$::mutable_$name$(int index) { + $annotate_mutable$; + // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$) + return $field_$.Mutable(index); + } + inline void $Msg$::set_$name$(int index, const TProtoStringType& value) { + $field_$.Mutable(index)->assign(value); + $annotate_set$; + // @@protoc_insertion_point(field_set:$pkg.Msg.field$) + } + inline void $Msg$::set_$name$(int index, TProtoStringType&& value) { + $field_$.Mutable(index)->assign(std::move(value)); + $annotate_set$; + // @@protoc_insertion_point(field_set:$pkg.Msg.field$) + } + inline void $Msg$::set_$name$(int index, const char* value) { + $DCHK$(value != nullptr); + $field_$.Mutable(index)->assign(value); + $annotate_set$; + // @@protoc_insertion_point(field_set_char:$pkg.Msg.field$) + } + inline void $Msg$::set_$name$(int index, const $byte$* value, + std::size_t size) { + $field_$.Mutable(index)->assign(reinterpret_cast<const char*>(value), size); + $annotate_set$; + // @@protoc_insertion_point(field_set_pointer:$pkg.Msg.field$) + } + inline TProtoStringType* $Msg$::_internal_add_$name$() { return $field_$.Add(); } + inline void $Msg$::add_$name$(const TProtoStringType& value) { + $field_$.Add()->assign(value); + $annotate_add$; + // @@protoc_insertion_point(field_add:$pkg.Msg.field$) + } + inline void $Msg$::add_$name$(TProtoStringType&& value) { + $field_$.Add(std::move(value)); + $annotate_add$; + // @@protoc_insertion_point(field_add:$pkg.Msg.field$) + } + inline void $Msg$::add_$name$(const char* value) { + $DCHK$(value != nullptr); + $field_$.Add()->assign(value); + $annotate_add$; + // @@protoc_insertion_point(field_add_char:$pkg.Msg.field$) + } + inline void $Msg$::add_$name$(const $byte$* value, std::size_t size) { + $field_$.Add()->assign(reinterpret_cast<const char*>(value), size); + $annotate_add$; + // @@protoc_insertion_point(field_add_pointer:$pkg.Msg.field$) + } + inline const ::$proto_ns$::RepeatedPtrField<TProtoStringType>& + $Msg$::$name$() const { + $annotate_list$; + // @@protoc_insertion_point(field_list:$pkg.Msg.field$) + return $field_$; + } + inline ::$proto_ns$::RepeatedPtrField<TProtoStringType>* $Msg$::mutable_$name$() { + $annotate_mutable_list$; + // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$) + return &$field_$; + } + )cc"); +} + +void RepeatedString::GenerateSerializeWithCachedSizesToArray( + io::Printer* p) const { + p->Emit({{"utf8_check", + [&] { + GenerateUtf8CheckCodeForString( + p, field_, options_, false, + "s.data(), static_cast<int>(s.length()),"); + }}}, + R"cc( + for (int i = 0, n = this->_internal_$name$_size(); i < n; ++i) { + const auto& s = this->_internal_$name$(i); + $utf8_check$; + target = stream->Write$DeclaredType$($number$, s, target); + } + )cc"); +} +} // namespace + +std::unique_ptr<FieldGeneratorBase> MakeSinguarStringGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc) { + return y_absl::make_unique<SingularString>(desc, options); +} + +std::unique_ptr<FieldGeneratorBase> MakeRepeatedStringGenerator( + const FieldDescriptor* desc, const Options& options, + MessageSCCAnalyzer* scc) { + return y_absl::make_unique<RepeatedString>(desc, options); +} + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.cc index 2d79ec11e59..bb024eb59f5 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.cc @@ -32,133 +32,140 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/cpp/file.h> +#include "google/protobuf/compiler/cpp/file.h" #include <iostream> -#include <map> #include <memory> -#include <queue> -#include <set> -#include <unordered_map> -#include <unordered_set> +#include <string> +#include <utility> #include <vector> -#include <google/protobuf/compiler/scc.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/cpp/enum.h> -#include <google/protobuf/compiler/cpp/extension.h> -#include <google/protobuf/compiler/cpp/field.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/compiler/cpp/message.h> -#include <google/protobuf/compiler/cpp/service.h> -#include <google/protobuf/descriptor.pb.h> +#include "google/protobuf/compiler/scc.h" +#include "y_absl/container/btree_map.h" +#include "y_absl/container/btree_set.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/strip.h" +#include "google/protobuf/compiler/cpp/enum.h" +#include "google/protobuf/compiler/cpp/extension.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/message.h" +#include "google/protobuf/compiler/cpp/names.h" +#include "google/protobuf/compiler/cpp/service.h" +#include "google/protobuf/compiler/retention.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { namespace compiler { namespace cpp { - namespace { - -// When we forward-declare things, we want to create a sorted order so our -// output is deterministic and minimizes namespace changes. -template <class T> -TProtoStringType GetSortKey(const T& val) { - return val.full_name(); -} - -template <> -TProtoStringType GetSortKey<FileDescriptor>(const FileDescriptor& val) { - return val.name(); -} - -template <class T> -bool CompareSortKeys(const T* a, const T* b) { - return GetSortKey(*a) < GetSortKey(*b); -} - -template <class T> -std::vector<const T*> Sorted(const std::unordered_set<const T*>& vals) { - std::vector<const T*> sorted(vals.begin(), vals.end()); - std::sort(sorted.begin(), sorted.end(), CompareSortKeys<T>); - return sorted; +using Sub = ::google::protobuf::io::Printer::Sub; + +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> FileVars( + const FileDescriptor* file, const Options& options) { + return { + {"filename", file->name()}, + {"package_ns", Namespace(file, options)}, + {"tablename", UniqueName("TableStruct", file, options)}, + {"desc_table", DescriptorTableName(file, options)}, + {"dllexport_decl", options.dllexport_decl}, + {"file_level_metadata", UniqueName("file_level_metadata", file, options)}, + {"file_level_enum_descriptors", + UniqueName("file_level_enum_descriptors", file, options)}, + {"file_level_service_descriptors", + UniqueName("file_level_service_descriptors", file, options)}, + }; } // TODO(b/203101078): remove pragmas that suppresses uninitialized warnings when // clang bug is fixed. -inline void MuteWuninitialized(Formatter& format) { - format( - "#if defined(__llvm__)\n" - " #pragma clang diagnostic push\n" - " #pragma clang diagnostic ignored \"-Wuninitialized\"\n" - "#endif // __llvm__\n"); +void MuteWuninitialized(io::Printer* p) { + p->Emit(R"( + #if defined(__llvm__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wuninitialized" + #endif // __llvm__ + )"); } -inline void UnmuteWuninitialized(Formatter& format) { - format( - "#if defined(__llvm__)\n" - " #pragma clang diagnostic pop\n" - "#endif // __llvm__\n"); +void UnmuteWuninitialized(io::Printer* p) { + p->Emit(R"( + #if defined(__llvm__) + #pragma clang diagnostic pop + #endif // __llvm__ + )"); } - } // namespace FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) : 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_["file_level_metadata"] = - UniqueName("file_level_metadata", file_, options_); - variables_["desc_table"] = DescriptorTableName(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_["filename"] = file_->name(); - variables_["package_ns"] = Namespace(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], variables_, i, options, &scc_analyzer_); - message_generators_.emplace_back(msg_gen); - msg_gen->AddGenerators(&enum_generators_, &extension_generators_); + + for (int i = 0; i < msgs.size(); ++i) { + message_generators_.push_back(std::make_unique<MessageGenerator>( + msgs[i], variables_, i, options, &scc_analyzer_)); + message_generators_.back()->AddGenerators(&enum_generators_, + &extension_generators_); } - for (int i = 0; i < file->enum_type_count(); i++) { - enum_generators_.emplace_back( - new EnumGenerator(file->enum_type(i), variables_, options)); + for (int i = 0; i < file->enum_type_count(); ++i) { + enum_generators_.push_back( + std::make_unique<EnumGenerator>(file->enum_type(i), options)); } - for (int i = 0; i < file->service_count(); i++) { - service_generators_.emplace_back( - new ServiceGenerator(file->service(i), variables_, options)); + for (int i = 0; i < file->service_count(); ++i) { + service_generators_.push_back(std::make_unique<ServiceGenerator>( + file->service(i), variables_, options)); } if (HasGenericServices(file_, options_)) { - for (int i = 0; i < service_generators_.size(); i++) { + 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_.emplace_back( - new ExtensionGenerator(file->extension(i), options, &scc_analyzer_)); + + for (int i = 0; i < file->extension_count(); ++i) { + extension_generators_.push_back(std::make_unique<ExtensionGenerator>( + file->extension(i), options, &scc_analyzer_)); } + for (int i = 0; i < file->weak_dependency_count(); ++i) { weak_deps_.insert(file->weak_dependency(i)); } } -FileGenerator::~FileGenerator() = default; +void FileGenerator::GenerateFile(io::Printer* p, GeneratedFileType file_type, + std::function<void()> cb) { + auto v = p->WithVars(FileVars(file_, options_)); + auto guard = IncludeGuard(file_, file_type, options_); + p->Emit({{"cb", cb}, {"guard", guard}}, R"( + // Generated by the protocol buffer compiler. DO NOT EDIT! + // source: $filename$ -void FileGenerator::GenerateMacroUndefs(io::Printer* printer) { - Formatter format(printer, variables_); + #ifndef $guard$ + #define $guard$ + + #include <limits> + #include <string> + #include <type_traits> + + $cb$; + + #endif // $guard$ + )"); +} + +void FileGenerator::GenerateMacroUndefs(io::Printer* p) { // 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. @@ -166,425 +173,478 @@ void FileGenerator::GenerateMacroUndefs(io::Printer* printer) { file_->name() != "google/protobuf/compiler/plugin.proto") { return; } - std::vector<TProtoStringType> names_to_undef; + std::vector<const FieldDescriptor*> fields; ListAllFields(file_, &fields); - for (int i = 0; i < fields.size(); i++) { - const TProtoStringType& name = fields[i]->name(); - static const char* kMacroNames[] = {"major", "minor"}; - for (int j = 0; j < GOOGLE_ARRAYSIZE(kMacroNames); ++j) { - if (name == kMacroNames[j]) { - names_to_undef.push_back(name); - break; - } - } - } - for (int i = 0; i < names_to_undef.size(); ++i) { - format( - "#ifdef $1$\n" - "#undef $1$\n" - "#endif\n", - names_to_undef[i]); - } -} - -void FileGenerator::GenerateHeader(io::Printer* printer) { - Formatter format(printer, variables_); - // port_def.inc must be included after all other includes. - IncludeFile("net/proto2/public/port_def.inc", printer); - format("#define $1$$ dllexport_decl$\n", FileDllExport(file_, options_)); - GenerateMacroUndefs(printer); - - // For Any support with lite protos, we need to friend AnyMetadata, so we - // forward-declare it here. - format( - "PROTOBUF_NAMESPACE_OPEN\n" - "namespace internal {\n" - "class AnyMetadata;\n" - "} // namespace internal\n" - "PROTOBUF_NAMESPACE_CLOSE\n"); - - GenerateGlobalStateFunctionDeclarations(printer); - - GenerateForwardDeclarations(printer); - - { - NamespaceOpener ns(Namespace(file_, options_), format); - - format("\n"); - - GenerateEnumDefinitions(printer); - - format(kThickSeparator); - format("\n"); - - GenerateMessageDefinitions(printer); - - format("\n"); - format(kThickSeparator); - format("\n"); - - GenerateServiceDefinitions(printer); - - GenerateExtensionIdentifiers(printer); - - format("\n"); - format(kThickSeparator); - format("\n"); + y_absl::flat_hash_set<y_absl::string_view> all_fields; + for (const FieldDescriptor* field : fields) { + all_fields.insert(field->name()); + } - GenerateInlineFunctionDefinitions(printer); + for (y_absl::string_view name : {"major", "minor"}) { + if (!all_fields.contains(name)) { + continue; + } - format( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n" - "\n"); + p->Emit({{"name", TProtoStringType(name)}}, R"( + #)" "ifdef" R"( $name$ + #)" "undef" R"( $name$ + #)" "endif" R"( // $name$ + )"); } +} - // We need to specialize some templates in the ::google::protobuf namespace: - GenerateProto2NamespaceEnumSpecializations(printer); - format( - "\n" - "// @@protoc_insertion_point(global_scope)\n" - "\n"); - IncludeFile("net/proto2/public/port_undef.inc", printer); +void FileGenerator::GenerateSharedHeaderCode(io::Printer* p) { + p->Emit( + { + {"port_def", + [&] { IncludeFile("third_party/protobuf/port_def.inc", p); }}, + {"port_undef", + [&] { IncludeFile("third_party/protobuf/port_undef.inc", p); }}, + {"dllexport_macro", FileDllExport(file_, options_)}, + {"undefs", [&] { GenerateMacroUndefs(p); }}, + {"global_state_decls", + [&] { GenerateGlobalStateFunctionDeclarations(p); }}, + {"fwd_decls", [&] { GenerateForwardDeclarations(p); }}, + {"proto2_ns_enums", + [&] { GenerateProto2NamespaceEnumSpecializations(p); }}, + {"main_decls", + [&] { + NamespaceOpener ns(Namespace(file_, options_), p); + p->Emit( + { + {"enums", [&] { GenerateEnumDefinitions(p); }}, + {"messages", [&] { GenerateMessageDefinitions(p); }}, + {"services", [&] { GenerateServiceDefinitions(p); }}, + {"extensions", [&] { GenerateExtensionIdentifiers(p); }}, + {"inline_fns", + [&] { GenerateInlineFunctionDefinitions(p); }}, + }, + R"( + $enums$ + + $hrule_thick$ + + $messages$ + + $hrule_thick$ + + $services$ + + $extensions$ + + $hrule_thick$ + + $inline_fns$ + + // @@protoc_insertion_point(namespace_scope) + )"); + }}, + }, + R"( + // Must be included last. + $port_def$ + + #define $dllexport_macro$$ dllexport_decl$ + $undefs$ + + PROTOBUF_NAMESPACE_OPEN + namespace internal { + class AnyMetadata; + } // namespace internal + PROTOBUF_NAMESPACE_CLOSE + + $global_state_decls$; + $fwd_decls$ + + $main_decls$ + + $proto2_ns_enums$ + + // @@protoc_insertion_point(global_scope) + + $port_undef$ + )"); } -void FileGenerator::GenerateProtoHeader(io::Printer* printer, - const TProtoStringType& info_path) { - Formatter format(printer, variables_); +void FileGenerator::GenerateProtoHeader(io::Printer* p, + y_absl::string_view info_path) { if (!options_.proto_h) { return; } - GenerateTopHeaderGuard(printer, false); - - 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); - format("#include \"$1$.proto.h\"\n", StripProto(dep->name())); - } - - format("// @@protoc_insertion_point(includes)\n"); - - GenerateMetadataPragma(printer, info_path); - - GenerateHeader(printer); - - GenerateBottomHeaderGuard(printer, false); -} - -void FileGenerator::GeneratePBHeader(io::Printer* printer, - const TProtoStringType& info_path) { - Formatter format(printer, variables_); - GenerateTopHeaderGuard(printer, true); - - if (options_.proto_h) { - TProtoStringType target_basename = StripProto(file_->name()); + GenerateFile(p, GeneratedFileType::kProtoH, [&] { if (!options_.opensource_runtime) { - GetBootstrapBasename(options_, target_basename, &target_basename); + p->Emit(R"( + #ifdef SWIG + #error "Do not SWIG-wrap protobufs." + #endif // SWIG + )"); } - format("#include \"$1$.proto.h\" // IWYU pragma: export\n", - target_basename); - } else { - GenerateLibraryIncludes(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 { - { - NamespaceOpener ns(Namespace(file_, options_), format); - format( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n"); + if (IsBootstrapProto(options_, file_)) { + p->Emit({{"name", StripProto(file_->name())}}, R"cc( + // IWYU pragma: private, include "$name$.proto.h" + )cc"); } - format( - "\n" - "// @@protoc_insertion_point(global_scope)\n" - "\n"); - } - GenerateBottomHeaderGuard(printer, true); + p->Emit( + { + {"library_includes", [&] { GenerateLibraryIncludes(p); }}, + {"proto_includes", + [&] { + for (int i = 0; i < file_->public_dependency_count(); ++i) { + const FileDescriptor* dep = file_->public_dependency(i); + p->Emit({{"name", StripProto(dep->name())}}, R"( + #include "$name$.proto.h" + )"); + } + }}, + {"metadata_pragma", [&] { GenerateMetadataPragma(p, info_path); }}, + {"header_main", [&] { GenerateSharedHeaderCode(p); }}, + }, + R"cc( + $library_includes$; + $proto_includes$; + // @@protoc_insertion_point(includes) + + $metadata_pragma$; + $header_main$; + )cc"); + }); } -void FileGenerator::GeneratePBDeps(io::Printer* printer, - const TProtoStringType& info_path) { - Formatter format(printer, variables_); - - GenerateTopHeaderGuard(printer, true, true); - - GenerateDependencyIncludes(printer); - - GenerateBottomHeaderGuard(printer, true, true); +void FileGenerator::GeneratePBHeader(io::Printer* p, + y_absl::string_view info_path) { + GenerateFile(p, GeneratedFileType::kPbH, [&] { + p->Emit( + { + {"library_includes", + [&] { + if (options_.proto_h) { + TProtoStringType target_basename = StripProto(file_->name()); + if (!options_.opensource_runtime) { + GetBootstrapBasename(options_, target_basename, + &target_basename); + } + p->Emit({{"name", target_basename}}, R"( + #include "$name$.proto.h" // IWYU pragma: export + )"); + } else { + GenerateLibraryIncludes(p); + } + }}, + {"proto_includes", + [&] { + if (options_.transitive_pb_h) { + GenerateDependencyIncludes(p); + } + }}, + {"metadata_pragma", [&] { GenerateMetadataPragma(p, info_path); }}, + {"header_main", + [&] { + if (!options_.proto_h) { + GenerateSharedHeaderCode(p); + return; + } + + { + NamespaceOpener ns(Namespace(file_, options_), p); + p->Emit(R"cc( + + // @@protoc_insertion_point(namespace_scope) + )cc"); + } + p->Emit(R"cc( + + // @@protoc_insertion_point(global_scope) + )cc"); + }}, + }, + R"cc( + $library_includes$; + $proto_includes$; + // @@protoc_insertion_point(includes) + + $metadata_pragma$; + $header_main$; + )cc"); + }); } -void FileGenerator::DoIncludeFile(const TProtoStringType& google3_name, - bool do_export, io::Printer* printer) { - Formatter format(printer, variables_); - const TProtoStringType prefix = "net/proto2/"; - GOOGLE_CHECK(google3_name.find(prefix) == 0) << google3_name; +void FileGenerator::DoIncludeFile(y_absl::string_view google3_name, + bool do_export, io::Printer* p) { + constexpr y_absl::string_view prefix = "third_party/protobuf/"; + Y_ABSL_CHECK(y_absl::StartsWith(google3_name, prefix)) << google3_name; + + auto v = p->WithVars( + {{"export_suffix", do_export ? "// IWYU pragma: export" : ""}}); if (options_.opensource_runtime) { - TProtoStringType path = google3_name.substr(prefix.size()); + y_absl::ConsumePrefix(&google3_name, prefix); + y_absl::ConsumePrefix(&google3_name, "internal/"); + y_absl::ConsumePrefix(&google3_name, "proto/"); + y_absl::ConsumePrefix(&google3_name, "public/"); + + TProtoStringType path; + if (y_absl::ConsumePrefix(&google3_name, "io/public/")) { + path = y_absl::StrCat("io/", google3_name); + } else { + path = TProtoStringType(google3_name); + } - path = StringReplace(path, "internal/", "", false); - path = StringReplace(path, "proto/", "", false); - path = StringReplace(path, "public/", "", false); if (options_.runtime_include_base.empty()) { - format("#include <google/protobuf/$1$>", path); + p->Emit({{"path", path}}, R"( + #include "google/protobuf/$path$"$ export_suffix$ + )"); } else { - format("#include \"$1$google/protobuf/$2$\"", - options_.runtime_include_base, path); + p->Emit({{"base", options_.runtime_include_base}, {"path", path}}, + R"( + #include "$base$google/protobuf/$path$"$ export_suffix$ + )"); } } else { - TProtoStringType path = google3_name; + TProtoStringType path(google3_name); // The bootstrapped proto generated code needs to use the // third_party/protobuf header paths to avoid circular dependencies. if (options_.bootstrap) { - path = StringReplace(google3_name, "net/proto2/public", - "third_party/protobuf", false); + constexpr y_absl::string_view bootstrap_prefix = "net/proto2/public"; + if (y_absl::ConsumePrefix(&google3_name, bootstrap_prefix)) { + path = y_absl::StrCat("third_party/protobuf", google3_name); + } } - format("#include \"$1$\"", path); - } - if (do_export) { - format(" // IWYU pragma: export"); + p->Emit({{"path", path}}, R"( + #include "$path$"$ export_suffix$ + )"); } - - format("\n"); } -TProtoStringType FileGenerator::CreateHeaderInclude(const TProtoStringType& basename, +TProtoStringType FileGenerator::CreateHeaderInclude(y_absl::string_view basename, const FileDescriptor* file) { - bool use_system_include = false; - TProtoStringType name = basename; - - if (options_.opensource_runtime) { - if (IsWellKnownMessage(file)) { - if (options_.runtime_include_base.empty()) { - use_system_include = true; - } else { - name = options_.runtime_include_base + basename; - } - } + if (options_.opensource_runtime && IsWellKnownMessage(file) && + !options_.runtime_include_base.empty()) { + return y_absl::StrCat("\"", options_.runtime_include_base, basename, "\""); } - TProtoStringType left = "\""; - TProtoStringType right = "\""; - if (use_system_include) { - left = "<"; - right = ">"; - } - return left + name + right; + return y_absl::StrCat("\"", basename, "\""); } -void FileGenerator::GenerateSourceIncludes(io::Printer* printer) { - Formatter format(printer, variables_); +void FileGenerator::GenerateSourceIncludes(io::Printer* p) { TProtoStringType target_basename = StripProto(file_->name()); 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_.transitive_pb_h) { - GenerateDependencyIncludes(printer); - } + y_absl::StrAppend(&target_basename, options_.proto_h ? ".proto.h" : ".pb.h"); + p->Emit({{"h_include", CreateHeaderInclude(target_basename, file_)}}, + R"( + // Generated by the protocol buffer compiler. DO NOT EDIT! + // source: $filename$ - IncludeFile("net/proto2/io/public/coded_stream.h", printer); + #)" "include" R"( $h_include$ + + #include <algorithm> + )"); + + IncludeFile("third_party/protobuf/io/coded_stream.h", p); // 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.h", printer); + IncludeFile("third_party/protobuf/extension_set.h", p); + IncludeFile("third_party/protobuf/wire_format_lite.h", p); // Unknown fields implementation in lite mode uses StringOutputStream if (!UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) { - IncludeFile("net/proto2/io/public/zero_copy_stream_impl_lite.h", printer); + IncludeFile("third_party/protobuf/io/zero_copy_stream_impl_lite.h", p); } if (HasDescriptorMethods(file_, options_)) { - 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); + IncludeFile("third_party/protobuf/descriptor.h", p); + IncludeFile("third_party/protobuf/generated_message_reflection.h", p); + IncludeFile("third_party/protobuf/reflection_ops.h", p); + IncludeFile("third_party/protobuf/wire_format.h", p); } if (HasGeneratedMethods(file_, options_) && options_.tctable_mode != Options::kTCTableNever) { - IncludeFile("net/proto2/public/generated_message_tctable_impl.h", printer); + IncludeFile("third_party/protobuf/generated_message_tctable_impl.h", p); } if (options_.proto_h) { // Use the smaller .proto.h files. - for (int i = 0; i < file_->dependency_count(); i++) { + for (int i = 0; i < file_->dependency_count(); ++i) { const FileDescriptor* dep = file_->dependency(i); - // Do not import weak deps. - if (!options_.opensource_runtime && IsDepWeak(dep)) continue; + + if (!options_.opensource_runtime && + IsDepWeak(dep)) { // Do not import weak deps. + continue; + } + TProtoStringType basename = StripProto(dep->name()); if (IsBootstrapProto(options_, file_)) { GetBootstrapBasename(options_, basename, &basename); } - format("#include \"$1$.proto.h\"\n", basename); + p->Emit({{"name", basename}}, R"( + #include "$name$.proto.h" + )"); } } + if (HasCordFields(file_, options_)) { - format( - "#include \"third_party/absl/strings/internal/string_constant.h\"\n"); + p->Emit(R"( + #include "y_absl/strings/internal/string_constant.h" + )"); } - format("// @@protoc_insertion_point(includes)\n"); - IncludeFile("net/proto2/public/port_def.inc", printer); -} + p->Emit(R"cc( + // @@protoc_insertion_point(includes) -void FileGenerator::GenerateSourcePrelude(io::Printer* printer) { - Formatter format(printer, variables_); + // Must be included last. + )cc"); + IncludeFile("third_party/protobuf/port_def.inc", p); +} +void FileGenerator::GenerateSourcePrelude(io::Printer* p) { // For MSVC builds, we use #pragma init_seg to move the initialization of our // libraries to happen before the user code. // This worksaround the fact that MSVC does not do constant initializers when // required by the standard. - format("\nPROTOBUF_PRAGMA_INIT_SEG\n"); - - // Generate convenience aliases. - format( - "\n" - "namespace _pb = ::$1$;\n" - "namespace _pbi = _pb::internal;\n", - ProtobufNamespace(options_)); + p->Emit(R"cc( + PROTOBUF_PRAGMA_INIT_SEG + namespace _pb = ::$proto_ns$; + namespace _pbi = ::$proto_ns$::internal; + )cc"); + if (HasGeneratedMethods(file_, options_) && options_.tctable_mode != Options::kTCTableNever) { - format("namespace _fl = _pbi::field_layout;\n"); + p->Emit(R"cc( + namespace _fl = ::$proto_ns$::internal::field_layout; + )cc"); } - format("\n"); } -void FileGenerator::GenerateSourceDefaultInstance(int idx, - io::Printer* printer) { - Formatter format(printer, variables_); +void FileGenerator::GenerateSourceDefaultInstance(int idx, io::Printer* p) { MessageGenerator* generator = message_generators_[idx].get(); + // Generate the split instance first because it's needed in the constexpr // constructor. - if (ShouldSplit(generator->descriptor_, options_)) { + if (ShouldSplit(generator->descriptor(), options_)) { // Use a union to disable the destructor of the _instance member. // We can constant initialize, but the object will still have a non-trivial // destructor that we need to elide. - format( - "struct $1$ {\n" - " PROTOBUF_CONSTEXPR $1$()\n" - " : _instance{", - DefaultInstanceType(generator->descriptor_, options_, - /*split=*/true)); - generator->GenerateInitDefaultSplitInstance(printer); - format( - "} {}\n" - " ~$1$() {}\n" - " union {\n" - " $2$ _instance;\n" - " };\n" - "};\n", - DefaultInstanceType(generator->descriptor_, options_, /*split=*/true), - StrCat(generator->classname_, "::Impl_::Split")); + // // NO_DESTROY is not necessary for correctness. The empty destructor is // enough. However, the empty destructor fails to be elided in some // configurations (like non-opt or with certain sanitizers). NO_DESTROY is // there just to improve performance and binary size in these builds. - format( - "PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT " - "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $1$ $2$;\n", - DefaultInstanceType(generator->descriptor_, options_, /*split=*/true), - DefaultInstanceName(generator->descriptor_, options_, /*split=*/true)); - } - - generator->GenerateConstexprConstructor(printer); - format( - "struct $1$ {\n" - " PROTOBUF_CONSTEXPR $1$()\n" - " : _instance(::_pbi::ConstantInitialized{}) {}\n" - " ~$1$() {}\n" - " union {\n" - " $2$ _instance;\n" - " };\n" - "};\n", - DefaultInstanceType(generator->descriptor_, options_), - generator->classname_); - format( - "PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT " - "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $1$ $2$;\n", - DefaultInstanceType(generator->descriptor_, options_), - DefaultInstanceName(generator->descriptor_, options_)); - - for (int i = 0; i < generator->descriptor_->field_count(); i++) { - const FieldDescriptor* field = generator->descriptor_->field(i); - if (IsStringInlined(field, options_)) { - // Force the initialization of the inlined string in the default instance. - format( - "PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 std::true_type " - "$1$::Impl_::_init_inline_$2$_ = " - "($3$._instance.$4$.Init(), std::true_type{});\n", - ClassName(generator->descriptor_), FieldName(field), - DefaultInstanceName(generator->descriptor_, options_), - FieldMemberName(field, ShouldSplit(field, options_))); + p->Emit( + { + {"type", DefaultInstanceType(generator->descriptor(), options_, + /*split=*/true)}, + {"name", DefaultInstanceName(generator->descriptor(), options_, + /*split=*/true)}, + {"default", + [&] { generator->GenerateInitDefaultSplitInstance(p); }}, + {"class", y_absl::StrCat(ClassName(generator->descriptor()), + "::Impl_::Split")}, + }, + R"cc( + struct $type$ { + PROTOBUF_CONSTEXPR $type$() : _instance{$default$} {} + union { + $class$ _instance; + }; + }; + + PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const $type$ $name$; + )cc"); + } + + generator->GenerateConstexprConstructor(p); + + p->Emit( + { + {"type", DefaultInstanceType(generator->descriptor(), options_)}, + {"name", DefaultInstanceName(generator->descriptor(), options_)}, + {"default", [&] { generator->GenerateInitDefaultSplitInstance(p); }}, + {"class", ClassName(generator->descriptor())}, + }, + R"cc( + struct $type$ { + PROTOBUF_CONSTEXPR $type$() : _instance(::_pbi::ConstantInitialized{}) {} + ~$type$() {} + union { + $class$ _instance; + }; + }; + + PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $type$ $name$; + )cc"); + + for (int i = 0; i < generator->descriptor()->field_count(); ++i) { + const FieldDescriptor* field = generator->descriptor()->field(i); + if (!IsStringInlined(field, options_)) { + continue; } + + // Force the initialization of the inlined string in the default instance. + p->Emit( + { + {"class", ClassName(generator->descriptor())}, + {"field", FieldName(field)}, + {"default", DefaultInstanceName(generator->descriptor(), options_)}, + {"member", FieldMemberName(field, ShouldSplit(field, options_))}, + }, + R"cc( + PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 std::true_type + $class$::Impl_::_init_inline_$field$_ = + ($default$._instance.$member$.Init(), std::true_type{}); + )cc"); } if (options_.lite_implicit_weak_fields) { - format( - "PROTOBUF_CONSTINIT const void* $1$ =\n" - " &$2$;\n", - DefaultInstancePtr(generator->descriptor_, options_), - DefaultInstanceName(generator->descriptor_, options_)); + p->Emit( + { + {"ptr", DefaultInstancePtr(generator->descriptor(), options_)}, + {"name", DefaultInstanceName(generator->descriptor(), options_)}, + }, + R"cc( + PROTOBUF_CONSTINIT const void* $ptr$ = &$name$; + )cc"); } } // A list of things defined in one .pb.cc file that we need to reference from // another .pb.cc file. struct FileGenerator::CrossFileReferences { + // When we forward-declare things, we want to create a sorted order so our + // output is deterministic and minimizes namespace changes. + struct DescCompare { + template <typename T> + bool operator()(const T* const& a, const T* const& b) const { + return a->full_name() < b->full_name(); + } + + bool operator()(const FileDescriptor* const& a, + const FileDescriptor* const& b) const { + return a->name() < b->name(); + } + }; + // Populated if we are referencing from messages or files. - std::unordered_set<const Descriptor*> weak_default_instances; + y_absl::btree_set<const Descriptor*, DescCompare> weak_default_instances; // Only if we are referencing from files. - std::unordered_set<const FileDescriptor*> strong_reflection_files; - std::unordered_set<const FileDescriptor*> weak_reflection_files; + y_absl::btree_set<const FileDescriptor*, DescCompare> strong_reflection_files; + y_absl::btree_set<const FileDescriptor*, DescCompare> weak_reflection_files; }; void FileGenerator::GetCrossFileReferencesForField(const FieldDescriptor* field, CrossFileReferences* refs) { const Descriptor* msg = field->message_type(); - if (msg == nullptr) return; + if (msg == nullptr) { + return; + } if (IsImplicitWeakField(field, options_, &scc_analyzer_) || IsWeak(field, options_)) { @@ -598,10 +658,13 @@ void FileGenerator::GetCrossFileReferencesForFile(const FileDescriptor* file, GetCrossFileReferencesForField(field, refs); }); - if (!HasDescriptorMethods(file, options_)) return; + if (!HasDescriptorMethods(file, options_)) { + return; + } - for (int i = 0; i < file->dependency_count(); i++) { + for (int i = 0; i < file->dependency_count(); ++i) { const FileDescriptor* dep = file->dependency(i); + if (IsDepWeak(dep)) { refs->weak_reflection_files.insert(dep); } else { @@ -612,119 +675,128 @@ void FileGenerator::GetCrossFileReferencesForFile(const FileDescriptor* file, // Generates references to variables defined in other files. void FileGenerator::GenerateInternalForwardDeclarations( - const CrossFileReferences& refs, io::Printer* printer) { - Formatter format(printer, variables_); - + const CrossFileReferences& refs, io::Printer* p) { { - NamespaceOpener ns(format); - for (auto instance : Sorted(refs.weak_default_instances)) { + NamespaceOpener ns(p); + for (auto instance : refs.weak_default_instances) { ns.ChangeTo(Namespace(instance, options_)); + if (options_.lite_implicit_weak_fields) { - format( - "PROTOBUF_CONSTINIT __attribute__((weak)) const void* $1$ =\n" - " &::_pbi::implicit_weak_message_default_instance;\n", - DefaultInstancePtr(instance, options_)); + p->Emit({{"ptr", DefaultInstancePtr(instance, options_)}}, R"cc( + PROTOBUF_CONSTINIT __attribute__((weak)) const void* $ptr$ = + &::_pbi::implicit_weak_message_default_instance; + )cc"); } else { - format("extern __attribute__((weak)) $1$ $2$;\n", - DefaultInstanceType(instance, options_), - DefaultInstanceName(instance, options_)); + p->Emit({{"type", DefaultInstanceType(instance, options_)}, + {"name", DefaultInstanceName(instance, options_)}}, + R"cc( + extern __attribute__((weak)) $type$ $name$; + )cc"); } } } - for (auto file : Sorted(refs.weak_reflection_files)) { - format( - "extern __attribute__((weak)) const ::_pbi::DescriptorTable $1$;\n", - DescriptorTableName(file, options_)); + for (auto file : refs.weak_reflection_files) { + p->Emit({{"table", DescriptorTableName(file, options_)}}, R"cc( + extern __attribute__((weak)) const ::_pbi::DescriptorTable $table$; + )cc"); } } -void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) { - Formatter format(printer, variables_); - GenerateSourceIncludes(printer); - GenerateSourcePrelude(printer); +void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* p) { + auto v = p->WithVars(FileVars(file_, options_)); - if (IsAnyMessage(file_, options_)) MuteWuninitialized(format); + GenerateSourceIncludes(p); + GenerateSourcePrelude(p); + + if (IsAnyMessage(file_, options_)) { + MuteWuninitialized(p); + } CrossFileReferences refs; - ForEachField(message_generators_[idx]->descriptor_, + ForEachField(message_generators_[idx]->descriptor(), [this, &refs](const FieldDescriptor* field) { GetCrossFileReferencesForField(field, &refs); }); - GenerateInternalForwardDeclarations(refs, printer); - { // package namespace - NamespaceOpener ns(Namespace(file_, options_), format); + GenerateInternalForwardDeclarations(refs, p); - // Define default instances - GenerateSourceDefaultInstance(idx, printer); + { + NamespaceOpener ns(Namespace(file_, options_), p); + p->Emit( + { + {"defaults", [&] { GenerateSourceDefaultInstance(idx, p); }}, + {"class_methods", + [&] { message_generators_[idx]->GenerateClassMethods(p); }}, + }, + R"cc( + $defaults$; - // Generate classes. - format("\n"); - message_generators_[idx]->GenerateClassMethods(printer); + $class_methods$; - format( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n"); - } // end package namespace + // @@protoc_insertion_point(namespace_scope) + )cc"); + } { - NamespaceOpener proto_ns(ProtobufNamespace(options_), format); - message_generators_[idx]->GenerateSourceInProto2Namespace(printer); + NamespaceOpener proto_ns(ProtobufNamespace(options_), p); + message_generators_[idx]->GenerateSourceInProto2Namespace(p); } - if (IsAnyMessage(file_, options_)) UnmuteWuninitialized(format); + if (IsAnyMessage(file_, options_)) { + UnmuteWuninitialized(p); + } - format( - "\n" - "// @@protoc_insertion_point(global_scope)\n"); + p->Emit(R"cc( + // @@protoc_insertion_point(global_scope) + )cc"); } -void FileGenerator::GenerateSourceForExtension(int idx, io::Printer* printer) { - Formatter format(printer, variables_); - GenerateSourceIncludes(printer); - GenerateSourcePrelude(printer); - NamespaceOpener ns(Namespace(file_, options_), format); - extension_generators_[idx]->GenerateDefinition(printer); +void FileGenerator::GenerateSourceForExtension(int idx, io::Printer* p) { + auto v = p->WithVars(FileVars(file_, options_)); + GenerateSourceIncludes(p); + GenerateSourcePrelude(p); + + NamespaceOpener ns(Namespace(file_, options_), p); + extension_generators_[idx]->GenerateDefinition(p); } -void FileGenerator::GenerateGlobalSource(io::Printer* printer) { - Formatter format(printer, variables_); - GenerateSourceIncludes(printer); - GenerateSourcePrelude(printer); +void FileGenerator::GenerateGlobalSource(io::Printer* p) { + auto v = p->WithVars(FileVars(file_, options_)); + GenerateSourceIncludes(p); + GenerateSourcePrelude(p); { // 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_)) { - GenerateReflectionInitializationCode(printer); + GenerateReflectionInitializationCode(p); } } - NamespaceOpener ns(Namespace(file_, options_), format); - - // Generate enums. - for (int i = 0; i < enum_generators_.size(); i++) { - enum_generators_[i]->GenerateMethods(i, printer); + NamespaceOpener ns(Namespace(file_, options_), p); + for (int i = 0; i < enum_generators_.size(); ++i) { + enum_generators_[i]->GenerateMethods(i, p); } } -void FileGenerator::GenerateSource(io::Printer* printer) { - Formatter format(printer, variables_); - GenerateSourceIncludes(printer); - GenerateSourcePrelude(printer); +void FileGenerator::GenerateSource(io::Printer* p) { + auto v = p->WithVars(FileVars(file_, options_)); + + GenerateSourceIncludes(p); + GenerateSourcePrelude(p); CrossFileReferences refs; GetCrossFileReferencesForFile(file_, &refs); - GenerateInternalForwardDeclarations(refs, printer); + GenerateInternalForwardDeclarations(refs, p); - if (IsAnyMessage(file_, options_)) MuteWuninitialized(format); + if (IsAnyMessage(file_, options_)) { + MuteWuninitialized(p); + } { - NamespaceOpener ns(Namespace(file_, options_), format); - - // Define default instances - for (int i = 0; i < message_generators_.size(); i++) { - GenerateSourceDefaultInstance(i, printer); + NamespaceOpener ns(Namespace(file_, options_), p); + for (int i = 0; i < message_generators_.size(); ++i) { + GenerateSourceDefaultInstance(i, p); } } @@ -732,144 +804,155 @@ void FileGenerator::GenerateSource(io::Printer* printer) { if (HasDescriptorMethods(file_, options_)) { // Define the code to initialize reflection. This code uses a global // constructor to register reflection data with the runtime pre-main. - GenerateReflectionInitializationCode(printer); + GenerateReflectionInitializationCode(p); } } { - NamespaceOpener ns(Namespace(file_, options_), format); + NamespaceOpener ns(Namespace(file_, options_), p); // Actually implement the protos // Generate enums. - for (int i = 0; i < enum_generators_.size(); i++) { - enum_generators_[i]->GenerateMethods(i, printer); + for (int i = 0; i < enum_generators_.size(); ++i) { + enum_generators_[i]->GenerateMethods(i, p); } // Generate classes. - for (int i = 0; i < message_generators_.size(); i++) { - format("\n"); - format(kThickSeparator); - format("\n"); - message_generators_[i]->GenerateClassMethods(printer); + for (int i = 0; i < message_generators_.size(); ++i) { + p->Emit(R"( + $hrule_thick$ + )"); + message_generators_[i]->GenerateClassMethods(p); } if (HasGenericServices(file_, options_)) { // Generate services. - for (int i = 0; i < service_generators_.size(); i++) { - if (i == 0) format("\n"); - format(kThickSeparator); - format("\n"); - service_generators_[i]->GenerateImplementation(printer); + for (int i = 0; i < service_generators_.size(); ++i) { + p->Emit(R"( + $hrule_thick$ + )"); + service_generators_[i]->GenerateImplementation(p); } } // Define extensions. - for (int i = 0; i < extension_generators_.size(); i++) { - extension_generators_[i]->GenerateDefinition(printer); + for (int i = 0; i < extension_generators_.size(); ++i) { + extension_generators_[i]->GenerateDefinition(p); } - format( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n"); + p->Emit(R"cc( + // @@protoc_insertion_point(namespace_scope) + )cc"); } { - NamespaceOpener proto_ns(ProtobufNamespace(options_), format); - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->GenerateSourceInProto2Namespace(printer); + NamespaceOpener proto_ns(ProtobufNamespace(options_), p); + for (int i = 0; i < message_generators_.size(); ++i) { + message_generators_[i]->GenerateSourceInProto2Namespace(p); } } - format( - "\n" - "// @@protoc_insertion_point(global_scope)\n"); + p->Emit(R"cc( + // @@protoc_insertion_point(global_scope) + )cc"); - if (IsAnyMessage(file_, options_)) UnmuteWuninitialized(format); + if (IsAnyMessage(file_, options_)) { + UnmuteWuninitialized(p); + } - IncludeFile("net/proto2/public/port_undef.inc", printer); + IncludeFile("third_party/protobuf/port_undef.inc", p); } -void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { - Formatter format(printer, variables_); - +void FileGenerator::GenerateReflectionInitializationCode(io::Printer* p) { if (!message_generators_.empty()) { - format("static ::_pb::Metadata $file_level_metadata$[$1$];\n", - message_generators_.size()); + p->Emit({{"len", message_generators_.size()}}, R"cc( + static ::_pb::Metadata $file_level_metadata$[$len$]; + )cc"); } + if (!enum_generators_.empty()) { - format( - "static const ::_pb::EnumDescriptor* " - "$file_level_enum_descriptors$[$1$];\n", - enum_generators_.size()); + p->Emit({{"len", enum_generators_.size()}}, R"cc( + static const ::_pb::EnumDescriptor* $file_level_enum_descriptors$[$len$]; + )cc"); } else { - format( - "static " - "constexpr ::_pb::EnumDescriptor const** " - "$file_level_enum_descriptors$ = nullptr;\n"); + p->Emit(R"cc( + static constexpr const ::_pb::EnumDescriptor** + $file_level_enum_descriptors$ = nullptr; + )cc"); } + if (HasGenericServices(file_, options_) && file_->service_count() > 0) { - format( - "static " - "const ::_pb::ServiceDescriptor* " - "$file_level_service_descriptors$[$1$];\n", - file_->service_count()); + p->Emit({{"len", file_->service_count()}}, R"cc( + static const ::_pb::ServiceDescriptor* + $file_level_service_descriptors$[$len$]; + )cc"); } else { - format( - "static " - "constexpr ::_pb::ServiceDescriptor const** " - "$file_level_service_descriptors$ = nullptr;\n"); + p->Emit(R"cc( + static constexpr const ::_pb::ServiceDescriptor** + $file_level_service_descriptors$ = nullptr; + )cc"); } if (!message_generators_.empty()) { - format( - "\n" - "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)); - } - format.Outdent(); - format( - "};\n" - "static const ::_pbi::MigrationSchema schemas[] " - "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n"); - format.Indent(); - { - int offset = 0; - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->GenerateSchema(printer, offset, - pairs[i].second); - offset += pairs[i].first; - } - } - format.Outdent(); - format( - "};\n" - "\nstatic const ::_pb::Message* const file_default_instances[] = {\n"); - format.Indent(); - for (int i = 0; i < message_generators_.size(); i++) { - const Descriptor* descriptor = message_generators_[i]->descriptor_; - format("&$1$::_$2$_default_instance_._instance,\n", - Namespace(descriptor, options_), // 1 - ClassName(descriptor)); // 2 - } - format.Outdent(); - format( - "};\n" - "\n"); + std::vector<std::pair<size_t, size_t>> offsets; + offsets.reserve(message_generators_.size()); + + p->Emit( + { + {"offsets", + [&] { + for (int i = 0; i < message_generators_.size(); ++i) { + offsets.push_back(message_generators_[i]->GenerateOffsets(p)); + } + }}, + {"schemas", + [&] { + int offset = 0; + for (int i = 0; i < message_generators_.size(); ++i) { + message_generators_[i]->GenerateSchema(p, offset, + offsets[i].second); + offset += offsets[i].first; + } + }}, + {"defaults", + [&] { + for (auto& gen : message_generators_) { + p->Emit( + { + {"ns", Namespace(gen->descriptor(), options_)}, + {"class", ClassName(gen->descriptor())}, + }, + R"cc( + &$ns$::_$class$_default_instance_._instance, + )cc"); + } + }}, + }, + R"cc( + const ::arc_ui32 $tablename$::offsets[] PROTOBUF_SECTION_VARIABLE( + protodesc_cold) = { + $offsets$, + }; + + static const ::_pbi::MigrationSchema + schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + $schemas$, + }; + + static const ::_pb::Message* const file_default_instances[] = { + $defaults$, + }; + )cc"); } else { - // we still need these symbols to exist - format( - // MSVC doesn't like empty arrays, so we add a dummy. - "const $uint32$ $tablename$::offsets[1] = {};\n" - "static constexpr ::_pbi::MigrationSchema* schemas = nullptr;\n" - "static constexpr ::_pb::Message* const* " - "file_default_instances = nullptr;\n" - "\n"); + // Ee still need these symbols to exist. + // + // MSVC doesn't like empty arrays, so we add a dummy. + p->Emit(R"cc( + const ::arc_ui32 $tablename$::offsets[1] = {}; + static constexpr ::_pbi::MigrationSchema* schemas = nullptr; + static constexpr ::_pb::Message* const* file_default_instances = nullptr; + )cc"); } // --------------------------------------------------------------- @@ -877,63 +960,87 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { // Embed the descriptor. We simply serialize the entire // FileDescriptorProto/ and embed it as a string literal, which is parsed and // built into real descriptors at initialization time. - const TProtoStringType protodef_name = - UniqueName("descriptor_table_protodef", file_, options_); - format("const char $1$[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =\n", - protodef_name); - format.Indent(); - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); + + FileDescriptorProto file_proto = StripSourceRetentionOptions(*file_); TProtoStringType file_data; file_proto.SerializeToString(&file_data); - { - if (file_data.size() > 65535) { - // Workaround for MSVC: "Error C1091: compiler limit: string exceeds - // 65535 bytes in length". Declare a static array of chars rather than - // use a string literal. Only write 25 bytes per line. - static const int kBytesPerLine = 25; - format("{ "); - for (int i = 0; i < file_data.size();) { - for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { - format("'$1$', ", CEscape(file_data.substr(i, 1))); - } - format("\n"); - } - format("'\\0' }"); // null-terminate - } else { - // 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)))); - } - } - format(";\n"); - } - format.Outdent(); + auto desc_name = UniqueName("descriptor_table_protodef", file_, options_); + p->Emit( + {{"desc_name", desc_name}, + {"encoded_file_proto", + [&] { + y_absl::string_view data = file_data; + if (data.size() <= 65535) { + static constexpr size_t kBytesPerLine = 40; + while (!data.empty()) { + auto to_write = std::min(kBytesPerLine, data.size()); + auto chunk = data.substr(0, to_write); + data = data.substr(to_write); + + p->Emit({{"text", EscapeTrigraphs(y_absl::CEscape(chunk))}}, R"cc( + "$text$" + )cc"); + } + return; + } + + // Workaround for MSVC: "Error C1091: compiler limit: string exceeds + // 65535 bytes in length". Declare a static array of chars rather than + // use a string literal. Only write 25 bytes per line. + static constexpr size_t kBytesPerLine = 25; + while (!data.empty()) { + auto to_write = std::min(kBytesPerLine, data.size()); + auto chunk = data.substr(0, to_write); + data = data.substr(to_write); + + TProtoStringType line; + for (char c : chunk) { + y_absl::StrAppend(&line, "'", + y_absl::CEscape(y_absl::string_view(&c, 1)), "', "); + } + + p->Emit({{"line", line}}, R"cc( + $line$ + )cc"); + } + }}}, + R"cc( + const char $desc_name$[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + $encoded_file_proto$, + }; + )cc"); CrossFileReferences refs; GetCrossFileReferencesForFile(file_, &refs); - int num_deps = + size_t num_deps = refs.strong_reflection_files.size() + refs.weak_reflection_files.size(); // Build array of DescriptorTable deps. if (num_deps > 0) { - format( - "static const ::_pbi::DescriptorTable* const " - "$desc_table$_deps[$1$] = {\n", - num_deps); - - for (auto dep : Sorted(refs.strong_reflection_files)) { - format(" &::$1$,\n", DescriptorTableName(dep, options_)); - } - for (auto dep : Sorted(refs.weak_reflection_files)) { - format(" &::$1$,\n", DescriptorTableName(dep, options_)); - } - - format("};\n"); + p->Emit( + { + {"len", num_deps}, + {"deps", + [&] { + for (auto dep : refs.strong_reflection_files) { + p->Emit({{"name", DescriptorTableName(dep, options_)}}, R"cc( + &::$name$, + )cc"); + } + for (auto dep : refs.weak_reflection_files) { + p->Emit({{"name", DescriptorTableName(dep, options_)}}, R"cc( + &::$name$, + )cc"); + } + }}, + }, + R"cc( + static const ::_pbi::DescriptorTable* const $desc_table$_deps[$len$] = + { + $deps$, + }; + )cc"); } // The DescriptorTable itself. @@ -941,391 +1048,354 @@ void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) { // however this might cause a tsan failure in superroot b/148382879, // so disable for now. bool eager = false; - format( - "static ::_pbi::once_flag $desc_table$_once;\n" - "const ::_pbi::DescriptorTable $desc_table$ = {\n" - " false, $1$, $2$, $3$,\n" - " \"$filename$\",\n" - " &$desc_table$_once, $4$, $5$, $6$,\n" - " schemas, file_default_instances, $tablename$::offsets,\n" - " $7$, $file_level_enum_descriptors$,\n" - " $file_level_service_descriptors$,\n" - "};\n" - // This function exists to be marked as weak. - // It can significantly speed up compilation by breaking up LLVM's SCC in - // the .pb.cc translation units. Large translation units see a reduction - // of more than 35% of walltime for optimized builds. - // Without the weak attribute all the messages in the file, including all - // the vtables and everything they use become part of the same SCC through - // a cycle like: - // GetMetadata -> descriptor table -> default instances -> - // vtables -> GetMetadata - // By adding a weak function here we break the connection from the - // individual vtables back into the descriptor table. - "PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* " - "$desc_table$_getter() {\n" - " return &$desc_table$;\n" - "}\n" - "\n", - eager ? "true" : "false", file_data.size(), protodef_name, - num_deps == 0 ? "nullptr" : variables_["desc_table"] + "_deps", num_deps, - message_generators_.size(), - message_generators_.empty() ? "nullptr" - : variables_["file_level_metadata"]); + p->Emit( + { + {"eager", eager ? "true" : "false"}, + {"file_proto_len", file_data.size()}, + {"proto_name", desc_name}, + {"deps_ptr", num_deps == 0 + ? "nullptr" + : y_absl::StrCat(p->LookupVar("desc_table"), "_deps")}, + {"num_deps", num_deps}, + {"num_msgs", message_generators_.size()}, + {"msgs_ptr", message_generators_.empty() + ? "nullptr" + : TProtoStringType(p->LookupVar("file_level_metadata"))}, + }, + R"cc( + static ::y_absl::once_flag $desc_table$_once; + const ::_pbi::DescriptorTable $desc_table$ = { + false, + $eager$, + $file_proto_len$, + $proto_name$, + "$filename$", + &$desc_table$_once, + $deps_ptr$, + $num_deps$, + $num_msgs$, + schemas, + file_default_instances, + $tablename$::offsets, + $msgs_ptr$, + $file_level_enum_descriptors$, + $file_level_service_descriptors$, + }; + + // This function exists to be marked as weak. + // It can significantly speed up compilation by breaking up LLVM's SCC + // in the .pb.cc translation units. Large translation units see a + // reduction of more than 35% of walltime for optimized builds. Without + // the weak attribute all the messages in the file, including all the + // vtables and everything they use become part of the same SCC through + // a cycle like: + // GetMetadata -> descriptor table -> default instances -> + // vtables -> GetMetadata + // By adding a weak function here we break the connection from the + // individual vtables back into the descriptor table. + PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* $desc_table$_getter() { + return &$desc_table$; + } + )cc"); // For descriptor.proto we want to avoid doing any dynamic initialization, // because in some situations that would otherwise pull in a lot of // unnecessary code that can't be stripped by --gc-sections. Descriptor // initialization will still be performed lazily when it's needed. - if (file_->name() != "net/proto2/proto/descriptor.proto") { - format( - "// Force running AddDescriptors() at dynamic initialization time.\n" - "PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 " - "static ::_pbi::AddDescriptorsRunner $1$(&$desc_table$);\n", - UniqueName("dynamic_init_dummy", file_, options_)); + if (file_->name() == "net/proto2/proto/descriptor.proto") { + return; } + + p->Emit({{"dummy", UniqueName("dynamic_init_dummy", file_, options_)}}, R"cc( + // Force running AddDescriptors() at dynamic initialization time. + PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 + static ::_pbi::AddDescriptorsRunner $dummy$(&$desc_table$); + )cc"); } class FileGenerator::ForwardDeclarations { public: - void AddMessage(const Descriptor* d) { classes_[ClassName(d)] = d; } - void AddEnum(const EnumDescriptor* d) { enums_[ClassName(d)] = d; } - void AddSplit(const Descriptor* d) { splits_[ClassName(d)] = d; } - - void Print(const Formatter& format, const Options& options) const { - for (const auto& p : enums_) { - const TProtoStringType& enumname = p.first; - const EnumDescriptor* enum_desc = p.second; - format( - "enum ${1$$2$$}$ : int;\n" - "bool $2$_IsValid(int value);\n", - enum_desc, enumname); + void AddMessage(const Descriptor* d) { classes_.emplace(ClassName(d), d); } + void AddEnum(const EnumDescriptor* d) { enums_.emplace(ClassName(d), d); } + void AddSplit(const Descriptor* d) { splits_.emplace(ClassName(d), d); } + + void Print(io::Printer* p, const Options& options) const { + for (const auto& e : enums_) { + p->Emit({Sub("enum", e.first).AnnotatedAs(e.second)}, R"cc( + enum $enum$ : int; + bool $enum$_IsValid(int value); + )cc"); } - for (const auto& p : classes_) { - const TProtoStringType& classname = p.first; - const Descriptor* class_desc = p.second; - format( - "class ${1$$2$$}$;\n" - "struct $3$;\n" - "$dllexport_decl $extern $3$ $4$;\n", - class_desc, classname, DefaultInstanceType(class_desc, options), - DefaultInstanceName(class_desc, options)); + + for (const auto& c : classes_) { + const Descriptor* desc = c.second; + p->Emit( + { + Sub("class", c.first).AnnotatedAs(desc), + {"default_type", DefaultInstanceType(desc, options)}, + {"default_name", DefaultInstanceName(desc, options)}, + }, + R"cc( + class $class$; + struct $default_type$; + $dllexport_decl $extern $default_type$ $default_name$; + )cc"); } - for (const auto& p : splits_) { - const Descriptor* class_desc = p.second; - format( - "struct $1$;\n" - "$dllexport_decl $extern $1$ $2$;\n", - DefaultInstanceType(class_desc, options, /*split=*/true), - DefaultInstanceName(class_desc, options, /*split=*/true)); + + for (const auto& s : splits_) { + const Descriptor* desc = s.second; + p->Emit( + { + {"default_type", + DefaultInstanceType(desc, options, /*split=*/true)}, + {"default_name", + DefaultInstanceName(desc, options, /*split=*/true)}, + }, + R"cc( + struct $default_type$; + $dllexport_decl $extern const $default_type$ $default_name$; + )cc"); } } - void PrintTopLevelDecl(const Formatter& format, - const Options& options) const { - for (const auto& pair : classes_) { - format( - "template<> $dllexport_decl $" - "$1$* Arena::CreateMaybeMessage<$1$>(Arena*);\n", - QualifiedClassName(pair.second, options)); + void PrintTopLevelDecl(io::Printer* p, const Options& options) const { + for (const auto& c : classes_) { + p->Emit({{"class", QualifiedClassName(c.second, options)}}, R"cc( + template <> + $dllexport_decl $$class$* Arena::CreateMaybeMessage<$class$>(Arena*); + )cc"); } } private: - std::map<TProtoStringType, const Descriptor*> classes_; - std::map<TProtoStringType, const EnumDescriptor*> enums_; - std::map<TProtoStringType, const Descriptor*> splits_; + y_absl::btree_map<TProtoStringType, const Descriptor*> classes_; + y_absl::btree_map<TProtoStringType, const EnumDescriptor*> enums_; + y_absl::btree_map<TProtoStringType, const Descriptor*> splits_; }; -static void PublicImportDFS(const FileDescriptor* fd, - std::unordered_set<const FileDescriptor*>* fd_set) { - for (int i = 0; i < fd->public_dependency_count(); i++) { +static void PublicImportDFS( + const FileDescriptor* fd, + y_absl::flat_hash_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); + if (fd_set.insert(dep).second) { + PublicImportDFS(dep, fd_set); + } } } -void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) { - Formatter format(printer, variables_); +void FileGenerator::GenerateForwardDeclarations(io::Printer* p) { std::vector<const Descriptor*> classes; - std::vector<const EnumDescriptor*> enums; - FlattenMessagesInFile(file_, &classes); // All messages need forward decls. - std::vector<const FieldDescriptor*> fields; - if (!options_.transitive_pb_h || options_.proto_h) { - ListAllFields(file_, &fields); - } - - if (!options_.transitive_pb_h) { - // Add forward declaration for all messages, enums, and extended messages - // defined outside the file - for (int i = 0; i < fields.size(); i++) { - const Descriptor* message_type = fields[i]->message_type(); - if (message_type && message_type->file() != file_) { - classes.push_back(message_type); - } - - const EnumDescriptor* enum_type = fields[i]->enum_type(); - if (enum_type && enum_type->file() != file_) { - enums.push_back(enum_type); - } - - if (fields[i]->is_extension()) { - const Descriptor* message_type = fields[i]->containing_type(); - if (message_type && message_type->file() != file_) { - classes.push_back(message_type); - } - } - } - } - + std::vector<const EnumDescriptor*> enums; if (options_.proto_h) { // proto.h needs extra forward declarations. // All classes / enums referred to as field members - 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()); + std::vector<const FieldDescriptor*> fields; + ListAllFields(file_, &fields); + for (const auto* field : fields) { + classes.push_back(field->containing_type()); + classes.push_back(field->message_type()); + enums.push_back(field->enum_type()); } + ListAllTypesForServices(file_, &classes); } // 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; - if (options_.transitive_pb_h) { - PublicImportDFS(file_, &public_set); - } + y_absl::flat_hash_set<const FileDescriptor*> public_set; + PublicImportDFS(file_, public_set); - std::map<TProtoStringType, ForwardDeclarations> decls; - for (int i = 0; i < classes.size(); i++) { - const Descriptor* d = classes[i]; - if (d && !public_set.count(d->file())) + y_absl::btree_map<TProtoStringType, ForwardDeclarations> decls; + for (const auto* d : classes) { + if (d != nullptr && !public_set.count(d->file())) decls[Namespace(d, options_)].AddMessage(d); } - for (int i = 0; i < enums.size(); i++) { - const EnumDescriptor* d = enums[i]; - if (d && !public_set.count(d->file())) - decls[Namespace(d, options_)].AddEnum(d); + for (const auto* e : enums) { + if (e != nullptr && !public_set.count(e->file())) + decls[Namespace(e, options_)].AddEnum(e); } for (const auto& mg : message_generators_) { - const Descriptor* d = mg->descriptor_; - if ((d != nullptr) && (public_set.count(d->file()) == 0u) && - ShouldSplit(mg->descriptor_, options_)) + const Descriptor* d = mg->descriptor(); + if (d != nullptr && public_set.count(d->file()) == 0u && + ShouldSplit(mg->descriptor(), options_)) decls[Namespace(d, options_)].AddSplit(d); } - { - NamespaceOpener ns(format); - for (const auto& pair : decls) { - ns.ChangeTo(pair.first); - pair.second.Print(format, options_); - } - } - format("PROTOBUF_NAMESPACE_OPEN\n"); - for (const auto& pair : decls) { - pair.second.PrintTopLevelDecl(format, options_); + NamespaceOpener ns(p); + for (const auto& decl : decls) { + ns.ChangeTo(decl.first); + decl.second.Print(p, options_); } - format("PROTOBUF_NAMESPACE_CLOSE\n"); -} - -void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer, bool pb_h, bool deps) { - Formatter format(printer, variables_); - // Generate top of header. - format( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $filename$\n" - "\n" - "#ifndef $1$\n" - "#define $1$\n" - "\n" - "#include <limits>\n" - "#include <string>\n", - IncludeGuard(file_, pb_h, deps, options_)); - 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, bool pb_h, bool deps) { - Formatter format(printer, variables_); - format("#endif // $GOOGLE_PROTOBUF$_INCLUDED_$1$\n", - IncludeGuard(file_, pb_h, deps, options_)); + ns.ChangeTo("PROTOBUF_NAMESPACE_ID"); + for (const auto& decl : decls) { + decl.second.PrintTopLevelDecl(p, options_); + } } -void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { - Formatter format(printer, variables_); +void FileGenerator::GenerateLibraryIncludes(io::Printer* p) { if (UsingImplicitWeakFields(file_, options_)) { - IncludeFile("net/proto2/public/implicit_weak_message.h", printer); + IncludeFile("third_party/protobuf/implicit_weak_message.h", p); } if (HasWeakFields(file_, options_)) { - GOOGLE_CHECK(!options_.opensource_runtime); - IncludeFile("net/proto2/public/weak_field_map.h", printer); + Y_ABSL_CHECK(!options_.opensource_runtime); + IncludeFile("third_party/protobuf/weak_field_map.h", p); } if (HasLazyFields(file_, options_, &scc_analyzer_)) { - GOOGLE_CHECK(!options_.opensource_runtime); - IncludeFile("net/proto2/public/lazy_field.h", printer); + Y_ABSL_CHECK(!options_.opensource_runtime); + IncludeFile("third_party/protobuf/lazy_field.h", p); } if (ShouldVerify(file_, options_, &scc_analyzer_)) { - IncludeFile("net/proto2/public/wire_format_verify.h", printer); + IncludeFile("third_party/protobuf/wire_format_verify.h", p); } 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); + IncludeFile("third_party/protobuf/port_def.inc", p); + p->Emit( + { + {"min_version", PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC}, + {"version", PROTOBUF_VERSION}, + }, + R"( + #if PROTOBUF_VERSION < $min_version$ + #error "This file was generated by a newer version of protoc which is" + #error "incompatible with your Protocol Buffer headers. Please update" + #error "your headers." + #endif // PROTOBUF_VERSION + + #if $version$ < 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 "regenerate this file with a newer version of protoc." + #endif // PROTOBUF_MIN_PROTOC_VERSION + )"); + IncludeFile("third_party/protobuf/port_undef.inc", p); } // OK, it's now safe to #include other files. - IncludeFile("net/proto2/io/public/coded_stream.h", printer); - IncludeFile("net/proto2/public/arena.h", printer); - IncludeFile("net/proto2/public/arenastring.h", printer); + IncludeFile("third_party/protobuf/io/coded_stream.h", p); + IncludeFile("third_party/protobuf/arena.h", p); + IncludeFile("third_party/protobuf/arenastring.h", p); if ((options_.force_inline_string || options_.profile_driven_inline_string) && !options_.opensource_runtime) { - IncludeFile("net/proto2/public/inlined_string_field.h", printer); + IncludeFile("third_party/protobuf/inlined_string_field.h", p); } if (HasSimpleBaseClasses(file_, options_)) { - IncludeFile("net/proto2/public/generated_message_bases.h", printer); + IncludeFile("third_party/protobuf/generated_message_bases.h", p); } if (HasGeneratedMethods(file_, options_) && options_.tctable_mode != Options::kTCTableNever) { - IncludeFile("net/proto2/public/generated_message_tctable_decl.h", printer); + IncludeFile("third_party/protobuf/generated_message_tctable_decl.h", p); } - IncludeFile("net/proto2/public/generated_message_util.h", printer); - IncludeFile("net/proto2/public/metadata_lite.h", printer); + IncludeFile("third_party/protobuf/generated_message_util.h", p); + IncludeFile("third_party/protobuf/metadata_lite.h", p); if (HasDescriptorMethods(file_, options_)) { - IncludeFile("net/proto2/public/generated_message_reflection.h", printer); + IncludeFile("third_party/protobuf/generated_message_reflection.h", p); } if (!message_generators_.empty()) { if (HasDescriptorMethods(file_, options_)) { - IncludeFile("net/proto2/public/message.h", printer); + IncludeFile("third_party/protobuf/message.h", p); } else { - IncludeFile("net/proto2/public/message_lite.h", printer); + IncludeFile("third_party/protobuf/message_lite.h", p); } } 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); + IncludeFileAndExport("third_party/protobuf/repeated_field.h", p); + IncludeFileAndExport("third_party/protobuf/extension_set.h", p); } else { // Google3 includes these files only when they are necessary. if (HasExtensionsOrExtendableMessage(file_)) { - IncludeFileAndExport("net/proto2/public/extension_set.h", printer); + IncludeFileAndExport("third_party/protobuf/extension_set.h", p); } if (HasRepeatedFields(file_)) { - IncludeFileAndExport("net/proto2/public/repeated_field.h", printer); + IncludeFileAndExport("third_party/protobuf/repeated_field.h", p); } if (HasStringPieceFields(file_, options_)) { - IncludeFile("net/proto2/public/string_piece_field_support.h", printer); + IncludeFile("third_party/protobuf/string_piece_field_support.h", p); } if (HasCordFields(file_, options_)) { - format("#include \"third_party/absl/strings/cord.h\"\n"); + p->Emit(R"( + #include "y_absl/strings/cord.h" + )"); } } if (HasMapFields(file_)) { - IncludeFileAndExport("net/proto2/public/map.h", printer); + IncludeFileAndExport("third_party/protobuf/map.h", p); if (HasDescriptorMethods(file_, options_)) { - IncludeFile("net/proto2/public/map_entry.h", printer); - IncludeFile("net/proto2/public/map_field_inl.h", printer); + IncludeFile("third_party/protobuf/map_entry.h", p); + IncludeFile("third_party/protobuf/map_field_inl.h", p); } else { - IncludeFile("net/proto2/public/map_entry_lite.h", printer); - IncludeFile("net/proto2/public/map_field_lite.h", printer); + IncludeFile("third_party/protobuf/map_entry_lite.h", p); + IncludeFile("third_party/protobuf/map_field_lite.h", p); } } if (HasEnumDefinitions(file_)) { if (HasDescriptorMethods(file_, options_)) { - IncludeFile("net/proto2/public/generated_enum_reflection.h", printer); + IncludeFile("third_party/protobuf/generated_enum_reflection.h", p); } else { - IncludeFile("net/proto2/public/generated_enum_util.h", printer); + IncludeFile("third_party/protobuf/generated_enum_util.h", p); } } if (HasGenericServices(file_, options_)) { - IncludeFile("net/proto2/public/service.h", printer); + IncludeFile("third_party/protobuf/service.h", p); } if (UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) { - IncludeFile("net/proto2/public/unknown_field_set.h", printer); + IncludeFile("third_party/protobuf/unknown_field_set.h", p); } } -void FileGenerator::GenerateMetadataPragma(io::Printer* printer, - const TProtoStringType& info_path) { - Formatter format(printer, variables_); - if (!info_path.empty() && !options_.annotation_pragma_name.empty() && - !options_.annotation_guard_name.empty()) { - 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"); +void FileGenerator::GenerateMetadataPragma(io::Printer* p, + y_absl::string_view info_path) { + if (info_path.empty() || options_.annotation_pragma_name.empty() || + options_.annotation_guard_name.empty()) { + return; } -} - -void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) { - Formatter format(printer, variables_); - std::queue<const FileDescriptor*> files_queue; - std::unordered_set<const FileDescriptor*> included_files; - files_queue.push(file_); - included_files.insert(file_); - - while (!files_queue.empty()) { - const FileDescriptor* file = files_queue.front(); - files_queue.pop(); - - for (int i = 0; i < file->dependency_count(); i++) { - // try figure out if this file have not been included yet - const FileDescriptor* dependency_file = file->dependency(i); - if (!options_.transitive_pb_h) { - auto [iter, is_inserted] = included_files.insert(dependency_file); - if (is_inserted) { - files_queue.push(dependency_file); - } else { - continue; - } - } - TProtoStringType basename = StripProto(dependency_file->name()); + p->Emit( + { + {"guard", options_.annotation_guard_name}, + {"pragma", options_.annotation_pragma_name}, + {"info_path", TProtoStringType(info_path)}, + }, + R"( + #ifdef $guard$ + #pragma $pragma$ "$info_path$" + #endif // $guard$ + )"); +} - // Do not import weak deps. - if (IsDepWeak(dependency_file)) continue; +void FileGenerator::GenerateDependencyIncludes(io::Printer* p) { + for (int i = 0; i < file_->dependency_count(); ++i) { + const FileDescriptor* dep = file_->dependency(i); - if (IsBootstrapProto(options_, file)) { - GetBootstrapBasename(options_, basename, &basename); - } + // Do not import weak deps. + if (IsDepWeak(dep)) { + continue; + } - format("#include $1$\n", - CreateHeaderInclude(basename + ".pb.h", dependency_file)); + TProtoStringType basename = StripProto(dep->name()); + if (IsBootstrapProto(options_, file_)) { + GetBootstrapBasename(options_, basename, &basename); } + + p->Emit( + {{"name", CreateHeaderInclude(y_absl::StrCat(basename, ".pb.h"), dep)}}, + "#" "include" "$name$\n" + ); } } -void FileGenerator::GenerateGlobalStateFunctionDeclarations( - io::Printer* printer) { - Formatter format(printer, variables_); +void FileGenerator::GenerateGlobalStateFunctionDeclarations(io::Printer* p) { // Forward-declare the DescriptorTable because this is referenced by .pb.cc // files depending on this file. // @@ -1333,114 +1403,102 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations( // 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" - "// Internal implementation detail -- do not use these members.\n" - "struct $dllexport_decl $$tablename$ {\n" - " static const $uint32$ offsets[];\n" - "};\n"); + p->Emit(R"cc( + // Internal implementation detail -- do not use these members. + struct $dllexport_decl $$tablename$ { + static const ::arc_ui32 offsets[]; + }; + )cc"); + if (HasDescriptorMethods(file_, options_)) { - format( - "$dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable " - "$desc_table$;\n"); + p->Emit(R"cc( + $dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable + $desc_table$; + )cc"); } } -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) { - format("\n"); - format(kThinSeparator); - format("\n"); - } - message_generators_[i]->GenerateClassDefinition(printer); +void FileGenerator::GenerateMessageDefinitions(io::Printer* p) { + for (int i = 0; i < message_generators_.size(); ++i) { + p->Emit(R"cc( + $hrule_thin$ + )cc"); + message_generators_[i]->GenerateClassDefinition(p); } } -void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) { - // Generate enum definitions. - for (int i = 0; i < enum_generators_.size(); i++) { - enum_generators_[i]->GenerateDefinition(printer); +void FileGenerator::GenerateEnumDefinitions(io::Printer* p) { + for (int i = 0; i < enum_generators_.size(); ++i) { + enum_generators_[i]->GenerateDefinition(p); } } -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) { - format("\n"); - format(kThinSeparator); - format("\n"); - } - service_generators_[i]->GenerateDeclarations(printer); - } +void FileGenerator::GenerateServiceDefinitions(io::Printer* p) { + if (!HasGenericServices(file_, options_)) { + return; + } - format("\n"); - format(kThickSeparator); - format("\n"); + for (int i = 0; i < service_generators_.size(); ++i) { + p->Emit(R"cc( + $hrule_thin$ + )cc"); + service_generators_[i]->GenerateDeclarations(p); } + + p->Emit(R"cc( + $hrule_thick$ + )cc"); } -void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) { +void FileGenerator::GenerateExtensionIdentifiers(io::Printer* p) { // Declare extension identifiers. These are in global scope and so only // the global scope extensions. for (auto& extension_generator : extension_generators_) { - if (extension_generator->IsScoped()) continue; - extension_generator->GenerateDeclaration(printer); + if (extension_generator->IsScoped()) { + continue; + } + extension_generator->GenerateDeclaration(p); } } -void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) { - Formatter format(printer, variables_); +void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* p) { // TODO(gerbens) remove pragmas when gcc is no longer used. Current version // of gcc fires a bogus error when compiled with strict-aliasing. - 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) { - format(kThinSeparator); - format("\n"); - } - message_generators_[i]->GenerateInlineMethods(printer); - } - format( - "#ifdef __GNUC__\n" - " #pragma GCC diagnostic pop\n" - "#endif // __GNUC__\n"); + p->Emit(R"( + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" + #endif // __GNUC__ + )"); + + for (int i = 0; i < message_generators_.size(); ++i) { + p->Emit(R"cc( + $hrule_thin$ + )cc"); + message_generators_[i]->GenerateInlineMethods(p); + } + + p->Emit(R"( + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif // __GNUC__ + )"); +} - for (int i = 0; i < message_generators_.size(); i++) { - if (i > 0) { - format(kThinSeparator); - format("\n"); - } +void FileGenerator::GenerateProto2NamespaceEnumSpecializations(io::Printer* p) { + // Emit GetEnumDescriptor specializations into google::protobuf namespace. + if (!HasEnumDefinitions(file_)) { + return; } -} -void FileGenerator::GenerateProto2NamespaceEnumSpecializations( - io::Printer* printer) { - Formatter format(printer, variables_); - // Emit GetEnumDescriptor specializations into google::protobuf namespace: - if (HasEnumDefinitions(file_)) { - 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"); - } + p->PrintRaw("\n"); + NamespaceOpener ns(ProtobufNamespace(options_), p); + p->PrintRaw("\n"); + for (auto& gen : enum_generators_) { + gen->GenerateGetEnumDescriptorSpecializations(p); } + p->PrintRaw("\n"); } - } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.h index 805b4979bf5..7f41bfae12f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.h @@ -36,53 +36,47 @@ #define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ #include <algorithm> +#include <functional> #include <memory> -#include <set> #include <string> #include <vector> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/cpp/field.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/compiler/scc.h> -#include <google/protobuf/compiler/cpp/options.h> - -namespace google { -namespace protobuf { -class FileDescriptor; // descriptor.h -namespace io { -class Printer; // printer.h -} -} // namespace protobuf -} // namespace google +#include "google/protobuf/stubs/common.h" +#include "google/protobuf/compiler/scc.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_check.h" +#include "google/protobuf/compiler/cpp/enum.h" +#include "google/protobuf/compiler/cpp/extension.h" +#include "google/protobuf/compiler/cpp/field.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/message.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/compiler/cpp/service.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/port.h" 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 FileGenerator { public: - // See generator.cc for the meaning of dllexport_decl. FileGenerator(const FileDescriptor* file, const Options& options); - ~FileGenerator(); - // Shared code between the two header generators below. - void GenerateHeader(io::Printer* printer); + FileGenerator(const FileGenerator&) = delete; + FileGenerator& operator=(const FileGenerator&) = delete; + + ~FileGenerator() = default; // 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 TProtoStringType& info_path); + void GenerateProtoHeader(io::Printer* p, y_absl::string_view 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 TProtoStringType& info_path); - void GeneratePBDeps(io::Printer* printer, const TProtoStringType& info_path); - void GenerateSource(io::Printer* printer); + void GeneratePBHeader(io::Printer* p, y_absl::string_view info_path); + void GenerateSource(io::Printer* p); // The following member functions are used when the lite_implicit_weak_fields // option is set. In this mode the code is organized a bit differently to @@ -93,78 +87,86 @@ class FileGenerator { int NumMessages() const { return message_generators_.size(); } int NumExtensions() const { return extension_generators_.size(); } // Generates the source file for one message. - void GenerateSourceForMessage(int idx, io::Printer* printer); + void GenerateSourceForMessage(int idx, io::Printer* p); // Generates the source file for one extension. - void GenerateSourceForExtension(int idx, io::Printer* printer); + void GenerateSourceForExtension(int idx, io::Printer* p); // Generates a source file containing everything except messages and // extensions. - void GenerateGlobalSource(io::Printer* printer); + void GenerateGlobalSource(io::Printer* p); private: + // Generates a file, setting up the necessary accoutrements that start and + // end the file, calling `cb` in between. + // + // This includes header guards and file-global variables. + void GenerateFile(io::Printer* p, GeneratedFileType file_type, + std::function<void()> cb); + + // Shared code between the two header generators. + void GenerateSharedHeaderCode(io::Printer* p); + // Internal type used by GenerateForwardDeclarations (defined in file.cc). class ForwardDeclarations; struct CrossFileReferences; - void IncludeFile(const TProtoStringType& google3_name, io::Printer* printer) { - DoIncludeFile(google3_name, false, printer); + void IncludeFile(y_absl::string_view google3_name, io::Printer* p) { + DoIncludeFile(google3_name, false, p); } - void IncludeFileAndExport(const TProtoStringType& google3_name, - io::Printer* printer) { - DoIncludeFile(google3_name, true, printer); + void IncludeFileAndExport(y_absl::string_view google3_name, io::Printer* p) { + DoIncludeFile(google3_name, true, p); } - void DoIncludeFile(const TProtoStringType& google3_name, bool do_export, - io::Printer* printer); + void DoIncludeFile(y_absl::string_view google3_name, bool do_export, + io::Printer* p); - TProtoStringType CreateHeaderInclude(const TProtoStringType& basename, + TProtoStringType CreateHeaderInclude(y_absl::string_view basename, const FileDescriptor* file); void GetCrossFileReferencesForField(const FieldDescriptor* field, CrossFileReferences* refs); void GetCrossFileReferencesForFile(const FileDescriptor* file, CrossFileReferences* refs); void GenerateInternalForwardDeclarations(const CrossFileReferences& refs, - io::Printer* printer); - void GenerateSourceIncludes(io::Printer* printer); - void GenerateSourcePrelude(io::Printer* printer); - void GenerateSourceDefaultInstance(int idx, io::Printer* printer); + io::Printer* p); + void GenerateSourceIncludes(io::Printer* p); + void GenerateSourcePrelude(io::Printer* p); + void GenerateSourceDefaultInstance(int idx, io::Printer* p); void GenerateInitForSCC(const SCC* scc, const CrossFileReferences& refs, - io::Printer* printer); - void GenerateReflectionInitializationCode(io::Printer* printer); + io::Printer* p); + void GenerateReflectionInitializationCode(io::Printer* p); // For other imports, generates their forward-declarations. - void GenerateForwardDeclarations(io::Printer* printer); + void GenerateForwardDeclarations(io::Printer* p); // Generates top or bottom of a header file. - void GenerateTopHeaderGuard(io::Printer* printer, bool pb_h, bool deps = false); - void GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h, bool deps = false); + void GenerateTopHeaderGuard(io::Printer* p, GeneratedFileType file_type); + void GenerateBottomHeaderGuard(io::Printer* p, GeneratedFileType file_type); // Generates #include directives. - void GenerateLibraryIncludes(io::Printer* printer); - void GenerateDependencyIncludes(io::Printer* printer); + void GenerateLibraryIncludes(io::Printer* p); + void GenerateDependencyIncludes(io::Printer* p); // 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 TProtoStringType& info_path); + void GenerateMetadataPragma(io::Printer* p, y_absl::string_view info_path); // Generates a couple of different pieces before definitions: - void GenerateGlobalStateFunctionDeclarations(io::Printer* printer); + void GenerateGlobalStateFunctionDeclarations(io::Printer* p); // Generates types for classes. - void GenerateMessageDefinitions(io::Printer* printer); + void GenerateMessageDefinitions(io::Printer* p); - void GenerateEnumDefinitions(io::Printer* printer); + void GenerateEnumDefinitions(io::Printer* p); // Generates generic service definitions. - void GenerateServiceDefinitions(io::Printer* printer); + void GenerateServiceDefinitions(io::Printer* p); // Generates extension identifiers. - void GenerateExtensionIdentifiers(io::Printer* printer); + void GenerateExtensionIdentifiers(io::Printer* p); // Generates inline function definitions. - void GenerateInlineFunctionDefinitions(io::Printer* printer); + void GenerateInlineFunctionDefinitions(io::Printer* p); - void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer); + void GenerateProto2NamespaceEnumSpecializations(io::Printer* p); // 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 @@ -173,24 +175,27 @@ class FileGenerator { // 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); + void GenerateMacroUndefs(io::Printer* p); bool IsDepWeak(const FileDescriptor* dep) const { if (weak_deps_.count(dep) != 0) { - GOOGLE_CHECK(!options_.opensource_runtime); + Y_ABSL_CHECK(!options_.opensource_runtime); return true; } return false; } - std::set<const FileDescriptor*> weak_deps_; + y_absl::flat_hash_set<const FileDescriptor*> weak_deps_; const FileDescriptor* file_; - const Options options_; + Options options_; MessageSCCAnalyzer scc_analyzer_; - std::map<TProtoStringType, TProtoStringType> variables_; + // This member is unused and should be deleted once all old-style variable + // maps are gone. + // TODO(b/245791219) + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> 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. @@ -198,8 +203,6 @@ class FileGenerator { 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); }; } // namespace cpp diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.cc index 0da2027a1e6..6187b72cbab 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.cc @@ -32,31 +32,68 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/cpp/generator.h> +#include "google/protobuf/compiler/cpp/generator.h" +#include <cstdlib> #include <memory> #include <string> #include <utility> #include <vector> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/compiler/cpp/file.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/compiler/cpp/file.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/descriptor.pb.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { +namespace { +TProtoStringType NumberedCcFileName(y_absl::string_view basename, int number) { + return y_absl::StrCat(basename, ".out/", number, ".cc"); +} -CppGenerator::CppGenerator() {} -CppGenerator::~CppGenerator() {} +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> CommonVars( + const Options& options) { + bool is_oss = options.opensource_runtime; + return { + {"proto_ns", ProtobufNamespace(options)}, + {"pb", y_absl::StrCat("::", ProtobufNamespace(options))}, + {"pbi", y_absl::StrCat("::", ProtobufNamespace(options), "::internal")}, -namespace { -TProtoStringType NumberedCcFileName(const TProtoStringType& basename, int number) { - return StrCat(basename, ".out/", number, ".cc"); + {"string", "TProtoStringType"}, + {"int8", "::int8_t"}, + {"int32", "::arc_i32"}, + {"int64", "::arc_i64"}, + {"uint8", "::uint8_t"}, + {"uint32", "::arc_ui32"}, + {"uint64", "::arc_ui64"}, + + {"hrule_thick", kThickSeparator}, + {"hrule_thin", kThinSeparator}, + + // 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 "Y_ABSL_CHECK". + // + // 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. + {"GOOGLE_PROTOBUF", is_oss ? "GOOGLE_PROTOBUF" + : "GOOGLE3_PROTOBU" + "F"}, + {"CHK", + "Y_ABSL_CHEC" + "K"}, + {"DCHK", + "Y_ABSL_DCHEC" + "K"}, + }; } } // namespace @@ -64,7 +101,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, const TProtoStringType& parameter, GeneratorContext* generator_context, TProtoStringType* error) const { - std::vector<std::pair<TProtoStringType, TProtoStringType> > options; + std::vector<std::pair<TProtoStringType, TProtoStringType>> options; ParseGeneratorParameter(parameter, &options); // ----------------------------------------------------------------- @@ -93,72 +130,69 @@ bool CppGenerator::Generate(const FileDescriptor* file, file_options.opensource_runtime = opensource_runtime_; file_options.runtime_include_base = runtime_include_base_; - for (int i = 0; i < options.size(); i++) { - if (options[i].first == "dllexport_decl") { - file_options.dllexport_decl = options[i].second; - } else if (options[i].first == "safe_boundary_check") { + for (const auto& option : options) { + const auto& key = option.first; + const auto& value = option.second; + + if (key == "dllexport_decl") { + file_options.dllexport_decl = value; + } else if (key == "safe_boundary_check") { file_options.safe_boundary_check = true; - } else if (options[i].first == "annotate_headers") { + } else if (key == "annotate_headers") { file_options.annotate_headers = true; - } else if (options[i].first == "annotation_pragma_name") { - file_options.annotation_pragma_name = options[i].second; - } else if (options[i].first == "annotation_guard_name") { - file_options.annotation_guard_name = options[i].second; - } else if (options[i].first == "speed") { + } else if (key == "annotation_pragma_name") { + file_options.annotation_pragma_name = value; + } else if (key == "annotation_guard_name") { + file_options.annotation_guard_name = value; + } else if (key == "speed") { file_options.enforce_mode = EnforceOptimizeMode::kSpeed; - } else if (options[i].first == "code_size") { + } else if (key == "code_size") { file_options.enforce_mode = EnforceOptimizeMode::kCodeSize; - } else if (options[i].first == "lite") { + } else if (key == "lite") { file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime; - } else if (options[i].first == "lite_implicit_weak_fields") { + } else if (key == "lite_implicit_weak_fields") { file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime; file_options.lite_implicit_weak_fields = true; - if (!options[i].second.empty()) { - file_options.num_cc_files = - strto32(options[i].second.c_str(), nullptr, 10); + if (!value.empty()) { + file_options.num_cc_files = std::strtol(value.c_str(), nullptr, 10); } - } else if (options[i].first == "proto_h") { + } else if (key == "proto_h") { file_options.proto_h = true; - } else if (options[i].first == "annotate_accessor") { + } else if (key == "proto_static_reflection_h") { + } else if (key == "annotate_accessor") { file_options.annotate_accessor = true; - } else if (options[i].first == "inject_field_listener_events") { + } else if (key == "inject_field_listener_events") { file_options.field_listener_options.inject_field_listener_events = true; - } else if (options[i].first == "forbidden_field_listener_events") { + } else if (key == "forbidden_field_listener_events") { std::size_t pos = 0; do { - std::size_t next_pos = options[i].second.find_first_of("+", pos); + std::size_t next_pos = value.find_first_of("+", pos); if (next_pos == TProtoStringType::npos) { - next_pos = options[i].second.size(); + next_pos = value.size(); } if (next_pos > pos) file_options.field_listener_options.forbidden_field_listener_events - .insert(options[i].second.substr(pos, next_pos - pos)); + .emplace(value.substr(pos, next_pos - pos)); pos = next_pos + 1; - } while (pos < options[i].second.size()); - } else if (options[i].first == "verified_lazy") { - file_options.unverified_lazy = false; - } else if (options[i].first == "unverified_lazy_message_sets") { + } while (pos < value.size()); + } else if (key == "unverified_lazy_message_sets") { file_options.unverified_lazy_message_sets = true; - } else if (options[i].first == "message_owned_arena_trial") { - file_options.message_owned_arena_trial = true; - } else if (options[i].first == "force_eagerly_verified_lazy") { + } else if (key == "force_eagerly_verified_lazy") { file_options.force_eagerly_verified_lazy = true; - } else if (options[i].first == "experimental_tail_call_table_mode") { - if (options[i].second == "never") { + } else if (key == "experimental_tail_call_table_mode") { + if (value == "never") { file_options.tctable_mode = Options::kTCTableNever; - } else if (options[i].second == "guarded") { + } else if (value == "guarded") { file_options.tctable_mode = Options::kTCTableGuarded; - } else if (options[i].second == "always") { + } else if (value == "always") { file_options.tctable_mode = Options::kTCTableAlways; } else { - *error = "Unknown value for experimental_tail_call_table_mode: " + - options[i].second; + *error = y_absl::StrCat( + "Unknown value for experimental_tail_call_table_mode: ", value); return false; } - } else if (options[i].first == "transitive_pb_h") { - file_options.transitive_pb_h = options[i].second != "false"; } else { - *error = "Unknown generator option: " + options[i].first; + *error = y_absl::StrCat("Unknown generator option: ", key); return false; } } @@ -176,6 +210,17 @@ bool CppGenerator::Generate(const FileDescriptor* file, TProtoStringType basename = StripProto(file->name()); + auto generate_reserved_static_reflection_header = [&basename, + &generator_context]() { + auto output = y_absl::WrapUnique(generator_context->Open( + y_absl::StrCat(basename, ".proto.static_reflection.h"))); + io::Printer(output.get()).Emit(R"cc( + // Reserved for future use. + )cc"); + }; + // Suppress maybe unused warning. + (void)generate_reserved_static_reflection_header; + if (MaybeBootstrap(file_options, generator_context, file_options.bootstrap, &basename)) { return true; @@ -185,58 +230,51 @@ bool CppGenerator::Generate(const FileDescriptor* file, // Generate header(s). if (file_options.proto_h) { - std::unique_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(basename + ".proto.h")); + auto output = y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(basename, ".proto.h"))); + GeneratedCodeInfo annotations; io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( &annotations); - TProtoStringType info_path = basename + ".proto.h.meta"; - io::Printer printer( - output.get(), '$', - file_options.annotate_headers ? &annotation_collector : nullptr); + io::Printer::Options options; + if (file_options.annotate_headers) { + options.annotation_collector = &annotation_collector; + } + + io::Printer p(output.get(), options); + auto v = p.WithVars(CommonVars(file_options)); + + TProtoStringType info_path = y_absl::StrCat(basename, ".proto.h.meta"); file_generator.GenerateProtoHeader( - &printer, file_options.annotate_headers ? info_path : ""); + &p, file_options.annotate_headers ? info_path : ""); + if (file_options.annotate_headers) { - std::unique_ptr<io::ZeroCopyOutputStream> info_output( - generator_context->Open(info_path)); + auto info_output = y_absl::WrapUnique(generator_context->Open(info_path)); annotations.SerializeToZeroCopyStream(info_output.get()); } } { - std::unique_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(basename + ".pb.h")); + auto output = y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(basename, ".pb.h"))); + GeneratedCodeInfo annotations; io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( &annotations); - TProtoStringType info_path = basename + ".pb.h.meta"; - io::Printer printer( - output.get(), '$', - file_options.annotate_headers ? &annotation_collector : nullptr); - file_generator.GeneratePBHeader( - &printer, file_options.annotate_headers ? info_path : ""); + io::Printer::Options options; if (file_options.annotate_headers) { - std::unique_ptr<io::ZeroCopyOutputStream> info_output( - generator_context->Open(info_path)); - annotations.SerializeToZeroCopyStream(info_output.get()); + options.annotation_collector = &annotation_collector; } - } - if (!file_options.transitive_pb_h) { - std::unique_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(basename + ".deps.pb.h")); - GeneratedCodeInfo annotations; - io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( - &annotations); - TProtoStringType info_path = basename + ".deps.pb.h.meta"; - io::Printer printer( - output.get(), '$', - file_options.annotate_headers ? &annotation_collector : NULL); - file_generator.GeneratePBDeps( - &printer, file_options.annotate_headers ? info_path : ""); + io::Printer p(output.get(), options); + auto v = p.WithVars(CommonVars(file_options)); + + TProtoStringType info_path = y_absl::StrCat(basename, ".pb.h.meta"); + file_generator.GeneratePBHeader( + &p, file_options.annotate_headers ? info_path : ""); + if (file_options.annotate_headers) { - std::unique_ptr<io::ZeroCopyOutputStream> info_output( - generator_context->Open(info_path)); + auto info_output = y_absl::WrapUnique(generator_context->Open(info_path)); annotations.SerializeToZeroCopyStream(info_output.get()); } } @@ -246,10 +284,12 @@ bool CppGenerator::Generate(const FileDescriptor* file, { // 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); + auto output = y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(basename, ".pb.cc"))); + io::Printer p(output.get()); + auto v = p.WithVars(CommonVars(file_options)); + + file_generator.GenerateGlobalSource(&p); } int num_cc_files = @@ -260,40 +300,48 @@ bool CppGenerator::Generate(const FileDescriptor* file, // 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(num_cc_files, file_options.num_cc_files) + Y_ABSL_CHECK_LE(num_cc_files, file_options.num_cc_files) << "There must be at least as many numbered .cc files as messages " "and extensions."; num_cc_files = file_options.num_cc_files; } + int cc_file_number = 0; - for (int i = 0; i < file_generator.NumMessages(); i++) { - std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open( + for (int i = 0; i < file_generator.NumMessages(); ++i) { + auto output = y_absl::WrapUnique(generator_context->Open( NumberedCcFileName(basename, cc_file_number++))); - io::Printer printer(output.get(), '$'); - file_generator.GenerateSourceForMessage(i, &printer); + io::Printer p(output.get()); + auto v = p.WithVars(CommonVars(file_options)); + + file_generator.GenerateSourceForMessage(i, &p); } - for (int i = 0; i < file_generator.NumExtensions(); i++) { - std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open( + + for (int i = 0; i < file_generator.NumExtensions(); ++i) { + auto output = y_absl::WrapUnique(generator_context->Open( NumberedCcFileName(basename, cc_file_number++))); - io::Printer printer(output.get(), '$'); - file_generator.GenerateSourceForExtension(i, &printer); + io::Printer p(output.get()); + auto v = p.WithVars(CommonVars(file_options)); + + file_generator.GenerateSourceForExtension(i, &p); } + // Create empty placeholder files if necessary to match the expected number // of files. - for (; cc_file_number < num_cc_files; ++cc_file_number) { - std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open( - NumberedCcFileName(basename, cc_file_number))); + while (cc_file_number < num_cc_files) { + (void)y_absl::WrapUnique(generator_context->Open( + NumberedCcFileName(basename, cc_file_number++))); } } else { - std::unique_ptr<io::ZeroCopyOutputStream> output( - generator_context->Open(basename + ".pb.cc")); - io::Printer printer(output.get(), '$'); - file_generator.GenerateSource(&printer); + auto output = y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(basename, ".pb.cc"))); + io::Printer p(output.get()); + auto v = p.WithVars(CommonVars(file_options)); + + file_generator.GenerateSource(&p); } return true; } - } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.h index aa63845d300..5f95dd1d2f5 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.h @@ -38,24 +38,27 @@ #define GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__ #include <string> -#include <google/protobuf/compiler/code_generator.h> +#include <utility> + +#include "google/protobuf/compiler/code_generator.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { namespace compiler { namespace cpp { - // CodeGenerator implementation which generates a C++ source file and // 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 PROTOC_EXPORT CppGenerator : public CodeGenerator { public: - CppGenerator(); - ~CppGenerator() override; + CppGenerator() = default; + CppGenerator(const CppGenerator&) = delete; + CppGenerator& operator=(const CppGenerator&) = delete; + ~CppGenerator() override = default; enum class Runtime { kGoogle3, // Use the internal google3 runtime. @@ -74,34 +77,29 @@ class PROTOC_EXPORT CppGenerator : public CodeGenerator { // If set to a non-empty string, generated code will do: // #include "<BASE>/google/protobuf/message.h" // instead of: - // #include <google/protobuf/message.h> + // #include "google/protobuf/message.h" // This has no effect if opensource_runtime = false. - void set_runtime_include_base(const TProtoStringType& base) { - runtime_include_base_ = base; + void set_runtime_include_base(TProtoStringType base) { + runtime_include_base_ = std::move(base); } - // implements CodeGenerator ---------------------------------------- bool Generate(const FileDescriptor* file, const TProtoStringType& parameter, GeneratorContext* generator_context, TProtoStringType* error) const override; uint64_t GetSupportedFeatures() const override { - // We don't fully support this yet, but this is needed to unblock the tests, - // and we will have full support before the experimental flag is removed. return FEATURE_PROTO3_OPTIONAL; } private: - bool opensource_runtime_ = true; + bool opensource_runtime_ = PROTO2_IS_OSS; TProtoStringType runtime_include_base_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator); }; - } // namespace cpp } // namespace compiler } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc index 48879f29d57..977aa87d85e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc @@ -32,35 +32,45 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/cpp/helpers.h> +#include "google/protobuf/compiler/cpp/helpers.h" +#include <algorithm> #include <cstdint> #include <functional> #include <limits> -#include <map> #include <memory> #include <queue> -#include <unordered_set> +#include <string> +#include <utility> #include <vector> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/cpp/names.h> -#include <google/protobuf/compiler/cpp/options.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/compiler/scc.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/dynamic_message.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/stubs/common.h" +#include "google/protobuf/compiler/scc.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/dynamic_message.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/strip.h" +#include "y_absl/strings/substitute.h" +#include "y_absl/synchronization/mutex.h" +#include "google/protobuf/compiler/cpp/names.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/strtod.h" +#include "google/protobuf/wire_format.h" +#include "google/protobuf/wire_format_lite.h" + // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -72,11 +82,12 @@ namespace { static const char kAnyMessageName[] = "Any"; static const char kAnyProtoFile[] = "google/protobuf/any.proto"; -TProtoStringType DotsToColons(const TProtoStringType& name) { - return StringReplace(name, ".", "::", true); +TProtoStringType DotsToColons(y_absl::string_view name) { + return y_absl::StrReplaceAll(name, {{".", "::"}}); } -static const char* const kKeywordList[] = { // +static const char* const kKeywordList[] = { + // "NULL", "alignas", "alignof", @@ -163,48 +174,36 @@ static const char* const kKeywordList[] = { // "wchar_t", "while", "xor", - "xor_eq"}; - -static std::unordered_set<TProtoStringType>* MakeKeywordsMap() { - auto* result = new std::unordered_set<TProtoStringType>(); - for (const auto keyword : kKeywordList) { - result->emplace(keyword); - } - return result; -} - -static std::unordered_set<TProtoStringType>& kKeywords = *MakeKeywordsMap(); + "xor_eq", + "char8_t", + "char16_t", + "char32_t", + "concept", + "consteval", + "constinit", + "co_await", + "co_return", + "co_yield", + "requires", +}; -TProtoStringType IntTypeName(const Options& options, const TProtoStringType& type) { - return "::NProtoBuf::" + type; -} +const y_absl::flat_hash_set<y_absl::string_view>& Keywords() { + static const auto* keywords = [] { + auto* keywords = new y_absl::flat_hash_set<y_absl::string_view>(); -void SetIntVar(const Options& options, const TProtoStringType& type, - std::map<TProtoStringType, TProtoStringType>* variables) { - (*variables)[type] = IntTypeName(options, type); + for (const auto keyword : kKeywordList) { + keywords->emplace(keyword); + } + return keywords; + }(); + return *keywords; } -// Returns true if the message can potentially allocate memory for its field. -// This is used to determine if message-owned arena will be useful. -bool AllocExpected(const Descriptor* descriptor) { - return false; +TProtoStringType IntTypeName(const Options& options, y_absl::string_view type) { + return y_absl::StrCat("::NProtoBuf::", type); } -// Describes different approaches to detect non-canonical int32 encoding. Only -// kNever or kAlways is eligible for *simple* verification methods. -enum class VerifyInt32Type { - kCustom, // Only check if field number matches. - kNever, // Do not check. - kAlways, // Always check. -}; -inline VerifySimpleType VerifyInt32TypeToVerifyCustom(VerifyInt32Type t) { - static VerifySimpleType kCustomTypes[] = { - VerifySimpleType::kCustom, VerifySimpleType::kCustomInt32Never, - VerifySimpleType::kCustomInt32Always}; - return kCustomTypes[static_cast<arc_i32>(t) - - static_cast<arc_i32>(VerifyInt32Type::kCustom)]; -} } // namespace @@ -232,86 +231,69 @@ bool IsLazilyVerifiedLazy(const FieldDescriptor* field, return false; } -void SetCommonVars(const Options& options, - std::map<TProtoStringType, TProtoStringType>* 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, "int8", variables); - SetIntVar(options, "uint8", variables); - SetIntVar(options, "uint32", variables); - SetIntVar(options, "uint64", variables); - SetIntVar(options, "int32", variables); - SetIntVar(options, "int64", variables); - (*variables)["string"] = "TProtoStringType"; +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> MessageVars( + const Descriptor* desc) { + y_absl::string_view prefix = IsMapEntryMessage(desc) ? "" : "_impl_."; + return { + {"any_metadata", y_absl::StrCat(prefix, "_any_metadata_")}, + {"cached_size", y_absl::StrCat(prefix, "_cached_size_")}, + {"extensions", y_absl::StrCat(prefix, "_extensions_")}, + {"has_bits", y_absl::StrCat(prefix, "_has_bits_")}, + {"inlined_string_donated_array", + y_absl::StrCat(prefix, "_inlined_string_donated_")}, + {"oneof_case", y_absl::StrCat(prefix, "_oneof_case_")}, + {"tracker", "Impl_::_tracker_"}, + {"weak_field_map", y_absl::StrCat(prefix, "_weak_field_map_")}, + {"split", y_absl::StrCat(prefix, "_split_")}, + {"cached_split_ptr", "cached_split_ptr"}, + }; } void SetCommonMessageDataVariables( const Descriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables) { - TProtoStringType prefix = IsMapEntryMessage(descriptor) ? "" : "_impl_."; - (*variables)["any_metadata"] = prefix + "_any_metadata_"; - (*variables)["cached_size"] = prefix + "_cached_size_"; - (*variables)["extensions"] = prefix + "_extensions_"; - (*variables)["has_bits"] = prefix + "_has_bits_"; - (*variables)["inlined_string_donated_array"] = - prefix + "_inlined_string_donated_"; - (*variables)["oneof_case"] = prefix + "_oneof_case_"; - (*variables)["tracker"] = "Impl_::_tracker_"; - (*variables)["weak_field_map"] = prefix + "_weak_field_map_"; - (*variables)["split"] = prefix + "_split_"; - (*variables)["cached_split_ptr"] = "cached_split_ptr"; -} - -void SetUnknownFieldsVariable(const Descriptor* descriptor, - const Options& options, - std::map<TProtoStringType, TProtoStringType>* variables) { - TProtoStringType proto_ns = ProtobufNamespace(options); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { + for (auto& pair : MessageVars(descriptor)) { + variables->emplace(pair); + } +} + +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> UnknownFieldsVars( + const Descriptor* desc, const Options& opts) { + TProtoStringType proto_ns = ProtobufNamespace(opts); + TProtoStringType unknown_fields_type; - if (UseUnknownFieldSet(descriptor->file(), options)) { - unknown_fields_type = "::" + proto_ns + "::UnknownFieldSet"; - (*variables)["unknown_fields"] = - "_internal_metadata_.unknown_fields<" + unknown_fields_type + ">(" + - unknown_fields_type + "::default_instance)"; + TProtoStringType default_instance; + if (UseUnknownFieldSet(desc->file(), opts)) { + unknown_fields_type = y_absl::StrCat("::", proto_ns, "::UnknownFieldSet"); + default_instance = y_absl::StrCat(unknown_fields_type, "::default_instance"); } else { unknown_fields_type = - PrimitiveTypeName(options, FieldDescriptor::CPPTYPE_STRING); - (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields<" + - unknown_fields_type + ">(::" + proto_ns + - "::internal::GetEmptyString)"; + PrimitiveTypeName(opts, FieldDescriptor::CPPTYPE_STRING); + default_instance = + y_absl::StrCat("::", proto_ns, "::internal::GetEmptyString"); + } + + return { + {"unknown_fields", + y_absl::Substitute("_internal_metadata_.unknown_fields<$0>($1)", + unknown_fields_type, default_instance)}, + {"unknown_fields_type", unknown_fields_type}, + {"have_unknown_fields", "_internal_metadata_.have_unknown_fields()"}, + {"mutable_unknown_fields", + y_absl::Substitute("_internal_metadata_.mutable_unknown_fields<$0>()", + unknown_fields_type)}, + }; +} + +void SetUnknownFieldsVariable( + const Descriptor* descriptor, const Options& options, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { + for (auto& pair : UnknownFieldsVars(descriptor, options)) { + variables->emplace(pair); } - (*variables)["unknown_fields_type"] = unknown_fields_type; - (*variables)["have_unknown_fields"] = - "_internal_metadata_.have_unknown_fields()"; - (*variables)["mutable_unknown_fields"] = - "_internal_metadata_.mutable_unknown_fields<" + unknown_fields_type + - ">()"; } -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, +TProtoStringType UnderscoresToCamelCase(y_absl::string_view input, bool cap_next_letter) { TProtoStringType result; // Note: I distrust ctype.h due to locales. @@ -342,7 +324,9 @@ const char kThickSeparator[] = const char kThinSeparator[] = "// -------------------------------------------------------------------\n"; -bool CanInitializeByZeroing(const FieldDescriptor* field) { +bool CanInitializeByZeroing(const FieldDescriptor* field, + const Options& options, + MessageSCCAnalyzer* scc_analyzer) { if (field->is_repeated() || field->is_extension()) return false; switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_ENUM: @@ -361,6 +345,57 @@ bool CanInitializeByZeroing(const FieldDescriptor* field) { return field->default_value_double() == 0; case FieldDescriptor::CPPTYPE_BOOL: return field->default_value_bool() == false; + case FieldDescriptor::CPPTYPE_MESSAGE: + // Non-repeated, non-lazy message fields are raw pointers initialized to + // null. + return !IsLazy(field, options, scc_analyzer); + default: + return false; + } +} + +bool CanClearByZeroing(const FieldDescriptor* field) { + if (field->is_repeated() || field->is_extension()) return false; + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_ENUM: + return field->default_value_enum()->number() == 0; + case FieldDescriptor::CPPTYPE_INT32: + return field->default_value_int32() == 0; + case FieldDescriptor::CPPTYPE_INT64: + return field->default_value_int64() == 0; + case FieldDescriptor::CPPTYPE_UINT32: + return field->default_value_uint32() == 0; + case FieldDescriptor::CPPTYPE_UINT64: + return field->default_value_uint64() == 0; + case FieldDescriptor::CPPTYPE_FLOAT: + return field->default_value_float() == 0; + case FieldDescriptor::CPPTYPE_DOUBLE: + return field->default_value_double() == 0; + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() == false; + default: + return false; + } +} + +// Determines if swap can be implemented via memcpy. +bool HasTrivialSwap(const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer) { + if (field->is_repeated() || field->is_extension()) return false; + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_BOOL: + return true; + case FieldDescriptor::CPPTYPE_MESSAGE: + // Non-repeated, non-lazy message fields are simply raw pointers, so we + // can swap them with memcpy. + return !IsLazy(field, options, scc_analyzer); default: return false; } @@ -369,9 +404,9 @@ bool CanInitializeByZeroing(const FieldDescriptor* field) { TProtoStringType ClassName(const Descriptor* descriptor) { const Descriptor* parent = descriptor->containing_type(); TProtoStringType res; - if (parent) res += ClassName(parent) + "_"; - res += descriptor->name(); - if (IsMapEntryMessage(descriptor)) res += "_DoNotUse"; + if (parent) y_absl::StrAppend(&res, ClassName(parent), "_"); + y_absl::StrAppend(&res, descriptor->name()); + if (IsMapEntryMessage(descriptor)) y_absl::StrAppend(&res, "_DoNotUse"); return ResolveKeyword(res); } @@ -379,8 +414,8 @@ TProtoStringType ClassName(const EnumDescriptor* enum_descriptor) { if (enum_descriptor->containing_type() == nullptr) { return ResolveKeyword(enum_descriptor->name()); } else { - return ClassName(enum_descriptor->containing_type()) + "_" + - enum_descriptor->name(); + return y_absl::StrCat(ClassName(enum_descriptor->containing_type()), "_", + enum_descriptor->name()); } } @@ -403,13 +438,13 @@ TProtoStringType QualifiedClassName(const EnumDescriptor* d) { TProtoStringType ExtensionName(const FieldDescriptor* d) { if (const Descriptor* scope = d->extension_scope()) - return StrCat(ClassName(scope), "::", ResolveKeyword(d->name())); + return y_absl::StrCat(ClassName(scope), "::", ResolveKeyword(d->name())); return ResolveKeyword(d->name()); } TProtoStringType QualifiedExtensionName(const FieldDescriptor* d, const Options& options) { - GOOGLE_DCHECK(d->is_extension()); + Y_ABSL_DCHECK(d->is_extension()); return QualifiedFileLevelSymbol(d->file(), ExtensionName(d), options); } @@ -417,32 +452,38 @@ TProtoStringType QualifiedExtensionName(const FieldDescriptor* d) { return QualifiedExtensionName(d, Options()); } -TProtoStringType Namespace(const TProtoStringType& package) { +TProtoStringType Namespace(y_absl::string_view package) { if (package.empty()) return ""; - return "::" + DotsToColons(package); + return y_absl::StrCat("::", DotsToColons(package)); } +TProtoStringType Namespace(const FileDescriptor* d) { return Namespace(d, {}); } TProtoStringType Namespace(const FileDescriptor* d, const Options& options) { - TProtoStringType ret = Namespace(d->package()); + TProtoStringType ns = Namespace(d->package()); if (IsWellKnownMessage(d) && options.opensource_runtime) { // Written with string concatenation to prevent rewriting of // ::google::protobuf. - ret = StringReplace(ret, - "::google::" - "protobuf", - "::PROTOBUF_NAMESPACE_ID", false); + constexpr y_absl::string_view prefix = + "::google::" // prevent clang-format reflowing + "protobuf"; + y_absl::string_view new_ns(ns); + y_absl::ConsumePrefix(&new_ns, prefix); + return y_absl::StrCat("::PROTOBUF_NAMESPACE_ID", new_ns); } - return ret; + return ns; } +TProtoStringType Namespace(const Descriptor* d) { return Namespace(d, {}); } TProtoStringType Namespace(const Descriptor* d, const Options& options) { return Namespace(d->file(), options); } +TProtoStringType Namespace(const FieldDescriptor* d) { return Namespace(d, {}); } TProtoStringType Namespace(const FieldDescriptor* d, const Options& options) { return Namespace(d->file(), options); } +TProtoStringType Namespace(const EnumDescriptor* d) { return Namespace(d, {}); } TProtoStringType Namespace(const EnumDescriptor* d, const Options& options) { return Namespace(d->file(), options); } @@ -455,13 +496,13 @@ TProtoStringType DefaultInstanceType(const Descriptor* descriptor, TProtoStringType DefaultInstanceName(const Descriptor* descriptor, const Options& /*options*/, bool split) { - return "_" + ClassName(descriptor, false) + (split ? "__Impl_Split" : "") + - "_default_instance_"; + return y_absl::StrCat("_", ClassName(descriptor, false), + (split ? "__Impl_Split" : ""), "_default_instance_"); } TProtoStringType DefaultInstancePtr(const Descriptor* descriptor, const Options& options, bool split) { - return DefaultInstanceName(descriptor, options, split) + "ptr_"; + return y_absl::StrCat(DefaultInstanceName(descriptor, options, split), "ptr_"); } TProtoStringType QualifiedDefaultInstanceName(const Descriptor* descriptor, @@ -473,7 +514,8 @@ TProtoStringType QualifiedDefaultInstanceName(const Descriptor* descriptor, TProtoStringType QualifiedDefaultInstancePtr(const Descriptor* descriptor, const Options& options, bool split) { - return QualifiedDefaultInstanceName(descriptor, options, split) + "ptr_"; + return y_absl::StrCat(QualifiedDefaultInstanceName(descriptor, options, split), + "ptr_"); } TProtoStringType DescriptorTableName(const FileDescriptor* file, @@ -488,60 +530,61 @@ TProtoStringType FileDllExport(const FileDescriptor* file, const Options& option TProtoStringType SuperClassName(const Descriptor* descriptor, const Options& options) { if (!HasDescriptorMethods(descriptor->file(), options)) { - return "::" + ProtobufNamespace(options) + "::MessageLite"; + return y_absl::StrCat("::", ProtobufNamespace(options), "::MessageLite"); } auto simple_base = SimpleBaseClass(descriptor, options); if (simple_base.empty()) { - return "::" + ProtobufNamespace(options) + "::Message"; + return y_absl::StrCat("::", ProtobufNamespace(options), "::Message"); } - return "::" + ProtobufNamespace(options) + "::internal::" + simple_base; + return y_absl::StrCat("::", ProtobufNamespace(options), + "::internal::", simple_base); } -TProtoStringType ResolveKeyword(const TProtoStringType& name) { - if (kKeywords.count(name) > 0) { - return name + "_"; +TProtoStringType ResolveKeyword(y_absl::string_view name) { + if (Keywords().count(name) > 0) { + return y_absl::StrCat(name, "_"); } - return name; + return TProtoStringType(name); } TProtoStringType FieldName(const FieldDescriptor* field) { TProtoStringType result = field->name(); - LowerString(&result); - if (kKeywords.count(result) > 0) { + y_absl::AsciiStrToLower(&result); + if (Keywords().count(result) > 0) { result.append("_"); } return result; } TProtoStringType FieldMemberName(const FieldDescriptor* field, bool split) { - StringPiece prefix = + y_absl::string_view prefix = IsMapEntryMessage(field->containing_type()) ? "" : "_impl_."; - StringPiece split_prefix = split ? "_split_->" : ""; + y_absl::string_view split_prefix = split ? "_split_->" : ""; if (field->real_containing_oneof() == nullptr) { - return StrCat(prefix, split_prefix, FieldName(field), "_"); + return y_absl::StrCat(prefix, split_prefix, FieldName(field), "_"); } // Oneof fields are never split. - GOOGLE_CHECK(!split); - return StrCat(prefix, field->containing_oneof()->name(), "_.", + Y_ABSL_CHECK(!split); + return y_absl::StrCat(prefix, field->containing_oneof()->name(), "_.", FieldName(field), "_"); } TProtoStringType OneofCaseConstantName(const FieldDescriptor* field) { - GOOGLE_DCHECK(field->containing_oneof()); + Y_ABSL_DCHECK(field->containing_oneof()); TProtoStringType field_name = UnderscoresToCamelCase(field->name(), true); - return "k" + field_name; + return y_absl::StrCat("k", field_name); } TProtoStringType QualifiedOneofCaseConstantName(const FieldDescriptor* field) { - GOOGLE_DCHECK(field->containing_oneof()); + Y_ABSL_DCHECK(field->containing_oneof()); const TProtoStringType qualification = QualifiedClassName(field->containing_type()); - return StrCat(qualification, "::", OneofCaseConstantName(field)); + return y_absl::StrCat(qualification, "::", OneofCaseConstantName(field)); } TProtoStringType EnumValueName(const EnumValueDescriptor* enum_value) { TProtoStringType result = enum_value->name(); - if (kKeywords.count(result) > 0) { + if (Keywords().count(result) > 0) { result.append("_"); } return result; @@ -567,13 +610,13 @@ int EstimateAlignmentSize(const FieldDescriptor* field) { case FieldDescriptor::CPPTYPE_MESSAGE: return 8; } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return -1; // Make compiler happy. } TProtoStringType FieldConstantName(const FieldDescriptor* field) { TProtoStringType field_name = UnderscoresToCamelCase(field->name(), true); - TProtoStringType result = "k" + field_name + "FieldNumber"; + TProtoStringType result = y_absl::StrCat("k", field_name, "FieldNumber"); if (!field->is_extension() && field->containing_type()->FindFieldByCamelcaseName( @@ -581,7 +624,7 @@ TProtoStringType FieldConstantName(const FieldDescriptor* field) { // This field's camelcase name is not unique. As a hack, add the field // number to the constant name. This makes the constant rather useless, // but what can we do? - result += "_" + StrCat(field->number()); + y_absl::StrAppend(&result, "_", field->number()); } return result; @@ -594,7 +637,7 @@ TProtoStringType FieldMessageTypeName(const FieldDescriptor* field, return QualifiedClassName(field->message_type(), options); } -TProtoStringType StripProto(const TProtoStringType& filename) { +TProtoStringType StripProto(y_absl::string_view filename) { /* * TODO(github/georgthegreat) remove this proxy method * once Google's internal codebase will become ready @@ -605,13 +648,13 @@ TProtoStringType StripProto(const TProtoStringType& filename) { const char* PrimitiveTypeName(FieldDescriptor::CppType type) { switch (type) { case FieldDescriptor::CPPTYPE_INT32: - return "arc_i32"; + return "::arc_i32"; case FieldDescriptor::CPPTYPE_INT64: - return "arc_i64"; + return "::arc_i64"; case FieldDescriptor::CPPTYPE_UINT32: - return "arc_ui32"; + return "::arc_ui32"; case FieldDescriptor::CPPTYPE_UINT64: - return "arc_ui64"; + return "::arc_ui64"; case FieldDescriptor::CPPTYPE_DOUBLE: return "double"; case FieldDescriptor::CPPTYPE_FLOAT: @@ -629,7 +672,7 @@ const char* PrimitiveTypeName(FieldDescriptor::CppType type) { // CppTypes are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return nullptr; } @@ -661,7 +704,7 @@ TProtoStringType PrimitiveTypeName(const Options& options, // CppTypes are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return ""; } @@ -709,7 +752,7 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) { // No default because we want the compiler to complain if any new // types are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return ""; } @@ -717,9 +760,9 @@ TProtoStringType Int32ToString(int number) { if (number == std::numeric_limits<arc_i32>::min()) { // This needs to be special-cased, see explanation here: // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661 - return StrCat(number + 1, " - 1"); + return y_absl::StrCat(number + 1, " - 1"); } else { - return StrCat(number); + return y_absl::StrCat(number); } } @@ -727,13 +770,13 @@ static TProtoStringType Int64ToString(arc_i64 number) { if (number == std::numeric_limits<arc_i64>::min()) { // This needs to be special-cased, see explanation here: // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661 - return StrCat("arc_i64{", number + 1, "} - 1"); + return y_absl::StrCat("::arc_i64{", number + 1, "} - 1"); } - return StrCat("arc_i64{", number, "}"); + return y_absl::StrCat("::arc_i64{", number, "}"); } static TProtoStringType UInt64ToString(arc_ui64 number) { - return StrCat("arc_ui64{", number, "u}"); + return y_absl::StrCat("::arc_ui64{", number, "u}"); } TProtoStringType DefaultValue(const FieldDescriptor* field) { @@ -745,7 +788,7 @@ TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* fie case FieldDescriptor::CPPTYPE_INT32: return Int32ToString(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: - return StrCat(field->default_value_uint32()) + "u"; + return y_absl::StrCat(field->default_value_uint32(), "u"); case FieldDescriptor::CPPTYPE_INT64: return Int64ToString(field->default_value_int64()); case FieldDescriptor::CPPTYPE_UINT64: @@ -759,7 +802,7 @@ TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* fie } else if (value != value) { return "std::numeric_limits<double>::quiet_NaN()"; } else { - return SimpleDtoa(value); + return io::SimpleDtoa(value); } } case FieldDescriptor::CPPTYPE_FLOAT: { @@ -771,7 +814,7 @@ TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* fie } else if (value != value) { return "std::numeric_limits<float>::quiet_NaN()"; } else { - TProtoStringType float_value = SimpleFtoa(value); + TProtoStringType float_value = io::SimpleFtoa(value); // If floating point value contains a period (.) or an exponent // (either E or e), then append suffix 'f' to make it a float // literal. @@ -786,73 +829,73 @@ TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* fie case FieldDescriptor::CPPTYPE_ENUM: // Lazy: Generate a static_cast because we don't have a helper function // that constructs the full name of an enum value. - return strings::Substitute( + return y_absl::Substitute( "static_cast< $0 >($1)", ClassName(field->enum_type(), true), Int32ToString(field->default_value_enum()->number())); case FieldDescriptor::CPPTYPE_STRING: - return "\"" + - EscapeTrigraphs(CEscape(field->default_value_string())) + - "\""; + return y_absl::StrCat( + "\"", EscapeTrigraphs(y_absl::CEscape(field->default_value_string())), + "\""); case FieldDescriptor::CPPTYPE_MESSAGE: - return "*" + FieldMessageTypeName(field, options) + - "::internal_default_instance()"; + return y_absl::StrCat("*", FieldMessageTypeName(field, options), + "::internal_default_instance()"); } // Can't actually get here; make compiler happy. (We could add a default // case above but then we wouldn't get the nice compiler warning when a // new type is added.) - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return ""; } // Convert a file name into a valid identifier. -TProtoStringType FilenameIdentifier(const TProtoStringType& filename) { +TProtoStringType FilenameIdentifier(y_absl::string_view filename) { TProtoStringType result; for (int i = 0; i < filename.size(); i++) { - if (ascii_isalnum(filename[i])) { + if (y_absl::ascii_isalnum(filename[i])) { result.push_back(filename[i]); } else { // Not alphanumeric. To avoid any possibility of name conflicts we // use the hex code for the character. - StrAppend(&result, "_", - strings::Hex(static_cast<uint8_t>(filename[i]))); + y_absl::StrAppend(&result, "_", + y_absl::Hex(static_cast<uint8_t>(filename[i]))); } } return result; } -TProtoStringType UniqueName(const TProtoStringType& name, const TProtoStringType& filename, +TProtoStringType UniqueName(y_absl::string_view name, y_absl::string_view filename, const Options& options) { - return name + "_" + FilenameIdentifier(filename); + return y_absl::StrCat(name, "_", FilenameIdentifier(filename)); } // Return the qualified C++ name for a file level symbol. TProtoStringType QualifiedFileLevelSymbol(const FileDescriptor* file, - const TProtoStringType& name, + y_absl::string_view name, const Options& options) { if (file->package().empty()) { - return StrCat("::", name); + return y_absl::StrCat("::", name); } - return StrCat(Namespace(file, options), "::", name); + return y_absl::StrCat(Namespace(file, options), "::", name); } // Escape C++ trigraphs by escaping question marks to \? -TProtoStringType EscapeTrigraphs(const TProtoStringType& to_escape) { - return StringReplace(to_escape, "?", "\\?", true); +TProtoStringType EscapeTrigraphs(y_absl::string_view to_escape) { + return y_absl::StrReplaceAll(to_escape, {{"?", "\\?"}}); } // Escaped function name to eliminate naming conflict. TProtoStringType SafeFunctionName(const Descriptor* descriptor, const FieldDescriptor* field, - const TProtoStringType& prefix) { + y_absl::string_view prefix) { // Do not use FieldName() since it will escape keywords. TProtoStringType name = field->name(); - LowerString(&name); - TProtoStringType function_name = prefix + name; + y_absl::AsciiStrToLower(&name); + TProtoStringType function_name = y_absl::StrCat(prefix, name); if (descriptor->FindFieldByName(function_name)) { // Single underscore will also make it conflicting with the private data // member. We use double underscore to escape function names. function_name.append("__"); - } else if (kKeywords.count(name) > 0) { + } else if (Keywords().count(name) > 0) { // If the field name is a keyword, we append the underscore back to keep it // consistent with other function names. function_name.append("_"); @@ -860,6 +903,9 @@ TProtoStringType SafeFunctionName(const Descriptor* descriptor, return function_name; } +bool IsProfileDriven(const Options& options) { + return options.access_info_map != nullptr; +} bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options) { (void)descriptor; @@ -907,6 +953,13 @@ bool HasLazyFields(const FileDescriptor* file, const Options& options, bool ShouldSplit(const Descriptor*, const Options&) { return false; } bool ShouldSplit(const FieldDescriptor*, const Options&) { return false; } +bool ShouldForceAllocationOnConstruction(const Descriptor* desc, + const Options& options) { + (void)desc; + (void)options; + 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) { @@ -1045,7 +1098,7 @@ bool ShouldVerify(const FileDescriptor* file, const Options& options, bool IsUtf8String(const FieldDescriptor* field) { return IsProto3(field->file()) && - field->type() == FieldDescriptor::TYPE_STRING; + field->type() == FieldDescriptor::TYPE_STRING; } VerifySimpleType ShouldVerifySimple(const Descriptor* descriptor) { @@ -1069,13 +1122,13 @@ bool IsStringOrMessage(const FieldDescriptor* field) { return true; } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return false; } FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field, const Options& options) { - GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); + Y_ABSL_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); if (options.opensource_runtime) { // Open-source protobuf release only supports STRING ctype. return FieldOptions::STRING; @@ -1095,7 +1148,7 @@ bool IsAnyMessage(const Descriptor* descriptor, const Options& options) { } bool IsWellKnownMessage(const FileDescriptor* file) { - static const std::unordered_set<TProtoStringType> well_known_files{ + static const auto* well_known_files = new y_absl::flat_hash_set<TProtoStringType>{ "google/protobuf/any.proto", "google/protobuf/api.proto", "google/protobuf/compiler/plugin.proto", @@ -1109,94 +1162,127 @@ bool IsWellKnownMessage(const FileDescriptor* file) { "google/protobuf/type.proto", "google/protobuf/wrappers.proto", }; - return well_known_files.find(file->name()) != well_known_files.end(); -} - -static bool FieldEnforceUtf8(const FieldDescriptor* field, - const Options& options) { - return true; + return well_known_files->find(file->name()) != well_known_files->end(); } -static bool FileUtf8Verification(const FileDescriptor* file, - const Options& options) { - return true; -} +void NamespaceOpener::ChangeTo(y_absl::string_view name) { + std::vector<TProtoStringType> new_stack = + y_absl::StrSplit(name, "::", y_absl::SkipEmpty()); + size_t len = std::min(name_stack_.size(), new_stack.size()); + size_t common_idx = 0; + while (common_idx < len) { + if (name_stack_[common_idx] != new_stack[common_idx]) { + break; + } + ++common_idx; + } -// Which level of UTF-8 enforcemant is placed on this file. -Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, - const Options& options) { - if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 && - FieldEnforceUtf8(field, options)) { - return Utf8CheckMode::kStrict; - } else if (GetOptimizeFor(field->file(), options) != - FileOptions::LITE_RUNTIME && - FileUtf8Verification(field->file(), options)) { - return Utf8CheckMode::kVerify; - } else { - return Utf8CheckMode::kNone; + for (size_t i = name_stack_.size(); i > common_idx; i--) { + const auto& ns = name_stack_[i - 1]; + if (ns == "PROTOBUF_NAMESPACE_ID") { + p_->Emit(R"cc( + PROTOBUF_NAMESPACE_CLOSE + )cc"); + } else { + p_->Emit({{"ns", ns}}, R"( + } // namespace $ns$ + )"); + } + } + for (size_t i = common_idx; i < new_stack.size(); ++i) { + const auto& ns = new_stack[i]; + if (ns == "PROTOBUF_NAMESPACE_ID") { + p_->Emit(R"cc( + PROTOBUF_NAMESPACE_OPEN + )cc"); + } else { + p_->Emit({{"ns", ns}}, R"( + namespace $ns$ { + )"); + } } + + name_stack_ = std::move(new_stack); } -static void GenerateUtf8CheckCode(const FieldDescriptor* field, +static void GenerateUtf8CheckCode(io::Printer* p, const FieldDescriptor* field, const Options& options, bool for_parse, - const char* parameters, - const char* strict_function, - const char* verify_function, - const Formatter& format) { - switch (GetUtf8CheckMode(field, options)) { - case Utf8CheckMode::kStrict: { + y_absl::string_view params, + y_absl::string_view strict_function, + y_absl::string_view verify_function) { + if (field->type() != FieldDescriptor::TYPE_STRING) return; + + auto v = p->WithVars({ + {"params", params}, + {"Strict", strict_function}, + {"Verify", verify_function}, + }); + + bool is_lite = + GetOptimizeFor(field->file(), options) == FileOptions::LITE_RUNTIME; + switch (internal::cpp::GetUtf8CheckMode(field, is_lite)) { + case internal::cpp::Utf8CheckMode::kStrict: if (for_parse) { - format("DO_("); - } - format("::$proto_ns$::internal::WireFormatLite::$1$(\n", strict_function); - format.Indent(); - format(parameters); - if (for_parse) { - format("::$proto_ns$::internal::WireFormatLite::PARSE,\n"); + p->Emit(R"cc( + DO_($pbi$::WireFormatLite::$Strict$( + $params$ $pbi$::WireFormatLite::PARSE, "$pkg.Msg.field$")); + )cc"); } else { - format("::$proto_ns$::internal::WireFormatLite::SERIALIZE,\n"); + p->Emit(R"cc( + $pbi$::WireFormatLite::$Strict$( + $params$ $pbi$::WireFormatLite::SERIALIZE, "$pkg.Msg.field$"); + )cc"); } - format("\"$1$\")", field->full_name()); - if (for_parse) { - format(")"); - } - format(";\n"); - format.Outdent(); break; - } - case Utf8CheckMode::kVerify: { - format("::$proto_ns$::internal::WireFormat::$1$(\n", verify_function); - format.Indent(); - format(parameters); + + case internal::cpp::Utf8CheckMode::kVerify: if (for_parse) { - format("::$proto_ns$::internal::WireFormat::PARSE,\n"); + p->Emit(R"cc( + $pbi$::WireFormat::$Verify$($params$ $pbi$::WireFormat::PARSE, + "$pkg.Msg.field$"); + )cc"); } else { - format("::$proto_ns$::internal::WireFormat::SERIALIZE,\n"); + p->Emit(R"cc( + $pbi$::WireFormat::$Verify$($params$ $pbi$::WireFormat::SERIALIZE, + "$pkg.Msg.field$"); + )cc"); } - format("\"$1$\");\n", field->full_name()); - format.Outdent(); break; - } - case Utf8CheckMode::kNone: + + case internal::cpp::Utf8CheckMode::kNone: break; } } void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, const Options& options, bool for_parse, - const char* parameters, + y_absl::string_view parameters, const Formatter& format) { - GenerateUtf8CheckCode(field, options, for_parse, parameters, - "VerifyUtf8String", "VerifyUTF8StringNamedField", - format); + GenerateUtf8CheckCode(format.printer(), field, options, for_parse, parameters, + "VerifyUtf8String", "VerifyUTF8StringNamedField"); } void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, const Options& options, bool for_parse, - const char* parameters, + y_absl::string_view parameters, const Formatter& format) { - GenerateUtf8CheckCode(field, options, for_parse, parameters, "VerifyUtf8Cord", - "VerifyUTF8CordNamedField", format); + GenerateUtf8CheckCode(format.printer(), field, options, for_parse, parameters, + "VerifyUtf8Cord", "VerifyUTF8CordNamedField"); +} + +void GenerateUtf8CheckCodeForString(io::Printer* p, + const FieldDescriptor* field, + const Options& options, bool for_parse, + y_absl::string_view parameters) { + GenerateUtf8CheckCode(p, field, options, for_parse, parameters, + "VerifyUtf8String", "VerifyUTF8StringNamedField"); +} + +void GenerateUtf8CheckCodeForCord(io::Printer* p, const FieldDescriptor* field, + const Options& options, bool for_parse, + y_absl::string_view parameters) { + GenerateUtf8CheckCode(p, field, options, for_parse, parameters, + "VerifyUtf8Cord", "VerifyUTF8CordNamedField"); } void FlattenMessagesInFile(const FileDescriptor* file, @@ -1243,7 +1329,9 @@ bool IsImplicitWeakField(const FieldDescriptor* field, const Options& options, } MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) { - if (analysis_cache_.count(scc)) return analysis_cache_[scc]; + auto it = analysis_cache_.find(scc); + if (it != analysis_cache_.end()) return it->second; + MessageAnalysis result; if (UsingImplicitWeakFields(scc->GetFile(), options_)) { result.contains_weak = true; @@ -1298,7 +1386,7 @@ MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) { // in the graph, the graph should be a DAG. Hence we shouldn't need to mark // nodes visited as we can never return to them. By inserting them here // we will go in an infinite loop if the SCC is not correct. - return analysis_cache_[scc] = result; + return analysis_cache_[scc] = std::move(result); } void ListAllFields(const Descriptor* d, @@ -1341,23 +1429,26 @@ void ListAllTypesForServices(const FileDescriptor* fd, } } -bool GetBootstrapBasename(const Options& options, const TProtoStringType& basename, +bool GetBootstrapBasename(const Options& options, y_absl::string_view basename, TProtoStringType* bootstrap_basename) { if (options.opensource_runtime) { return false; } - std::unordered_map<TProtoStringType, TProtoStringType> bootstrap_mapping{ - {"net/proto2/proto/descriptor", - "third_party/protobuf/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; + static const auto* bootstrap_mapping = + // TODO(b/242858704) Replace these with string_view once we remove + // StringPiece. + new y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>{ + {"net/proto2/proto/descriptor", + "third_party/protobuf/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 = TProtoStringType(basename); return false; } else { *bootstrap_basename = iter->second; @@ -1381,70 +1472,64 @@ bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context, // Adjust basename, but don't abort code generation. *basename = bootstrap_basename; return false; - } else { - const TProtoStringType& 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; } + + auto pb_h = y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(*basename, ".pb.h"))); + + io::Printer p(pb_h.get()); + p.Emit( + { + {"fwd_to", bootstrap_basename}, + {"file", FilenameIdentifier(*basename)}, + {"fwd_to_suffix", options.opensource_runtime ? "pb" : "proto"}, + {"swig_evil", + [&] { + if (options.opensource_runtime) { + return; + } + p.Emit(R"( + #ifdef SWIG + %include "$fwd_to$.pb.h" + #endif // SWIG + )"); + }}, + }, + R"( + #ifndef PROTOBUF_INCLUDED_$file$_FORWARD_PB_H + #define PROTOBUF_INCLUDED_$file$_FORWARD_PB_H + #include "$fwd_to$.$fwd_to_suffix$.h" // IWYU pragma: export + #endif // PROTOBUF_INCLUDED_$file$_FORWARD_PB_H + $swig_evil$; + )"); + + auto proto_h = y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(*basename, ".proto.h"))); + io::Printer(proto_h.get()) + .Emit( + { + {"fwd_to", bootstrap_basename}, + {"file", FilenameIdentifier(*basename)}, + }, + R"( + #ifndef PROTOBUF_INCLUDED_$file$_FORWARD_PROTO_H + #define PROTOBUF_INCLUDED_$file$_FORWARD_PROTO_H + #include "$fwd_to$.proto.h" // IWYU pragma: export + #endif // PROTOBUF_INCLUDED_$file$_FORWARD_PROTO_H + )"); + + auto pb_cc = y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(*basename, ".pb.cc"))); + io::Printer(pb_cc.get()).PrintRaw("\n"); + + (void)y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(*basename, ".pb.h.meta"))); + + (void)y_absl::WrapUnique( + generator_context->Open(y_absl::StrCat(*basename, ".proto.h.meta"))); + + // Abort code generation. + return true; } static bool HasExtensionFromFile(const Message& msg, const FileDescriptor* file, @@ -1492,9 +1577,18 @@ static bool HasExtensionFromFile(const Message& msg, const FileDescriptor* file, static bool HasBootstrapProblem(const FileDescriptor* file, const Options& options, bool* has_opt_codesize_extension) { - static auto& cache = *new std::unordered_map<const FileDescriptor*, bool>; - auto it = cache.find(file); - if (it != cache.end()) return it->second; + struct BoostrapGlobals { + y_absl::Mutex mutex; + y_absl::flat_hash_set<const FileDescriptor*> cached Y_ABSL_GUARDED_BY(mutex); + y_absl::flat_hash_set<const FileDescriptor*> non_cached + Y_ABSL_GUARDED_BY(mutex); + }; + static auto& bootstrap_cache = *new BoostrapGlobals(); + + y_absl::MutexLock lock(&bootstrap_cache.mutex); + if (bootstrap_cache.cached.contains(file)) return true; + if (bootstrap_cache.non_cached.contains(file)) return false; + // In order to build the data structures for the reflective parse, it needs // to parse the serialized descriptor describing all the messages defined in // this file. Obviously this presents a bootstrap problem for descriptor @@ -1530,9 +1624,13 @@ static bool HasBootstrapProblem(const FileDescriptor* file, Message* fd_proto = factory.GetPrototype(fd_proto_descriptor)->New(); fd_proto->ParseFromString(linkedin_fd_proto.SerializeAsString()); - bool& res = cache[file]; - res = HasExtensionFromFile(*fd_proto, file, options, - has_opt_codesize_extension); + bool res = HasExtensionFromFile(*fd_proto, file, options, + has_opt_codesize_extension); + if (res) { + bootstrap_cache.cached.insert(file); + } else { + bootstrap_cache.non_cached.insert(file); + } delete fd_proto; return res; } @@ -1557,38 +1655,21 @@ FileOptions_OptimizeMode GetOptimizeFor(const FileDescriptor* file, case EnforceOptimizeMode::kNoEnforcement: if (file->options().optimize_for() == FileOptions::CODE_SIZE) { if (HasBootstrapProblem(file, options, has_opt_codesize_extension)) { - GOOGLE_LOG(WARNING) << "Proto states optimize_for = CODE_SIZE, but we " - "cannot honor that because it contains custom option " - "extensions defined in the same proto."; + Y_ABSL_LOG(WARNING) + << "Proto states optimize_for = CODE_SIZE, but we " + "cannot honor that because it contains custom option " + "extensions defined in the same proto."; return FileOptions::SPEED; } } return file->options().optimize_for(); } - GOOGLE_LOG(FATAL) << "Unknown optimization enforcement requested."; + Y_ABSL_LOG(FATAL) << "Unknown optimization enforcement requested."; // The phony return below serves to silence a warning from GCC 8. return FileOptions::SPEED; } -inline bool IsMessageOwnedArenaEligible(const Descriptor* desc, - const Options& options) { - return GetOptimizeFor(desc->file(), options) != FileOptions::LITE_RUNTIME && - !options.bootstrap && !options.opensource_runtime && - AllocExpected(desc); -} - -bool EnableMessageOwnedArena(const Descriptor* desc, const Options& options) { - (void)desc; - (void)options; - return false; -} - -bool EnableMessageOwnedArenaTrial(const Descriptor* desc, - const Options& options) { - return false; -} - bool HasMessageFieldOrExtension(const Descriptor* desc) { if (desc->extension_range_count() > 0) return true; for (const auto* f : FieldRange(desc)) { @@ -1597,6 +1678,21 @@ bool HasMessageFieldOrExtension(const Descriptor* desc) { return false; } +std::vector<io::Printer::Sub> AnnotatedAccessors( + const FieldDescriptor* field, y_absl::Span<const y_absl::string_view> prefixes, + y_absl::optional<google::protobuf::io::AnnotationCollector::Semantic> semantic) { + auto field_name = FieldName(field); + + std::vector<io::Printer::Sub> vars; + for (auto prefix : prefixes) { + vars.push_back(io::Printer::Sub(y_absl::StrCat(prefix, "name"), + y_absl::StrCat(prefix, field_name)) + .AnnotatedAs({field, semantic})); + } + + return vars; +} + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.h index 690a577591e..437c178c60c 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.h @@ -38,21 +38,27 @@ #include <algorithm> #include <cstdint> #include <iterator> -#include <map> #include <string> - -#include <google/protobuf/compiler/scc.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/cpp/names.h> -#include <google/protobuf/compiler/cpp/options.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 <tuple> + +#include "google/protobuf/compiler/scc.h" +#include "google/protobuf/compiler/code_generator.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/types/optional.h" +#include "google/protobuf/compiler/cpp/names.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/port.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/io/printer.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -84,19 +90,22 @@ inline TProtoStringType DeprecatedAttribute(const Options& /* options */, extern const char kThickSeparator[]; extern const char kThinSeparator[]; -void SetCommonVars(const Options& options, - std::map<TProtoStringType, TProtoStringType>* variables); +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> MessageVars( + const Descriptor* desc); // Variables to access message data from the message scope. void SetCommonMessageDataVariables( const Descriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables); + +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> UnknownFieldsVars( + const Descriptor* desc, const Options& opts); -void SetUnknownFieldsVariable(const Descriptor* descriptor, - const Options& options, - std::map<TProtoStringType, TProtoStringType>* variables); +void SetUnknownFieldsVariable( + const Descriptor* descriptor, const Options& options, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables); -bool GetBootstrapBasename(const Options& options, const TProtoStringType& basename, +bool GetBootstrapBasename(const Options& options, y_absl::string_view basename, TProtoStringType* bootstrap_basename); bool MaybeBootstrap(const Options& options, GeneratorContext* generator_context, bool bootstrap_flag, TProtoStringType* basename); @@ -110,18 +119,31 @@ TProtoStringType Namespace(const FileDescriptor* d, const Options& options); TProtoStringType Namespace(const Descriptor* d, const Options& options); TProtoStringType Namespace(const FieldDescriptor* d, const Options& options); TProtoStringType Namespace(const EnumDescriptor* d, const Options& options); +PROTOC_EXPORT TProtoStringType Namespace(const FileDescriptor* d); +PROTOC_EXPORT TProtoStringType Namespace(const Descriptor* d); +PROTOC_EXPORT TProtoStringType Namespace(const FieldDescriptor* d); +PROTOC_EXPORT TProtoStringType Namespace(const EnumDescriptor* d); + +class MessageSCCAnalyzer; +// Returns true if it's safe to init "field" to zero. +bool CanInitializeByZeroing(const FieldDescriptor* field, + const Options& options, + MessageSCCAnalyzer* scc_analyzer); // Returns true if it's safe to reset "field" to zero. -bool CanInitializeByZeroing(const FieldDescriptor* field); +bool CanClearByZeroing(const FieldDescriptor* field); +// Determines if swap can be implemented via memcpy. +bool HasTrivialSwap(const FieldDescriptor* field, const Options& options, + MessageSCCAnalyzer* scc_analyzer); -TProtoStringType ClassName(const Descriptor* descriptor); -TProtoStringType ClassName(const EnumDescriptor* enum_descriptor); +PROTOC_EXPORT TProtoStringType ClassName(const Descriptor* descriptor); +PROTOC_EXPORT TProtoStringType ClassName(const EnumDescriptor* enum_descriptor); TProtoStringType QualifiedClassName(const Descriptor* d, const Options& options); TProtoStringType QualifiedClassName(const EnumDescriptor* d, const Options& options); -TProtoStringType QualifiedClassName(const Descriptor* d); -TProtoStringType QualifiedClassName(const EnumDescriptor* d); +PROTOC_EXPORT TProtoStringType QualifiedClassName(const Descriptor* d); +PROTOC_EXPORT TProtoStringType QualifiedClassName(const EnumDescriptor* d); // DEPRECATED just use ClassName or QualifiedClassName, a boolean is very // unreadable at the callsite. @@ -187,13 +209,13 @@ TProtoStringType SuperClassName(const Descriptor* descriptor, const Options& options); // Adds an underscore if necessary to prevent conflicting with a keyword. -TProtoStringType ResolveKeyword(const TProtoStringType& name); +TProtoStringType ResolveKeyword(y_absl::string_view name); // 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(). -TProtoStringType FieldName(const FieldDescriptor* field); +PROTOC_EXPORT TProtoStringType FieldName(const FieldDescriptor* field); // Returns the (unqualified) private member name for this field in C++ code. TProtoStringType FieldMemberName(const FieldDescriptor* field, bool split); @@ -220,7 +242,7 @@ inline const Descriptor* FieldScope(const FieldDescriptor* field) { TProtoStringType FieldMessageTypeName(const FieldDescriptor* field, const Options& options); -// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.). +// Get the C++ type name for a primitive type (e.g. "double", "::int32", etc.). const char* PrimitiveTypeName(FieldDescriptor::CppType type); TProtoStringType PrimitiveTypeName(const Options& options, FieldDescriptor::CppType type); @@ -239,25 +261,25 @@ TProtoStringType DefaultValue(const Options& options, const FieldDescriptor* fie TProtoStringType DefaultValue(const FieldDescriptor* field); // Convert a file name into a valid identifier. -TProtoStringType FilenameIdentifier(const TProtoStringType& filename); +TProtoStringType FilenameIdentifier(y_absl::string_view filename); // For each .proto file generates a unique name. To prevent collisions of // symbols in the global namespace -TProtoStringType UniqueName(const TProtoStringType& name, const TProtoStringType& filename, +TProtoStringType UniqueName(y_absl::string_view name, y_absl::string_view filename, const Options& options); -inline TProtoStringType UniqueName(const TProtoStringType& name, const FileDescriptor* d, +inline TProtoStringType UniqueName(y_absl::string_view name, const FileDescriptor* d, const Options& options) { return UniqueName(name, d->name(), options); } -inline TProtoStringType UniqueName(const TProtoStringType& name, const Descriptor* d, +inline TProtoStringType UniqueName(y_absl::string_view name, const Descriptor* d, const Options& options) { return UniqueName(name, d->file(), options); } -inline TProtoStringType UniqueName(const TProtoStringType& name, const EnumDescriptor* d, +inline TProtoStringType UniqueName(y_absl::string_view name, const EnumDescriptor* d, const Options& options) { return UniqueName(name, d->file(), options); } -inline TProtoStringType UniqueName(const TProtoStringType& name, +inline TProtoStringType UniqueName(y_absl::string_view name, const ServiceDescriptor* d, const Options& options) { return UniqueName(name, d->file(), options); @@ -270,38 +292,36 @@ inline Options InternalRuntimeOptions() { options.opensource_runtime = false; return options; } -inline TProtoStringType UniqueName(const TProtoStringType& name, - const TProtoStringType& filename) { +inline TProtoStringType UniqueName(y_absl::string_view name, + y_absl::string_view filename) { return UniqueName(name, filename, InternalRuntimeOptions()); } -inline TProtoStringType UniqueName(const TProtoStringType& name, - const FileDescriptor* d) { +inline TProtoStringType UniqueName(y_absl::string_view name, const FileDescriptor* d) { return UniqueName(name, d->name(), InternalRuntimeOptions()); } -inline TProtoStringType UniqueName(const TProtoStringType& name, const Descriptor* d) { +inline TProtoStringType UniqueName(y_absl::string_view name, const Descriptor* d) { return UniqueName(name, d->file(), InternalRuntimeOptions()); } -inline TProtoStringType UniqueName(const TProtoStringType& name, - const EnumDescriptor* d) { +inline TProtoStringType UniqueName(y_absl::string_view name, const EnumDescriptor* d) { return UniqueName(name, d->file(), InternalRuntimeOptions()); } -inline TProtoStringType UniqueName(const TProtoStringType& name, +inline TProtoStringType UniqueName(y_absl::string_view name, const ServiceDescriptor* d) { return UniqueName(name, d->file(), InternalRuntimeOptions()); } // Return the qualified C++ name for a file level symbol. TProtoStringType QualifiedFileLevelSymbol(const FileDescriptor* file, - const TProtoStringType& name, + y_absl::string_view name, const Options& options); // Escape C++ trigraphs by escaping question marks to \? -TProtoStringType EscapeTrigraphs(const TProtoStringType& to_escape); +TProtoStringType EscapeTrigraphs(y_absl::string_view to_escape); // Escaped function name to eliminate naming conflict. TProtoStringType SafeFunctionName(const Descriptor* descriptor, const FieldDescriptor* field, - const TProtoStringType& prefix); + y_absl::string_view prefix); // Returns true if generated messages have public unknown fields accessors inline bool PublicUnknownFieldsAccessors(const Descriptor* message) { @@ -321,12 +341,14 @@ inline bool UseUnknownFieldSet(const FileDescriptor* file, inline bool IsWeak(const FieldDescriptor* field, const Options& options) { if (field->options().weak()) { - GOOGLE_CHECK(!options.opensource_runtime); + Y_ABSL_CHECK(!options.opensource_runtime); return true; } return false; } +bool IsProfileDriven(const Options& options); + bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options); // For a string field, returns the effective ctype. If the actual ctype is @@ -350,8 +372,6 @@ inline bool IsStringPiece(const FieldDescriptor* field, EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE; } -class MessageSCCAnalyzer; - // Does the given FileDescriptor use lazy fields? bool HasLazyFields(const FileDescriptor* file, const Options& options, MessageSCCAnalyzer* scc_analyzer); @@ -377,17 +397,16 @@ bool ShouldSplit(const Descriptor* desc, const Options& options); // Is the given field being split out? bool ShouldSplit(const FieldDescriptor* field, const Options& options); +// Should we generate code that force creating an allocation in the constructor +// of the given message? +bool ShouldForceAllocationOnConstruction(const Descriptor* desc, + const Options& options); + inline bool IsFieldUsed(const FieldDescriptor* /* field */, const Options& /* options */) { return true; } -// Returns true if "field" is stripped. -inline bool IsFieldStripped(const FieldDescriptor* /*field*/, - const Options& /*options*/) { - return false; -} - // Does the file contain any definitions that need extension_set.h? bool HasExtensionsOrExtendableMessage(const FileDescriptor* file); @@ -448,42 +467,20 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) { // Returns true if the field's CPPTYPE is string or message. bool IsStringOrMessage(const FieldDescriptor* field); -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, +TProtoStringType UnderscoresToCamelCase(y_absl::string_view input, bool cap_next_letter); inline bool IsProto3(const FileDescriptor* file) { return file->syntax() == FileDescriptor::SYNTAX_PROTO3; } -inline bool HasHasbit(const FieldDescriptor* field) { - // This predicate includes proto3 message fields only if they have "optional". - // Foo submsg1 = 1; // HasHasbit() == false - // optional Foo submsg2 = 2; // HasHasbit() == true - // This is slightly odd, as adding "optional" to a singular proto3 field does - // not change the semantics or API. However whenever any field in a message - // has a hasbit, it forces reflection to include hasbit offsets for *all* - // fields, even if almost all of them are set to -1 (no hasbit). So to avoid - // causing a sudden size regression for ~all proto3 messages, we give proto3 - // message fields a hasbit only if "optional" is present. If the user is - // explicitly writing "optional", it is likely they are writing it on - // primitive fields also. - return (field->has_optional_keyword() || field->is_required()) && - !field->options().weak(); -} - -// Returns true if 'enum' semantics are such that unknown values are preserved -// in the enum field itself, rather than going to the UnknownFieldSet. -inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) { - return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; -} - inline bool IsCrossFileMessage(const FieldDescriptor* field) { return field->type() == FieldDescriptor::TYPE_MESSAGE && field->message_type()->file() != field->file(); } inline TProtoStringType MakeDefaultName(const FieldDescriptor* field) { - return StrCat("_i_give_permission_to_break_this_code_default_", + return y_absl::StrCat("_i_give_permission_to_break_this_code_default_", FieldName(field), "_"); } @@ -498,11 +495,11 @@ inline TProtoStringType MakeDefaultName(const FieldDescriptor* field) { // exists at some nested level like: // internal_container_._i_give_permission_to_break_this_code_default_field_; inline TProtoStringType MakeDefaultFieldName(const FieldDescriptor* field) { - return StrCat("Impl_::", MakeDefaultName(field)); + return y_absl::StrCat("Impl_::", MakeDefaultName(field)); } inline TProtoStringType MakeVarintCachedSizeName(const FieldDescriptor* field) { - return StrCat("_", FieldName(field), "_cached_byte_size_"); + return y_absl::StrCat("_", FieldName(field), "_cached_byte_size_"); } // Semantically distinct from MakeVarintCachedSizeName in that it gives the C++ @@ -518,7 +515,7 @@ inline TProtoStringType MakeVarintCachedSizeName(const FieldDescriptor* field) { // internal_container_._field_cached_byte_size_; inline TProtoStringType MakeVarintCachedSizeFieldName(const FieldDescriptor* field, bool split) { - return StrCat("_impl_.", split ? "_split_->" : "", "_", + return y_absl::StrCat("_impl_.", split ? "_split_->" : "", "_", FieldName(field), "_cached_byte_size_"); } @@ -531,20 +528,34 @@ bool IsAnyMessage(const Descriptor* descriptor, const Options& options); bool IsWellKnownMessage(const FileDescriptor* descriptor); -inline TProtoStringType IncludeGuard(const FileDescriptor* file, bool pb_h, - bool deps, +enum class GeneratedFileType : int { kPbH, kProtoH, kProtoStaticReflectionH }; + +inline TProtoStringType IncludeGuard(const FileDescriptor* file, + GeneratedFileType file_type, const Options& options) { // If we are generating a .pb.h file and the proto_h option is enabled, then // the .pb.h gets an extra suffix. - TProtoStringType filename_identifier = FilenameIdentifier( - file->name() + (deps ? ".deps": "") + (pb_h && options.proto_h ? ".pb.h" : "")); + TProtoStringType extension; + switch (file_type) { + case GeneratedFileType::kPbH: + extension = ".pb.h"; + break; + case GeneratedFileType::kProtoH: + extension = ".proto.h"; + break; + case GeneratedFileType::kProtoStaticReflectionH: + extension = ".proto.static_reflection.h"; + } + TProtoStringType filename_identifier = + FilenameIdentifier(file->name() + extension); if (IsWellKnownMessage(file)) { // For well-known messages we need third_party/protobuf and net/proto2 to // have distinct include guards, because some source files include both and // both need to be defined (the third_party copies will be in the // google::protobuf_opensource namespace). - return MacroPrefix(options) + "_INCLUDED_" + filename_identifier; + return y_absl::StrCat(MacroPrefix(options), "_INCLUDED_", + filename_identifier); } else { // Ideally this case would use distinct include guards for opensource and // google3 protos also. (The behavior of "first #included wins" is not @@ -552,7 +563,7 @@ inline TProtoStringType IncludeGuard(const FileDescriptor* file, bool pb_h, // the identical include guards to avoid compile errors. // // We should clean this up so that this case can be removed. - return "GOOGLE_PROTOBUF_INCLUDED_" + filename_identifier; + return y_absl::StrCat("GOOGLE_PROTOBUF_INCLUDED_", filename_identifier); } } @@ -663,7 +674,7 @@ class PROTOC_EXPORT MessageSCCAnalyzer { }; SCCAnalyzer<DepsGenerator> analyzer_; Options options_; - std::map<const SCC*, MessageAnalysis> analysis_cache_; + y_absl::flat_hash_map<const SCC*, MessageAnalysis> analysis_cache_; }; void ListAllFields(const Descriptor* d, @@ -747,6 +758,8 @@ inline bool HasImplData(const Descriptor* desc, const Options& options) { return !HasSimpleBaseClass(desc, options); } +// DO NOT USE IN NEW CODE! Use io::Printer directly instead. See b/242326974. +// // 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 @@ -789,15 +802,15 @@ class PROTOC_EXPORT Formatter { public: explicit Formatter(io::Printer* printer) : printer_(printer) {} Formatter(io::Printer* printer, - const std::map<TProtoStringType, TProtoStringType>& vars) + const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& vars) : printer_(printer), vars_(vars) {} template <typename T> - void Set(const TProtoStringType& key, const T& value) { + void Set(y_absl::string_view key, const T& value) { vars_[key] = ToString(value); } - void AddMap(const std::map<TProtoStringType, TProtoStringType>& vars) { + void AddMap(const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& vars) { for (const auto& keyval : vars) vars_[keyval.first] = keyval.second; } @@ -839,31 +852,69 @@ class PROTOC_EXPORT Formatter { private: Formatter* format_; - std::map<TProtoStringType, TProtoStringType> vars_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars_; }; private: io::Printer* printer_; - std::map<TProtoStringType, TProtoStringType> vars_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars_; // Convenience overloads to accept different types as arguments. - static TProtoStringType ToString(const TProtoStringType& s) { return s; } + static TProtoStringType ToString(y_absl::string_view s) { return TProtoStringType(s); } template <typename I, typename = typename std::enable_if< std::is_integral<I>::value>::type> static TProtoStringType ToString(I x) { - return StrCat(x); + return y_absl::StrCat(x); + } + static TProtoStringType ToString(y_absl::Hex x) { return y_absl::StrCat(x); } + static TProtoStringType ToString(const FieldDescriptor* d) { + return Payload(d, GeneratedCodeInfo::Annotation::NONE); + } + static TProtoStringType ToString(const Descriptor* d) { + return Payload(d, GeneratedCodeInfo::Annotation::NONE); + } + static TProtoStringType ToString(const EnumDescriptor* d) { + return Payload(d, GeneratedCodeInfo::Annotation::NONE); } - static TProtoStringType ToString(strings::Hex x) { return StrCat(x); } - static TProtoStringType ToString(const FieldDescriptor* d) { return Payload(d); } - static TProtoStringType ToString(const Descriptor* d) { return Payload(d); } - static TProtoStringType ToString(const EnumDescriptor* d) { return Payload(d); } static TProtoStringType ToString(const EnumValueDescriptor* d) { - return Payload(d); + return Payload(d, GeneratedCodeInfo::Annotation::NONE); + } + static TProtoStringType ToString(const OneofDescriptor* d) { + return Payload(d, GeneratedCodeInfo::Annotation::NONE); + } + + static TProtoStringType ToString( + std::tuple<const FieldDescriptor*, + GeneratedCodeInfo::Annotation::Semantic> + p) { + return Payload(std::get<0>(p), std::get<1>(p)); + } + static TProtoStringType ToString( + std::tuple<const Descriptor*, GeneratedCodeInfo::Annotation::Semantic> + p) { + return Payload(std::get<0>(p), std::get<1>(p)); + } + static TProtoStringType ToString( + std::tuple<const EnumDescriptor*, GeneratedCodeInfo::Annotation::Semantic> + p) { + return Payload(std::get<0>(p), std::get<1>(p)); + } + static TProtoStringType ToString( + std::tuple<const EnumValueDescriptor*, + GeneratedCodeInfo::Annotation::Semantic> + p) { + return Payload(std::get<0>(p), std::get<1>(p)); + } + static TProtoStringType ToString( + std::tuple<const OneofDescriptor*, + GeneratedCodeInfo::Annotation::Semantic> + p) { + return Payload(std::get<0>(p), std::get<1>(p)); } - static TProtoStringType ToString(const OneofDescriptor* d) { return Payload(d); } template <typename Descriptor> - static TProtoStringType Payload(const Descriptor* descriptor) { + static TProtoStringType Payload(const Descriptor* descriptor, + GeneratedCodeInfo::Annotation::Semantic semantic) { std::vector<int> path; descriptor->GetLocationPath(&path); GeneratedCodeInfo::Annotation annotation; @@ -871,119 +922,71 @@ class PROTOC_EXPORT Formatter { annotation.add_path(index); } annotation.set_source_file(descriptor->file()->name()); + annotation.set_semantic(semantic); return annotation.SerializeAsString(); } }; -template <class T> -void PrintFieldComment(const Formatter& format, const T* field) { +template <typename T> +TProtoStringType FieldComment(const T* field) { // Print the field's (or oneof's) proto-syntax definition as a comment. // We don't want to print group bodies so we cut off after the first // line. DebugStringOptions options; options.elide_group_body = true; options.elide_oneof_body = true; - TProtoStringType def = field->DebugStringWithOptions(options); - format("// $1$\n", def.substr(0, def.find_first_of('\n'))); + + for (y_absl::string_view chunk : + y_absl::StrSplit(field->DebugStringWithOptions(options), '\n')) { + return TProtoStringType(chunk); + } + + return "<unknown>"; +} + +template <class T> +void PrintFieldComment(const Formatter& format, const T* field) { + format("// $1$\n", FieldComment(field)); } class PROTOC_EXPORT NamespaceOpener { public: - explicit NamespaceOpener(const Formatter& format) - : printer_(format.printer()) {} - NamespaceOpener(const TProtoStringType& name, const Formatter& format) + explicit NamespaceOpener(io::Printer* p) : p_(p) {} + explicit NamespaceOpener(const Formatter& format) : p_(format.printer()) {} + NamespaceOpener(y_absl::string_view name, const Formatter& format) : NamespaceOpener(format) { ChangeTo(name); } + NamespaceOpener(y_absl::string_view name, io::Printer* p) : NamespaceOpener(p) { + ChangeTo(name); + } ~NamespaceOpener() { ChangeTo(""); } - void ChangeTo(const TProtoStringType& name) { - std::vector<TProtoStringType> new_stack_ = - Split(name, "::", true); - size_t len = std::min(name_stack_.size(), new_stack_.size()); - size_t common_idx = 0; - while (common_idx < len) { - if (name_stack_[common_idx] != new_stack_[common_idx]) break; - common_idx++; - } - for (auto it = name_stack_.crbegin(); - it != name_stack_.crend() - common_idx; ++it) { - if (*it == "PROTOBUF_NAMESPACE_ID") { - printer_->Print("PROTOBUF_NAMESPACE_CLOSE\n"); - } else { - printer_->Print("} // namespace $ns$\n", "ns", *it); - } - } - name_stack_.swap(new_stack_); - for (size_t i = common_idx; i < name_stack_.size(); ++i) { - if (name_stack_[i] == "PROTOBUF_NAMESPACE_ID") { - printer_->Print("PROTOBUF_NAMESPACE_OPEN\n"); - } else { - printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]); - } - } - } + void ChangeTo(y_absl::string_view name); private: - io::Printer* printer_; + io::Printer* p_; std::vector<TProtoStringType> name_stack_; }; -enum class Utf8CheckMode { - kStrict = 0, // Parsing will fail if non UTF-8 data is in string fields. - kVerify = 1, // Only log an error but parsing will succeed. - kNone = 2, // No UTF-8 check. -}; - -Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, - const Options& options); - void GenerateUtf8CheckCodeForString(const FieldDescriptor* field, const Options& options, bool for_parse, - const char* parameters, + y_absl::string_view parameters, const Formatter& format); void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field, const Options& options, bool for_parse, - const char* parameters, + y_absl::string_view parameters, const Formatter& format); -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; -}; +void GenerateUtf8CheckCodeForString(io::Printer* p, + const FieldDescriptor* field, + const Options& options, bool for_parse, + y_absl::string_view parameters); -template <typename T> -FieldRangeImpl<T> FieldRange(const T* desc) { - return {desc}; -} +void GenerateUtf8CheckCodeForCord(io::Printer* p, const FieldDescriptor* field, + const Options& options, bool for_parse, + y_absl::string_view parameters); struct OneOfRangeImpl { struct Iterator { @@ -994,7 +997,7 @@ struct OneOfRangeImpl { value_type operator*() { return descriptor->oneof_decl(idx); } friend bool operator==(const Iterator& a, const Iterator& b) { - GOOGLE_DCHECK(a.descriptor == b.descriptor); + Y_ABSL_DCHECK(a.descriptor == b.descriptor); return a.idx == b.idx; } friend bool operator!=(const Iterator& a, const Iterator& b) { @@ -1020,12 +1023,8 @@ struct OneOfRangeImpl { inline OneOfRangeImpl OneOfRange(const Descriptor* desc) { return {desc}; } -PROTOC_EXPORT TProtoStringType StripProto(const TProtoStringType& filename); - -bool EnableMessageOwnedArena(const Descriptor* desc, const Options& options); - -bool EnableMessageOwnedArenaTrial(const Descriptor* desc, - const Options& options); +// Strips ".proto" or ".protodevel" from the end of a filename. +PROTOC_EXPORT TProtoStringType StripProto(y_absl::string_view filename); bool ShouldVerify(const Descriptor* descriptor, const Options& options, MessageSCCAnalyzer* scc_analyzer); @@ -1055,11 +1054,21 @@ bool IsUtf8String(const FieldDescriptor* field); bool HasMessageFieldOrExtension(const Descriptor* desc); +// Generates a vector of substitutions for use with Printer::WithVars that +// contains annotated accessor names for a particular field. +// +// Each substitution will be named `y_absl::StrCat(prefix, "name")`, and will +// be annotated with `field`. +std::vector<io::Printer::Sub> AnnotatedAccessors( + const FieldDescriptor* field, y_absl::Span<const y_absl::string_view> prefixes, + y_absl::optional<google::protobuf::io::AnnotationCollector::Semantic> semantic = + y_absl::nullopt); + } // namespace cpp } // namespace compiler } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.h deleted file mode 100644 index 678a128bd18..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.h +++ /dev/null @@ -1,83 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__ - -#include <map> -#include <string> - -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/compiler/cpp/message_field.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace cpp { - -class MapFieldGenerator : public FieldGenerator { - public: - MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options, - MessageSCCAnalyzer* scc_analyzer); - ~MapFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GeneratePrivateMembers(io::Printer* printer) const override; - void GenerateAccessorDeclarations(io::Printer* printer) const override; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateMergingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override {} - void GenerateCopyConstructorCode(io::Printer* printer) const override; - void GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const override; - void GenerateByteSize(io::Printer* printer) const override; - void GenerateIsInitialized(io::Printer* printer) const override; - void GenerateConstexprAggregateInitializer( - io::Printer* printer) const override; - void GenerateCopyAggregateInitializer(io::Printer* printer) const override; - void GenerateAggregateInitializer(io::Printer* printer) const override; - void GenerateDestructorCode(io::Printer* printer) const override; - void GenerateArenaDestructorCode(io::Printer* printer) const override; - ArenaDtorNeeds NeedsArenaDestructor() const override; - - private: - const bool has_required_fields_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); -}; - -} // namespace cpp -} // namespace compiler -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.cc index 77702a68dfc..a80ae0922af 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.cc @@ -32,49 +32,60 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/cpp/message.h> +#include "google/protobuf/compiler/cpp/message.h" #include <algorithm> +#include <array> +#include <cmath> #include <cstdint> #include <functional> -#include <map> +#include <limits> #include <memory> -#include <unordered_map> +#include <type_traits> #include <utility> #include <vector> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/generated_message_util.h> -#include <google/protobuf/map_entry_lite.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/stringprintf.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/cpp/enum.h> -#include <google/protobuf/compiler/cpp/extension.h> -#include <google/protobuf/compiler/cpp/field.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/compiler/cpp/padding_optimizer.h> -#include <google/protobuf/compiler/cpp/parse_function_generator.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/stubs/hash.h> +#include "google/protobuf/stubs/common.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/map_entry_lite.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/str_join.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/cpp/enum.h" +#include "google/protobuf/compiler/cpp/extension.h" +#include "google/protobuf/compiler/cpp/field.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/names.h" +#include "google/protobuf/compiler/cpp/padding_optimizer.h" +#include "google/protobuf/compiler/cpp/parse_function_generator.h" +#include "google/protobuf/compiler/cpp/tracker.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { namespace compiler { namespace cpp { - -using internal::WireFormat; -using internal::WireFormatLite; - namespace { +using ::google::protobuf::internal::WireFormat; +using ::google::protobuf::internal::WireFormatLite; +using ::google::protobuf::internal::cpp::HasHasbit; +using ::google::protobuf::internal::cpp::Utf8CheckMode; +using Sub = ::google::protobuf::io::Printer::Sub; static constexpr int kNoHasbit = -1; @@ -84,27 +95,28 @@ static constexpr int kNoHasbit = -1; // masks must be non-zero. TProtoStringType ConditionalToCheckBitmasks( const std::vector<arc_ui32>& masks, bool return_success = true, - StringPiece has_bits_var = "_impl_._has_bits_") { + y_absl::string_view has_bits_var = "_impl_._has_bits_") { std::vector<TProtoStringType> parts; for (int i = 0; i < masks.size(); i++) { if (masks[i] == 0) continue; - TProtoStringType m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); + TProtoStringType m = y_absl::StrCat("0x", y_absl::Hex(masks[i], y_absl::kZeroPad8)); // Each xor evaluates to 0 if the expected bits are present. parts.push_back( - StrCat("((", has_bits_var, "[", i, "] & ", m, ") ^ ", m, ")")); + y_absl::StrCat("((", has_bits_var, "[", i, "] & ", m, ") ^ ", m, ")")); } - GOOGLE_CHECK(!parts.empty()); + Y_ABSL_CHECK(!parts.empty()); // If we have multiple parts, each expected to be 0, then bitwise-or them. TProtoStringType result = parts.size() == 1 ? parts[0] - : StrCat("(", Join(parts, "\n | "), ")"); + : y_absl::StrCat("(", y_absl::StrJoin(parts, "\n | "), ")"); return result + (return_success ? " == 0" : " != 0"); } -void PrintPresenceCheck(const Formatter& format, const FieldDescriptor* field, - const std::vector<int>& has_bit_indices, - io::Printer* printer, int* cached_has_word_index) { +void PrintPresenceCheck(const FieldDescriptor* field, + const std::vector<int>& has_bit_indices, io::Printer* p, + int* cached_has_word_index) { + Formatter format(p); if (!field->options().weak()) { int has_bit_index = has_bit_indices[field->index()]; if (*cached_has_word_index != (has_bit_index / 32)) { @@ -112,7 +124,7 @@ void PrintPresenceCheck(const Formatter& format, const FieldDescriptor* field, format("cached_has_bits = $has_bits$[$1$];\n", *cached_has_word_index); } const TProtoStringType mask = - StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + y_absl::StrCat(y_absl::Hex(1u << (has_bit_index % 32), y_absl::kZeroPad8)); format("if (cached_has_bits & 0x$1$u) {\n", mask); } else { format("if (has_$1$()) {\n", FieldName(field)); @@ -166,32 +178,11 @@ bool IsPOD(const FieldDescriptor* field) { } } -// Helper for the code that emits the SharedCtor() and InternalSwap() methods. -// Anything that is a POD or a "normal" message (represented by a pointer) can -// be manipulated as raw bytes. -bool CanBeManipulatedAsRawBytes(const FieldDescriptor* field, - const Options& options, - MessageSCCAnalyzer* scc_analyzer) { - bool ret = CanInitializeByZeroing(field); - - // Non-repeated, non-lazy message fields are simply raw pointers, so we can - // swap them or 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() && !IsLazy(field, options, scc_analyzer) && - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); - return ret; -} - -bool StrContains(const TProtoStringType& haystack, const TProtoStringType& needle) { - return haystack.find(needle) != TProtoStringType::npos; -} - // Finds runs of fields for which `predicate` is true. // 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. -using RunMap = std::unordered_map<const FieldDescriptor*, size_t>; +using RunMap = y_absl::flat_hash_map<const FieldDescriptor*, size_t>; RunMap FindRuns(const std::vector<const FieldDescriptor*>& fields, const std::function<bool(const FieldDescriptor*)>& predicate) { RunMap runs; @@ -215,13 +206,14 @@ RunMap FindRuns(const std::vector<const FieldDescriptor*>& fields, // considered non-default (will be sent over the wire), for message types // without true field presence. Should only be called if // !HasHasbit(field). -bool EmitFieldNonDefaultCondition(io::Printer* printer, - const TProtoStringType& prefix, +bool EmitFieldNonDefaultCondition(io::Printer* p, const TProtoStringType& prefix, const FieldDescriptor* field) { - GOOGLE_CHECK(!HasHasbit(field)); - Formatter format(printer); - format.Set("prefix", prefix); - format.Set("name", FieldName(field)); + Y_ABSL_CHECK(!HasHasbit(field)); + Formatter format(p); + auto v = p->WithVars({{ + {"prefix", prefix}, + {"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()) { @@ -232,18 +224,18 @@ bool EmitFieldNonDefaultCondition(io::Printer* printer, format("if ($prefix$_internal_has_$name$()) {\n"); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT) { format( - "static_assert(sizeof(arc_ui32) == sizeof(float), \"Code assumes " - "arc_ui32 and float are the same size.\");\n" + "static_assert(sizeof(::arc_ui32) == sizeof(float), \"Code assumes " + "::arc_ui32 and float are the same size.\");\n" "float tmp_$name$ = $prefix$_internal_$name$();\n" - "arc_ui32 raw_$name$;\n" + "::arc_ui32 raw_$name$;\n" "memcpy(&raw_$name$, &tmp_$name$, sizeof(tmp_$name$));\n" "if (raw_$name$ != 0) {\n"); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) { format( - "static_assert(sizeof(arc_ui64) == sizeof(double), \"Code assumes " - "arc_ui64 and double are the same size.\");\n" + "static_assert(sizeof(::arc_ui64) == sizeof(double), \"Code assumes " + "::arc_ui64 and double are the same size.\");\n" "double tmp_$name$ = $prefix$_internal_$name$();\n" - "arc_ui64 raw_$name$;\n" + "::arc_ui64 raw_$name$;\n" "memcpy(&raw_$name$, &tmp_$name$, sizeof(tmp_$name$));\n" "if (raw_$name$ != 0) {\n"); } else { @@ -252,7 +244,7 @@ bool EmitFieldNonDefaultCondition(io::Printer* printer, format.Indent(); return true; } else if (field->real_containing_oneof()) { - format("if (_internal_has_$name$()) {\n"); + format("if ($has_field$) {\n"); format.Indent(); return true; } @@ -271,11 +263,17 @@ bool HasHasMethod(const FieldDescriptor* field) { field->has_optional_keyword() || field->real_containing_oneof(); } +bool HasInternalHasMethod(const FieldDescriptor* field) { + return !HasHasbit(field) && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE; +} + // Collects map entry message type information. -void CollectMapInfo(const Options& options, const Descriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables) { - GOOGLE_CHECK(IsMapEntryMessage(descriptor)); - std::map<TProtoStringType, TProtoStringType>& vars = *variables; +void CollectMapInfo( + const Options& options, const Descriptor* descriptor, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { + Y_ABSL_CHECK(IsMapEntryMessage(descriptor)); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& vars = *variables; const FieldDescriptor* key = descriptor->map_key(); const FieldDescriptor* val = descriptor->map_value(); vars["key_cpp"] = PrimitiveTypeName(options, key->cpp_type()); @@ -289,26 +287,10 @@ void CollectMapInfo(const Options& options, const Descriptor* descriptor, default: vars["val_cpp"] = PrimitiveTypeName(options, val->cpp_type()); } - vars["key_wire_type"] = - "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); - vars["val_wire_type"] = - "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); -} - -// Does the given field have a private (internal helper only) has_$name$() -// method? -bool HasPrivateHasMethod(const FieldDescriptor* field) { - // Only for oneofs in message types with no field presence. has_$name$(), - // based on the oneof case, is still useful internally for generated code. - return IsProto3(field->file()) && field->real_containing_oneof(); -} - -// TODO(ckennelly): Cull these exclusions if/when these protos do not have -// their methods overridden by subclasses. - -bool ShouldMarkClassAsFinal(const Descriptor* descriptor, - const Options& options) { - return false; + vars["key_wire_type"] = y_absl::StrCat( + "TYPE_", y_absl::AsciiStrToUpper(DeclaredTypeMethodName(key->type()))); + vars["val_wire_type"] = y_absl::StrCat( + "TYPE_", y_absl::AsciiStrToUpper(DeclaredTypeMethodName(val->type()))); } @@ -376,16 +358,16 @@ std::vector<std::vector<const FieldDescriptor*>> CollectFields( // masked to tell if any thing in "fields" is present. arc_ui32 GenChunkMask(const std::vector<const FieldDescriptor*>& fields, const std::vector<int>& has_bit_indices) { - GOOGLE_CHECK(!fields.empty()); + Y_ABSL_CHECK(!fields.empty()); int first_index_offset = has_bit_indices[fields.front()->index()] / 32; arc_ui32 chunk_mask = 0; 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); + Y_ABSL_CHECK_EQ(first_index_offset, index / 32); chunk_mask |= static_cast<arc_ui32>(1) << (index % 32); } - GOOGLE_CHECK_NE(0, chunk_mask); + Y_ABSL_CHECK_NE(0, chunk_mask); return chunk_mask; } @@ -411,7 +393,6 @@ class ColdChunkSkipper { has_bit_indices_(has_bit_indices), access_info_map_(options.access_info_map), cold_threshold_(cold_threshold) { - SetCommonVars(options, &variables_); SetCommonMessageDataVariables(descriptor, &variables_); } @@ -419,8 +400,8 @@ class ColdChunkSkipper { // prefix to _has_bits_ to allow MergeFrom to use "from._has_bits_". // Otherwise, it should be "". void OnStartChunk(int chunk, int cached_has_word_index, - const TProtoStringType& from, io::Printer* printer); - bool OnEndChunk(int chunk, io::Printer* printer); + const TProtoStringType& from, io::Printer* p); + bool OnEndChunk(int chunk, io::Printer* p); private: bool IsColdChunk(int chunk); @@ -433,7 +414,7 @@ class ColdChunkSkipper { const std::vector<int>& has_bit_indices_; const AccessInfoMap* access_info_map_; const double cold_threshold_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; int limit_chunk_ = -1; }; @@ -448,9 +429,8 @@ bool ColdChunkSkipper::IsColdChunk(int chunk) { void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index, - const TProtoStringType& from, - io::Printer* printer) { - Formatter format(printer, variables_); + const TProtoStringType& from, io::Printer* p) { + Formatter format(p); if (!access_info_map_) { return; } else if (chunk < limit_chunk_) { @@ -484,7 +464,7 @@ void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index, 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); + Y_ABSL_CHECK_EQ(this_word, hasbit_index / 32); mask |= 1 << (hasbit_index % 32); } } @@ -492,7 +472,7 @@ void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index, if (this_word != first_word) { format(" ||\n "); } - format.Set("mask", strings::Hex(mask, strings::ZERO_PAD_8)); + auto v = p->WithVars({{"mask", y_absl::Hex(mask, y_absl::kZeroPad8)}}); if (this_word == cached_has_word_index) { format("(cached_has_bits & 0x$mask$u) != 0"); } else { @@ -503,8 +483,8 @@ void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index, format.Indent(); } -bool ColdChunkSkipper::OnEndChunk(int chunk, io::Printer* printer) { - Formatter format(printer, variables_); +bool ColdChunkSkipper::OnEndChunk(int chunk, io::Printer* p) { + Formatter format(p); if (chunk != limit_chunk_ - 1) { return false; } @@ -513,86 +493,37 @@ bool ColdChunkSkipper::OnEndChunk(int chunk, io::Printer* printer) { return true; } -void MaySetAnnotationVariable(const Options& options, - StringPiece annotation_name, - StringPiece injector_template_prefix, - StringPiece injector_template_suffix, - std::map<TProtoStringType, TProtoStringType>* variables) { - if (options.field_listener_options.forbidden_field_listener_events.count( - TProtoStringType(annotation_name))) - return; - (*variables)[StrCat("annotate_", annotation_name)] = strings::Substitute( - StrCat(injector_template_prefix, injector_template_suffix), - (*variables)["classtype"]); +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> ClassVars( + const Descriptor* desc, Options opts) { + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars = MessageVars(desc); + + vars.emplace("pkg", Namespace(desc, opts)); + vars.emplace("Msg", ClassName(desc, false)); + vars.emplace("pkg::Msg", QualifiedClassName(desc, opts)); + vars.emplace("pkg.Msg", desc->full_name()); + + // Old-style names, to be removed once all usages are gone in this and other + // files. + vars.emplace("classname", ClassName(desc, false)); + vars.emplace("classtype", QualifiedClassName(desc, opts)); + vars.emplace("full_name", desc->full_name()); + vars.emplace("superclass", SuperClassName(desc, opts)); + + for (auto& pair : UnknownFieldsVars(desc, opts)) { + vars.emplace(pair); + } + + return vars; } -void GenerateExtensionAnnotations( - const Descriptor* descriptor, const Options& options, - std::map<TProtoStringType, TProtoStringType>* variables) { - const std::map<TProtoStringType, TProtoStringType> accessor_annotations_to_hooks = { - {"annotate_extension_has", "OnHasExtension"}, - {"annotate_extension_clear", "OnClearExtension"}, - {"annotate_extension_repeated_size", "OnExtensionSize"}, - {"annotate_extension_get", "OnGetExtension"}, - {"annotate_extension_mutable", "OnMutableExtension"}, - {"annotate_extension_set", "OnSetExtension"}, - {"annotate_extension_release", "OnReleaseExtension"}, - {"annotate_repeated_extension_get", "OnGetExtension"}, - {"annotate_repeated_extension_mutable", "OnMutableExtension"}, - {"annotate_repeated_extension_set", "OnSetExtension"}, - {"annotate_repeated_extension_add", "OnAddExtension"}, - {"annotate_repeated_extension_add_mutable", "OnAddMutableExtension"}, - {"annotate_repeated_extension_list", "OnListExtension"}, - {"annotate_repeated_extension_list_mutable", "OnMutableListExtension"}, +y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> HasbitVars( + int has_bit_index) { + return { + {"has_array_index", y_absl::StrCat(has_bit_index / 32)}, + {"has_mask", + y_absl::StrCat( + "0x", y_absl::Hex(1u << (has_bit_index % 32), y_absl::kZeroPad8), "u")}, }; - for (const auto& annotation : accessor_annotations_to_hooks) { - (*variables)[annotation.first] = ""; - } - if (!HasTracker(descriptor, options)) { - return; - } - StringPiece tracker = (*variables)["tracker"]; - StringPiece extensions = (*variables)["extensions"]; - for (const auto& annotation : accessor_annotations_to_hooks) { - const TProtoStringType& annotation_name = annotation.first; - const TProtoStringType& listener_call = annotation.second; - if (!StrContains(annotation_name, "repeated") && - !StrContains(annotation_name, "size") && - !StrContains(annotation_name, "clear")) { - // Primitive fields accessors. - // "Has" is here as users calling "has" on a repeated field is a mistake. - (*variables)[annotation_name] = StrCat( - " ", tracker, ".", listener_call, - "(this, id.number(), _proto_TypeTraits::GetPtr(id.number(), ", - extensions, ", id.default_value_ref()));"); - } else if (StrContains(annotation_name, "repeated") && - !StrContains(annotation_name, "list") && - !StrContains(annotation_name, "size")) { - // Repeated index accessors. - TProtoStringType str_index = "index"; - if (StrContains(annotation_name, "add")) { - str_index = StrCat(extensions, ".ExtensionSize(id.number()) - 1"); - } - (*variables)[annotation_name] = - StrCat(" ", tracker, ".", listener_call, - "(this, id.number(), " - "_proto_TypeTraits::GetPtr(id.number(), ", - extensions, ", ", str_index, "));"); - } else if (StrContains(annotation_name, "list") || - StrContains(annotation_name, "size")) { - // Repeated full accessors. - (*variables)[annotation_name] = StrCat( - " ", tracker, ".", listener_call, - "(this, id.number(), _proto_TypeTraits::GetRepeatedPtr(id.number(), ", - extensions, "));"); - } else { - // Generic accessors such as "clear". - // TODO(b/190614678): Generalize clear from both repeated and non repeated - // calls, currently their underlying memory interfaces are very different. - // Or think of removing clear callback as no usages are needed and no - // memory exist after calling clear(). - } - } } } // anonymous namespace @@ -601,68 +532,28 @@ void GenerateExtensionAnnotations( MessageGenerator::MessageGenerator( const Descriptor* descriptor, - const std::map<TProtoStringType, TProtoStringType>& vars, int index_in_file_messages, - const Options& options, MessageSCCAnalyzer* scc_analyzer) + const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>&, + int index_in_file_messages, const Options& options, + 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), - max_inlined_string_index_(0), - num_weak_fields_(0), - scc_analyzer_(scc_analyzer), - variables_(vars) { - if (!message_layout_helper_) { - message_layout_helper_.reset(new PaddingOptimizer()); - } - SetCommonMessageDataVariables(descriptor, &variables_); + field_generators_(descriptor), + scc_analyzer_(scc_analyzer) { - // Variables that apply to this class - variables_["classname"] = classname_; - variables_["classtype"] = QualifiedClassName(descriptor_, options); - variables_["full_name"] = descriptor_->full_name(); - variables_["superclass"] = SuperClassName(descriptor_, options_); - variables_["annotate_serialize"] = ""; - variables_["annotate_deserialize"] = ""; - variables_["annotate_reflection"] = ""; - variables_["annotate_bytesize"] = ""; - variables_["annotate_mergefrom"] = ""; - - if (HasTracker(descriptor_, options_)) { - const TProtoStringType injector_template = - StrCat(" ", variables_["tracker"], "."); - - MaySetAnnotationVariable(options, "serialize", injector_template, - "OnSerialize(this);\n", &variables_); - MaySetAnnotationVariable(options, "deserialize", injector_template, - "OnDeserialize(this);\n", &variables_); - // TODO(danilak): Ideally annotate_reflection should not exist and we need - // to annotate all reflective calls on our own, however, as this is a cause - // for side effects, i.e. reading values dynamically, we want the users know - // that dynamic access can happen. - MaySetAnnotationVariable(options, "reflection", injector_template, - "OnGetMetadata();\n", &variables_); - MaySetAnnotationVariable(options, "bytesize", injector_template, - "OnByteSize(this);\n", &variables_); - MaySetAnnotationVariable(options, "mergefrom", injector_template, - "OnMergeFrom(_this, &from);\n", &variables_); + if (!message_layout_helper_) { + message_layout_helper_ = std::make_unique<PaddingOptimizer>(); } - GenerateExtensionAnnotations(descriptor_, options_, &variables_); - - SetUnknownFieldsVariable(descriptor_, options_, &variables_); - // Compute optimized field order to be used for layout and initialization // purposes. for (auto field : FieldRange(descriptor_)) { - if (IsFieldStripped(field, options_)) { + if (IsWeak(field, options_)) { + ++num_weak_fields_; continue; } - if (IsWeak(field, options_)) { - num_weak_fields_++; - } else if (!field->real_containing_oneof()) { + if (!field->real_containing_oneof()) { optimized_order_.push_back(field); } } @@ -683,34 +574,26 @@ MessageGenerator::MessageGenerator( inlined_string_indices_.resize(descriptor_->field_count(), kNoHasbit); // The bitset[0] is for arena dtor tracking. Donating states start from // bitset[1]; - max_inlined_string_index_++; + ++max_inlined_string_index_; } + inlined_string_indices_[field->index()] = max_inlined_string_index_++; } } + field_generators_.Build(options_, scc_analyzer_, has_bit_indices_, + inlined_string_indices_); - if (!has_bit_indices_.empty()) { - field_generators_.SetHasBitIndices(has_bit_indices_); - } - - if (!inlined_string_indices_.empty()) { - field_generators_.SetInlinedStringIndices(inlined_string_indices_); - } - - num_required_fields_ = 0; for (int i = 0; i < descriptor->field_count(); i++) { if (descriptor->field(i)->is_required()) { ++num_required_fields_; } } - parse_function_generator_.reset(new ParseFunctionGenerator( + parse_function_generator_ = std::make_unique<ParseFunctionGenerator>( descriptor_, max_has_bit_index_, has_bit_indices_, - inlined_string_indices_, options_, scc_analyzer_, variables_)); + inlined_string_indices_, options_, scc_analyzer_, variables_); } -MessageGenerator::~MessageGenerator() = default; - size_t MessageGenerator::HasBitsSize() const { return (max_has_bit_index_ + 31) / 32; } @@ -739,94 +622,131 @@ void MessageGenerator::AddGenerators( std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators) { for (int i = 0; i < descriptor_->enum_type_count(); i++) { enum_generators->emplace_back( - new EnumGenerator(descriptor_->enum_type(i), variables_, options_)); + std::make_unique<EnumGenerator>(descriptor_->enum_type(i), options_)); enum_generators_.push_back(enum_generators->back().get()); } for (int i = 0; i < descriptor_->extension_count(); i++) { - extension_generators->emplace_back(new ExtensionGenerator( + extension_generators->emplace_back(std::make_unique<ExtensionGenerator>( descriptor_->extension(i), options_, scc_analyzer_)); extension_generators_.push_back(extension_generators->back().get()); } } -void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { - Formatter format(printer, variables_); +void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* p) { + auto v = p->WithVars(MessageVars(descriptor_)); + Formatter format(p); + // optimized_fields_ does not contain fields where // field->real_containing_oneof() // so we need to iterate over those as well. // // We place the non-oneof fields in optimized_order_, as that controls the - // order of the _has_bits_ entries and we want GDB's pretty printers to be + // order of the _has_bits_ entries and we want GDB's pretty ps to be // able to infer these indices from the k[FIELDNAME]FieldNumber order. 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 (auto field : FieldRange(descriptor_)) { - if (!field->real_containing_oneof() && !field->options().weak() && - !IsFieldStripped(field, options_)) { + if (!field->real_containing_oneof() && !field->options().weak()) { continue; } ordered_fields.push_back(field); } if (!ordered_fields.empty()) { - format("enum : int {\n"); - for (auto field : ordered_fields) { - Formatter::SaveState save(&format); - - std::map<TProtoStringType, TProtoStringType> vars; - SetCommonFieldVariables(field, &vars, options_); - format.AddMap(vars); - format(" ${1$$2$$}$ = $number$,\n", field, FieldConstantName(field)); - } - format("};\n"); + p->Emit({{ + "kFields", + [&] { + for (auto field : ordered_fields) { + auto v = p->WithVars(FieldVars(field, options_)); + p->Emit({Sub("kField", FieldConstantName(field)) + .AnnotatedAs(field)}, + R"cc( + $kField$ = $number$, + )cc"); + } + }, + }}, + R"cc( + enum : int { + $kFields$, + }; + )cc"); } for (auto field : ordered_fields) { - PrintFieldComment(format, field); - - Formatter::SaveState save(&format); - - std::map<TProtoStringType, TProtoStringType> vars; - SetCommonFieldVariables(field, &vars, options_); - format.AddMap(vars); - - if (field->is_repeated()) { - format("$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field, - !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}"); - if (!IsFieldStripped(field, options_)) { - format( - "private:\n" - "int ${1$_internal_$name$_size$}$() const;\n" - "public:\n", - field); - } - } else if (HasHasMethod(field)) { - format("$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field, - !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}"); - if (!IsFieldStripped(field, options_)) { - format( - "private:\n" - "bool _internal_has_$name$() const;\n" - "public:\n"); - } - } else if (HasPrivateHasMethod(field)) { - if (!IsFieldStripped(field, options_)) { - format( - "private:\n" - "bool ${1$_internal_has_$name$$}$() const;\n" - "public:\n", - field); - } - } - format("$deprecated_attr$void ${1$clear_$name$$}$()$2$\n", field, - !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}"); - - // Generate type-specific accessor declarations. - field_generators_.get(field).GenerateAccessorDeclarations(printer); - - format("\n"); + auto name = FieldName(field); + + auto v = p->WithVars(FieldVars(field, options_)); + auto t = p->WithVars(MakeTrackerCalls(field, options_)); + p->Emit( + {{"field_comment", FieldComment(field)}, + Sub("const_impl", "const;").WithSuffix(";"), + Sub("impl", ";").WithSuffix(";"), + {"sizer", + [&] { + if (!field->is_repeated()) return; + p->Emit({Sub("name_size", y_absl::StrCat(name, "_size")) + .AnnotatedAs(field)}, + R"cc( + $deprecated_attr $int $name_size$() $const_impl$; + )cc"); + + p->Emit({Sub("_internal_name_size", + y_absl::StrCat("_internal_", name, "_size")) + .AnnotatedAs(field)}, + R"cc( + private: + int $_internal_name_size$() const; + + public: + )cc"); + }}, + {"hazzer", + [&] { + if (!field->has_presence()) return; + p->Emit({Sub("has_name", y_absl::StrCat("has_", name)) + .AnnotatedAs(field)}, + R"cc( + $deprecated_attr $bool $has_name$() $const_impl$; + )cc"); + }}, + {"internal_hazzer", + [&] { + if (field->is_repeated() || !HasInternalHasMethod(field)) { + return; + } + p->Emit( + {Sub("_internal_has_name", y_absl::StrCat("_internal_has_", name)) + .AnnotatedAs(field)}, + R"cc( + private: + bool $_internal_has_name$() const; + + public: + )cc"); + }}, + {"clearer", + [&] { + p->Emit({Sub("clear_name", y_absl::StrCat("clear_", name)) + .AnnotatedAs(field)}, + R"cc( + $deprecated_attr $void $clear_name$() $impl$; + )cc"); + }}, + {"accessors", + [&] { + field_generators_.get(field).GenerateAccessorDeclarations(p); + }}}, + R"cc( + // $field_comment$ + $sizer$; + $hazzer$; + $internal_hazzer$; + $clearer$; + $accessors$; + )cc"); } if (descriptor_->extension_range_count() > 0) { @@ -839,211 +759,195 @@ void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) { // For similar reason, we use "_field_type" and "_is_packed" as parameter // names below, so that "field_type" and "is_packed" can be used as field // names. - format(R"( -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline bool HasExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const { -$annotate_extension_has$ - return $extensions$.Has(id.number()); -} + p->Emit(R"cc( + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline bool HasExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id) const { + $annotate_extension_has$; + return $extensions$.Has(id.number()); + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline void ClearExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) { - $extensions$.ClearExtension(id.number()); -$annotate_extension_clear$ -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline void ClearExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id) { + $extensions$.ClearExtension(id.number()); + $annotate_extension_clear$; + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline int ExtensionSize( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const { -$annotate_extension_repeated_size$ - return $extensions$.ExtensionSize(id.number()); -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline int ExtensionSize( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id) const { + $annotate_extension_repeated_size$; + return $extensions$.ExtensionSize(id.number()); + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline typename _proto_TypeTraits::Singular::ConstType GetExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const { -$annotate_extension_get$ - return _proto_TypeTraits::Get(id.number(), $extensions$, - id.default_value()); -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id) const { + $annotate_extension_get$; + return _proto_TypeTraits::Get(id.number(), $extensions$, id.default_value()); + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) { -$annotate_extension_mutable$ - return _proto_TypeTraits::Mutable(id.number(), _field_type, - &$extensions$); -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id) { + $annotate_extension_mutable$; + return _proto_TypeTraits::Mutable(id.number(), _field_type, &$extensions$); + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline void SetExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id, - typename _proto_TypeTraits::Singular::ConstType value) { - _proto_TypeTraits::Set(id.number(), _field_type, value, &$extensions$); -$annotate_extension_set$ -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::ConstType value) { + _proto_TypeTraits::Set(id.number(), _field_type, value, &$extensions$); + $annotate_extension_set$; + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline void SetAllocatedExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id, - typename _proto_TypeTraits::Singular::MutableType value) { - _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, - &$extensions$); -$annotate_extension_set$ -} -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline void UnsafeArenaSetAllocatedExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id, - typename _proto_TypeTraits::Singular::MutableType value) { - _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, - value, &$extensions$); -$annotate_extension_set$ -} -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -PROTOBUF_NODISCARD inline - typename _proto_TypeTraits::Singular::MutableType - ReleaseExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) { -$annotate_extension_release$ - return _proto_TypeTraits::Release(id.number(), _field_type, - &$extensions$); -} -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline typename _proto_TypeTraits::Singular::MutableType -UnsafeArenaReleaseExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) { -$annotate_extension_release$ - return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, - &$extensions$); -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline void SetAllocatedExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::SetAllocated(id.number(), _field_type, value, + &$extensions$); + $annotate_extension_set$; + } + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline void UnsafeArenaSetAllocatedExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id, + typename _proto_TypeTraits::Singular::MutableType value) { + _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type, + value, &$extensions$); + $annotate_extension_set$; + } + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + PROTOBUF_NODISCARD inline + typename _proto_TypeTraits::Singular::MutableType + ReleaseExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id) { + $annotate_extension_release$; + return _proto_TypeTraits::Release(id.number(), _field_type, &$extensions$); + } + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Singular::MutableType + UnsafeArenaReleaseExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id) { + $annotate_extension_release$; + return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type, + &$extensions$); + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id, - int index) const { -$annotate_repeated_extension_get$ - return _proto_TypeTraits::Get(id.number(), $extensions$, index); -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id, + int index) const { + $annotate_repeated_extension_get$; + return _proto_TypeTraits::Get(id.number(), $extensions$, index); + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id, - int index) { -$annotate_repeated_extension_mutable$ - return _proto_TypeTraits::Mutable(id.number(), index, &$extensions$); -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id, + int index) { + $annotate_repeated_extension_mutable$; + return _proto_TypeTraits::Mutable(id.number(), index, &$extensions$); + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline void SetExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id, - int index, typename _proto_TypeTraits::Repeated::ConstType value) { - _proto_TypeTraits::Set(id.number(), index, value, &$extensions$); -$annotate_repeated_extension_set$ -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline void SetExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id, + int index, typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Set(id.number(), index, value, &$extensions$); + $annotate_repeated_extension_set$; + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) { - typename _proto_TypeTraits::Repeated::MutableType to_add = - _proto_TypeTraits::Add(id.number(), _field_type, &$extensions$); -$annotate_repeated_extension_add_mutable$ - return to_add; -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id) { + typename _proto_TypeTraits::Repeated::MutableType to_add = + _proto_TypeTraits::Add(id.number(), _field_type, &$extensions$); + $annotate_repeated_extension_add_mutable$; + return to_add; + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline void AddExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id, - typename _proto_TypeTraits::Repeated::ConstType value) { - _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, - &$extensions$); -$annotate_repeated_extension_add$ -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline void AddExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id, + typename _proto_TypeTraits::Repeated::ConstType value) { + _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value, + &$extensions$); + $annotate_repeated_extension_add$; + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& -GetRepeatedExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const { -$annotate_repeated_extension_list$ - return _proto_TypeTraits::GetRepeated(id.number(), $extensions$); -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& + GetRepeatedExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id) const { + $annotate_repeated_extension_list$; + return _proto_TypeTraits::GetRepeated(id.number(), $extensions$); + } -template <typename _proto_TypeTraits, - ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type, - bool _is_packed> -inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* -MutableRepeatedExtension( - const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< - $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) { -$annotate_repeated_extension_list_mutable$ - return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, - _is_packed, &$extensions$); -} + template <typename _proto_TypeTraits, $pbi$::FieldType _field_type, + bool _is_packed> + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* + MutableRepeatedExtension( + const $pbi$::ExtensionIdentifier<$Msg$, _proto_TypeTraits, + _field_type, _is_packed>& id) { + $annotate_repeated_extension_list_mutable$; + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, + _is_packed, &$extensions$); + } + )cc"); -)"); // 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"); + // Special-case MessageSet. + p->Emit(R"cc( + GOOGLE_PROTOBUF_EXTENSION_MESSAGE_SET_ACCESSORS($Msg$); + )cc"); } } for (auto oneof : OneOfRange(descriptor_)) { Formatter::SaveState saver(&format); - format.Set("oneof_name", oneof->name()); - format.Set("camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true)); + auto v = p->WithVars({ + {"oneof_name", oneof->name()}, + {"camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true)}, + }); format( "void ${1$clear_$oneof_name$$}$();\n" "$camel_oneof_name$Case $oneof_name$_case() const;\n", @@ -1052,13 +956,9 @@ $annotate_repeated_extension_list_mutable$ } void MessageGenerator::GenerateSingularFieldHasBits( - const FieldDescriptor* field, Formatter format) { - if (IsFieldStripped(field, options_)) { - format( - "inline bool $classname$::has_$name$() const { " - "__builtin_trap(); }\n"); - return; - } + const FieldDescriptor* field, io::Printer* p) { + auto t = p->WithVars(MakeTrackerCalls(field, options_)); + Formatter format(p); if (field->options().weak()) { format( "inline bool $classname$::has_$name$() const {\n" @@ -1069,15 +969,13 @@ void MessageGenerator::GenerateSingularFieldHasBits( } if (HasHasbit(field)) { int has_bit_index = HasBitIndex(field); - GOOGLE_CHECK_NE(has_bit_index, kNoHasbit); + Y_ABSL_CHECK_NE(has_bit_index, kNoHasbit); - format.Set("has_array_index", has_bit_index / 32); - format.Set("has_mask", - strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + auto v = p->WithVars(HasbitVars(has_bit_index)); format( - "inline bool $classname$::_internal_has_$name$() const {\n" - " bool value = " - "($has_bits$[$has_array_index$] & 0x$has_mask$u) != 0;\n"); + "inline bool $classname$::has_$name$() const {\n" + "$annotate_has$" + " bool value = ($has_bits$[$has_array_index$] & $has_mask$) != 0;\n"); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !IsLazy(field, options_, scc_analyzer_)) { @@ -1089,10 +987,6 @@ void MessageGenerator::GenerateSingularFieldHasBits( format( " return value;\n" - "}\n" - "inline bool $classname$::has_$name$() const {\n" - "$annotate_has$" - " return _internal_has_$name$();\n" "}\n"); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // Message fields have a has_$name$() method. @@ -1116,12 +1010,14 @@ void MessageGenerator::GenerateSingularFieldHasBits( } } -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())); +void MessageGenerator::GenerateOneofHasBits(io::Printer* p) { + Formatter format(p); + for (const auto* oneof : OneOfRange(descriptor_)) { + auto v = p->WithVars({ + {"oneof_index", oneof->index()}, + {"oneof_name", oneof->name()}, + {"cap_oneof_name", y_absl::AsciiStrToUpper(oneof->name())}, + }); format( "inline bool $classname$::has_$oneof_name$() const {\n" " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" @@ -1133,40 +1029,24 @@ void MessageGenerator::GenerateOneofHasBits(io::Printer* printer) { } void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field, - const Formatter& format) { - if (IsFieldStripped(field, options_)) { - if (HasHasMethod(field)) { - format( - "inline bool $classname$::has_$name$() const { " - "__builtin_trap(); }\n"); - } - format( - "inline void $classname$::set_has_$name$() { __builtin_trap(); " - "}\n"); - return; - } + io::Printer* p) { + auto t = p->WithVars(MakeTrackerCalls(field, options_)); + Formatter format(p); // 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). - // - // If has_$name$() is private, there is no need to add an internal accessor. - // Only annotate public accessors. + // Oneofs also have private _internal_has_$name$() a helper method. if (HasHasMethod(field)) { format( - "inline bool $classname$::_internal_has_$name$() const {\n" - " return $oneof_name$_case() == k$field_name$;\n" - "}\n" "inline bool $classname$::has_$name$() const {\n" "$annotate_has$" - " return _internal_has_$name$();\n" + " return $has_field$;\n" "}\n"); - } else if (HasPrivateHasMethod(field)) { + } + if (HasInternalHasMethod(field)) { format( "inline bool $classname$::_internal_has_$name$() const {\n" - " return $oneof_name$_case() == k$field_name$;\n" + " return $has_field$;\n" "}\n"); } // set_has_$name$() for oneof fields is always private; hence should not be @@ -1178,11 +1058,9 @@ void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field, } void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field, - bool is_inline, Formatter format) { - if (IsFieldStripped(field, options_)) { - format("void $classname$::clear_$name$() { __builtin_trap(); }\n"); - return; - } + bool is_inline, io::Printer* p) { + auto t = p->WithVars(MakeTrackerCalls(field, options_)); + Formatter format(p); // Generate clear_$name$(). if (is_inline) { @@ -1195,9 +1073,10 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field, if (field->real_containing_oneof()) { // Clear this field only if it is the active field in this oneof, // otherwise ignore - format("if (_internal_has_$name$()) {\n"); + auto t = p->WithVars(MakeTrackerCalls(field, options_)); + format("if ($has_field$) {\n"); format.Indent(); - field_generators_.get(field).GenerateClearingCode(format.printer()); + field_generators_.get(field).GenerateClearingCode(p); format("clear_has_$oneof_name$();\n"); format.Outdent(); format("}\n"); @@ -1205,13 +1084,11 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field, if (ShouldSplit(field, options_)) { format("if (IsSplitMessageDefault()) return;\n"); } - field_generators_.get(field).GenerateClearingCode(format.printer()); + field_generators_.get(field).GenerateClearingCode(p); if (HasHasbit(field)) { int has_bit_index = HasBitIndex(field); - 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"); + auto v = p->WithVars(HasbitVars(has_bit_index)); + format("$has_bits$[$has_array_index$] &= ~$has_mask$;\n"); } } format("$annotate_clear$"); @@ -1219,81 +1096,60 @@ void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field, format("}\n"); } -void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) { - Formatter format(printer, variables_); +void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* p) { + Formatter format(p); format("// $classname$\n\n"); for (auto field : FieldRange(descriptor_)) { PrintFieldComment(format, field); - if (IsFieldStripped(field, options_)) { - continue; - } - - std::map<TProtoStringType, TProtoStringType> vars; - SetCommonFieldVariables(field, &vars, options_); - - Formatter::SaveState saver(&format); - format.AddMap(vars); - + auto v = p->WithVars(FieldVars(field, options_)); + auto t = p->WithVars(MakeTrackerCalls(field, options_)); // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { - if (IsFieldStripped(field, options_)) { - format( - "inline int $classname$::$name$_size() const { " - "__builtin_trap(); }\n"); - } else { - format( - "inline int $classname$::_internal_$name$_size() const {\n" - " return $field$$1$.size();\n" - "}\n" - "inline int $classname$::$name$_size() const {\n" - "$annotate_size$" - " return _internal_$name$_size();\n" - "}\n", - IsImplicitWeakField(field, options_, scc_analyzer_) && - field->message_type() - ? ".weak" - : ""); - } + format( + "inline int $classname$::_internal_$name$_size() const {\n" + " return $field$$1$.size();\n" + "}\n" + "inline int $classname$::$name$_size() const {\n" + "$annotate_size$" + " return _internal_$name$_size();\n" + "}\n", + IsImplicitWeakField(field, options_, scc_analyzer_) && + field->message_type() + ? ".weak" + : ""); } else if (field->real_containing_oneof()) { - format.Set("field_name", UnderscoresToCamelCase(field->name(), true)); - format.Set("oneof_name", field->containing_oneof()->name()); - format.Set("oneof_index", - StrCat(field->containing_oneof()->index())); - GenerateOneofMemberHasBits(field, format); + GenerateOneofMemberHasBits(field, p); } else { // Singular field. - GenerateSingularFieldHasBits(field, format); + GenerateSingularFieldHasBits(field, p); } if (!IsCrossFileMaybeMap(field)) { - GenerateFieldClear(field, true, format); + GenerateFieldClear(field, true, p); } - // Generate type-specific accessors. - if (!IsFieldStripped(field, options_)) { - field_generators_.get(field).GenerateInlineAccessorDefinitions(printer); - } + field_generators_.get(field).GenerateInlineAccessorDefinitions(p); format("\n"); } // Generate has_$name$() and clear_has_$name$() functions for oneofs. - GenerateOneofHasBits(printer); + GenerateOneofHasBits(p); } -void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { - Formatter format(printer, variables_); - format.Set("class_final", - ShouldMarkClassAsFinal(descriptor_, options_) ? "final" : ""); +void MessageGenerator::GenerateClassDefinition(io::Printer* p) { + auto v = p->WithVars(ClassVars(descriptor_, options_)); + auto t = p->WithVars(MakeTrackerCalls(descriptor_, options_)); + Formatter format(p); if (IsMapEntryMessage(descriptor_)) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; CollectMapInfo(options_, descriptor_, &vars); vars["lite"] = HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite"; - format.AddMap(vars); + auto v = p->WithVars(std::move(vars)); format( "class $classname$ : public " "::$proto_ns$::internal::MapEntry$lite$<$classname$, \n" @@ -1314,7 +1170,9 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { " static const $classname$* internal_default_instance() { return " "reinterpret_cast<const " "$classname$*>(&_$classname$_default_instance_); }\n"); - auto utf8_check = GetUtf8CheckMode(descriptor_->field(0), options_); + auto utf8_check = internal::cpp::GetUtf8CheckMode( + descriptor_->field(0), GetOptimizeFor(descriptor_->file(), options_) == + FileOptions::LITE_RUNTIME); if (descriptor_->field(0)->type() == FieldDescriptor::TYPE_STRING && utf8_check != Utf8CheckMode::kNone) { if (utf8_check == Utf8CheckMode::kStrict) { @@ -1326,7 +1184,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { " }\n", descriptor_->field(0)->full_name()); } else { - GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify); + Y_ABSL_CHECK(utf8_check == Utf8CheckMode::kVerify); format( " static bool ValidateKey(TProtoStringType* s) {\n" "#ifndef NDEBUG\n" @@ -1355,7 +1213,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { " }\n", descriptor_->field(1)->full_name()); } else { - GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify); + Y_ABSL_CHECK(utf8_check == Utf8CheckMode::kVerify); format( " static bool ValidateValue(TProtoStringType* s) {\n" "#ifndef NDEBUG\n" @@ -1386,25 +1244,14 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { } format( - "class $dllexport_decl $${1$$classname$$}$$ class_final$ :\n" + "class $dllexport_decl $${1$$classname$$}$ final :\n" " public $superclass$ /* @@protoc_insertion_point(" "class_definition:$full_name$) */ {\n", descriptor_); format(" public:\n"); format.Indent(); - if (EnableMessageOwnedArena(descriptor_, options_)) { - format( - "inline $classname$() : $classname$(" - "::$proto_ns$::Arena::InternalCreateMessageOwnedArena(), true) {}\n"); - } else if (EnableMessageOwnedArenaTrial(descriptor_, options_)) { - format( - "inline $classname$() : $classname$(InMoaTrial() ? " - "::$proto_ns$::Arena::InternalCreateMessageOwnedArena() : nullptr, " - "InMoaTrial()) {}\n"); - } else { - format("inline $classname$() : $classname$(nullptr) {}\n"); - } + format("inline $classname$() : $classname$(nullptr) {}\n"); if (!HasSimpleBaseClass(descriptor_, options_)) { format("~$classname$() override;\n"); } @@ -1489,7 +1336,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { format("$1$ = $2$,\n", OneofCaseConstantName(field), // 1 field->number()); // 2 } - format("$1$_NOT_SET = 0,\n", ToUpper(oneof->name())); + format("$1$_NOT_SET = 0,\n", y_absl::AsciiStrToUpper(oneof->name())); format.Outdent(); format( "};\n" @@ -1518,8 +1365,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { " return $any_metadata$.PackFrom(GetArena(), message);\n" "}\n" "bool PackFrom(const ::$proto_ns$::Message& message,\n" - " ::PROTOBUF_NAMESPACE_ID::ConstStringParam " - "type_url_prefix) {\n" + " ::y_absl::string_view type_url_prefix) {\n" " $DCHK$_NE(&message, this);\n" " return $any_metadata$.PackFrom(GetArena(), message, " "type_url_prefix);\n" @@ -1541,8 +1387,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { "!std::is_convertible<T, const ::$proto_ns$::Message&>" "::value>::type>\n" "bool PackFrom(const T& message,\n" - " ::PROTOBUF_NAMESPACE_ID::ConstStringParam " - "type_url_prefix) {\n" + " ::y_absl::string_view type_url_prefix) {\n" " return $any_metadata$.PackFrom<T>(GetArena(), message, " "type_url_prefix);" "}\n" @@ -1560,8 +1405,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { "}\n" "template <typename T>\n" "bool PackFrom(const T& message,\n" - " ::PROTOBUF_NAMESPACE_ID::ConstStringParam " - "type_url_prefix) {\n" + " ::y_absl::string_view type_url_prefix) {\n" " return $any_metadata$.PackFrom(GetArena(), message, " "type_url_prefix);\n" "}\n" @@ -1574,8 +1418,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { "template<typename T> bool Is() const {\n" " return $any_metadata$.Is<T>();\n" "}\n" - "static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam " - "type_url,\n" + "static bool ParseAnyTypeUrl(::y_absl::string_view type_url,\n" " TProtoStringType* full_type_name);\n"); } @@ -1612,9 +1455,9 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { // For instances that derive from Message (rather than MessageLite), some // methods are virtual and should be marked as final. - format.Set("full_final", HasDescriptorMethods(descriptor_->file(), options_) - ? "final" - : ""); + auto v2 = p->WithVars( + {{"full_final", + HasDescriptorMethods(descriptor_->file(), options_) ? "final" : ""}}); if (HasGeneratedMethods(descriptor_->file(), options_)) { if (HasDescriptorMethods(descriptor_->file(), options_)) { @@ -1662,9 +1505,9 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { "PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;\n" "bool IsInitialized() const final;\n" "\n" - "size_t ByteSizeLong() const final;\n"); + "::size_t ByteSizeLong() const final;\n"); - parse_function_generator_->GenerateMethodDecls(printer); + parse_function_generator_->GenerateMethodDecls(p); format( "$uint8$* _InternalSerialize(\n" @@ -1683,7 +1526,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { "int GetCachedSize() const final { return " "$cached_size$.Get(); }" "\n\nprivate:\n" - "void SharedCtor(::$proto_ns$::Arena* arena, bool is_message_owned);\n" + "void SharedCtor(::$proto_ns$::Arena* arena);\n" "void SharedDtor();\n" "void SetCachedSize(int size) const$ full_final$;\n" "void InternalSwap($classname$* other);\n"); @@ -1693,19 +1536,16 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { // Friend AnyMetadata so that it can call this FullMessageName() method. "\nprivate:\n" "friend class ::$proto_ns$::internal::AnyMetadata;\n" - "static $1$ FullMessageName() {\n" + "static ::y_absl::string_view FullMessageName() {\n" " return \"$full_name$\";\n" - "}\n", - options_.opensource_runtime ? "::PROTOBUF_NAMESPACE_ID::StringPiece" - : "::StringPiece"); + "}\n"); 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" - " bool is_message_owned = false);\n"); + "explicit $classname$(::$proto_ns$::Arena* arena);\n"); switch (NeedsArenaDestructor()) { case ArenaDtorNeeds::kOnDemand: @@ -1758,7 +1598,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { format( "private:\n" "inline bool IsSplitMessageDefault() const {\n" - " return $split$ == reinterpret_cast<Impl_::Split*>(&$1$);\n" + " return $split$ == reinterpret_cast<const Impl_::Split*>(&$1$);\n" "}\n" "PROTOBUF_NOINLINE void PrepareSplitMessageForWrite();\n" "public:\n", @@ -1773,8 +1613,9 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { for (int i = 0; i < descriptor_->nested_type_count(); i++) { const Descriptor* nested_type = descriptor_->nested_type(i); if (!IsMapEntryMessage(nested_type)) { - format.Set("nested_full_name", ClassName(nested_type, false)); - format.Set("nested_name", ResolveKeyword(nested_type->name())); + auto v = + p->WithVars({{"nested_full_name", ClassName(nested_type, false)}, + {"nested_name", ResolveKeyword(nested_type->name())}}); format("typedef ${1$$nested_full_name$$}$ ${1$$nested_name$$}$;\n", nested_type); } @@ -1787,7 +1628,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { // 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); + enum_generators_[i]->GenerateSymbolImports(p); format("\n"); } @@ -1796,11 +1637,11 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { "\n"); // Generate accessor methods for all fields. - GenerateFieldAccessorDeclarations(printer); + GenerateFieldAccessorDeclarations(p); // Declare extension identifiers. for (int i = 0; i < descriptor_->extension_count(); i++) { - extension_generators_[i]->GenerateDeclaration(printer); + extension_generators_[i]->GenerateDeclaration(p); } @@ -1835,11 +1676,11 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { num_required_fields_ > 1) { format( "// helper for ByteSizeLong()\n" - "size_t RequiredFieldsByteSizeFallback() const;\n\n"); + "::size_t RequiredFieldsByteSizeFallback() const;\n\n"); } if (HasGeneratedMethods(descriptor_->file(), options_)) { - parse_function_generator_->GenerateDataDecls(printer); + parse_function_generator_->GenerateDataDecls(p); } // Prepare decls for _cached_size_ and _has_bits_. Their position in the @@ -1852,7 +1693,7 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { const size_t sizeof_has_bits = HasBitsSize(); const TProtoStringType has_bits_decl = sizeof_has_bits == 0 ? "" - : StrCat("::$proto_ns$::internal::HasBits<", + : y_absl::StrCat("::$proto_ns$::internal::HasBits<", sizeof_has_bits, "> _has_bits_;\n"); format( @@ -1907,10 +1748,9 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { // Emit some private and static members for (auto field : optimized_order_) { - const FieldGenerator& generator = field_generators_.get(field); - generator.GenerateStaticMembers(printer); + field_generators_.get(field).GenerateStaticMembers(p); if (!ShouldSplit(field, options_)) { - generator.GeneratePrivateMembers(printer); + field_generators_.get(field).GeneratePrivateMembers(p); } } if (ShouldSplit(descriptor_, options_)) { @@ -1918,14 +1758,15 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { format.Indent(); for (auto field : optimized_order_) { if (!ShouldSplit(field, options_)) continue; - const FieldGenerator& generator = field_generators_.get(field); - generator.GeneratePrivateMembers(printer); + field_generators_.get(field).GeneratePrivateMembers(p); } format.Outdent(); format( " typedef void InternalArenaConstructable_;\n" " typedef void DestructorSkippable_;\n" "};\n" + "static_assert(std::is_trivially_copy_constructible<Split>::value);\n" + "static_assert(std::is_trivially_destructible<Split>::value);\n" "Split* _split_;\n"); } @@ -1941,16 +1782,12 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { " ::$proto_ns$::internal::ConstantInitialized _constinit_;\n", camel_oneof_name); for (auto field : FieldRange(oneof)) { - if (!IsFieldStripped(field, options_)) { - field_generators_.get(field).GeneratePrivateMembers(printer); - } + field_generators_.get(field).GeneratePrivateMembers(p); } format.Outdent(); format("} $1$_;\n", oneof->name()); for (auto field : FieldRange(oneof)) { - if (!IsFieldStripped(field, options_)) { - field_generators_.get(field).GenerateStaticMembers(printer); - } + field_generators_.get(field).GenerateStaticMembers(p); } } @@ -1986,9 +1823,6 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { } if (ShouldSplit(descriptor_, options_)) { - format( - "static Impl_::Split* CreateSplitMessage(" - "::$proto_ns$::Arena* arena);\n"); format("friend struct $1$;\n", DefaultInstanceType(descriptor_, options_, /*split=*/true)); } @@ -1999,19 +1833,23 @@ void MessageGenerator::GenerateClassDefinition(io::Printer* printer) { format.Outdent(); format("};"); - GOOGLE_DCHECK(!need_to_emit_cached_size); + Y_ABSL_DCHECK(!need_to_emit_cached_size); } // NOLINT(readability/fn_size) -void MessageGenerator::GenerateInlineMethods(io::Printer* printer) { +void MessageGenerator::GenerateInlineMethods(io::Printer* p) { + auto v = p->WithVars(ClassVars(descriptor_, options_)); + auto t = p->WithVars(MakeTrackerCalls(descriptor_, options_)); if (IsMapEntryMessage(descriptor_)) return; - GenerateFieldAccessorDefinitions(printer); + GenerateFieldAccessorDefinitions(p); // Generate oneof_case() functions. 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()); + Formatter format(p); + auto v = p->WithVars({ + {"camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true)}, + {"oneof_name", oneof->name()}, + {"oneof_index", oneof->index()}, + }); format( "inline $classname$::$camel_oneof_name$Case $classname$::" "${1$$oneof_name$_case$}$() const {\n" @@ -2022,9 +1860,11 @@ void MessageGenerator::GenerateInlineMethods(io::Printer* printer) { } } -void MessageGenerator::GenerateSchema(io::Printer* printer, int offset, +void MessageGenerator::GenerateSchema(io::Printer* p, int offset, int has_offset) { - Formatter format(printer, variables_); + auto v = p->WithVars(ClassVars(descriptor_, options_)); + auto t = p->WithVars(MakeTrackerCalls(descriptor_, options_)); + Formatter format(p); has_offset = !has_bit_indices_.empty() || IsMapEntryMessage(descriptor_) ? offset + has_offset : -1; @@ -2032,17 +1872,18 @@ void MessageGenerator::GenerateSchema(io::Printer* printer, int offset, if (inlined_string_indices_.empty()) { inlined_string_indices_offset = -1; } else { - GOOGLE_DCHECK_NE(has_offset, -1); - GOOGLE_DCHECK(!IsMapEntryMessage(descriptor_)); + Y_ABSL_DCHECK_NE(has_offset, -1); + Y_ABSL_DCHECK(!IsMapEntryMessage(descriptor_)); inlined_string_indices_offset = has_offset + has_bit_indices_.size(); } - format("{ $1$, $2$, $3$, sizeof($classtype$)},\n", offset, has_offset, inlined_string_indices_offset); } -void MessageGenerator::GenerateClassMethods(io::Printer* printer) { - Formatter format(printer, variables_); +void MessageGenerator::GenerateClassMethods(io::Printer* p) { + auto v = p->WithVars(ClassVars(descriptor_, options_)); + auto t = p->WithVars(MakeTrackerCalls(descriptor_, options_)); + Formatter format(p); if (IsMapEntryMessage(descriptor_)) { format( "$classname$::$classname$() {}\n" @@ -2087,7 +1928,7 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) { } format( "bool $classname$::ParseAnyTypeUrl(\n" - " ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,\n" + " ::y_absl::string_view type_url,\n" " TProtoStringType* full_type_name) {\n" " return ::_pbi::ParseAnyTypeUrl(type_url, full_type_name);\n" "}\n" @@ -2101,16 +1942,21 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) { if (!has_bit_indices_.empty()) { format( "using HasBits = " - "decltype(std::declval<$classname$>().$has_bits$);\n"); + "decltype(std::declval<$classname$>().$has_bits$);\n" + "static constexpr ::arc_i32 kHasBitsOffset =\n" + " 8 * PROTOBUF_FIELD_OFFSET($classname$, _impl_._has_bits_);\n"); + } + if (descriptor_->real_oneof_decl_count() > 0) { + format( + "static constexpr ::arc_i32 kOneofCaseOffset =\n" + " PROTOBUF_FIELD_OFFSET($classtype$, $oneof_case$);\n"); } for (auto field : FieldRange(descriptor_)) { - field_generators_.get(field).GenerateInternalAccessorDeclarations(printer); - if (IsFieldStripped(field, options_)) { - continue; - } + auto t = p->WithVars(MakeTrackerCalls(field, options_)); + field_generators_.get(field).GenerateInternalAccessorDeclarations(p); if (HasHasbit(field)) { int has_bit_index = HasBitIndex(field); - GOOGLE_CHECK_NE(has_bit_index, kNoHasbit) << field->full_name(); + Y_ABSL_CHECK_NE(has_bit_index, kNoHasbit) << field->full_name(); format( "static void set_has_$1$(HasBits* has_bits) {\n" " (*has_bits)[$2$] |= $3$u;\n" @@ -2131,65 +1977,54 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) { format.Outdent(); format("};\n\n"); for (auto field : FieldRange(descriptor_)) { - if (!IsFieldStripped(field, options_)) { - field_generators_.get(field).GenerateInternalAccessorDefinitions( - printer); - } + field_generators_.get(field).GenerateInternalAccessorDefinitions(p); } // Generate non-inline field definitions. for (auto field : FieldRange(descriptor_)) { - if (IsFieldStripped(field, options_)) { - continue; - } - field_generators_.get(field).GenerateNonInlineAccessorDefinitions(printer); + auto v = p->WithVars(FieldVars(field, options_)); + auto t = p->WithVars(MakeTrackerCalls(field, options_)); + field_generators_.get(field).GenerateNonInlineAccessorDefinitions(p); if (IsCrossFileMaybeMap(field)) { - Formatter::SaveState saver(&format); - std::map<TProtoStringType, TProtoStringType> vars; - SetCommonFieldVariables(field, &vars, options_); - if (field->real_containing_oneof()) { - SetCommonOneofFieldVariables(field, &vars); - } - format.AddMap(vars); - GenerateFieldClear(field, false, format); + GenerateFieldClear(field, false, p); } } - GenerateStructors(printer); + GenerateStructors(p); format("\n"); if (descriptor_->real_oneof_decl_count() > 0) { - GenerateOneofClear(printer); + GenerateOneofClear(p); format("\n"); } if (HasGeneratedMethods(descriptor_->file(), options_)) { - GenerateClear(printer); + GenerateClear(p); format("\n"); if (!HasSimpleBaseClass(descriptor_, options_)) { - parse_function_generator_->GenerateMethodImpls(printer); + parse_function_generator_->GenerateMethodImpls(p); format("\n"); - parse_function_generator_->GenerateDataDefinitions(printer); + parse_function_generator_->GenerateDataDefinitions(p); } - GenerateSerializeWithCachedSizesToArray(printer); + GenerateSerializeWithCachedSizesToArray(p); format("\n"); - GenerateByteSize(printer); + GenerateByteSize(p); format("\n"); - GenerateMergeFrom(printer); + GenerateMergeFrom(p); format("\n"); - GenerateClassSpecificMergeImpl(printer); + GenerateClassSpecificMergeImpl(p); format("\n"); - GenerateCopyFrom(printer); + GenerateCopyFrom(p); format("\n"); - GenerateIsInitialized(printer); + GenerateIsInitialized(p); format("\n"); } @@ -2197,14 +2032,19 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) { format( "void $classname$::PrepareSplitMessageForWrite() {\n" " if (IsSplitMessageDefault()) {\n" - " $split$ = CreateSplitMessage(GetArenaForAllocation());\n" + " void* chunk = " + "::PROTOBUF_NAMESPACE_ID::internal::CreateSplitMessageGeneric(" + "GetArenaForAllocation(), &$1$, sizeof(Impl_::Split), this, &$2$);\n" + " $split$ = reinterpret_cast<Impl_::Split*>(chunk);\n" " }\n" - "}\n"); + "}\n", + DefaultInstanceName(descriptor_, options_, /*split=*/true), + DefaultInstanceName(descriptor_, options_, /*split=*/false)); } - GenerateVerify(printer); + GenerateVerify(p); - GenerateSwap(printer); + GenerateSwap(p); format("\n"); if (HasDescriptorMethods(descriptor_->file(), options_)) { @@ -2242,9 +2082,10 @@ void MessageGenerator::GenerateClassMethods(io::Printer* printer) { } } -std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( - io::Printer* printer) { - Formatter format(printer, variables_); +std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(io::Printer* p) { + auto v = p->WithVars(ClassVars(descriptor_, options_)); + auto t = p->WithVars(MakeTrackerCalls(descriptor_, options_)); + Formatter format(p); if (!has_bit_indices_.empty() || IsMapEntryMessage(descriptor_)) { format("PROTOBUF_FIELD_OFFSET($classtype$, $has_bits$),\n"); @@ -2274,15 +2115,20 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( } else { format("~0u, // no _inlined_string_donated_\n"); } - const int kNumGenericOffsets = 6; // the number of fixed offsets above + if (ShouldSplit(descriptor_, options_)) { + format( + "PROTOBUF_FIELD_OFFSET($classtype$, $split$),\n" + "sizeof($classtype$::Impl_::Split),\n"); + } else { + format( + "~0u, // no _split_\n" + "~0u, // no sizeof(Split)\n"); + } + const int kNumGenericOffsets = 8; // the number of fixed offsets above const size_t offsets = kNumGenericOffsets + descriptor_->field_count() + descriptor_->real_oneof_decl_count(); size_t entries = offsets; for (auto field : FieldRange(descriptor_)) { - if (IsFieldStripped(field, options_)) { - format("~0u, // stripped\n"); - continue; - } // TODO(sbenza): We should not have an entry in the offset table for fields // that do not use them. if (field->options().weak() || field->real_containing_oneof()) { @@ -2293,7 +2139,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( format("PROTOBUF_FIELD_OFFSET($classtype$$1$, $2$)", ShouldSplit(field, options_) ? "::Impl_::Split" : "", ShouldSplit(field, options_) - ? FieldName(field) + "_" + ? y_absl::StrCat(FieldName(field), "_") : FieldMemberName(field, /*cold=*/false)); } @@ -2302,12 +2148,17 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( // offset of the field, so that the information is available when // reflectively accessing the field at run time. // - // Embed whether the field is eagerly verified lazy or inlined string to the - // LSB of the offset. + // We embed whether the field is cold to the MSB of the offset, and whether + // the field is eagerly verified lazy or inlined string to the LSB of the + // offset. + + if (ShouldSplit(field, options_)) { + format(" | ::_pbi::kSplitFieldOffsetMask /*split*/"); + } if (IsEagerlyVerifiedLazy(field, options_, scc_analyzer_)) { - format(" | 0x1u // eagerly verified lazy\n"); + format(" | 0x1u /*eagerly verified lazy*/"); } else if (IsStringInlined(field, options_)) { - format(" | 0x1u // inlined\n"); + format(" | 0x1u /*inlined*/"); } format(",\n"); } @@ -2317,7 +2168,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( format("PROTOBUF_FIELD_OFFSET($classtype$, _impl_.$1$_),\n", oneof->name()); count++; } - GOOGLE_CHECK_EQ(count, descriptor_->real_oneof_decl_count()); + Y_ABSL_CHECK_EQ(count, descriptor_->real_oneof_decl_count()); if (IsMapEntryMessage(descriptor_)) { entries += 2; @@ -2328,7 +2179,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( entries += has_bit_indices_.size(); for (int i = 0; i < has_bit_indices_.size(); i++) { const TProtoStringType index = - has_bit_indices_[i] >= 0 ? StrCat(has_bit_indices_[i]) : "~0u"; + has_bit_indices_[i] >= 0 ? y_absl::StrCat(has_bit_indices_[i]) : "~0u"; format("$1$,\n", index); } } @@ -2337,7 +2188,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( for (int inlined_string_index : inlined_string_indices_) { const TProtoStringType index = inlined_string_index >= 0 - ? StrCat(inlined_string_index, ", // inlined_string_index") + ? y_absl::StrCat(inlined_string_index, ", // inlined_string_index") : "~0u,"; format("$1$\n", index); } @@ -2346,15 +2197,13 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( return std::make_pair(entries, offsets); } -void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) { +void MessageGenerator::GenerateSharedConstructorCode(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; - Formatter format(printer, variables_); + Formatter format(p); format( - "inline void $classname$::SharedCtor(\n" - " ::_pb::Arena* arena, bool is_message_owned) {\n" - " (void)arena;\n" - " (void)is_message_owned;\n"); + "inline void $classname$::SharedCtor(::_pb::Arena* arena) {\n" + " (void)arena;\n"); format.Indent(); // Impl_ _impl_. @@ -2389,17 +2238,23 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) { // Initialize member variables with arena constructor. for (auto field : optimized_order_) { - GOOGLE_DCHECK(!IsFieldStripped(field, options_)); if (ShouldSplit(field, options_)) { continue; } put_sep(); - field_generators_.get(field).GenerateAggregateInitializer(printer); + field_generators_.get(field).GenerateAggregateInitializer(p); } if (ShouldSplit(descriptor_, options_)) { put_sep(); - format("decltype($split$){reinterpret_cast<Impl_::Split*>(&$1$)}", - DefaultInstanceName(descriptor_, options_, /*split=*/true)); + // We can't assign the default split to this->split without the const_cast + // because the former is a const. The const_cast is safe because we don't + // intend to modify the default split through this pointer, and we also + // expect the default split to be in the rodata section which is protected + // from mutation. + format( + "decltype($split$){const_cast<Impl_::Split*>" + "(reinterpret_cast<const Impl_::Split*>(&$1$))}", + DefaultInstanceName(descriptor_, options_, /*split=*/true)); } for (auto oneof : OneOfRange(descriptor_)) { put_sep(); @@ -2436,13 +2291,7 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) { // is needed. format("if (arena != nullptr) {\n"); if (NeedsArenaDestructor() == ArenaDtorNeeds::kOnDemand) { - format( - " if (!is_message_owned) {\n" - " $inlined_string_donated_array$[0] = ~0u;\n" - " } else {\n" - // We should not register ArenaDtor for MOA. - " $inlined_string_donated_array$[0] = 0xFFFFFFFEu;\n" - " }\n"); + format(" $inlined_string_donated_array$[0] = ~0u;\n"); } else { format(" $inlined_string_donated_array$[0] = 0xFFFFFFFEu;\n"); } @@ -2457,7 +2306,14 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) { if (ShouldSplit(field, options_)) { continue; } - field_generators_.get(field).GenerateConstructorCode(printer); + field_generators_.get(field).GenerateConstructorCode(p); + } + + if (ShouldForceAllocationOnConstruction(descriptor_, options_)) { + format( + "#ifdef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION\n" + "$mutable_unknown_fields$;\n" + "#endif // PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION\n"); } for (auto oneof : OneOfRange(descriptor_)) { @@ -2468,49 +2324,12 @@ void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) { format("}\n\n"); } -void MessageGenerator::GenerateCreateSplitMessage(io::Printer* printer) { - Formatter format(printer, variables_); - format( - "$classname$::Impl_::Split* " - "$classname$::CreateSplitMessage(::$proto_ns$::Arena* arena) {\n"); - format.Indent(); - const char* field_sep = " "; - const auto put_sep = [&] { - format("\n$1$ ", field_sep); - field_sep = ","; - }; - format( - "const size_t size = sizeof(Impl_::Split);\n" - "void* chunk = (arena == nullptr) ?\n" - " ::operator new(size) :\n" - " arena->AllocateAligned(size, alignof(Impl_::Split));\n" - "Impl_::Split* ptr = reinterpret_cast<Impl_::Split*>(chunk);\n" - "new (ptr) Impl_::Split{"); - format.Indent(); - for (const FieldDescriptor* field : optimized_order_) { - GOOGLE_DCHECK(!IsFieldStripped(field, options_)); - if (ShouldSplit(field, options_)) { - put_sep(); - field_generators_.get(field).GenerateAggregateInitializer(printer); - } - } - format.Outdent(); - format("};\n"); - for (const FieldDescriptor* field : optimized_order_) { - GOOGLE_DCHECK(!IsFieldStripped(field, options_)); - if (ShouldSplit(field, options_)) { - field_generators_.get(field).GenerateCreateSplitMessageCode(printer); - } - } - format("return ptr;\n"); - format.Outdent(); - format("}\n"); -} - -void MessageGenerator::GenerateInitDefaultSplitInstance(io::Printer* printer) { +void MessageGenerator::GenerateInitDefaultSplitInstance(io::Printer* p) { if (!ShouldSplit(descriptor_, options_)) return; - Formatter format(printer, variables_); + auto v = p->WithVars(ClassVars(descriptor_, options_)); + auto t = p->WithVars(MakeTrackerCalls(descriptor_, options_)); + Formatter format(p); const char* field_sep = " "; const auto put_sep = [&] { format("\n$1$ ", field_sep); @@ -2519,15 +2338,14 @@ void MessageGenerator::GenerateInitDefaultSplitInstance(io::Printer* printer) { for (const auto* field : optimized_order_) { if (ShouldSplit(field, options_)) { put_sep(); - field_generators_.get(field).GenerateConstexprAggregateInitializer( - printer); + field_generators_.get(field).GenerateConstexprAggregateInitializer(p); } } } -void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) { +void MessageGenerator::GenerateSharedDestructorCode(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; - Formatter format(printer, variables_); + Formatter format(p); format("inline void $classname$::SharedDtor() {\n"); format.Indent(); @@ -2543,7 +2361,7 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) { if (ShouldSplit(field, options_)) { continue; } - field_generators_.get(field).GenerateDestructorCode(printer); + field_generators_.get(field).GenerateDestructorCode(p); } if (ShouldSplit(descriptor_, options_)) { format("if (!IsSplitMessageDefault()) {\n"); @@ -2551,7 +2369,7 @@ void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) { format("auto* $cached_split_ptr$ = $split$;\n"); for (auto field : optimized_order_) { if (ShouldSplit(field, options_)) { - field_generators_.get(field).GenerateDestructorCode(printer); + field_generators_.get(field).GenerateDestructorCode(p); } } format("delete $cached_split_ptr$;\n"); @@ -2586,17 +2404,16 @@ ArenaDtorNeeds MessageGenerator::NeedsArenaDestructor() const { if (HasSimpleBaseClass(descriptor_, options_)) return ArenaDtorNeeds::kNone; ArenaDtorNeeds needs = ArenaDtorNeeds::kNone; for (const auto* field : FieldRange(descriptor_)) { - if (IsFieldStripped(field, options_)) continue; needs = std::max(needs, field_generators_.get(field).NeedsArenaDestructor()); } return needs; } -void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) { - GOOGLE_CHECK(NeedsArenaDestructor() > ArenaDtorNeeds::kNone); +void MessageGenerator::GenerateArenaDestructorCode(io::Printer* p) { + Y_ABSL_CHECK(NeedsArenaDestructor() > ArenaDtorNeeds::kNone); - Formatter format(printer, variables_); + Formatter format(p); // Generate the ArenaDtor() method. Track whether any fields actually produced // code that needs to be called. @@ -2611,19 +2428,15 @@ void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) { // Process non-oneof fields first. for (auto field : optimized_order_) { - if (IsFieldStripped(field, options_) || ShouldSplit(field, options_)) - continue; - const FieldGenerator& fg = field_generators_.get(field); - fg.GenerateArenaDestructorCode(printer); + if (ShouldSplit(field, options_)) continue; + field_generators_.get(field).GenerateArenaDestructorCode(p); } if (ShouldSplit(descriptor_, options_)) { format("if (!_this->IsSplitMessageDefault()) {\n"); format.Indent(); for (auto field : optimized_order_) { - if (IsFieldStripped(field, options_) || !ShouldSplit(field, options_)) - continue; - const FieldGenerator& fg = field_generators_.get(field); - fg.GenerateArenaDestructorCode(printer); + if (!ShouldSplit(field, options_)) continue; + field_generators_.get(field).GenerateArenaDestructorCode(p); } format.Outdent(); format("}\n"); @@ -2632,8 +2445,7 @@ void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) { // Process oneof fields. for (auto oneof : OneOfRange(descriptor_)) { for (auto field : FieldRange(oneof)) { - if (IsFieldStripped(field, options_)) continue; - field_generators_.get(field).GenerateArenaDestructorCode(printer); + field_generators_.get(field).GenerateArenaDestructorCode(p); } } @@ -2641,8 +2453,10 @@ void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) { format("}\n"); } -void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) { - Formatter format(printer, variables_); +void MessageGenerator::GenerateConstexprConstructor(io::Printer* p) { + auto v = p->WithVars(ClassVars(descriptor_, options_)); + auto t = p->WithVars(MakeTrackerCalls(descriptor_, options_)); + Formatter format(p); if (IsMapEntryMessage(descriptor_) || !HasImplData(descriptor_, options_)) { format( @@ -2685,12 +2499,11 @@ void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) { continue; } put_sep(); - field_generators_.get(field).GenerateConstexprAggregateInitializer( - printer); + field_generators_.get(field).GenerateConstexprAggregateInitializer(p); } if (ShouldSplit(descriptor_, options_)) { put_sep(); - format("/*decltype($split$)*/&$1$._instance", + format("/*decltype($split$)*/const_cast<Impl_::Split*>(&$1$._instance)", DefaultInstanceName(descriptor_, options_, /*split=*/true)); } @@ -2725,8 +2538,8 @@ void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) { format("} {}\n"); } -void MessageGenerator::GenerateCopyConstructorBody(io::Printer* printer) const { - Formatter format(printer, variables_); +void MessageGenerator::GenerateCopyConstructorBody(io::Printer* p) const { + Formatter format(p); const RunMap runs = FindRuns(optimized_order_, [this](const FieldDescriptor* field) { @@ -2735,20 +2548,14 @@ void MessageGenerator::GenerateCopyConstructorBody(io::Printer* printer) const { TProtoStringType pod_template = "::memcpy(&$first$, &from.$first$,\n" - " static_cast<size_t>(reinterpret_cast<char*>(&$last$) -\n" + " static_cast<::size_t>(reinterpret_cast<char*>(&$last$) -\n" " reinterpret_cast<char*>(&$first$)) + sizeof($last$));\n"; - if (ShouldSplit(descriptor_, options_)) { - format("if (!from.IsSplitMessageDefault()) {\n"); - format.Indent(); - format("_this->PrepareSplitMessageForWrite();\n"); - for (auto field : optimized_order_) { - if (ShouldSplit(field, options_)) { - field_generators_.get(field).GenerateCopyConstructorCode(printer); - } - } - format.Outdent(); - format("}\n"); + if (ShouldForceAllocationOnConstruction(descriptor_, options_)) { + format( + "#ifdef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION\n" + "$mutable_unknown_fields$;\n" + "#endif // PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION\n"); } for (size_t i = 0; i < optimized_order_.size(); ++i) { @@ -2768,33 +2575,47 @@ void MessageGenerator::GenerateCopyConstructorBody(io::Printer* printer) const { const TProtoStringType last_field_name = FieldMemberName(optimized_order_[i + run_length - 1], /*cold=*/false); - format.Set("first", first_field_name); - format.Set("last", last_field_name); - + auto v = p->WithVars({ + {"first", first_field_name}, + {"last", last_field_name}, + }); format(pod_template.c_str()); i += run_length - 1; // ++i at the top of the loop. } else { - field_generators_.get(field).GenerateCopyConstructorCode(printer); + field_generators_.get(field).GenerateCopyConstructorCode(p); } } + + if (ShouldSplit(descriptor_, options_)) { + format("if (!from.IsSplitMessageDefault()) {\n"); + format.Indent(); + format("_this->PrepareSplitMessageForWrite();\n"); + // TODO(b/122856539): cache the split pointers. + for (auto field : optimized_order_) { + if (ShouldSplit(field, options_)) { + field_generators_.get(field).GenerateCopyConstructorCode(p); + } + } + format.Outdent(); + format("}\n"); + } } -void MessageGenerator::GenerateStructors(io::Printer* printer) { - Formatter format(printer, variables_); +void MessageGenerator::GenerateStructors(io::Printer* p) { + Formatter format(p); format( - "$classname$::$classname$(::$proto_ns$::Arena* arena,\n" - " bool is_message_owned)\n" - " : $1$(arena, is_message_owned) {\n", + "$classname$::$classname$(::$proto_ns$::Arena* arena)\n" + " : $1$(arena) {\n", SuperClassName(descriptor_, options_)); if (!HasSimpleBaseClass(descriptor_, options_)) { - format(" SharedCtor(arena, is_message_owned);\n"); + format(" SharedCtor(arena);\n"); if (NeedsArenaDestructor() == ArenaDtorNeeds::kRequired) { format( - " if (arena != nullptr && !is_message_owned) {\n" + " if (arena != nullptr) {\n" " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n" " }\n"); } @@ -2803,9 +2624,30 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" "}\n"); - std::map<TProtoStringType, TProtoStringType> vars; - SetUnknownFieldsVariable(descriptor_, options_, &vars); - format.AddMap(vars); + // If the message contains only scalar fields (ints and enums), + // then we can copy the entire impl_ section with a single statement. + bool copy_construct_impl = + !ShouldSplit(descriptor_, options_) && + !HasSimpleBaseClass(descriptor_, options_) && + (descriptor_->extension_range_count() == 0 && + descriptor_->real_oneof_decl_count() == 0 && num_weak_fields_ == 0); + for (const auto& field : optimized_order_) { + if (!copy_construct_impl) break; + if (field->is_repeated() || field->is_extension()) { + copy_construct_impl = false; + } else if (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM && + field->cpp_type() != FieldDescriptor::CPPTYPE_INT32 && + field->cpp_type() != FieldDescriptor::CPPTYPE_INT64 && + field->cpp_type() != FieldDescriptor::CPPTYPE_UINT32 && + field->cpp_type() != FieldDescriptor::CPPTYPE_UINT64 && + field->cpp_type() != FieldDescriptor::CPPTYPE_FLOAT && + field->cpp_type() != FieldDescriptor::CPPTYPE_DOUBLE && + field->cpp_type() != FieldDescriptor::CPPTYPE_BOOL) { + copy_construct_impl = false; + } else { + // non-repeated integer fields are fine to copy en masse. + } + } // Generate the copy constructor. if (UsingImplicitWeakFields(descriptor_->file(), options_)) { @@ -2818,6 +2660,16 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { " : $classname$() {\n" " MergeFrom(from);\n" "}\n"); + } else if (copy_construct_impl) { + format( + "$classname$::$classname$(const $classname$& from)\n" + " : $superclass$(), _impl_(from._impl_) {\n" + " _internal_metadata_.MergeFrom<$unknown_fields_type$>(\n" + " from._internal_metadata_);\n"); + format( + " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" + "}\n" + "\n"); } else { format( "$classname$::$classname$(const $classname$& from)\n" @@ -2863,12 +2715,14 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { continue; } put_sep(); - field_generators_.get(field).GenerateCopyAggregateInitializer(printer); + field_generators_.get(field).GenerateCopyAggregateInitializer(p); } if (ShouldSplit(descriptor_, options_)) { put_sep(); - format("decltype($split$){reinterpret_cast<Impl_::Split*>(&$1$)}", - DefaultInstanceName(descriptor_, options_, /*split=*/true)); + format( + "decltype($split$){const_cast<Impl_::Split*>" + "(reinterpret_cast<const Impl_::Split*>(&$1$))}", + DefaultInstanceName(descriptor_, options_, /*split=*/true)); } for (auto oneof : OneOfRange(descriptor_)) { put_sep(); @@ -2907,7 +2761,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { "from.$extensions$);\n"); } - GenerateCopyConstructorBody(printer); + GenerateCopyConstructorBody(p); // Copy oneof fields. Oneof field requires oneof case check. for (auto oneof : OneOfRange(descriptor_)) { @@ -2919,9 +2773,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { for (auto field : FieldRange(oneof)) { format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); - if (!IsFieldStripped(field, options_)) { - field_generators_.get(field).GenerateMergingCode(printer); - } + field_generators_.get(field).GenerateMergingCode(p); format("break;\n"); format.Outdent(); format("}\n"); @@ -2930,7 +2782,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { "case $1$_NOT_SET: {\n" " break;\n" "}\n", - ToUpper(oneof->name())); + y_absl::AsciiStrToUpper(oneof->name())); format.Outdent(); format("}\n"); } @@ -2943,11 +2795,7 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { } // Generate the shared constructor code. - GenerateSharedConstructorCode(printer); - - if (ShouldSplit(descriptor_, options_)) { - GenerateCreateSplitMessage(printer); - } + GenerateSharedConstructorCode(p); // Generate the destructor. if (!HasSimpleBaseClass(descriptor_, options_)) { @@ -2977,11 +2825,11 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { } // Generate the shared destructor code. - GenerateSharedDestructorCode(printer); + GenerateSharedDestructorCode(p); // Generate the arena-specific destructor code. if (NeedsArenaDestructor() > ArenaDtorNeeds::kNone) { - GenerateArenaDestructorCode(printer); + GenerateArenaDestructorCode(p); } if (!HasSimpleBaseClass(descriptor_, options_)) { @@ -2993,8 +2841,10 @@ void MessageGenerator::GenerateStructors(io::Printer* printer) { } } -void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) { - Formatter format(printer, variables_); +void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* p) { + auto v = p->WithVars(ClassVars(descriptor_, options_)); + auto t = p->WithVars(MakeTrackerCalls(descriptor_, options_)); + Formatter format(p); format( "template<> " "PROTOBUF_NOINLINE $classtype$*\n" @@ -3003,9 +2853,9 @@ void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) { "}\n"); } -void MessageGenerator::GenerateClear(io::Printer* printer) { +void MessageGenerator::GenerateClear(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; - Formatter format(printer, variables_); + Formatter format(p); // The maximum number of bytes we will memset to zero without checking their // hasbit to see if a zero-init is necessary. @@ -3031,7 +2881,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { // checks all hasbits in the chunk and skips it if none are set. int zero_init_bytes = 0; for (const auto& field : optimized_order_) { - if (CanInitializeByZeroing(field)) { + if (CanClearByZeroing(field)) { zero_init_bytes += EstimateAlignmentSize(field); } } @@ -3044,12 +2894,12 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { chunk_count++; // This predicate guarantees that there is only a single zero-init // (memset) per chunk, and if present it will be at the beginning. - bool same = HasByteIndex(a) == HasByteIndex(b) && - a->is_repeated() == b->is_repeated() && - ShouldSplit(a, options_) == ShouldSplit(b, options_) && - (CanInitializeByZeroing(a) == CanInitializeByZeroing(b) || - (CanInitializeByZeroing(a) && - (chunk_count == 1 || merge_zero_init))); + bool same = + HasByteIndex(a) == HasByteIndex(b) && + a->is_repeated() == b->is_repeated() && + ShouldSplit(a, options_) == ShouldSplit(b, options_) && + (CanClearByZeroing(a) == CanClearByZeroing(b) || + (CanClearByZeroing(a) && (chunk_count == 1 || merge_zero_init))); if (!same) chunk_count = 0; return same; }); @@ -3057,18 +2907,29 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { ColdChunkSkipper cold_skipper(descriptor_, options_, chunks, has_bit_indices_, kColdRatio); int cached_has_word_index = -1; - - for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { + bool first_split_chunk_processed = false; + for (size_t chunk_index = 0; chunk_index < chunks.size(); chunk_index++) { std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index]; - cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer); + cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", p); const FieldDescriptor* memset_start = nullptr; const FieldDescriptor* memset_end = nullptr; bool saw_non_zero_init = false; - bool chunk_is_cold = !chunk.empty() && ShouldSplit(chunk.front(), options_); + bool chunk_is_split = + !chunk.empty() && ShouldSplit(chunk.front(), options_); + // All chunks after the first split chunk should also be split. + Y_ABSL_CHECK(!first_split_chunk_processed || chunk_is_split); + if (chunk_is_split && !first_split_chunk_processed) { + // Some fields are cleared without checking has_bit. So we add the + // condition here to avoid writing to the default split instance. + format("if (!IsSplitMessageDefault()) {\n"); + format.Indent(); + first_split_chunk_processed = true; + } + for (const auto& field : chunk) { - if (CanInitializeByZeroing(field)) { - GOOGLE_CHECK(!saw_non_zero_init); + if (CanClearByZeroing(field)) { + Y_ABSL_CHECK(!saw_non_zero_init); if (!memset_start) memset_start = field; memset_end = field; } else { @@ -3089,13 +2950,13 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { // Emit an if() that will let us skip the whole chunk if none are set. arc_ui32 chunk_mask = GenChunkMask(chunk, has_bit_indices_); TProtoStringType chunk_mask_str = - StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8)); + y_absl::StrCat(y_absl::Hex(chunk_mask, y_absl::kZeroPad8)); // 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. - GOOGLE_DCHECK_LE(2, popcnt(chunk_mask)); - GOOGLE_DCHECK_GE(8, popcnt(chunk_mask)); + Y_ABSL_DCHECK_LE(2, popcnt(chunk_mask)); + Y_ABSL_DCHECK_GE(8, popcnt(chunk_mask)); if (cached_has_word_index != HasWordIndex(chunk.front())) { cached_has_word_index = HasWordIndex(chunk.front()); @@ -3105,31 +2966,25 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { format.Indent(); } - if (chunk_is_cold) { - format("if (!IsSplitMessageDefault()) {\n"); - format.Indent(); - } - if (memset_start) { if (memset_start == memset_end) { // For clarity, do not memset a single field. - field_generators_.get(memset_start) - .GenerateMessageClearingCode(printer); + field_generators_.get(memset_start).GenerateMessageClearingCode(p); } else { - GOOGLE_CHECK_EQ(chunk_is_cold, ShouldSplit(memset_start, options_)); - GOOGLE_CHECK_EQ(chunk_is_cold, ShouldSplit(memset_end, options_)); + Y_ABSL_CHECK_EQ(chunk_is_split, ShouldSplit(memset_start, options_)); + Y_ABSL_CHECK_EQ(chunk_is_split, ShouldSplit(memset_end, options_)); format( - "::memset(&$1$, 0, static_cast<size_t>(\n" + "::memset(&$1$, 0, static_cast<::size_t>(\n" " reinterpret_cast<char*>(&$2$) -\n" " reinterpret_cast<char*>(&$1$)) + sizeof($2$));\n", - FieldMemberName(memset_start, chunk_is_cold), - FieldMemberName(memset_end, chunk_is_cold)); + FieldMemberName(memset_start, chunk_is_split), + FieldMemberName(memset_end, chunk_is_split)); } } // Clear all non-zero-initializable fields in the chunk. for (const auto& field : chunk) { - if (CanInitializeByZeroing(field)) continue; + if (CanClearByZeroing(field)) continue; // It's faster to just overwrite primitive types, but we should only // clear strings and messages if they were set. // @@ -3140,11 +2995,10 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); if (have_enclosing_if) { - PrintPresenceCheck(format, field, has_bit_indices_, printer, - &cached_has_word_index); + PrintPresenceCheck(field, has_bit_indices_, p, &cached_has_word_index); } - field_generators_.get(field).GenerateMessageClearingCode(printer); + field_generators_.get(field).GenerateMessageClearingCode(p); if (have_enclosing_if) { format.Outdent(); @@ -3152,17 +3006,19 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { } } - if (chunk_is_cold) { + if (have_outer_if) { format.Outdent(); format("}\n"); } - if (have_outer_if) { - format.Outdent(); - format("}\n"); + if (chunk_index == chunks.size() - 1) { + if (first_split_chunk_processed) { + format.Outdent(); + format("}\n"); + } } - if (cold_skipper.OnEndChunk(chunk_index, printer)) { + if (cold_skipper.OnEndChunk(chunk_index, p)) { // Reset here as it may have been updated in just closed if statement. cached_has_word_index = -1; } @@ -3184,21 +3040,18 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { format("$has_bits$.Clear();\n"); } - std::map<TProtoStringType, TProtoStringType> vars; - SetUnknownFieldsVariable(descriptor_, options_, &vars); - format.AddMap(vars); format("_internal_metadata_.Clear<$unknown_fields_type$>();\n"); format.Outdent(); format("}\n"); } -void MessageGenerator::GenerateOneofClear(io::Printer* printer) { +void MessageGenerator::GenerateOneofClear(io::Printer* p) { // Generated function clears the active field and union case (e.g. foo_case_). int i = 0; for (auto oneof : OneOfRange(descriptor_)) { - Formatter format(printer, variables_); - format.Set("oneofname", oneof->name()); + Formatter format(p); + auto v = p->WithVars({{"oneofname", oneof->name()}}); format( "void $classname$::clear_$oneofname$() {\n" @@ -3210,10 +3063,10 @@ void MessageGenerator::GenerateOneofClear(io::Printer* printer) { format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); // We clear only allocated objects in oneofs - if (!IsStringOrMessage(field) || IsFieldStripped(field, options_)) { + if (!IsStringOrMessage(field)) { format("// No need to clear\n"); } else { - field_generators_.get(field).GenerateClearingCode(printer); + field_generators_.get(field).GenerateClearingCode(p); } format("break;\n"); format.Outdent(); @@ -3223,12 +3076,12 @@ void MessageGenerator::GenerateOneofClear(io::Printer* printer) { "case $1$_NOT_SET: {\n" " break;\n" "}\n", - ToUpper(oneof->name())); + y_absl::AsciiStrToUpper(oneof->name())); format.Outdent(); format( "}\n" "$oneof_case$[$1$] = $2$_NOT_SET;\n", - i, ToUpper(oneof->name())); + i, y_absl::AsciiStrToUpper(oneof->name())); format.Outdent(); format( "}\n" @@ -3237,9 +3090,9 @@ void MessageGenerator::GenerateOneofClear(io::Printer* printer) { } } -void MessageGenerator::GenerateSwap(io::Printer* printer) { +void MessageGenerator::GenerateSwap(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; - Formatter format(printer, variables_); + Formatter format(p); format("void $classname$::InternalSwap($classname$* other) {\n"); format.Indent(); @@ -3252,9 +3105,6 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) { "\n"); } - std::map<TProtoStringType, TProtoStringType> vars; - SetUnknownFieldsVariable(descriptor_, options_, &vars); - format.AddMap(vars); if (HasNonSplitOptionalString(descriptor_, options_)) { format( "auto* lhs_arena = GetArenaForAllocation();\n" @@ -3272,7 +3122,7 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) { const RunMap runs = FindRuns(optimized_order_, [this](const FieldDescriptor* field) { return !ShouldSplit(field, options_) && - CanBeManipulatedAsRawBytes(field, options_, scc_analyzer_); + HasTrivialSwap(field, options_, scc_analyzer_); }); for (size_t i = 0; i < optimized_order_.size(); ++i) { @@ -3293,8 +3143,10 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) { const TProtoStringType last_field_name = FieldMemberName( optimized_order_[i + run_length - 1], /*cold=*/false); - format.Set("first", first_field_name); - format.Set("last", last_field_name); + auto v = p->WithVars({ + {"first", first_field_name}, + {"last", last_field_name}, + }); format( "::PROTOBUF_NAMESPACE_ID::internal::memswap<\n" @@ -3307,7 +3159,7 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) { i += run_length - 1; // ++i at the top of the loop. } else { - field_generators_.get(field).GenerateSwappingCode(printer); + field_generators_.get(field).GenerateSwappingCode(p); } } if (ShouldSplit(descriptor_, options_)) { @@ -3344,8 +3196,8 @@ void MessageGenerator::GenerateSwap(io::Printer* printer) { format("}\n"); } -void MessageGenerator::GenerateMergeFrom(io::Printer* printer) { - Formatter format(printer, variables_); +void MessageGenerator::GenerateMergeFrom(io::Printer* p) { + Formatter format(p); if (!HasSimpleBaseClass(descriptor_, options_)) { if (HasDescriptorMethods(descriptor_->file(), options_)) { // We don't override the generalized MergeFrom (aka that which @@ -3391,10 +3243,11 @@ void MessageGenerator::GenerateMergeFrom(io::Printer* printer) { } } -void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) { +void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; - // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast. - Formatter format(printer, variables_); + // Generate the class-specific MergeFrom, which avoids the Y_ABSL_CHECK and + // cast. + Formatter format(p); if (!HasDescriptorMethods(descriptor_->file(), options_)) { // For messages that don't inherit from Message, just implement MergeFrom // directly. @@ -3445,20 +3298,19 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) { const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index]; bool have_outer_if = chunk.size() > 1 && HasByteIndex(chunk.front()) != kNoHasbit; - cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "from.", - printer); + cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "from.", p); if (have_outer_if) { // Emit an if() that will let us skip the whole chunk if none are set. arc_ui32 chunk_mask = GenChunkMask(chunk, has_bit_indices_); TProtoStringType chunk_mask_str = - StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8)); + y_absl::StrCat(y_absl::Hex(chunk_mask, y_absl::kZeroPad8)); // 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. - GOOGLE_DCHECK_LE(2, popcnt(chunk_mask)); - GOOGLE_DCHECK_GE(8, popcnt(chunk_mask)); + Y_ABSL_DCHECK_LE(2, popcnt(chunk_mask)); + Y_ABSL_DCHECK_GE(8, popcnt(chunk_mask)); if (cached_has_word_index != HasWordIndex(chunk.front())) { cached_has_word_index = HasWordIndex(chunk.front()); @@ -3473,16 +3325,16 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) { // Go back and emit merging code for each of the fields we processed. bool deferred_has_bit_changes = false; for (const auto field : chunk) { - const FieldGenerator& generator = field_generators_.get(field); + const auto& generator = field_generators_.get(field); if (field->is_repeated()) { - generator.GenerateMergingCode(printer); + generator.GenerateMergingCode(p); } else if (field->is_optional() && !HasHasbit(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); + EmitFieldNonDefaultCondition(p, "from.", field); + generator.GenerateMergingCode(p); if (have_enclosing_if) { format.Outdent(); format("}\n"); @@ -3490,18 +3342,20 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) { } else if (field->options().weak() || cached_has_word_index != HasWordIndex(field)) { // Check hasbit, not using cached bits. - GOOGLE_CHECK(HasHasbit(field)); - format("if (from._internal_has_$1$()) {\n", FieldName(field)); + Y_ABSL_CHECK(HasHasbit(field)); + auto v = p->WithVars(HasbitVars(HasBitIndex(field))); + format( + "if ((from.$has_bits$[$has_array_index$] & $has_mask$) != 0) {\n"); format.Indent(); - generator.GenerateMergingCode(printer); + generator.GenerateMergingCode(p); format.Outdent(); format("}\n"); } else { // Check hasbit, using cached bits. - GOOGLE_CHECK(HasHasbit(field)); + Y_ABSL_CHECK(HasHasbit(field)); int has_bit_index = has_bit_indices_[field->index()]; - const TProtoStringType mask = StrCat( - strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); + const TProtoStringType mask = y_absl::StrCat( + y_absl::Hex(1u << (has_bit_index % 32), y_absl::kZeroPad8)); format("if (cached_has_bits & 0x$1$u) {\n", mask); format.Indent(); @@ -3509,9 +3363,9 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) { // Defer hasbit modification until the end of chunk. // This can reduce the number of loads/stores by up to 7 per 8 fields. deferred_has_bit_changes = true; - generator.GenerateCopyConstructorCode(printer); + generator.GenerateCopyConstructorCode(p); } else { - generator.GenerateMergingCode(printer); + generator.GenerateMergingCode(p); } format.Outdent(); @@ -3522,7 +3376,7 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) { if (have_outer_if) { if (deferred_has_bit_changes) { // Flush the has bits for the primitives we deferred. - GOOGLE_CHECK_LE(0, cached_has_word_index); + Y_ABSL_CHECK_LE(0, cached_has_word_index); format("_this->$has_bits$[$1$] |= cached_has_bits;\n", cached_has_word_index); } @@ -3531,7 +3385,7 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) { format("}\n"); } - if (cold_skipper.OnEndChunk(chunk_index, printer)) { + if (cold_skipper.OnEndChunk(chunk_index, p)) { // Reset here as it may have been updated in just closed if statement. cached_has_word_index = -1; } @@ -3544,9 +3398,7 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) { for (auto field : FieldRange(oneof)) { format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); - if (!IsFieldStripped(field, options_)) { - field_generators_.get(field).GenerateMergingCode(printer); - } + field_generators_.get(field).GenerateMergingCode(p); format("break;\n"); format.Outdent(); format("}\n"); @@ -3555,7 +3407,7 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) { "case $1$_NOT_SET: {\n" " break;\n" "}\n", - ToUpper(oneof->name())); + y_absl::AsciiStrToUpper(oneof->name())); format.Outdent(); format("}\n"); } @@ -3582,9 +3434,9 @@ void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) { format("}\n"); } -void MessageGenerator::GenerateCopyFrom(io::Printer* printer) { +void MessageGenerator::GenerateCopyFrom(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; - Formatter format(printer, variables_); + Formatter format(p); if (HasDescriptorMethods(descriptor_->file(), options_)) { // We don't override the generalized CopyFrom (aka that which // takes in the Message base class as a parameter); instead we just @@ -3613,21 +3465,22 @@ void MessageGenerator::GenerateCopyFrom(io::Printer* printer) { // It is also disabled if a message has neither message fields nor // extensions, as it's impossible to copy from its descendant. // - // Note that FailIfCopyFromDescendant is implemented by reflection and not - // available for lite runtime. In that case, check if the size of the source - // has changed after Clear. - format("#ifndef NDEBUG\n"); + // Note that IsDescendant is implemented by reflection and not available for + // lite runtime. In that case, check if the size of the source has changed + // after Clear. if (HasDescriptorMethods(descriptor_->file(), options_)) { - format("FailIfCopyFromDescendant(*this, from);\n"); + format( + "$DCHK$(!::_pbi::IsDescendant(*this, from))\n" + " << \"Source of CopyFrom cannot be a descendant of the " + "target.\";\n" + "Clear();\n"); } else { - format("size_t from_size = from.ByteSizeLong();\n"); - } - format( - "#endif\n" - "Clear();\n"); - if (!HasDescriptorMethods(descriptor_->file(), options_)) { 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" @@ -3643,15 +3496,15 @@ void MessageGenerator::GenerateCopyFrom(io::Printer* printer) { format("}\n"); } -void MessageGenerator::GenerateVerify(io::Printer* printer) { +void MessageGenerator::GenerateVerify(io::Printer* p) { } void MessageGenerator::GenerateSerializeOneofFields( - io::Printer* printer, const std::vector<const FieldDescriptor*>& fields) { - Formatter format(printer, variables_); - GOOGLE_CHECK(!fields.empty()); + io::Printer* p, const std::vector<const FieldDescriptor*>& fields) { + Formatter format(p); + Y_ABSL_CHECK(!fields.empty()); if (fields.size() == 1) { - GenerateSerializeOneField(printer, fields[0], -1); + GenerateSerializeOneField(p, fields[0], -1); return; } // We have multiple mutually exclusive choices. Emit a switch statement. @@ -3661,8 +3514,7 @@ void MessageGenerator::GenerateSerializeOneofFields( for (auto field : fields) { format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); - field_generators_.get(field).GenerateSerializeWithCachedSizesToArray( - printer); + field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(p); format("break;\n"); format.Outdent(); format("}\n"); @@ -3674,10 +3526,11 @@ void MessageGenerator::GenerateSerializeOneofFields( "}\n"); } -void MessageGenerator::GenerateSerializeOneField(io::Printer* printer, +void MessageGenerator::GenerateSerializeOneField(io::Printer* p, const FieldDescriptor* field, int cached_has_bits_index) { - Formatter format(printer, variables_); + auto v = p->WithVars(FieldVars(field, options_)); + Formatter format(p); if (!field->options().weak()) { // For weakfields, PrintFieldComment is called during iteration. PrintFieldComment(format, field); @@ -3688,22 +3541,20 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* printer, } else if (HasHasbit(field)) { // Attempt to use the state of cached_has_bits, if possible. int has_bit_index = HasBitIndex(field); + auto v = p->WithVars(HasbitVars(has_bit_index)); if (cached_has_bits_index == has_bit_index / 32) { - const TProtoStringType mask = - StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8)); - - format("if (cached_has_bits & 0x$1$u) {\n", mask); + format("if (cached_has_bits & $has_mask$) {\n"); } else { - format("if (_internal_has_$1$()) {\n", FieldName(field)); + field_generators_.get(field).GenerateIfHasField(p); } format.Indent(); have_enclosing_if = true; } else if (field->is_optional() && !HasHasbit(field)) { - have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field); + have_enclosing_if = EmitFieldNonDefaultCondition(p, "this->", field); } - field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(printer); + field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(p); if (have_enclosing_if) { format.Outdent(); @@ -3713,21 +3564,20 @@ void MessageGenerator::GenerateSerializeOneField(io::Printer* printer, } void MessageGenerator::GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* range) { - std::map<TProtoStringType, TProtoStringType> vars = variables_; - vars["start"] = StrCat(range->start); - vars["end"] = StrCat(range->end); - Formatter format(printer, vars); + io::Printer* p, const Descriptor::ExtensionRange* range) { + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars = variables_; + vars["start"] = y_absl::StrCat(range->start); + vars["end"] = y_absl::StrCat(range->end); + Formatter format(p, vars); format("// Extension range [$start$, $end$)\n"); format( "target = $extensions$._InternalSerialize(\n" "internal_default_instance(), $start$, $end$, target, stream);\n\n"); } -void MessageGenerator::GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) { +void MessageGenerator::GenerateSerializeWithCachedSizesToArray(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; - Formatter format(printer, variables_); + Formatter format(p); if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. format( @@ -3738,9 +3588,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesToArray( " target = $extensions$." "InternalSerializeMessageSetWithCachedSizesToArray(\n" // "internal_default_instance(), target, stream);\n"); - std::map<TProtoStringType, TProtoStringType> vars; - SetUnknownFieldsVariable(descriptor_, options_, &vars); - format.AddMap(vars); + format( " target = ::_pbi::" "InternalSerializeUnknownMessageSetItemsToArray(\n" @@ -3766,14 +3614,14 @@ void MessageGenerator::GenerateSerializeWithCachedSizesToArray( format.Indent(); } - GenerateSerializeWithCachedSizesBody(printer); + GenerateSerializeWithCachedSizesBody(p); if (!ShouldSerializeInOrder(descriptor_, options_)) { format.Outdent(); format("#else // NDEBUG\n"); format.Indent(); - GenerateSerializeWithCachedSizesBodyShuffled(printer); + GenerateSerializeWithCachedSizesBodyShuffled(p); format.Outdent(); format("#endif // !NDEBUG\n"); @@ -3788,10 +3636,9 @@ void MessageGenerator::GenerateSerializeWithCachedSizesToArray( "}\n"); } -void MessageGenerator::GenerateSerializeWithCachedSizesBody( - io::Printer* printer) { +void MessageGenerator::GenerateSerializeWithCachedSizesBody(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; - Formatter format(printer, variables_); + Formatter format(p); // 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" @@ -3799,9 +3646,9 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( // compiler's emitted code might check has_y() even when has_x() is true. class LazySerializerEmitter { public: - LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer) + LazySerializerEmitter(MessageGenerator* mg, io::Printer* p) : mg_(mg), - format_(printer), + p_(p), eager_(IsProto3(mg->descriptor_->file())), cached_has_bit_index_(kNoHasbit) {} @@ -3810,6 +3657,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( // If conditions allow, try to accumulate a run of fields from the same // oneof, and handle them at the next Flush(). void Emit(const FieldDescriptor* field) { + Formatter format(p_); if (eager_ || MustFlush(field)) { Flush(); } @@ -3825,14 +3673,13 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( // Reload. int new_index = has_bit_index / 32; - format_("cached_has_bits = _impl_._has_bits_[$1$];\n", new_index); + format("cached_has_bits = _impl_._has_bits_[$1$];\n", new_index); cached_has_bit_index_ = new_index; } } - mg_->GenerateSerializeOneField(format_.printer(), field, - cached_has_bit_index_); + mg_->GenerateSerializeOneField(p_, field, cached_has_bit_index_); } else { v_.push_back(field); } @@ -3846,7 +3693,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( void Flush() { if (!v_.empty()) { - mg_->GenerateSerializeOneofFields(format_.printer(), v_); + mg_->GenerateSerializeOneofFields(p_, v_); v_.clear(); } } @@ -3860,8 +3707,8 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( } MessageGenerator* mg_; - Formatter format_; - const bool eager_; + io::Printer* p_; + bool eager_; std::vector<const FieldDescriptor*> v_; // cached_has_bit_index_ maintains that: @@ -3872,8 +3719,8 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( class LazyExtensionRangeEmitter { public: - LazyExtensionRangeEmitter(MessageGenerator* mg, io::Printer* printer) - : mg_(mg), format_(printer) {} + LazyExtensionRangeEmitter(MessageGenerator* mg, io::Printer* p) + : mg_(mg), p_(p) {} void AddToRange(const Descriptor::ExtensionRange* range) { if (!has_current_range_) { @@ -3889,15 +3736,14 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( void Flush() { if (has_current_range_) { - mg_->GenerateSerializeOneExtensionRange(format_.printer(), - ¤t_combined_range_); + mg_->GenerateSerializeOneExtensionRange(p_, ¤t_combined_range_); } has_current_range_ = false; } private: MessageGenerator* mg_; - Formatter format_; + io::Printer* p_; bool has_current_range_ = false; Descriptor::ExtensionRange current_combined_range_; }; @@ -3947,8 +3793,8 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( // Merge the fields and the extension ranges, both sorted by field number. { - LazySerializerEmitter e(this, printer); - LazyExtensionRangeEmitter re(this, printer); + LazySerializerEmitter e(this, p); + LazyExtensionRangeEmitter re(this, p); LargestWeakFieldHolder largest_weak_field; int i, j; for (i = 0, j = 0; @@ -3957,9 +3803,6 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( (i < descriptor_->field_count() && ordered_fields[i]->number() < sorted_extensions[j]->start)) { const FieldDescriptor* field = ordered_fields[i++]; - if (IsFieldStripped(field, options_)) { - continue; - } re.Flush(); if (field->options().weak()) { largest_weak_field.ReplaceIfLarger(field); @@ -3978,9 +3821,6 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( e.EmitIfNotNull(largest_weak_field.Release()); } - std::map<TProtoStringType, TProtoStringType> vars; - SetUnknownFieldsVariable(descriptor_, options_, &vars); - format.AddMap(vars); format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n"); format.Indent(); if (UseUnknownFieldSet(descriptor_->file(), options_)) { @@ -3999,8 +3839,8 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBody( } void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( - io::Printer* printer) { - Formatter format(printer, variables_); + io::Printer* p) { + Formatter format(p); std::vector<const FieldDescriptor*> ordered_fields = SortFieldsByNumber(descriptor_); @@ -4021,7 +3861,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( int num_fields = ordered_fields.size() + sorted_extensions.size(); constexpr int kLargePrime = 1000003; - GOOGLE_CHECK_LT(num_fields, kLargePrime) + Y_ABSL_CHECK_LT(num_fields, kLargePrime) << "Prime offset must be greater than the number of fields to ensure " "those are coprime."; @@ -4042,7 +3882,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( format("case $1$: {\n", index++); format.Indent(); - GenerateSerializeOneField(printer, f, -1); + GenerateSerializeOneField(p, f, -1); format("break;\n"); format.Outdent(); @@ -4053,7 +3893,7 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( format("case $1$: {\n", index++); format.Indent(); - GenerateSerializeOneExtensionRange(printer, r); + GenerateSerializeOneExtensionRange(p, r); format("break;\n"); format.Outdent(); @@ -4070,9 +3910,6 @@ void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled( format.Outdent(); format("}\n"); - std::map<TProtoStringType, TProtoStringType> vars; - SetUnknownFieldsVariable(descriptor_, options_, &vars); - format.AddMap(vars); format("if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n"); format.Indent(); if (UseUnknownFieldSet(descriptor_->file(), options_)) { @@ -4106,20 +3943,17 @@ std::vector<arc_ui32> MessageGenerator::RequiredFieldsBitMask() const { return masks; } -void MessageGenerator::GenerateByteSize(io::Printer* printer) { +void MessageGenerator::GenerateByteSize(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; - Formatter format(printer, variables_); + Formatter format(p); if (descriptor_->options().message_set_wire_format()) { // Special-case MessageSet. - std::map<TProtoStringType, TProtoStringType> vars; - SetUnknownFieldsVariable(descriptor_, options_, &vars); - format.AddMap(vars); format( - "size_t $classname$::ByteSizeLong() const {\n" + "::size_t $classname$::ByteSizeLong() const {\n" "$annotate_bytesize$" "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n" - " size_t total_size = $extensions$.MessageSetByteSize();\n" + " ::size_t total_size = $extensions$.MessageSetByteSize();\n" " if ($have_unknown_fields$) {\n" " total_size += ::_pbi::\n" " ComputeUnknownMessageSetItemsSize($unknown_fields$);\n" @@ -4136,20 +3970,18 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { // Emit a function (rarely used, we hope) that handles the required fields // by checking for each one individually. format( - "size_t $classname$::RequiredFieldsByteSizeFallback() const {\n" + "::size_t $classname$::RequiredFieldsByteSizeFallback() const {\n" "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:" "$full_name$)\n"); format.Indent(); - format("size_t total_size = 0;\n"); + format("::size_t total_size = 0;\n"); for (auto field : optimized_order_) { if (field->is_required()) { - format( - "\n" - "if (_internal_has_$1$()) {\n", - FieldName(field)); + format("\n"); + field_generators_.get(field).GenerateIfHasField(p); format.Indent(); PrintFieldComment(format, field); - field_generators_.get(field).GenerateByteSize(printer); + field_generators_.get(field).GenerateByteSize(p); format.Outdent(); format("}\n"); } @@ -4162,12 +3994,12 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { } format( - "size_t $classname$::ByteSizeLong() const {\n" + "::size_t $classname$::ByteSizeLong() const {\n" "$annotate_bytesize$" "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n"); format.Indent(); format( - "size_t total_size = 0;\n" + "::size_t total_size = 0;\n" "\n"); if (descriptor_->extension_range_count() > 0) { @@ -4176,10 +4008,6 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { "\n"); } - std::map<TProtoStringType, TProtoStringType> vars; - SetUnknownFieldsVariable(descriptor_, options_, &vars); - format.AddMap(vars); - // Handle required fields (if any). We expect all of them to be // present, so emit one conditional that checks for that. If they are all // present then the fast path executes; otherwise the slow path executes. @@ -4194,7 +4022,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { for (auto field : optimized_order_) { if (!field->is_required()) continue; PrintFieldComment(format, field); - field_generators_.get(field).GenerateByteSize(printer); + field_generators_.get(field).GenerateByteSize(p); format("\n"); } format.Outdent(); @@ -4207,9 +4035,9 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { for (auto field : optimized_order_) { if (!field->is_required()) continue; PrintFieldComment(format, field); - format("if (_internal_has_$1$()) {\n", FieldName(field)); + field_generators_.get(field).GenerateIfHasField(p); format.Indent(); - field_generators_.get(field).GenerateByteSize(printer); + field_generators_.get(field).GenerateByteSize(p); format.Outdent(); format("}\n"); } @@ -4239,19 +4067,19 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index]; const bool have_outer_if = chunk.size() > 1 && HasWordIndex(chunk[0]) != kNoHasbit; - cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer); + cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", p); if (have_outer_if) { // Emit an if() that will let us skip the whole chunk if none are set. arc_ui32 chunk_mask = GenChunkMask(chunk, has_bit_indices_); TProtoStringType chunk_mask_str = - StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8)); + y_absl::StrCat(y_absl::Hex(chunk_mask, y_absl::kZeroPad8)); // 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. - GOOGLE_DCHECK_LE(2, popcnt(chunk_mask)); - GOOGLE_DCHECK_GE(8, popcnt(chunk_mask)); + Y_ABSL_DCHECK_LE(2, popcnt(chunk_mask)); + Y_ABSL_DCHECK_GE(8, popcnt(chunk_mask)); if (cached_has_word_index != HasWordIndex(chunk.front())) { cached_has_word_index = HasWordIndex(chunk.front()); @@ -4264,7 +4092,6 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { // Go back and emit checks for each of the fields we processed. for (int j = 0; j < chunk.size(); j++) { const FieldDescriptor* field = chunk[j]; - const FieldGenerator& generator = field_generators_.get(field); bool have_enclosing_if = false; bool need_extra_newline = false; @@ -4274,17 +4101,15 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { // No presence check is required. need_extra_newline = true; } else if (HasHasbit(field)) { - PrintPresenceCheck(format, field, has_bit_indices_, printer, - &cached_has_word_index); + PrintPresenceCheck(field, has_bit_indices_, p, &cached_has_word_index); have_enclosing_if = true; } else { // Without field presence: field is serialized only if it has a // non-default value. - have_enclosing_if = - EmitFieldNonDefaultCondition(printer, "this->", field); + have_enclosing_if = EmitFieldNonDefaultCondition(p, "this->", field); } - generator.GenerateByteSize(printer); + field_generators_.get(field).GenerateByteSize(p); if (have_enclosing_if) { format.Outdent(); @@ -4302,7 +4127,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { format("}\n"); } - if (cold_skipper.OnEndChunk(chunk_index, printer)) { + if (cold_skipper.OnEndChunk(chunk_index, p)) { // Reset here as it may have been updated in just closed if statement. cached_has_word_index = -1; } @@ -4317,9 +4142,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { PrintFieldComment(format, field); format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); - if (!IsFieldStripped(field, options_)) { - field_generators_.get(field).GenerateByteSize(printer); - } + field_generators_.get(field).GenerateByteSize(p); format("break;\n"); format.Outdent(); format("}\n"); @@ -4328,7 +4151,7 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { "case $1$_NOT_SET: {\n" " break;\n" "}\n", - ToUpper(oneof->name())); + y_absl::AsciiStrToUpper(oneof->name())); format.Outdent(); format("}\n"); } @@ -4367,15 +4190,15 @@ void MessageGenerator::GenerateByteSize(io::Printer* printer) { format("}\n"); } -void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { +void MessageGenerator::GenerateIsInitialized(io::Printer* p) { if (HasSimpleBaseClass(descriptor_, options_)) return; - Formatter format(printer, variables_); + Formatter format(p); format("bool $classname$::IsInitialized() const {\n"); format.Indent(); if (descriptor_->extension_range_count() > 0) { format( - "if (!$extensions$.IsInitialized()) {\n" + "if (!$extensions$.IsInitialized(internal_default_instance())) {\n" " return false;\n" "}\n\n"); } @@ -4388,7 +4211,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { // Now check that all non-oneof embedded messages are initialized. for (auto field : optimized_order_) { - field_generators_.get(field).GenerateIsInitialized(printer); + field_generators_.get(field).GenerateIsInitialized(p); } if (num_weak_fields_) { // For Weak fields. @@ -4416,9 +4239,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { for (auto field : FieldRange(oneof)) { format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true)); format.Indent(); - if (!IsFieldStripped(field, options_)) { - field_generators_.get(field).GenerateIsInitialized(printer); - } + field_generators_.get(field).GenerateIsInitialized(p); format("break;\n"); format.Outdent(); format("}\n"); @@ -4427,7 +4248,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { "case $1$_NOT_SET: {\n" " break;\n" "}\n", - ToUpper(oneof->name())); + y_absl::AsciiStrToUpper(oneof->name())); format.Outdent(); format("}\n"); } @@ -4443,4 +4264,4 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.h index 960bea8e5af..f1dcd65ef20 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.h @@ -36,40 +36,38 @@ #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ #include <cstdint> +#include <limits> #include <memory> -#include <set> #include <string> - -#include <google/protobuf/compiler/cpp/field.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/compiler/cpp/message_layout_helper.h> -#include <google/protobuf/compiler/cpp/options.h> -#include <google/protobuf/compiler/cpp/parse_function_generator.h> - -namespace google { -namespace protobuf { -namespace io { -class Printer; // printer.h -} -} // namespace protobuf -} // namespace google +#include <utility> +#include <vector> + +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/cpp/enum.h" +#include "google/protobuf/compiler/cpp/extension.h" +#include "google/protobuf/compiler/cpp/field.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/message_layout_helper.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/compiler/cpp/parse_function_generator.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { - -class EnumGenerator; // enum.h -class ExtensionGenerator; // extension.h - class MessageGenerator { public: - // See generator.cc for the meaning of dllexport_decl. - MessageGenerator(const Descriptor* descriptor, - const std::map<TProtoStringType, TProtoStringType>& vars, - int index_in_file_messages, const Options& options, - MessageSCCAnalyzer* scc_analyzer); - ~MessageGenerator(); + MessageGenerator( + const Descriptor* descriptor, + const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& ignored, + int index_in_file_messages, const Options& options, + MessageSCCAnalyzer* scc_analyzer); + + MessageGenerator(const MessageGenerator&) = delete; + MessageGenerator& operator=(const MessageGenerator&) = delete; + + ~MessageGenerator() = default; // Append the two types of nested generators to the corresponding vector. void AddGenerators( @@ -77,95 +75,94 @@ class MessageGenerator { std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators); // Generate definitions for this class and all its nested types. - void GenerateClassDefinition(io::Printer* printer); + void GenerateClassDefinition(io::Printer* p); // Generate definitions of inline methods (placed at the end of the header // file). - void GenerateInlineMethods(io::Printer* printer); - - // Source file stuff. + void GenerateInlineMethods(io::Printer* p); // Generate all non-inline methods for this class. - void GenerateClassMethods(io::Printer* printer); + void GenerateClassMethods(io::Printer* p); // Generate source file code that should go outside any namespace. - void GenerateSourceInProto2Namespace(io::Printer* printer); + void GenerateSourceInProto2Namespace(io::Printer* p); - private: - // Generate declarations and definitions of accessors for fields. - void GenerateFieldAccessorDeclarations(io::Printer* printer); - void GenerateFieldAccessorDefinitions(io::Printer* printer); + + void GenerateInitDefaultSplitInstance(io::Printer* p); + + // Generate the constexpr constructor for constant initialization of the + // default instance. + void GenerateConstexprConstructor(io::Printer* p); + + void GenerateSchema(io::Printer* p, int offset, int has_offset); // Generate the field offsets array. Returns the a pair of the total number // of entries generated and the index of the first has_bit entry. - std::pair<size_t, size_t> GenerateOffsets(io::Printer* printer); - void GenerateSchema(io::Printer* printer, int offset, int has_offset); + std::pair<size_t, size_t> GenerateOffsets(io::Printer* p); + + const Descriptor* descriptor() const { return descriptor_; } + + private: + // Generate declarations and definitions of accessors for fields. + void GenerateFieldAccessorDeclarations(io::Printer* p); + void GenerateFieldAccessorDefinitions(io::Printer* p); // Generate constructors and destructor. - void GenerateStructors(io::Printer* printer); + void GenerateStructors(io::Printer* p); // The compiler typically generates multiple copies of each constructor and // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx // Placing common code in a separate method reduces the generated code size. // // Generate the shared constructor code. - void GenerateSharedConstructorCode(io::Printer* printer); + void GenerateSharedConstructorCode(io::Printer* p); // Generate the shared destructor code. - void GenerateSharedDestructorCode(io::Printer* printer); + void GenerateSharedDestructorCode(io::Printer* p); // Generate the arena-specific destructor code. - void GenerateArenaDestructorCode(io::Printer* printer); - - // Generate the constexpr constructor for constant initialization of the - // default instance. - void GenerateConstexprConstructor(io::Printer* printer); - - void GenerateCreateSplitMessage(io::Printer* printer); - void GenerateInitDefaultSplitInstance(io::Printer* printer); + void GenerateArenaDestructorCode(io::Printer* p); // Generate standard Message methods. - void GenerateClear(io::Printer* printer); - void GenerateOneofClear(io::Printer* printer); - void GenerateVerify(io::Printer* printer); - void GenerateSerializeWithCachedSizes(io::Printer* printer); - void GenerateSerializeWithCachedSizesToArray(io::Printer* printer); - void GenerateSerializeWithCachedSizesBody(io::Printer* printer); - void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* printer); - void GenerateByteSize(io::Printer* printer); - void GenerateMergeFrom(io::Printer* printer); - void GenerateClassSpecificMergeImpl(io::Printer* printer); - void GenerateCopyFrom(io::Printer* printer); - void GenerateSwap(io::Printer* printer); - void GenerateIsInitialized(io::Printer* printer); + void GenerateClear(io::Printer* p); + void GenerateOneofClear(io::Printer* p); + void GenerateVerify(io::Printer* p); + void GenerateSerializeWithCachedSizes(io::Printer* p); + void GenerateSerializeWithCachedSizesToArray(io::Printer* p); + void GenerateSerializeWithCachedSizesBody(io::Printer* p); + void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* p); + void GenerateByteSize(io::Printer* p); + void GenerateMergeFrom(io::Printer* p); + void GenerateClassSpecificMergeImpl(io::Printer* p); + void GenerateCopyFrom(io::Printer* p); + void GenerateSwap(io::Printer* p); + void GenerateIsInitialized(io::Printer* p); // Helpers for GenerateSerializeWithCachedSizes(). // // cached_has_bit_index maintains that: // cached_has_bits = _has_bits_[cached_has_bit_index] // for cached_has_bit_index >= 0 - void GenerateSerializeOneField(io::Printer* printer, - const FieldDescriptor* field, + void GenerateSerializeOneField(io::Printer* p, const FieldDescriptor* field, 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(). void GenerateSerializeOneofFields( - io::Printer* printer, const std::vector<const FieldDescriptor*>& fields); + io::Printer* p, const std::vector<const FieldDescriptor*>& fields); void GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* range); + io::Printer* p, const Descriptor::ExtensionRange* range); // Generates has_foo() functions and variables for singular field has-bits. void GenerateSingularFieldHasBits(const FieldDescriptor* field, - Formatter format); + io::Printer* p); // Generates has_foo() functions and variables for oneof field has-bits. - void GenerateOneofHasBits(io::Printer* printer); + void GenerateOneofHasBits(io::Printer* p); // Generates has_foo_bar() functions for oneof members. - void GenerateOneofMemberHasBits(const FieldDescriptor* field, - const Formatter& format); + void GenerateOneofMemberHasBits(const FieldDescriptor* field, io::Printer* p); // Generates the clear_foo() method for a field. void GenerateFieldClear(const FieldDescriptor* field, bool is_inline, - Formatter format); + io::Printer* p); // Generates the body of the message's copy constructor. - void GenerateCopyConstructorBody(io::Printer* printer) const; + void GenerateCopyConstructorBody(io::Printer* p) const; // Returns the level that this message needs ArenaDtor. If the message has // a field that is not arena-exclusive, it needs an ArenaDtor @@ -181,17 +178,15 @@ class MessageGenerator { size_t HasBitsSize() const; size_t InlinedStringDonatedSize() const; - int HasBitIndex(const FieldDescriptor* a) const; - int HasByteIndex(const FieldDescriptor* a) const; - int HasWordIndex(const FieldDescriptor* a) const; - bool SameHasByte(const FieldDescriptor* a, const FieldDescriptor* b) const; + int HasBitIndex(const FieldDescriptor* field) const; + int HasByteIndex(const FieldDescriptor* field) const; + int HasWordIndex(const FieldDescriptor* field) const; std::vector<arc_ui32> RequiredFieldsBitMask() const; const Descriptor* descriptor_; int index_in_file_messages_; - TProtoStringType classname_; Options options_; - FieldGeneratorMap field_generators_; + FieldGeneratorTable 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. @@ -199,29 +194,27 @@ class MessageGenerator { // optimized_order_ excludes oneof fields and weak fields. std::vector<const FieldDescriptor*> optimized_order_; std::vector<int> has_bit_indices_; - int max_has_bit_index_; + int max_has_bit_index_ = 0; // A map from field index to inlined_string index. For non-inlined-string // fields, the element is -1. If there is no inlined string in the message, // this is empty. std::vector<int> inlined_string_indices_; // The count of inlined_string fields in the message. - int max_inlined_string_index_; + int max_inlined_string_index_ = 0; std::vector<const EnumGenerator*> enum_generators_; std::vector<const ExtensionGenerator*> extension_generators_; - int num_required_fields_; - int num_weak_fields_; + int num_required_fields_ = 0; + int num_weak_fields_ = 0; std::unique_ptr<MessageLayoutHelper> message_layout_helper_; std::unique_ptr<ParseFunctionGenerator> parse_function_generator_; MessageSCCAnalyzer* scc_analyzer_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; - friend class FileGenerator; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); }; } // namespace cpp diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.h deleted file mode 100644 index 70c42c0eacc..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.h +++ /dev/null @@ -1,148 +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: [email protected] (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__ - -#include <map> -#include <string> - -#include <google/protobuf/compiler/cpp/field.h> -#include <google/protobuf/compiler/cpp/helpers.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace cpp { - -class MessageFieldGenerator : public FieldGenerator { - public: - MessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options, - MessageSCCAnalyzer* scc_analyzer); - ~MessageFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GeneratePrivateMembers(io::Printer* printer) const override; - void GenerateAccessorDeclarations(io::Printer* printer) const override; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateNonInlineAccessorDefinitions( - io::Printer* printer) const override; - void GenerateInternalAccessorDeclarations( - io::Printer* printer) const override; - void GenerateInternalAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateMessageClearingCode(io::Printer* printer) const override; - void GenerateMergingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateDestructorCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override {} - void GenerateCopyConstructorCode(io::Printer* printer) const override; - void GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const override; - void GenerateByteSize(io::Printer* printer) const override; - void GenerateIsInitialized(io::Printer* printer) const override; - void GenerateConstexprAggregateInitializer( - io::Printer* printer) const override; - void GenerateAggregateInitializer(io::Printer* printer) const override; - void GenerateCopyAggregateInitializer(io::Printer* printer) const override; - - protected: - const bool implicit_weak_field_; - const bool has_required_fields_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); -}; - -class MessageOneofFieldGenerator : public MessageFieldGenerator { - public: - MessageOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options, - MessageSCCAnalyzer* scc_analyzer); - ~MessageOneofFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateNonInlineAccessorDefinitions( - io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - - // MessageFieldGenerator, from which we inherit, overrides this so we need to - // override it as well. - void GenerateMessageClearingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateDestructorCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override; - void GenerateIsInitialized(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); -}; - -class RepeatedMessageFieldGenerator : public FieldGenerator { - public: - RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - const Options& options, - MessageSCCAnalyzer* scc_analyzer); - ~RepeatedMessageFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GeneratePrivateMembers(io::Printer* printer) const override; - void GenerateAccessorDeclarations(io::Printer* printer) const override; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateMergingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override; - void GenerateCopyConstructorCode(io::Printer* printer) const override {} - void GenerateDestructorCode(io::Printer* printer) const override; - void GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const override; - void GenerateByteSize(io::Printer* printer) const override; - void GenerateIsInitialized(io::Printer* printer) const override; - - private: - const bool implicit_weak_field_; - const bool has_required_fields_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); -}; - -} // namespace cpp -} // namespace compiler -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_layout_helper.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_layout_helper.h index a8813a1f225..7727e674663 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_layout_helper.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_layout_helper.h @@ -35,8 +35,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__ -#include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/cpp/options.h> +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/cpp/options.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/names.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/names.h index 8220f7dde8c..438b27e3d24 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/names.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/names.h @@ -33,8 +33,10 @@ #include <string> +#include "y_absl/strings/string_view.h" + // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -43,10 +45,23 @@ class Descriptor; class EnumDescriptor; class EnumValueDescriptor; class FieldDescriptor; +class FileDescriptor; namespace compiler { namespace cpp { +// Returns the fully qualified C++ namespace. +// +// For example, if you had: +// package foo.bar; +// message Baz { message Moo {} } +// Then the qualified namespace for Moo would be: +// ::foo::bar +PROTOC_EXPORT TProtoStringType Namespace(const FileDescriptor* d); +PROTOC_EXPORT TProtoStringType Namespace(const Descriptor* d); +PROTOC_EXPORT TProtoStringType Namespace(const FieldDescriptor* d); +PROTOC_EXPORT TProtoStringType Namespace(const EnumDescriptor* d); + // Returns the unqualified C++ name. // // For example, if you had: @@ -54,8 +69,8 @@ namespace cpp { // message Baz { message Moo {} } // Then the non-qualified version would be: // Baz_Moo -TProtoStringType ClassName(const Descriptor* descriptor); -TProtoStringType ClassName(const EnumDescriptor* enum_descriptor); +PROTOC_EXPORT TProtoStringType ClassName(const Descriptor* descriptor); +PROTOC_EXPORT TProtoStringType ClassName(const EnumDescriptor* enum_descriptor); // Returns the fully qualified C++ name. // @@ -64,34 +79,35 @@ TProtoStringType ClassName(const EnumDescriptor* enum_descriptor); // message Baz { message Moo {} } // Then the qualified ClassName for Moo would be: // ::foo::bar::Baz_Moo -TProtoStringType QualifiedClassName(const Descriptor* d); -TProtoStringType QualifiedClassName(const EnumDescriptor* d); -TProtoStringType QualifiedExtensionName(const FieldDescriptor* d); +PROTOC_EXPORT TProtoStringType QualifiedClassName(const Descriptor* d); +PROTOC_EXPORT TProtoStringType QualifiedClassName(const EnumDescriptor* d); +PROTOC_EXPORT TProtoStringType QualifiedExtensionName(const FieldDescriptor* d); // 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(). -TProtoStringType FieldName(const FieldDescriptor* field); +PROTOC_EXPORT TProtoStringType FieldName(const FieldDescriptor* field); // Requires that this field is in a oneof. Returns the (unqualified) case // constant for this field. -TProtoStringType OneofCaseConstantName(const FieldDescriptor* field); +PROTOC_EXPORT TProtoStringType OneofCaseConstantName(const FieldDescriptor* field); // Returns the quafilied case constant for this field. -TProtoStringType QualifiedOneofCaseConstantName(const FieldDescriptor* field); +PROTOC_EXPORT TProtoStringType QualifiedOneofCaseConstantName( + const FieldDescriptor* field); // Get the (unqualified) name that should be used for this enum value in C++ // code. -TProtoStringType EnumValueName(const EnumValueDescriptor* enum_value); +PROTOC_EXPORT TProtoStringType EnumValueName(const EnumValueDescriptor* enum_value); // Strips ".proto" or ".protodevel" from the end of a filename. -PROTOC_EXPORT TProtoStringType StripProto(const TProtoStringType& filename); +PROTOC_EXPORT TProtoStringType StripProto(y_absl::string_view filename); } // namespace cpp } // namespace compiler } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/options.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/options.h index 14546ca6187..449ed69f5d1 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/options.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/options.h @@ -33,14 +33,17 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__ -#include <set> #include <string> + +#include "y_absl/container/flat_hash_set.h" + #include <google/protobuf/stubs/port.h> namespace google { namespace protobuf { namespace compiler { class AccessInfoMap; +class SplitMap; namespace cpp { @@ -53,12 +56,13 @@ enum class EnforceOptimizeMode { struct FieldListenerOptions { bool inject_field_listener_events = false; - std::set<TProtoStringType> forbidden_field_listener_events; + y_absl::flat_hash_set<TProtoStringType> forbidden_field_listener_events; }; // Generator options (see generator.cc for a description of each): struct Options { const AccessInfoMap* access_info_map = nullptr; + const SplitMap* split_map = nullptr; TProtoStringType dllexport_decl; TProtoStringType runtime_include_base; TProtoStringType annotation_pragma_name; @@ -79,12 +83,10 @@ struct Options { bool bootstrap = false; bool opensource_runtime = false; bool annotate_accessor = false; - bool unused_field_stripping = false; bool unverified_lazy_message_sets = false; - bool unverified_lazy = false; bool profile_driven_inline_string = true; - bool message_owned_arena_trial = false; bool force_split = false; + bool profile_driven_split = true; #ifdef PROTOBUF_STABLE_EXPERIMENTS bool force_eagerly_verified_lazy = true; bool force_inline_string = true; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.cc index 20910520d63..5f2bfba18c4 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.cc @@ -28,9 +28,10 @@ // (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/cpp/padding_optimizer.h> +#include "google/protobuf/compiler/cpp/padding_optimizer.h" -#include <google/protobuf/compiler/cpp/helpers.h> +#include "y_absl/log/absl_log.h" +#include "google/protobuf/compiler/cpp/helpers.h" namespace google { namespace protobuf { @@ -85,41 +86,11 @@ class FieldGroup { } // namespace -// Reorder 'fields' so that if the fields are output into a c++ class in the new -// order, fields of similar family (see below) are together and within each -// family, alignment padding is minimized. -// -// We try to do this while keeping each field as close as possible to its field -// number order so that we don't reduce cache locality much for function that -// access each field in order. Originally, OptimizePadding used declaration -// order for its decisions, but generated code minus the serializer/parsers uses -// the output of OptimizePadding as well (stored in -// MessageGenerator::optimized_order_). Since the serializers use field number -// order, we use that as a tie-breaker. -// -// We classify each field into a particular "family" of fields, that we perform -// the same operation on in our generated functions. -// -// REPEATED is placed first, as the C++ compiler automatically initializes -// these fields in layout order. -// -// 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 -// MessageFieldGenerator::GenerateConstructorCode), which allows them to be -// memset. -// -// ZERO_INITIALIZABLE is memset in Clear/SharedCtor -// -// OTHER these fields are initialized one-by-one. -void PaddingOptimizer::OptimizeLayout( - std::vector<const FieldDescriptor*>* fields, const Options& options, - MessageSCCAnalyzer* scc_analyzer) { +static void OptimizeLayoutHelper(std::vector<const FieldDescriptor*>* fields, + const Options& options, + MessageSCCAnalyzer* scc_analyzer) { + if (fields->empty()) return; + // The sorted numeric order of Family determines the declaration order in the // memory layout. enum Family { @@ -151,7 +122,7 @@ void PaddingOptimizer::OptimizeLayout( if (IsLazy(field, options, scc_analyzer)) { f = LAZY_MESSAGE; } - } else if (CanInitializeByZeroing(field)) { + } else if (CanInitializeByZeroing(field, options, scc_analyzer)) { f = ZERO_INITIALIZABLE; } @@ -167,8 +138,9 @@ void PaddingOptimizer::OptimizeLayout( aligned_to_8[f].push_back(FieldGroup(j, field)); break; default: - GOOGLE_LOG(FATAL) << "Unknown alignment size " << EstimateAlignmentSize(field) - << "for a field " << field->full_name() << "."; + Y_ABSL_LOG(FATAL) << "Unknown alignment size " + << EstimateAlignmentSize(field) << "for a field " + << field->full_name() << "."; } } @@ -222,6 +194,61 @@ void PaddingOptimizer::OptimizeLayout( } } +// Reorder 'fields' so that if the fields are output into a c++ class in the new +// order, fields of similar family (see below) are together and within each +// family, alignment padding is minimized. +// +// We try to do this while keeping each field as close as possible to its field +// number order so that we don't reduce cache locality much for function that +// access each field in order. Originally, OptimizePadding used declaration +// order for its decisions, but generated code minus the serializer/parsers uses +// the output of OptimizePadding as well (stored in +// MessageGenerator::optimized_order_). Since the serializers use field number +// order, we use that as a tie-breaker. +// +// We classify each field into a particular "family" of fields, that we perform +// the same operation on in our generated functions. +// +// REPEATED is placed first, as the C++ compiler automatically initializes +// these fields in layout order. +// +// 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 +// MessageFieldGenerator::GenerateConstructorCode), which allows them to be +// memset. +// +// ZERO_INITIALIZABLE is memset in Clear/SharedCtor +// +// OTHER these fields are initialized one-by-one. +// +// If there are split fields in `fields`, they will be placed at the end. The +// order within split fields follows the same rule, aka classify and order by +// "family". +void PaddingOptimizer::OptimizeLayout( + std::vector<const FieldDescriptor*>* fields, const Options& options, + MessageSCCAnalyzer* scc_analyzer) { + std::vector<const FieldDescriptor*> normal; + std::vector<const FieldDescriptor*> split; + for (const auto* field : *fields) { + if (ShouldSplit(field, options)) { + split.push_back(field); + } else { + normal.push_back(field); + } + } + OptimizeLayoutHelper(&normal, options, scc_analyzer); + OptimizeLayoutHelper(&split, options, scc_analyzer); + fields->clear(); + fields->insert(fields->end(), normal.begin(), normal.end()); + fields->insert(fields->end(), split.begin(), split.end()); +} + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.h index 9c76f38c471..4f55e649a3d 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.h @@ -35,7 +35,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__ -#include <google/protobuf/compiler/cpp/message_layout_helper.h> +#include "google/protobuf/compiler/cpp/message_layout_helper.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.cc index 1b97182acd6..74ede841a8f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.cc @@ -28,15 +28,25 @@ // (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/cpp/parse_function_generator.h> +#include "google/protobuf/compiler/cpp/parse_function_generator.h" #include <algorithm> #include <limits> #include <string> #include <utility> +#include <vector> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/compiler/cpp/helpers.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/generated_message_tctable_gen.h" +#include "google/protobuf/generated_message_tctable_impl.h" +#include "google/protobuf/wire_format.h" + +#include "util/generic/string.h" + +using TProtoStringType = TString; namespace google { namespace protobuf { @@ -44,16 +54,26 @@ namespace compiler { namespace cpp { namespace { +using internal::TailCallTableInfo; +using internal::cpp::Utf8CheckMode; using google::protobuf::internal::WireFormat; using google::protobuf::internal::WireFormatLite; +bool UseDirectTcParserTable(const FieldDescriptor* field, + const Options& options) { + if (field->cpp_type() != field->CPPTYPE_MESSAGE) return false; + auto* m = field->message_type(); + return !m->options().message_set_wire_format() && + m->file()->options().optimize_for() != FileOptions::CODE_SIZE && + !HasSimpleBaseClass(m, options) && !HasTracker(m, options) + ; // NOLINT(whitespace/semicolon) +} + std::vector<const FieldDescriptor*> GetOrderedFields( const Descriptor* descriptor, const Options& options) { std::vector<const FieldDescriptor*> ordered_fields; for (auto field : FieldRange(descriptor)) { - if (!IsFieldStripped(field, options)) { - ordered_fields.push_back(field); - } + ordered_fields.push_back(field); } std::sort(ordered_fields.begin(), ordered_fields.end(), [](const FieldDescriptor* a, const FieldDescriptor* b) { @@ -66,371 +86,33 @@ bool HasInternalAccessors(const FieldOptions::CType ctype) { return ctype == FieldOptions::STRING || ctype == FieldOptions::CORD; } -int TagSize(arc_ui32 field_number) { - if (field_number < 16) return 1; - GOOGLE_CHECK_LT(field_number, (1 << 14)) - << "coded tag for " << field_number << " too big for uint16_t"; - return 2; -} - -TProtoStringType FieldParseFunctionName( - const TailCallTableInfo::FieldEntryInfo& entry, const Options& options); - -bool IsFieldEligibleForFastParsing( - const TailCallTableInfo::FieldEntryInfo& entry, const Options& options, - MessageSCCAnalyzer* scc_analyzer) { - const auto* field = entry.field; - // Map, oneof, weak, and lazy fields are not handled on the fast path. - if (field->is_map() || field->real_containing_oneof() || - field->options().weak() || - IsImplicitWeakField(field, options, scc_analyzer) || - IsLazy(field, options, scc_analyzer)) { - return false; - } - - // We will check for a valid auxiliary index range later. However, we might - // want to change the value we check for inlined string fields. - int aux_idx = entry.aux_idx; - - switch (field->type()) { - case FieldDescriptor::TYPE_ENUM: - // If enum values are not validated at parse time, then this field can be - // handled on the fast path like an int32. - if (HasPreservingUnknownEnumSemantics(field)) { - break; - } - if (field->is_repeated() && field->is_packed()) { - return false; - } - break; - - // Some bytes fields can be handled on fast path. - case FieldDescriptor::TYPE_STRING: - case FieldDescriptor::TYPE_BYTES: - if (field->options().ctype() != FieldOptions::STRING) { - return false; - } - if (IsStringInlined(field, options)) { - GOOGLE_CHECK(!field->is_repeated()); - // For inlined strings, the donation state index is stored in the - // `aux_idx` field of the fast parsing info. We need to check the range - // of that value instead of the auxiliary index. - aux_idx = entry.inlined_string_idx; - } - break; - - default: - break; - } - - if (HasHasbit(field)) { - // The tailcall parser can only update the first 32 hasbits. Fields with - // has-bits beyond the first 32 are handled by mini parsing/fallback. - GOOGLE_CHECK_GE(entry.hasbit_idx, 0) << field->DebugString(); - if (entry.hasbit_idx >= 32) return false; - } - - // If the field needs auxiliary data, then the aux index is needed. This - // must fit in a uint8_t. - if (aux_idx > std::numeric_limits<uint8_t>::max()) { - return false; - } - - // The largest tag that can be read by the tailcall parser is two bytes - // when varint-coded. This allows 14 bits for the numeric tag value: - // byte 0 byte 1 - // 1nnnnttt 0nnnnnnn - // ^^^^^^^ ^^^^^^^ - if (field->number() >= 1 << 11) return false; - - return true; -} - -std::vector<TailCallTableInfo::FastFieldInfo> SplitFastFieldsForSize( - const std::vector<TailCallTableInfo::FieldEntryInfo>& field_entries, - int table_size_log2, const Options& options, - MessageSCCAnalyzer* scc_analyzer) { - std::vector<TailCallTableInfo::FastFieldInfo> result(1 << table_size_log2); - const arc_ui32 idx_mask = result.size() - 1; - - for (const auto& entry : field_entries) { - if (!IsFieldEligibleForFastParsing(entry, options, scc_analyzer)) { - continue; - } - - const auto* field = entry.field; - arc_ui32 tag = WireFormat::MakeTag(field); - - // Construct the varint-coded tag. If it is more than 7 bits, we need to - // shift the high bits and add a continue bit. - if (arc_ui32 hibits = tag & 0xFFFFFF80) { - tag = tag + hibits + 128; // tag = lobits + 2*hibits + 128 - } - - // The field index is determined by the low bits of the field number, where - // the table size determines the width of the mask. The largest table - // supported is 32 entries. The parse loop uses these bits directly, so that - // the dispatch does not require arithmetic: - // byte 0 byte 1 - // tag: 1nnnnttt 0nnnnnnn - // ^^^^^ - // idx (table_size_log2=5) - // This means that any field number that does not fit in the lower 4 bits - // will always have the top bit of its table index asserted. - const arc_ui32 fast_idx = (tag >> 3) & idx_mask; - - TailCallTableInfo::FastFieldInfo& info = result[fast_idx]; - if (info.field != nullptr) { - // This field entry is already filled. - continue; - } - - // Fill in this field's entry: - GOOGLE_CHECK(info.func_name.empty()) << info.func_name; - info.func_name = FieldParseFunctionName(entry, options); - info.field = field; - info.coded_tag = tag; - // If this field does not have presence, then it can set an out-of-bounds - // bit (tailcall parsing uses a arc_ui64 for hasbits, but only stores 32). - info.hasbit_idx = HasHasbit(field) ? entry.hasbit_idx : 63; - if (IsStringInlined(field, options)) { - GOOGLE_CHECK(!field->is_repeated()); - info.aux_idx = static_cast<uint8_t>(entry.inlined_string_idx); - } else { - info.aux_idx = static_cast<uint8_t>(entry.aux_idx); - } - } - return result; -} - -// Filter out fields that will be handled by mini parsing. -std::vector<const FieldDescriptor*> FilterMiniParsedFields( - const std::vector<const FieldDescriptor*>& fields, const Options& options, - MessageSCCAnalyzer* scc_analyzer) { - std::vector<const FieldDescriptor*> generated_fallback_fields; - - for (const auto* field : fields) { - bool handled = false; - switch (field->type()) { - case FieldDescriptor::TYPE_DOUBLE: - case FieldDescriptor::TYPE_FLOAT: - case FieldDescriptor::TYPE_FIXED32: - case FieldDescriptor::TYPE_SFIXED32: - case FieldDescriptor::TYPE_FIXED64: - case FieldDescriptor::TYPE_SFIXED64: - case FieldDescriptor::TYPE_BOOL: - case FieldDescriptor::TYPE_UINT32: - case FieldDescriptor::TYPE_SINT32: - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_UINT64: - case FieldDescriptor::TYPE_SINT64: - case FieldDescriptor::TYPE_INT64: - // These are handled by MiniParse, so we don't need any generated - // fallback code. - handled = true; - break; - - case FieldDescriptor::TYPE_ENUM: - if (field->is_repeated() && !HasPreservingUnknownEnumSemantics(field)) { - // TODO(b/206890171): handle packed repeated closed enums - // Non-packed repeated can be handled using tables, but we still - // need to generate fallback code for all repeated enums in order to - // handle packed encoding. This is because of the lite/full split - // when handling invalid enum values in a packed field. - handled = false; - } else { - handled = true; - } - break; - - case FieldDescriptor::TYPE_BYTES: - case FieldDescriptor::TYPE_STRING: - if (IsStringInlined(field, options)) { - // TODO(b/198211897): support InilnedStringField. - handled = false; - } else { - handled = true; - } - break; - - case FieldDescriptor::TYPE_MESSAGE: - case FieldDescriptor::TYPE_GROUP: - // TODO(b/210762816): support remaining field types. - if (field->is_map() || IsWeak(field, options) || - IsImplicitWeakField(field, options, scc_analyzer) || - IsLazy(field, options, scc_analyzer)) { - handled = false; - } else { - handled = true; - } - break; - - default: - handled = false; - break; - } - if (!handled) generated_fallback_fields.push_back(field); - } - - return generated_fallback_fields; -} - } // namespace -TailCallTableInfo::TailCallTableInfo( - const Descriptor* descriptor, const Options& options, - const std::vector<const FieldDescriptor*>& ordered_fields, - const std::vector<int>& has_bit_indices, - const std::vector<int>& inlined_string_indices, - MessageSCCAnalyzer* scc_analyzer) { - int oneof_count = descriptor->real_oneof_decl_count(); - // If this message has any oneof fields, store the case offset in the first - // auxiliary entry. - if (oneof_count > 0) { - GOOGLE_LOG_IF(DFATAL, ordered_fields.empty()) - << "Invalid message: " << descriptor->full_name() << " has " - << oneof_count << " oneof declarations, but no fields"; - aux_entries.push_back(StrCat("_fl::Offset{offsetof(", - ClassName(descriptor), - ", _impl_._oneof_case_)}")); +class ParseFunctionGenerator::GeneratedOptionProvider final + : public internal::TailCallTableInfo::OptionProvider { + public: + explicit GeneratedOptionProvider(ParseFunctionGenerator* gen) : gen_(gen) {} + TailCallTableInfo::PerFieldOptions GetForField( + const FieldDescriptor* field) const final { + return {IsLazy(field, gen_->options_, gen_->scc_analyzer_), + IsStringInlined(field, gen_->options_), + IsImplicitWeakField(field, gen_->options_, gen_->scc_analyzer_), + UseDirectTcParserTable(field, gen_->options_), + GetOptimizeFor(field->file(), gen_->options_) == + FileOptions::LITE_RUNTIME, + ShouldSplit(field, gen_->options_)}; } - // If this message has any inlined string fields, store the donation state - // offset in the second auxiliary entry. - if (!inlined_string_indices.empty()) { - aux_entries.resize(2); // pad if necessary - aux_entries[1] = - StrCat("_fl::Offset{offsetof(", ClassName(descriptor), - ", _impl_._inlined_string_donated_)}"); - } - - // Fill in mini table entries. - for (const FieldDescriptor* field : ordered_fields) { - field_entries.push_back( - {field, (HasHasbit(field) ? has_bit_indices[field->index()] : -1)}); - auto& entry = field_entries.back(); - - if (field->type() == FieldDescriptor::TYPE_MESSAGE || - field->type() == FieldDescriptor::TYPE_GROUP) { - // Message-typed fields have a FieldAux with the default instance pointer. - if (field->is_map()) { - // TODO(b/205904770): generate aux entries for maps - } else if (IsWeak(field, options)) { - // Don't generate anything for weak fields. They are handled by the - // generated fallback. - } else if (IsImplicitWeakField(field, options, scc_analyzer)) { - // Implicit weak fields don't need to store a default instance pointer. - } else if (IsLazy(field, options, scc_analyzer)) { - // Lazy fields are handled by the generated fallback function. - } else { - field_entries.back().aux_idx = aux_entries.size(); - const Descriptor* field_type = field->message_type(); - aux_entries.push_back(StrCat( - "reinterpret_cast<const ", QualifiedClassName(field_type, options), - "*>(&", QualifiedDefaultInstanceName(field_type, options), ")")); - } - } else if (field->type() == FieldDescriptor::TYPE_ENUM && - !HasPreservingUnknownEnumSemantics(field)) { - // Enum fields which preserve unknown values (proto3 behavior) are - // effectively int32 fields with respect to parsing -- i.e., the value - // does not need to be validated at parse time. - // - // Enum fields which do not preserve unknown values (proto2 behavior) use - // a FieldAux to store validation information. If the enum values are - // sequential (and within a range we can represent), then the FieldAux - // entry represents the range using the minimum value (which must fit in - // an int16_t) and count (a uint16_t). Otherwise, the entry holds a - // pointer to the generated Name_IsValid function. - - entry.aux_idx = aux_entries.size(); - const EnumDescriptor* enum_type = field->enum_type(); - GOOGLE_CHECK_GT(enum_type->value_count(), 0) << enum_type->DebugString(); - - // Check if the enum values are a single, contiguous range. - std::vector<int> enum_values; - for (int i = 0, N = enum_type->value_count(); i < N; ++i) { - enum_values.push_back(enum_type->value(i)->number()); - } - auto values_begin = enum_values.begin(); - auto values_end = enum_values.end(); - std::sort(values_begin, values_end); - enum_values.erase(std::unique(values_begin, values_end), values_end); - - if (enum_values.back() - enum_values[0] == enum_values.size() - 1 && - enum_values[0] >= std::numeric_limits<int16_t>::min() && - enum_values[0] <= std::numeric_limits<int16_t>::max() && - enum_values.size() <= std::numeric_limits<uint16_t>::max()) { - entry.is_enum_range = true; - aux_entries.push_back( - StrCat(enum_values[0], ", ", enum_values.size())); - } else { - entry.is_enum_range = false; - aux_entries.push_back( - StrCat(QualifiedClassName(enum_type, options), "_IsValid")); - } - } else if ((field->type() == FieldDescriptor::TYPE_STRING || - field->type() == FieldDescriptor::TYPE_BYTES) && - IsStringInlined(field, options)) { - GOOGLE_CHECK(!field->is_repeated()); - // Inlined strings have an extra marker to represent their donation state. - int idx = inlined_string_indices[field->index()]; - // For mini parsing, the donation state index is stored as an `offset` - // auxiliary entry. - entry.aux_idx = aux_entries.size(); - aux_entries.push_back(StrCat("_fl::Offset{", idx, "}")); - // For fast table parsing, the donation state index is stored instead of - // the aux_idx (this will limit the range to 8 bits). - entry.inlined_string_idx = idx; - } - } - - // Choose the smallest fast table that covers the maximum number of fields. - table_size_log2 = 0; // fallback value - int num_fast_fields = -1; - for (int try_size_log2 : {0, 1, 2, 3, 4, 5}) { - size_t try_size = 1 << try_size_log2; - auto split_fields = SplitFastFieldsForSize(field_entries, try_size_log2, - options, scc_analyzer); - GOOGLE_CHECK_EQ(split_fields.size(), try_size); - int try_num_fast_fields = 0; - for (const auto& info : split_fields) { - if (info.field != nullptr) ++try_num_fast_fields; - } - // Use this size if (and only if) it covers more fields. - if (try_num_fast_fields > num_fast_fields) { - fast_path_fields = std::move(split_fields); - table_size_log2 = try_size_log2; - num_fast_fields = try_num_fast_fields; - } - // The largest table we allow has the same number of entries as the message - // has fields, rounded up to the next power of 2 (e.g., a message with 5 - // fields can have a fast table of size 8). A larger table *might* cover - // more fields in certain cases, but a larger table in that case would have - // mostly empty entries; so, we cap the size to avoid pathologically sparse - // tables. - if (try_size > ordered_fields.size()) { - break; - } - } - - // Filter out fields that are handled by MiniParse. We don't need to generate - // a fallback for these, which saves code size. - fallback_fields = FilterMiniParsedFields(ordered_fields, options, - scc_analyzer); - - // If there are no fallback fields, and at most one extension range, the - // parser can use a generic fallback function. Otherwise, a message-specific - // fallback routine is needed. - use_generated_fallback = - !fallback_fields.empty() || descriptor->extension_range_count() > 1; -} + private: + ParseFunctionGenerator* gen_; +}; ParseFunctionGenerator::ParseFunctionGenerator( const Descriptor* descriptor, int max_has_bit_index, const std::vector<int>& has_bit_indices, const std::vector<int>& inlined_string_indices, const Options& options, MessageSCCAnalyzer* scc_analyzer, - const std::map<TProtoStringType, TProtoStringType>& vars) + const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& vars) : descriptor_(descriptor), scc_analyzer_(scc_analyzer), options_(options), @@ -440,10 +122,9 @@ ParseFunctionGenerator::ParseFunctionGenerator( num_hasbits_(max_has_bit_index) { if (should_generate_tctable()) { tc_table_info_.reset(new TailCallTableInfo( - descriptor_, options_, ordered_fields_, has_bit_indices, - inlined_string_indices, scc_analyzer)); + descriptor_, ordered_fields_, GeneratedOptionProvider(this), + has_bit_indices, inlined_string_indices)); } - SetCommonVars(options_, &variables_); SetCommonMessageDataVariables(descriptor_, &variables_); SetUnknownFieldsVariable(descriptor_, options_, &variables_); variables_["classname"] = ClassName(descriptor, false); @@ -518,11 +199,14 @@ bool ParseFunctionGenerator::should_generate_tctable() const { if (options_.tctable_mode == Options::kTCTableNever) { return false; } + if (HasSimpleBaseClass(descriptor_, options_)) { + return false; + } return true; } void ParseFunctionGenerator::GenerateTailcallParseFunction(Formatter& format) { - GOOGLE_CHECK(should_generate_tctable()); + Y_ABSL_CHECK(should_generate_tctable()); // Generate an `_InternalParse` that starts the tail-calling loop. format( @@ -536,20 +220,47 @@ void ParseFunctionGenerator::GenerateTailcallParseFunction(Formatter& format) { "}\n\n"); } +static bool NeedsUnknownEnumSupport(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->field_count(); ++i) { + auto* field = descriptor->field(i); + if (field->is_repeated() && field->cpp_type() == field->CPPTYPE_ENUM && + !internal::cpp::HasPreservingUnknownEnumSemantics(field)) { + return true; + } + } + return false; +} + void ParseFunctionGenerator::GenerateTailcallFallbackFunction( Formatter& format) { - GOOGLE_CHECK(should_generate_tctable()); + Y_ABSL_CHECK(should_generate_tctable()); format( "const char* $classname$::Tct_ParseFallback(PROTOBUF_TC_PARAM_DECL) {\n" "#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) return nullptr\n"); format.Indent(); format("auto* typed_msg = static_cast<$classname$*>(msg);\n"); + // If we need a side channel, generate the check to jump to the generic + // handler to deal with the side channel data. + if (NeedsUnknownEnumSupport(descriptor_)) { + format( + "if (PROTOBUF_PREDICT_FALSE(\n" + " _pbi::TcParser::MustFallbackToGeneric(PROTOBUF_TC_PARAM_PASS))) " + "{\n" + " PROTOBUF_MUSTTAIL return " + "::_pbi::TcParser::GenericFallback$1$(PROTOBUF_TC_PARAM_PASS);\n" + "}\n", + GetOptimizeFor(descriptor_->file(), options_) == + FileOptions::LITE_RUNTIME + ? "Lite" + : ""); + } + if (num_hasbits_ > 0) { // Sync hasbits - format("typed_msg->_impl_._has_bits_[0] = hasbits;\n"); + format("typed_msg->_impl_._has_bits_[0] |= hasbits;\n"); } - format("arc_ui32 tag = data.tag();\n"); + format("::arc_ui32 tag = data.tag();\n"); format.Set("msg", "typed_msg->"); format.Set("this", "typed_msg"); @@ -592,6 +303,12 @@ struct NumToEntryTable { static NumToEntryTable MakeNumToEntryTable( const std::vector<const FieldDescriptor*>& field_descriptors); +static int FieldNameDataSize(const std::vector<uint8_t>& data) { + // We add a +1 here to allow for a NUL termination character. It makes the + // codegen nicer. + return data.empty() ? 0 : data.size() + 1; +} + void ParseFunctionGenerator::GenerateDataDecls(io::Printer* printer) { if (!should_generate_tctable()) { return; @@ -604,10 +321,12 @@ void ParseFunctionGenerator::GenerateDataDecls(io::Printer* printer) { } auto field_num_to_entry_table = MakeNumToEntryTable(ordered_fields_); format( + "friend class ::$proto_ns$::internal::TcParser;\n" "static const ::$proto_ns$::internal::" "TcParseTable<$1$, $2$, $3$, $4$, $5$> _table_;\n", tc_table_info_->table_size_log2, ordered_fields_.size(), - tc_table_info_->aux_entries.size(), CalculateFieldNamesSize(), + tc_table_info_->aux_entries.size(), + FieldNameDataSize(tc_table_info_->field_name_data), field_num_to_entry_table.size16()); if (should_generate_guarded_tctable()) { format.Outdent(); @@ -656,7 +375,7 @@ void ParseFunctionGenerator::GenerateLoopingParseFunction(Formatter& format) { format.Indent(); format( - "arc_ui32 tag;\n" + "::arc_ui32 tag;\n" "ptr = ::_pbi::ReadTag(ptr, &tag);\n"); GenerateParseIterationBody(format, descriptor_, ordered_fields_); @@ -706,7 +425,7 @@ static NumToEntryTable MakeNumToEntryTable( for (; field_entry_index != N; ++field_entry_index) { auto* field_descriptor = field_descriptors[field_entry_index]; arc_ui32 fnum = field_descriptor->number(); - GOOGLE_CHECK_GT(fnum, last_skip_entry_start); + Y_ABSL_CHECK_GT(fnum, last_skip_entry_start); if (start_new_block == false) { // If the next field number is within 15 of the last_skip_entry_start, we // continue writing just to that entry. If it's between 16 and 31 more, @@ -739,16 +458,16 @@ static NumToEntryTable MakeNumToEntryTable( } void ParseFunctionGenerator::GenerateTailCallTable(Formatter& format) { - GOOGLE_CHECK(should_generate_tctable()); + Y_ABSL_CHECK(should_generate_tctable()); // All entries without a fast-path parsing function need a fallback. TProtoStringType fallback; if (tc_table_info_->use_generated_fallback) { - fallback = ClassName(descriptor_) + "::Tct_ParseFallback"; + fallback = y_absl::StrCat(ClassName(descriptor_), "::Tct_ParseFallback"); } else { fallback = "::_pbi::TcParser::GenericFallback"; if (GetOptimizeFor(descriptor_->file(), options_) == FileOptions::LITE_RUNTIME) { - fallback += "Lite"; + y_absl::StrAppend(&fallback, "Lite"); } } @@ -761,12 +480,13 @@ void ParseFunctionGenerator::GenerateTailCallTable(Formatter& format) { // unknown fields and potentially an extension range. auto field_num_to_entry_table = MakeNumToEntryTable(ordered_fields_); format( - "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1\n" + "PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1\n" "const ::_pbi::TcParseTable<$1$, $2$, $3$, $4$, $5$> " "$classname$::_table_ = " "{\n", tc_table_info_->table_size_log2, ordered_fields_.size(), - tc_table_info_->aux_entries.size(), CalculateFieldNamesSize(), + tc_table_info_->aux_entries.size(), + FieldNameDataSize(tc_table_info_->field_name_data), field_num_to_entry_table.size16()); { auto table_scope = format.ScopedIndent(); @@ -849,7 +569,7 @@ void ParseFunctionGenerator::GenerateTailCallTable(Formatter& format) { format("65535, 65535\n"); } if (ordered_fields_.empty()) { - GOOGLE_LOG_IF(DFATAL, !tc_table_info_->aux_entries.empty()) + Y_ABSL_DLOG_IF(FATAL, !tc_table_info_->aux_entries.empty()) << "Invalid message: " << descriptor_->full_name() << " has " << tc_table_info_->aux_entries.size() << " auxiliary field entries, but no fields"; @@ -874,19 +594,62 @@ void ParseFunctionGenerator::GenerateTailCallTable(Formatter& format) { { // aux_entries[] auto aux_scope = format.ScopedIndent(); - for (const TProtoStringType& aux_entry : tc_table_info_->aux_entries) { - format("{$1$},\n", aux_entry); + for (const auto& aux_entry : tc_table_info_->aux_entries) { + switch (aux_entry.type) { + case TailCallTableInfo::kNothing: + format("{},\n"); + break; + case TailCallTableInfo::kInlinedStringDonatedOffset: + format( + "{_fl::Offset{offsetof($classname$, " + "_impl_._inlined_string_donated_)}},\n"); + break; + case TailCallTableInfo::kSplitOffset: + format( + "{_fl::Offset{offsetof($classname$, _impl_._split_)}},\n"); + break; + case TailCallTableInfo::kSplitSizeof: + format("{_fl::Offset{sizeof($classname$::Impl_::Split)}},\n"); + break; + case TailCallTableInfo::kSubMessage: + format("{::_pbi::FieldAuxDefaultMessage{}, &$1$},\n", + QualifiedDefaultInstanceName( + aux_entry.field->message_type(), options_)); + break; + case TailCallTableInfo::kSubTable: + format("{::_pbi::TcParser::GetTable<$1$>()},\n", + QualifiedClassName(aux_entry.field->message_type(), + options_)); + break; + case TailCallTableInfo::kSubMessageWeak: + format("{::_pbi::FieldAuxDefaultMessage{}, &$1$},\n", + QualifiedDefaultInstancePtr( + aux_entry.field->message_type(), options_)); + break; + case TailCallTableInfo::kEnumRange: + format("{$1$, $2$},\n", aux_entry.enum_range.start, + aux_entry.enum_range.size); + break; + case TailCallTableInfo::kEnumValidator: + format( + "{$1$_IsValid},\n", + QualifiedClassName(aux_entry.field->enum_type(), options_)); + break; + case TailCallTableInfo::kNumericOffset: + format("{_fl::Offset{$1$}},\n", aux_entry.offset); + break; + } } } format("}}, {{\n"); } } // ordered_fields_.empty() - { - // field_names[] - auto field_name_scope = format.ScopedIndent(); - GenerateFieldNames(format); - } - format("}},\n"); + { + // field_names[] + auto field_name_scope = format.ScopedIndent(); + GenerateFieldNames(format); + } + format("}},\n"); } format("};\n\n"); // _table_ } @@ -898,145 +661,174 @@ void ParseFunctionGenerator::GenerateFastFieldEntries(Formatter& format) { } if (info.func_name.empty()) { format("{::_pbi::TcParser::MiniParse, {}},\n"); + } else if (info.field == nullptr) { + // Fast slot that is not associated with a field. Eg end group tags. + format("{$1$, {$2$, $3$}},\n", info.func_name, info.coded_tag, + info.nonfield_info); } else { - bool cold = ShouldSplit(info.field, options_); + Y_ABSL_CHECK(!ShouldSplit(info.field, options_)); + + TProtoStringType func_name = info.func_name; + if (GetOptimizeFor(info.field->file(), options_) == FileOptions::SPEED) { + // For 1-byte tags we have a more optimized version of the varint parser + // that can hardcode the offset and has bit. + if (y_absl::EndsWith(func_name, "V8S1") || + y_absl::EndsWith(func_name, "V32S1") || + y_absl::EndsWith(func_name, "V64S1")) { + TProtoStringType field_type = y_absl::EndsWith(func_name, "V8S1") ? "bool" + : y_absl::EndsWith(func_name, "V32S1") + ? "::arc_ui32" + : "::arc_ui64"; + func_name = y_absl::StrCat( + "::_pbi::TcParser::SingularVarintNoZag1<", field_type, + ", offsetof(", // + ClassName(info.field->containing_type()), // + ", ", // + FieldMemberName(info.field, /*split=*/false), // + "), ", // + info.hasbit_idx, // + ">()"); + } + } + format( "{$1$,\n" - " {$2$, $3$, $4$, PROTOBUF_FIELD_OFFSET($classname$$5$, $6$)}},\n", - info.func_name, info.coded_tag, info.hasbit_idx, info.aux_idx, - cold ? "::Impl_::Split" : "", - cold ? FieldName(info.field) + "_" - : FieldMemberName(info.field, /*cold=*/false)); + " {$2$, $3$, $4$, PROTOBUF_FIELD_OFFSET($classname$, $5$)}},\n", + func_name, info.coded_tag, info.hasbit_idx, info.aux_idx, + FieldMemberName(info.field, /*split=*/false)); } } } static void FormatFieldKind(Formatter& format, - const TailCallTableInfo::FieldEntryInfo& entry, - const Options& options, - MessageSCCAnalyzer* scc_analyzer) { - const FieldDescriptor* field = entry.field; - // Spell the field kind in proto language declaration order, starting with - // cardinality: - format("(::_fl::kFc"); - if (HasHasbit(field)) { - format("Optional"); - } else if (field->is_repeated()) { - format("Repeated"); - } else if (field->real_containing_oneof()) { - format("Oneof"); - } else { - format("Singular"); - } + const TailCallTableInfo::FieldEntryInfo& entry) { + // In here we convert the runtime value of entry.type_card back into a + // sequence of literal enum labels. We use the mnenonic labels for nicer + // codegen. + namespace fl = internal::field_layout; + const uint16_t type_card = entry.type_card; + const int rep_index = (type_card & fl::kRepMask) >> fl::kRepShift; + const int tv_index = (type_card & fl::kTvMask) >> fl::kTvShift; + + // Use `0|` prefix to eagerly convert the enums to int to avoid enum-enum + // operations. They are deprecated in C++20. + format("(0 | "); + static constexpr const char* kFieldCardNames[] = {"Singular", "Optional", + "Repeated", "Oneof"}; + static_assert((fl::kFcSingular >> fl::kFcShift) == 0, ""); + static_assert((fl::kFcOptional >> fl::kFcShift) == 1, ""); + static_assert((fl::kFcRepeated >> fl::kFcShift) == 2, ""); + static_assert((fl::kFcOneof >> fl::kFcShift) == 3, ""); + + format("::_fl::kFc$1$", + kFieldCardNames[(type_card & fl::kFcMask) >> fl::kFcShift]); + +#define PROTOBUF_INTERNAL_TYPE_CARD_CASE(x) \ + case fl::k##x: \ + format(" | ::_fl::k" #x); \ + break + + switch (type_card & fl::kFkMask) { + case fl::kFkString: { + switch (type_card & ~fl::kFcMask & ~fl::kRepMask & ~fl::kSplitMask) { + PROTOBUF_INTERNAL_TYPE_CARD_CASE(Bytes); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(RawString); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(Utf8String); + default: + Y_ABSL_LOG(FATAL) << "Unknown type_card: 0x" << type_card; + } - // The rest of the type uses convenience aliases: - format(" | ::_fl::k"); - if (field->is_repeated() && field->is_packed()) { - format("Packed"); - } - switch (field->type()) { - case FieldDescriptor::TYPE_DOUBLE: - format("Double"); - break; - case FieldDescriptor::TYPE_FLOAT: - format("Float"); - break; - case FieldDescriptor::TYPE_FIXED32: - format("Fixed32"); - break; - case FieldDescriptor::TYPE_SFIXED32: - format("SFixed32"); - break; - case FieldDescriptor::TYPE_FIXED64: - format("Fixed64"); - break; - case FieldDescriptor::TYPE_SFIXED64: - format("SFixed64"); - break; - case FieldDescriptor::TYPE_BOOL: - format("Bool"); + static constexpr const char* kRepNames[] = {"AString", "IString", "Cord", + "SPiece", "SString"}; + static_assert((fl::kRepAString >> fl::kRepShift) == 0, ""); + static_assert((fl::kRepIString >> fl::kRepShift) == 1, ""); + static_assert((fl::kRepCord >> fl::kRepShift) == 2, ""); + static_assert((fl::kRepSPiece >> fl::kRepShift) == 3, ""); + static_assert((fl::kRepSString >> fl::kRepShift) == 4, ""); + + format(" | ::_fl::kRep$1$", kRepNames[rep_index]); break; - case FieldDescriptor::TYPE_ENUM: - if (HasPreservingUnknownEnumSemantics(field)) { - // No validation is required. - format("OpenEnum"); - } else if (entry.is_enum_range) { - // Validation is done by range check (start/length in FieldAux). - format("EnumRange"); - } else { - // Validation uses the generated _IsValid function. - format("Enum"); + } + + case fl::kFkMessage: { + format(" | ::_fl::kMessage"); + + static constexpr const char* kRepNames[] = {nullptr, "Group", "Lazy"}; + static_assert((fl::kRepGroup >> fl::kRepShift) == 1, ""); + static_assert((fl::kRepLazy >> fl::kRepShift) == 2, ""); + + if (auto* rep = kRepNames[rep_index]) { + format(" | ::_fl::kRep$1$", rep); } - break; - case FieldDescriptor::TYPE_UINT32: - format("UInt32"); - break; - case FieldDescriptor::TYPE_SINT32: - format("SInt32"); - break; - case FieldDescriptor::TYPE_INT32: - format("Int32"); - break; - case FieldDescriptor::TYPE_UINT64: - format("UInt64"); - break; - case FieldDescriptor::TYPE_SINT64: - format("SInt64"); - break; - case FieldDescriptor::TYPE_INT64: - format("Int64"); - break; - case FieldDescriptor::TYPE_BYTES: - format("Bytes"); - break; - case FieldDescriptor::TYPE_STRING: { - auto mode = GetUtf8CheckMode(field, options); - switch (mode) { - case Utf8CheckMode::kStrict: - format("Utf8String"); - break; - case Utf8CheckMode::kVerify: - format("RawString"); - break; - case Utf8CheckMode::kNone: - // Treat LITE_RUNTIME strings as bytes. - format("Bytes"); - break; - default: - GOOGLE_LOG(FATAL) << "Invalid Utf8CheckMode (" << static_cast<int>(mode) - << ") for " << field->DebugString(); + static constexpr const char* kXFormNames[] = {nullptr, "Default", "Table", + "WeakPtr"}; + static_assert((fl::kTvDefault >> fl::kTvShift) == 1, ""); + static_assert((fl::kTvTable >> fl::kTvShift) == 2, ""); + static_assert((fl::kTvWeakPtr >> fl::kTvShift) == 3, ""); + + if (auto* xform = kXFormNames[tv_index]) { + format(" | ::_fl::kTv$1$", xform); } break; } - case FieldDescriptor::TYPE_GROUP: - format("Message | ::_fl::kRepGroup"); + case fl::kFkMap: + format(" | ::_fl::kMap"); break; - case FieldDescriptor::TYPE_MESSAGE: - if (field->is_map()) { - format("Map"); - } else { - format("Message"); - if (IsLazy(field, options, scc_analyzer)) { - format(" | ::_fl::kRepLazy"); - } else if (IsImplicitWeakField(field, options, scc_analyzer)) { - format(" | ::_fl::kRepIWeak"); - } - } + + case fl::kFkNone: break; - } - // Fill in extra information about string and bytes field representations. - if (field->type() == FieldDescriptor::TYPE_BYTES || - field->type() == FieldDescriptor::TYPE_STRING) { - if (field->is_repeated()) { - format(" | ::_fl::kRepSString"); - } else { - format(" | ::_fl::kRepAString"); + case fl::kFkVarint: + case fl::kFkPackedVarint: + case fl::kFkFixed: + case fl::kFkPackedFixed: { + switch (type_card & ~fl::kFcMask & ~fl::kSplitMask) { + PROTOBUF_INTERNAL_TYPE_CARD_CASE(Bool); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(Fixed32); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(UInt32); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(SFixed32); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(Int32); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(SInt32); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(Float); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(Enum); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(EnumRange); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(OpenEnum); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(Fixed64); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(UInt64); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(SFixed64); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(Int64); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(SInt64); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(Double); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedBool); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFixed32); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedUInt32); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSFixed32); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedInt32); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSInt32); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFloat); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnum); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnumRange); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedOpenEnum); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFixed64); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedUInt64); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSFixed64); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedInt64); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSInt64); + PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedDouble); + default: + Y_ABSL_LOG(FATAL) << "Unknown type_card: 0x" << type_card; + } } } + if (type_card & fl::kSplitMask) { + format(" | ::_fl::kSplitTrue"); + } + +#undef PROTOBUF_INTERNAL_TYPE_CARD_CASE + format(")"); } @@ -1051,91 +843,81 @@ void ParseFunctionGenerator::GenerateFieldEntries(Formatter& format) { format("/* weak */ 0, 0, 0, 0"); } else { const OneofDescriptor* oneof = field->real_containing_oneof(); - bool cold = ShouldSplit(field, options_); - format("PROTOBUF_FIELD_OFFSET($classname$$1$, $2$), $3$, $4$,\n ", - cold ? "::Impl_::Split" : "", - cold ? FieldName(field) + "_" - : FieldMemberName(field, /*cold=*/false), - (oneof ? oneof->index() : entry.hasbit_idx), entry.aux_idx); - FormatFieldKind(format, entry, options_, scc_analyzer_); + bool split = ShouldSplit(field, options_); + if (split) { + format("PROTOBUF_FIELD_OFFSET($classname$::Impl_::Split, $1$), ", + y_absl::StrCat(FieldName(field), "_")); + } else { + format("PROTOBUF_FIELD_OFFSET($classname$, $1$), ", + FieldMemberName(field, /*cold=*/false)); + } + if (oneof) { + format("_Internal::kOneofCaseOffset + $1$, ", 4 * oneof->index()); + } else if (num_hasbits_ > 0 || IsMapEntryMessage(descriptor_)) { + if (entry.hasbit_idx >= 0) { + format("_Internal::kHasBitsOffset + $1$, ", entry.hasbit_idx); + } else { + format("$1$, ", entry.hasbit_idx); + } + } else { + format("0, "); + } + format("$1$,\n ", entry.aux_idx); + FormatFieldKind(format, entry); } format("},\n"); } } -static constexpr int kMaxNameLength = 255; - -int ParseFunctionGenerator::CalculateFieldNamesSize() const { - // The full name of the message appears first. - int size = std::min(static_cast<int>(descriptor_->full_name().size()), - kMaxNameLength); - int lengths_size = 1; - for (const auto& entry : tc_table_info_->field_entries) { - const FieldDescriptor* field = entry.field; - GOOGLE_CHECK_LE(field->name().size(), kMaxNameLength); - size += field->name().size(); - lengths_size += 1; +void ParseFunctionGenerator::GenerateFieldNames(Formatter& format) { + if (tc_table_info_->field_name_data.empty()) { + // No names to output. + return; } - // align to an 8-byte boundary - lengths_size = (lengths_size + 7) & -8; - return size + lengths_size + 1; -} -static void FormatOctal(Formatter& format, int size) { - int octal_size = ((size >> 6) & 3) * 100 + // - ((size >> 3) & 7) * 10 + // - ((size >> 0) & 7); - format("\\$1$", octal_size); -} + // We could just output the bytes directly, but we want it to look better than + // that in the source code. Also, it is more efficient for compilation time to + // have a literal string than an initializer list of chars. -void ParseFunctionGenerator::GenerateFieldNames(Formatter& format) { - // First, we output the size of each string, as an unsigned byte. The first - // string is the message name. - int count = 1; + const int total_sizes = + static_cast<int>(((tc_table_info_->field_entries.size() + 1) + 7) & ~7); + const uint8_t* p = tc_table_info_->field_name_data.data(); + const uint8_t* sizes = p; + const uint8_t* sizes_end = sizes + total_sizes; + + // First print all the sizes as octal format("\""); - FormatOctal(format, - std::min(static_cast<int>(descriptor_->full_name().size()), 255)); - for (const auto& entry : tc_table_info_->field_entries) { - FormatOctal(format, entry.field->name().size()); - ++count; - } - while (count & 7) { // align to an 8-byte boundary - format("\\0"); - ++count; + for (int i = 0; i < total_sizes; ++i) { + int size = *p++; + int octal_size = ((size >> 6) & 3) * 100 + // + ((size >> 3) & 7) * 10 + // + ((size >> 0) & 7); + format("\\$1$", octal_size); } format("\"\n"); - // The message name is stored at the beginning of the string - TProtoStringType message_name = descriptor_->full_name(); - if (message_name.size() > kMaxNameLength) { - static constexpr int kNameHalfLength = (kMaxNameLength - 3) / 2; - message_name = StrCat( - message_name.substr(0, kNameHalfLength), "...", - message_name.substr(message_name.size() - kNameHalfLength)); - } - format("\"$1$\"\n", message_name); - // Then we output the actual field names - for (const auto& entry : tc_table_info_->field_entries) { - const FieldDescriptor* field = entry.field; - format("\"$1$\"\n", field->name()); + + // Then print each name in a line of its own + for (; sizes < sizes_end; p += *sizes++) { + if (*sizes != 0) format("\"$1$\"\n", TProtoStringType((const char*)p, (const char*)p + *sizes)); } } void ParseFunctionGenerator::GenerateArenaString(Formatter& format, const FieldDescriptor* field) { - if (HasHasbit(field)) { + if (internal::cpp::HasHasbit(field)) { format("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field)); } format( "if (arena != nullptr) {\n" " ptr = ctx->ReadArenaString(ptr, &$msg$$field$, arena"); if (IsStringInlined(field, options_)) { - GOOGLE_DCHECK(!inlined_string_indices_.empty()); + Y_ABSL_DCHECK(!inlined_string_indices_.empty()); int inlined_string_index = inlined_string_indices_[field->index()]; - GOOGLE_DCHECK_GT(inlined_string_index, 0); + Y_ABSL_DCHECK_GT(inlined_string_index, 0); format(", &$msg$$inlined_string_donated_array$[0], $1$, $this$", inlined_string_index); } else { - GOOGLE_DCHECK(field->default_value_string().empty()); + Y_ABSL_DCHECK(field->default_value_string().empty()); } format( ");\n" @@ -1184,7 +966,9 @@ void ParseFunctionGenerator::GenerateStrings(Formatter& format, // to verify UTF8 when we already know parsing failed. format("CHK_(ptr);\n"); if (!check_utf8) return; // return if this is a bytes field - auto level = GetUtf8CheckMode(field, options_); + auto level = internal::cpp::GetUtf8CheckMode( + field, + GetOptimizeFor(field->file(), options_) == FileOptions::LITE_RUNTIME); switch (level) { case Utf8CheckMode::kNone: return; @@ -1198,7 +982,7 @@ void ParseFunctionGenerator::GenerateStrings(Formatter& format, TProtoStringType field_name; field_name = "nullptr"; if (HasDescriptorMethods(field->file(), options_)) { - field_name = StrCat("\"", field->full_name(), "\""); + field_name = y_absl::StrCat("\"", field->full_name(), "\""); } format("::_pbi::VerifyUTF8(str, $1$)", field_name); switch (level) { @@ -1219,7 +1003,7 @@ void ParseFunctionGenerator::GenerateLengthDelim(Formatter& format, const FieldDescriptor* field) { if (field->is_packable()) { if (field->type() == FieldDescriptor::TYPE_ENUM && - !HasPreservingUnknownEnumSemantics(field)) { + !internal::cpp::HasPreservingUnknownEnumSemantics(field)) { TProtoStringType enum_type = QualifiedClassName(field->enum_type(), options_); format( "ptr = " @@ -1246,9 +1030,9 @@ void ParseFunctionGenerator::GenerateLengthDelim(Formatter& format, case FieldDescriptor::TYPE_MESSAGE: { if (field->is_map()) { const FieldDescriptor* val = field->message_type()->map_value(); - GOOGLE_CHECK(val); + Y_ABSL_CHECK(val); if (val->type() == FieldDescriptor::TYPE_ENUM && - !HasPreservingUnknownEnumSemantics(field)) { + !internal::cpp::HasPreservingUnknownEnumSemantics(field)) { format( "auto object = " "::$proto_ns$::internal::InitEnumParseWrapper<" @@ -1267,13 +1051,13 @@ void ParseFunctionGenerator::GenerateLengthDelim(Formatter& format, format( "ctx->set_lazy_eager_verify_func($1$);\n", eager_verify - ? StrCat("&", ClassName(field->message_type(), true), + ? y_absl::StrCat("&", ClassName(field->message_type(), true), "::InternalVerify") : "nullptr"); } if (field->real_containing_oneof()) { format( - "if (!$msg$_internal_has_$name$()) {\n" + "if ($msg$$1$_case() != k$2$) {\n" " $msg$clear_$1$();\n" " $msg$$field$ = ::$proto_ns$::Arena::CreateMessage<\n" " ::$proto_ns$::internal::LazyField>(" @@ -1281,8 +1065,9 @@ void ParseFunctionGenerator::GenerateLengthDelim(Formatter& format, " $msg$set_has_$name$();\n" "}\n" "auto* lazy_field = $msg$$field$;\n", - field->containing_oneof()->name()); - } else if (HasHasbit(field)) { + field->containing_oneof()->name(), + UnderscoresToCamelCase(field->name(), true)); + } else if (internal::cpp::HasHasbit(field)) { format( "_Internal::set_has_$name$(&$has_bits$);\n" "auto* lazy_field = &$msg$$field$;\n"); @@ -1333,8 +1118,8 @@ void ParseFunctionGenerator::GenerateLengthDelim(Formatter& format, break; } default: - GOOGLE_LOG(FATAL) << "Illegal combination for length delimited wiretype " - << " filed type is " << field->type(); + Y_ABSL_LOG(FATAL) << "Illegal combination for length delimited wiretype " + << " filed type is " << field->type(); } } } @@ -1356,29 +1141,31 @@ void ParseFunctionGenerator::GenerateFieldBody( {{"name", FieldName(field)}, {"primitive_type", PrimitiveTypeName(options_, field->cpp_type())}}); if (field->is_repeated()) { - format.AddMap({{"put_field", StrCat("add_", FieldName(field))}, - {"mutable_field", StrCat("add_", FieldName(field))}}); + format.AddMap({{"put_field", y_absl::StrCat("add_", FieldName(field))}, + {"mutable_field", y_absl::StrCat("add_", FieldName(field))}}); } else { format.AddMap( - {{"put_field", StrCat("set_", FieldName(field))}, - {"mutable_field", StrCat("mutable_", FieldName(field))}}); + {{"put_field", y_absl::StrCat("set_", FieldName(field))}, + {"mutable_field", y_absl::StrCat("mutable_", FieldName(field))}}); } arc_ui32 tag = WireFormatLite::MakeTag(field->number(), wiretype); switch (wiretype) { case WireFormatLite::WIRETYPE_VARINT: { - TProtoStringType type = PrimitiveTypeName(options_, field->cpp_type()); if (field->type() == FieldDescriptor::TYPE_ENUM) { format.Set("enum_type", QualifiedClassName(field->enum_type(), options_)); format( - "$uint64$ val = ::$proto_ns$::internal::ReadVarint64(&ptr);\n" + "$uint32$ val = ::$proto_ns$::internal::ReadVarint32(&ptr);\n" "CHK_(ptr);\n"); - if (!HasPreservingUnknownEnumSemantics(field)) { - format("if (PROTOBUF_PREDICT_TRUE($enum_type$_IsValid(val))) {\n"); + if (!internal::cpp::HasPreservingUnknownEnumSemantics(field)) { + format( + "if " + "(PROTOBUF_PREDICT_TRUE($enum_type$_IsValid(static_cast<int>(val)" + "))) {\n"); format.Indent(); } format("$msg$_internal_$put_field$(static_cast<$enum_type$>(val));\n"); - if (!HasPreservingUnknownEnumSemantics(field)) { + if (!internal::cpp::HasPreservingUnknownEnumSemantics(field)) { format.Outdent(); format( "} else {\n" @@ -1405,7 +1192,7 @@ void ParseFunctionGenerator::GenerateFieldBody( "CHK_(ptr);\n", zigzag, size); } else { - if (HasHasbit(field)) { + if (internal::cpp::HasHasbit(field)) { format("_Internal::set_has_$name$(&$has_bits$);\n"); } format( @@ -1424,7 +1211,7 @@ void ParseFunctionGenerator::GenerateFieldBody( "::$proto_ns$::internal::UnalignedLoad<$primitive_type$>(ptr));\n" "ptr += sizeof($primitive_type$);\n"); } else { - if (HasHasbit(field)) { + if (internal::cpp::HasHasbit(field)) { format("_Internal::set_has_$name$(&$has_bits$);\n"); } format( @@ -1446,7 +1233,7 @@ void ParseFunctionGenerator::GenerateFieldBody( break; } case WireFormatLite::WIRETYPE_END_GROUP: { - GOOGLE_LOG(FATAL) << "Can't have end group field\n"; + Y_ABSL_LOG(FATAL) << "Can't have end group field\n"; break; } } // switch (wire_type) @@ -1460,7 +1247,7 @@ static arc_ui32 ExpectedTag(const FieldDescriptor* field, if (field->is_packable()) { auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type()); expected_tag = WireFormatLite::MakeTag(field->number(), expected_wiretype); - GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + Y_ABSL_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED); auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED; arc_ui32 fallback_tag = WireFormatLite::MakeTag(field->number(), fallback_wiretype); @@ -1599,8 +1386,9 @@ void ParseFunctionGenerator::GenerateFieldSwitch( format.Outdent(); } format( - "} else\n" + "} else {\n" " goto handle_unusual;\n" + "}\n" "$next_tag$;\n"); format.Outdent(); } // for loop over ordered fields @@ -1612,113 +1400,6 @@ void ParseFunctionGenerator::GenerateFieldSwitch( format("} // switch\n"); } -namespace { - -TProtoStringType FieldParseFunctionName( - const TailCallTableInfo::FieldEntryInfo& entry, const Options& options) { - const FieldDescriptor* field = entry.field; - TProtoStringType name = "::_pbi::TcParser::Fast"; - - switch (field->type()) { - case FieldDescriptor::TYPE_FIXED32: - case FieldDescriptor::TYPE_SFIXED32: - case FieldDescriptor::TYPE_FLOAT: - name.append("F32"); - break; - - case FieldDescriptor::TYPE_FIXED64: - case FieldDescriptor::TYPE_SFIXED64: - case FieldDescriptor::TYPE_DOUBLE: - name.append("F64"); - break; - - case FieldDescriptor::TYPE_BOOL: - name.append("V8"); - break; - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_UINT32: - name.append("V32"); - break; - case FieldDescriptor::TYPE_INT64: - case FieldDescriptor::TYPE_UINT64: - name.append("V64"); - break; - - case FieldDescriptor::TYPE_ENUM: - if (HasPreservingUnknownEnumSemantics(field)) { - name.append("V32"); - break; - } - if (field->is_repeated() && field->is_packed()) { - GOOGLE_LOG(DFATAL) << "Enum validation not handled: " << field->DebugString(); - return ""; - } - name.append(entry.is_enum_range ? "Er" : "Ev"); - break; - - case FieldDescriptor::TYPE_SINT32: - name.append("Z32"); - break; - case FieldDescriptor::TYPE_SINT64: - name.append("Z64"); - break; - - case FieldDescriptor::TYPE_BYTES: - name.append("B"); - if (IsStringInlined(field, options)) { - name.append("i"); - } - break; - case FieldDescriptor::TYPE_STRING: - switch (GetUtf8CheckMode(field, options)) { - case Utf8CheckMode::kNone: - name.append("B"); - break; - case Utf8CheckMode::kVerify: - name.append("S"); - break; - case Utf8CheckMode::kStrict: - name.append("U"); - break; - default: - GOOGLE_LOG(DFATAL) << "Mode not handled: " - << static_cast<int>(GetUtf8CheckMode(field, options)); - return ""; - } - if (IsStringInlined(field, options)) { - name.append("i"); - } - break; - - case FieldDescriptor::TYPE_MESSAGE: - name.append("M"); - break; - case FieldDescriptor::TYPE_GROUP: - name.append("G"); - break; - - default: - GOOGLE_LOG(DFATAL) << "Type not handled: " << field->DebugString(); - return ""; - } - - // The field implementation functions are prefixed by cardinality: - // `S` for optional or implicit fields. - // `R` for non-packed repeated. - // `P` for packed repeated. - name.append(field->is_packed() ? "P" - : field->is_repeated() ? "R" - : field->real_containing_oneof() ? "O" - : "S"); - - // Append the tag length. Fast parsing only handles 1- or 2-byte tags. - name.append(TagSize(field->number()) == 1 ? "1" : "2"); - - return name; -} - -} // namespace - } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.h index 7e2b674852f..c12c2057328 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.h @@ -31,72 +31,32 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_PARSE_FUNCTION_GENERATOR_H__ -#include <map> #include <string> #include <vector> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/wire_format_lite.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/compiler/cpp/options.h> +#include "google/protobuf/descriptor.h" +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/generated_message_tctable_gen.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format_lite.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { -// Helper class for generating tailcall parsing functions. -struct TailCallTableInfo { - TailCallTableInfo(const Descriptor* descriptor, const Options& options, - const std::vector<const FieldDescriptor*>& ordered_fields, - const std::vector<int>& has_bit_indices, - const std::vector<int>& inlined_string_indices, - MessageSCCAnalyzer* scc_analyzer); - - // Fields parsed by the table fast-path. - struct FastFieldInfo { - TProtoStringType func_name; - const FieldDescriptor* field; - uint16_t coded_tag; - uint8_t hasbit_idx; - uint8_t aux_idx; - }; - std::vector<FastFieldInfo> fast_path_fields; - - // Fields parsed by mini parsing routines. - struct FieldEntryInfo { - const FieldDescriptor* field; - int hasbit_idx; - int inlined_string_idx; - uint16_t aux_idx; - // True for enums entirely covered by the start/length fields of FieldAux: - bool is_enum_range; - }; - std::vector<FieldEntryInfo> field_entries; - std::vector<TProtoStringType> aux_entries; - - // Fields parsed by generated fallback function. - std::vector<const FieldDescriptor*> fallback_fields; - - // Table size. - int table_size_log2; - // Mask for has-bits of required fields. - arc_ui32 has_hasbits_required_mask; - // True if a generated fallback function is required instead of generic. - bool use_generated_fallback; -}; - // ParseFunctionGenerator generates the _InternalParse function for a message // (and any associated supporting members). class ParseFunctionGenerator { public: - ParseFunctionGenerator(const Descriptor* descriptor, int max_has_bit_index, - const std::vector<int>& has_bit_indices, - const std::vector<int>& inlined_string_indices, - const Options& options, - MessageSCCAnalyzer* scc_analyzer, - const std::map<TProtoStringType, TProtoStringType>& vars); + ParseFunctionGenerator( + const Descriptor* descriptor, int max_has_bit_index, + const std::vector<int>& has_bit_indices, + const std::vector<int>& inlined_string_indices, const Options& options, + MessageSCCAnalyzer* scc_analyzer, + const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& vars); // Emits class-level method declarations to `printer`: void GenerateMethodDecls(io::Printer* printer); @@ -111,6 +71,8 @@ class ParseFunctionGenerator { void GenerateDataDefinitions(io::Printer* printer); private: + class GeneratedOptionProvider; + // Returns true if tailcall table code should be generated. bool should_generate_tctable() const; @@ -134,7 +96,6 @@ class ParseFunctionGenerator { void GenerateTailCallTable(Formatter& format); void GenerateFastFieldEntries(Formatter& format); void GenerateFieldEntries(Formatter& format); - int CalculateFieldNamesSize() const; void GenerateFieldNames(Formatter& format); // Generates parsing code for an `ArenaString` field. @@ -165,8 +126,8 @@ class ParseFunctionGenerator { const Descriptor* descriptor_; MessageSCCAnalyzer* scc_analyzer_; const Options& options_; - std::map<TProtoStringType, TProtoStringType> variables_; - std::unique_ptr<TailCallTableInfo> tc_table_info_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; + std::unique_ptr<internal::TailCallTableInfo> tc_table_info_; std::vector<int> inlined_string_indices_; const std::vector<const FieldDescriptor*> ordered_fields_; int num_hasbits_; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.cc deleted file mode 100644 index 9dbf16ae7eb..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.cc +++ /dev/null @@ -1,539 +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: [email protected] (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <google/protobuf/compiler/cpp/primitive_field.h> - -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/cpp/helpers.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace cpp { - -using internal::WireFormatLite; - -namespace { - -// For encodings with fixed sizes, returns that size in bytes. Otherwise -// returns -1. -int FixedSize(FieldDescriptor::Type type) { - switch (type) { - case FieldDescriptor::TYPE_INT32: - return -1; - case FieldDescriptor::TYPE_INT64: - return -1; - case FieldDescriptor::TYPE_UINT32: - return -1; - case FieldDescriptor::TYPE_UINT64: - return -1; - case FieldDescriptor::TYPE_SINT32: - return -1; - case FieldDescriptor::TYPE_SINT64: - return -1; - case FieldDescriptor::TYPE_FIXED32: - return WireFormatLite::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64: - return WireFormatLite::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: - return WireFormatLite::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: - return WireFormatLite::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT: - return WireFormatLite::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE: - return WireFormatLite::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL: - return WireFormatLite::kBoolSize; - case FieldDescriptor::TYPE_ENUM: - return -1; - - case FieldDescriptor::TYPE_STRING: - return -1; - case FieldDescriptor::TYPE_BYTES: - return -1; - case FieldDescriptor::TYPE_GROUP: - return -1; - case FieldDescriptor::TYPE_MESSAGE: - return -1; - - // No default because we want the compiler to complain if any new - // types are added. - } - GOOGLE_LOG(FATAL) << "Can't get here."; - return -1; -} - -void SetPrimitiveVariables(const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables, - const Options& options) { - SetCommonFieldVariables(descriptor, variables, options); - (*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type()); - (*variables)["default"] = DefaultValue(options, descriptor); - (*variables)["cached_byte_size_name"] = MakeVarintCachedSizeName(descriptor); - bool cold = ShouldSplit(descriptor, options); - (*variables)["cached_byte_size_field"] = - MakeVarintCachedSizeFieldName(descriptor, cold); - (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor)); - int fixed_size = FixedSize(descriptor->type()); - if (fixed_size != -1) { - (*variables)["fixed_size"] = StrCat(fixed_size); - } - (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name( - static_cast<FieldDescriptorProto_Type>(descriptor->type())); - (*variables)["full_name"] = descriptor->full_name(); -} - -} // namespace - -// =================================================================== - -PrimitiveFieldGenerator::PrimitiveFieldGenerator( - const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(descriptor, options) { - SetPrimitiveVariables(descriptor, &variables_, options); -} - -PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} - -void PrimitiveFieldGenerator::GeneratePrivateMembers( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$type$ $name$_;\n"); -} - -void PrimitiveFieldGenerator::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" - "private:\n" - "$type$ ${1$_internal_$name$$}$() const;\n" - "void ${1$_internal_set_$name$$}$($type$ value);\n" - "public:\n", - descriptor_); -} - -void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "inline $type$ $classname$::_internal_$name$() const {\n" - " return $field$;\n" - "}\n" - "inline $type$ $classname$::$name$() const {\n" - "$annotate_get$" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return _internal_$name$();\n" - "}\n" - "inline void $classname$::_internal_set_$name$($type$ value) {\n" - " $set_hasbit$\n" - " $field$ = value;\n" - "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" - "$maybe_prepare_split_message$" - " _internal_set_$name$(value);\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); -} - -void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$ = $default$;\n"); -} - -void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const { - Formatter format(printer, variables_); - format("_this->_internal_set_$name$(from._internal_$name$());\n"); -} - -void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { - Formatter format(printer, variables_); - format("swap($field$, other->$field$);\n"); -} - -void PrimitiveFieldGenerator::GenerateCopyConstructorCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("_this->$field$ = from.$field$;\n"); -} - -void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "target = stream->EnsureSpace(target);\n" - "target = " - "::_pbi::WireFormatLite::Write$declared_type$ToArray(" - "$number$, this->_internal_$name$(), target);\n"); -} - -void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const { - Formatter format(printer, variables_); - int fixed_size = FixedSize(descriptor_->type()); - if (fixed_size == -1) { - if (internal::WireFormat::TagSize(descriptor_->number(), - descriptor_->type()) == 1) { - // Adding one is very common and it turns out it can be done for - // free inside of WireFormatLite, so we can save an instruction here. - format( - "total_size += ::_pbi::WireFormatLite::" - "$declared_type$SizePlusOne(this->_internal_$name$());\n"); - } else { - format( - "total_size += $tag_size$ +\n" - " ::_pbi::WireFormatLite::$declared_type$Size(\n" - " this->_internal_$name$());\n"); - } - } else { - format("total_size += $tag_size$ + $fixed_size$;\n"); - } -} - -void PrimitiveFieldGenerator::GenerateConstexprAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("/*decltype($field$)*/$default$"); -} - -void PrimitiveFieldGenerator::GenerateAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - if (ShouldSplit(descriptor_, options_)) { - format("decltype(Impl_::Split::$name$_){$default$}"); - return; - } - format("decltype($field$){$default$}"); -} - -void PrimitiveFieldGenerator::GenerateCopyAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("decltype($field$){}"); -} - -// =================================================================== - -PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( - const FieldDescriptor* descriptor, const Options& options) - : PrimitiveFieldGenerator(descriptor, options) { - SetCommonOneofFieldVariables(descriptor, &variables_); -} - -PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} - -void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "inline $type$ $classname$::_internal_$name$() const {\n" - " if (_internal_has_$name$()) {\n" - " return $field$;\n" - " }\n" - " return $default$;\n" - "}\n" - "inline void $classname$::_internal_set_$name$($type$ value) {\n" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " }\n" - " $field$ = value;\n" - "}\n" - "inline $type$ $classname$::$name$() const {\n" - "$annotate_get$" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return _internal_$name$();\n" - "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" - " _internal_set_$name$(value);\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); -} - -void PrimitiveOneofFieldGenerator::GenerateClearingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$ = $default$;\n"); -} - -void PrimitiveOneofFieldGenerator::GenerateSwappingCode( - io::Printer* printer) const { - // Don't print any swapping code. Swapping the union will swap this field. -} - -void PrimitiveOneofFieldGenerator::GenerateConstructorCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$ns$::_$classname$_default_instance_.$field$ = $default$;\n"); -} - -// =================================================================== - -RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( - const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(descriptor, options) { - SetPrimitiveVariables(descriptor, &variables_, options); - - if (descriptor->is_packed()) { - variables_["packed_reader"] = "ReadPackedPrimitive"; - variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline"; - } else { - variables_["packed_reader"] = "ReadPackedPrimitiveNoInline"; - variables_["repeated_reader"] = "ReadRepeatedPrimitive"; - } -} - -RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} - -void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n"); - if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 && - HasGeneratedMethods(descriptor_->file(), options_)) { - format("mutable std::atomic<int> $cached_byte_size_name$;\n"); - } -} - -void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "private:\n" - "$type$ ${1$_internal_$name$$}$(int index) const;\n" - "const ::$proto_ns$::RepeatedField< $type$ >&\n" - " ${1$_internal_$name$$}$() const;\n" - "void ${1$_internal_add_$name$$}$($type$ value);\n" - "::$proto_ns$::RepeatedField< $type$ >*\n" - " ${1$_internal_mutable_$name$$}$();\n" - "public:\n" - "$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 { - Formatter format(printer, variables_); - format( - "inline $type$ $classname$::_internal_$name$(int index) const {\n" - " return $field$.Get(index);\n" - "}\n" - "inline $type$ $classname$::$name$(int index) const {\n" - "$annotate_get$" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return _internal_$name$(index);\n" - "}\n" - "inline void $classname$::set_$name$(int index, $type$ value) {\n" - "$annotate_set$" - " $field$.Set(index, value);\n" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "inline void $classname$::_internal_add_$name$($type$ value) {\n" - " $field$.Add(value);\n" - "}\n" - "inline void $classname$::add_$name$($type$ value) {\n" - " _internal_add_$name$(value);\n" - "$annotate_add$" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "inline const ::$proto_ns$::RepeatedField< $type$ >&\n" - "$classname$::_internal_$name$() const {\n" - " return $field$;\n" - "}\n" - "inline const ::$proto_ns$::RepeatedField< $type$ >&\n" - "$classname$::$name$() const {\n" - "$annotate_list$" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return _internal_$name$();\n" - "}\n" - "inline ::$proto_ns$::RepeatedField< $type$ >*\n" - "$classname$::_internal_mutable_$name$() {\n" - " return &$field$;\n" - "}\n" - "inline ::$proto_ns$::RepeatedField< $type$ >*\n" - "$classname$::mutable_$name$() {\n" - "$annotate_mutable_list$" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return _internal_mutable_$name$();\n" - "}\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateClearingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$.Clear();\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateMergingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("_this->$field$.MergeFrom(from.$field$);\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$.InternalSwap(&other->$field$);\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateDestructorCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$.~RepeatedField();\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const { - Formatter format(printer, variables_); - if (descriptor_->is_packed()) { - if (FixedSize(descriptor_->type()) == -1) { - format( - "{\n" - " int byte_size = " - "$cached_byte_size_field$.load(std::memory_order_relaxed);\n" - " if (byte_size > 0) {\n" - " target = stream->Write$declared_type$Packed(\n" - " $number$, _internal_$name$(), byte_size, target);\n" - " }\n" - "}\n"); - } else { - format( - "if (this->_internal_$name$_size() > 0) {\n" - " target = stream->WriteFixedPacked($number$, _internal_$name$(), " - "target);\n" - "}\n"); - } - } else { - format( - "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n" - " target = stream->EnsureSpace(target);\n" - " target = ::_pbi::WireFormatLite::" - "Write$declared_type$ToArray($number$, this->_internal_$name$(i), " - "target);\n" - "}\n"); - } -} - -void RepeatedPrimitiveFieldGenerator::GenerateByteSize( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("{\n"); - format.Indent(); - int fixed_size = FixedSize(descriptor_->type()); - if (fixed_size == -1) { - format( - "size_t data_size = ::_pbi::WireFormatLite::\n" - " $declared_type$Size(this->$field$);\n"); - } else { - format( - "unsigned int count = static_cast<unsigned " - "int>(this->_internal_$name$_size());\n" - "size_t data_size = $fixed_size$UL * count;\n"); - } - - if (descriptor_->is_packed()) { - format( - "if (data_size > 0) {\n" - " total_size += $tag_size$ +\n" - " " - "::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n" - "}\n"); - if (FixedSize(descriptor_->type()) == -1) { - format( - "int cached_size = ::_pbi::ToCachedSize(data_size);\n" - "$cached_byte_size_field$.store(cached_size,\n" - " std::memory_order_relaxed);\n"); - } - format("total_size += data_size;\n"); - } else { - format( - "total_size += $tag_size$ *\n" - " " - "::_pbi::FromIntSize(this->_internal_$name$_size());\n" - "total_size += data_size;\n"); - } - format.Outdent(); - format("}\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateConstexprAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("/*decltype($field$)*/{}"); - if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 && - HasGeneratedMethods(descriptor_->file(), options_)) { - format("\n, /*decltype($cached_byte_size_field$)*/{0}"); - } -} - -void RepeatedPrimitiveFieldGenerator::GenerateAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("decltype($field$){arena}"); - if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 && - HasGeneratedMethods(descriptor_->file(), options_)) { - // std::atomic has no move constructor, which prevents explicit aggregate - // initialization pre-C++17. - format("\n, /*decltype($cached_byte_size_field$)*/{0}"); - } -} - -void RepeatedPrimitiveFieldGenerator::GenerateCopyAggregateInitializer( - io::Printer* printer) const { - - Formatter format(printer, variables_); - format("decltype($field$){from.$field$}"); - if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 && - HasGeneratedMethods(descriptor_->file(), options_)) { - // std::atomic has no move constructor. - format("\n, /*decltype($cached_byte_size_field$)*/{0}"); - } -} - -} // namespace cpp -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.h deleted file mode 100644 index bb8a08aa141..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.h +++ /dev/null @@ -1,126 +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: [email protected] (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__ - -#include <map> -#include <string> - -#include <google/protobuf/compiler/cpp/field.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace cpp { - -class PrimitiveFieldGenerator : public FieldGenerator { - public: - PrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~PrimitiveFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GeneratePrivateMembers(io::Printer* printer) const override; - void GenerateAccessorDeclarations(io::Printer* printer) const override; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateMergingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override {} - void GenerateCopyConstructorCode(io::Printer* printer) const override; - void GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const override; - void GenerateByteSize(io::Printer* printer) const override; - void GenerateConstexprAggregateInitializer( - io::Printer* printer) const override; - void GenerateAggregateInitializer(io::Printer* printer) const override; - void GenerateCopyAggregateInitializer(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); -}; - -class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { - public: - PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~PrimitiveOneofFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); -}; - -class RepeatedPrimitiveFieldGenerator : public FieldGenerator { - public: - RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~RepeatedPrimitiveFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GeneratePrivateMembers(io::Printer* printer) const override; - void GenerateAccessorDeclarations(io::Printer* printer) const override; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateMergingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override {} - void GenerateCopyConstructorCode(io::Printer* /*printer*/) const override { - GOOGLE_CHECK(!ShouldSplit(descriptor_, options_)); - } - void GenerateDestructorCode(io::Printer* printer) const override; - void GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const override; - void GenerateByteSize(io::Printer* printer) const override; - void GenerateConstexprAggregateInitializer( - io::Printer* printer) const override; - void GenerateAggregateInitializer(io::Printer* printer) const override; - void GenerateCopyAggregateInitializer(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); -}; - -} // namespace cpp -} // namespace compiler -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.cc index fae7128a097..ae1d2b8a2da 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.cc @@ -32,293 +32,279 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/cpp/service.h> +#include "google/protobuf/compiler/cpp/service.h" -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/cpp/helpers.h> +#include <string> + +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { - -namespace { - -void InitMethodVariables(const MethodDescriptor* method, const Options& options, - Formatter* format) { - format->Set("name", method->name()); - format->Set("input_type", QualifiedClassName(method->input_type(), options)); - format->Set("output_type", - QualifiedClassName(method->output_type(), options)); -} - -} // namespace - -ServiceGenerator::ServiceGenerator( - const ServiceDescriptor* descriptor, - const std::map<TProtoStringType, TProtoStringType>& vars, const Options& options) - : descriptor_(descriptor), vars_(vars), options_(options) { - vars_["classname"] = descriptor_->name(); - vars_["full_name"] = descriptor_->full_name(); -} - -ServiceGenerator::~ServiceGenerator() {} - void ServiceGenerator::GenerateDeclarations(io::Printer* printer) { - Formatter format(printer, vars_); - // Forward-declare the stub type. - format( - "class $classname$_Stub;\n" - "\n"); - - GenerateInterface(printer); - GenerateStubDefinition(printer); -} - -void ServiceGenerator::GenerateInterface(io::Printer* printer) { - 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(); - - format( - "\n" - "typedef $classname$_Stub Stub;\n" - "\n" - "static const ::$proto_ns$::ServiceDescriptor* descriptor();\n" - "\n"); - - GenerateMethodSignatures(VIRTUAL, printer); - - 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(); - format( - "\n" - " private:\n" - " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n" - "};\n" - "\n"); -} - -void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) { - Formatter format(printer, vars_); - format( - "class $dllexport_decl $$classname$_Stub : public $classname$ {\n" - " public:\n"); - - printer->Indent(); - - 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(); - format( - " private:\n" - " ::$proto_ns$::RpcChannel* channel_;\n" - " bool owns_channel_;\n" - " GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n" - "};\n" - "\n"); + auto vars = printer->WithVars(&vars_); + printer->Emit( + { + {"virts", [&] { GenerateMethodSignatures(kVirtual, printer); }}, + {"impls", [&] { GenerateMethodSignatures(kNonVirtual, printer); }}, + }, + R"cc( + class $classname$_Stub; + class $dllexport_decl $$classname$ : public ::$proto_ns$::Service { + protected: + $classname$() = default; + + public: + using Stub = $classname$_Stub; + + $classname$(const $classname$&) = delete; + $classname$& operator=(const $classname$&) = delete; + virtual ~$classname$() = default; + + static const ::$proto_ns$::ServiceDescriptor* descriptor(); + + $virts$; + + // implements Service ---------------------------------------------- + const ::$proto_ns$::ServiceDescriptor* GetDescriptor() override; + + void CallMethod(const ::$proto_ns$::MethodDescriptor* method, + ::$proto_ns$::RpcController* controller, + const ::$proto_ns$::Message* request, + ::$proto_ns$::Message* response, + ::google::protobuf::Closure* done) override; + + const ::$proto_ns$::Message& GetRequestPrototype( + const ::$proto_ns$::MethodDescriptor* method) const override; + + const ::$proto_ns$::Message& GetResponsePrototype( + const ::$proto_ns$::MethodDescriptor* method) const override; + }; + + class $dllexport_decl $$classname$_Stub final : public $classname$ { + public: + $classname$_Stub(::$proto_ns$::RpcChannel* channel); + $classname$_Stub(::$proto_ns$::RpcChannel* channel, + ::$proto_ns$::Service::ChannelOwnership ownership); + + $classname$_Stub(const $classname$_Stub&) = delete; + $classname$_Stub& operator=(const $classname$_Stub&) = delete; + + ~$classname$_Stub() override; + + inline ::$proto_ns$::RpcChannel* channel() { return channel_; } + + // implements $classname$ ------------------------------------------ + $impls$; + + private: + ::$proto_ns$::RpcChannel* channel_; + bool owns_channel_; + }; + )cc"); } -void ServiceGenerator::GenerateMethodSignatures(VirtualOrNon virtual_or_non, +void ServiceGenerator::GenerateMethodSignatures(VirtualOrNot virtual_or_not, io::Printer* printer) { - for (int i = 0; i < descriptor_->method_count(); i++) { + for (int i = 0; i < descriptor_->method_count(); ++i) { const MethodDescriptor* method = descriptor_->method(i); - Formatter format(printer, vars_); - InitMethodVariables(method, options_, &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"); + + printer->Emit( + { + {"name", method->name()}, + {"input", QualifiedClassName(method->input_type(), *options_)}, + {"output", QualifiedClassName(method->output_type(), *options_)}, + {"virtual", virtual_or_not == kVirtual ? "virtual" : ""}, + {"override", virtual_or_not != kVirtual ? "override" : ""}, + }, + // No cc, clang-format does not format this string well due to the + // $ override$ substitution. + R"( + $virtual $void $name$(::$proto_ns$::RpcController* controller, + const $input$* request, + $output$* response, + ::google::protobuf::Closure* done)$ override$; + )"); } } // =================================================================== void ServiceGenerator::GenerateImplementation(io::Printer* printer) { - Formatter format(printer, vars_); - format( - "$classname$::~$classname$() {}\n" - "\n" - "const ::$proto_ns$::ServiceDescriptor* $classname$::descriptor() {\n" - " " - "::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n" - " return $file_level_service_descriptors$[$1$];\n" - "}\n" - "\n" - "const ::$proto_ns$::ServiceDescriptor* $classname$::GetDescriptor() {\n" - " return descriptor();\n" - "}\n" - "\n", - index_in_metadata_); - - // Generate methods of the interface. - GenerateNotImplementedMethods(printer); - GenerateCallMethod(printer); - GenerateGetPrototype(REQUEST, printer); - GenerateGetPrototype(RESPONSE, printer); - - // Generate stub implementation. - 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); + auto vars = printer->WithVars(&vars_); + printer->Emit( + { + {"index", index_in_metadata_}, + {"no_impl_methods", [&] { GenerateNotImplementedMethods(printer); }}, + {"call_method", [&] { GenerateCallMethod(printer); }}, + {"get_request", [&] { GenerateGetPrototype(kRequest, printer); }}, + {"get_response", [&] { GenerateGetPrototype(kResponse, printer); }}, + {"stub_methods", [&] { GenerateStubMethods(printer); }}, + }, + R"cc( + const ::$proto_ns$::ServiceDescriptor* $classname$::descriptor() { + ::$proto_ns$::internal::AssignDescriptors(&$desc_table$); + return $file_level_service_descriptors$[$index$]; + } + + const ::$proto_ns$::ServiceDescriptor* $classname$::GetDescriptor() { + return descriptor(); + } + + $no_impl_methods$; + + $call_method$; + + $get_request$; + + $get_response$; + + $classname$_Stub::$classname$_Stub(::$proto_ns$::RpcChannel* channel) + : channel_(channel), owns_channel_(false) {} + + $classname$_Stub::$classname$_Stub( + ::$proto_ns$::RpcChannel* channel, + ::$proto_ns$::Service::ChannelOwnership ownership) + : channel_(channel), + owns_channel_(ownership == + ::$proto_ns$::Service::STUB_OWNS_CHANNEL) {} + + $classname$_Stub::~$classname$_Stub() { + if (owns_channel_) delete channel_; + } + + $stub_methods$; + )cc"); } void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) { - for (int i = 0; i < descriptor_->method_count(); i++) { + for (int i = 0; i < descriptor_->method_count(); ++i) { const MethodDescriptor* method = descriptor_->method(i); - Formatter format(printer, vars_); - InitMethodVariables(method, options_, &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"); + + printer->Emit( + { + {"name", method->name()}, + {"input", QualifiedClassName(method->input_type(), *options_)}, + {"output", QualifiedClassName(method->output_type(), *options_)}, + }, + R"cc( + void $classname$::$name$(::$proto_ns$::RpcController* controller, + const $input$*, $output$*, ::google::protobuf::Closure* done) { + controller->SetFailed("Method $name$() not implemented."); + done->Run(); + } + )cc"); } } void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { - 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_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); - Formatter format_method(printer, vars_); - InitMethodVariables(method, options_, &format_method); - - // Note: down_cast does not work here because it only works on pointers, - // not references. - format_method( - " case $1$:\n" - " $name$(controller,\n" - " ::$proto_ns$::internal::DownCast<const $input_type$*>(\n" - " request),\n" - " ::$proto_ns$::internal::DownCast<$output_type$*>(\n" - " response),\n" - " done);\n" - " break;\n", - i); - } - - format( - " default:\n" - " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" - " break;\n" - " }\n" - "}\n" - "\n"); + printer->Emit( + { + {"index", y_absl::StrCat(index_in_metadata_)}, + {"cases", [&] { GenerateCallMethodCases(printer); }}, + }, + R"cc( + void $classname$::CallMethod( + const ::$proto_ns$::MethodDescriptor* method, + ::$proto_ns$::RpcController* controller, + const ::$proto_ns$::Message* request, + ::$proto_ns$::Message* response, ::google::protobuf::Closure* done) { + Y_ABSL_DCHECK_EQ(method->service(), $file_level_service_descriptors$[$index$]); + switch (method->index()) { + $cases$; + + default: + Y_ABSL_LOG(FATAL) << "Bad method index; this should never happen."; + break; + } + } + )cc"); } void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, io::Printer* printer) { - Formatter format(printer, vars_); - if (which == REQUEST) { - format("const ::$proto_ns$::Message& $classname$::GetRequestPrototype(\n"); - } else { - format("const ::$proto_ns$::Message& $classname$::GetResponsePrototype(\n"); - } - - format( - " const ::$proto_ns$::MethodDescriptor* method) const {\n" - " GOOGLE_DCHECK_EQ(method->service(), descriptor());\n" - " switch(method->index()) {\n"); + printer->Emit( + { + {"which", which == kRequest ? "Request" : "Response"}, + {"which_type", which == kRequest ? "input" : "output"}, + {"cases", + [&] { + for (int i = 0; i < descriptor_->method_count(); ++i) { + const MethodDescriptor* method = descriptor_->method(i); + const Descriptor* type = which == kRequest + ? method->input_type() + : method->output_type(); + + printer->Emit( + { + {"index", y_absl::StrCat(i)}, + {"type", QualifiedClassName(type, *options_)}, + }, + R"cc( + case $index$: + return $type$::default_instance(); + )cc"); + } + }}, + }, + R"cc( + const ::$proto_ns$::Message& $classname$::Get$which$Prototype( + const ::$proto_ns$::MethodDescriptor* method) const { + Y_ABSL_DCHECK_EQ(method->service(), descriptor()); + switch (method->index()) { + $cases$; + + default: + Y_ABSL_LOG(FATAL) << "Bad method index; this should never happen."; + return *::$proto_ns$::MessageFactory::generated_factory() + ->GetPrototype(method->$which_type$_type()); + } + } + )cc"); +} - for (int i = 0; i < descriptor_->method_count(); i++) { +void ServiceGenerator::GenerateCallMethodCases(io::Printer* printer) { + 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(); - - format( - " case $1$:\n" - " return $2$::default_instance();\n", - i, QualifiedClassName(type, options_)); + printer->Emit( + { + {"name", method->name()}, + {"input", QualifiedClassName(method->input_type(), *options_)}, + {"output", QualifiedClassName(method->output_type(), *options_)}, + {"index", y_absl::StrCat(i)}, + }, + R"cc( + case $index$: + $name$(controller, + ::$proto_ns$::internal::DownCast<const $input$*>(request), + ::$proto_ns$::internal::DownCast<$output$*>(response), done); + break; + )cc"); } - - 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++) { + for (int i = 0; i < descriptor_->method_count(); ++i) { const MethodDescriptor* method = descriptor_->method(i); - Formatter format(printer, vars_); - InitMethodVariables(method, options_, &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); + + printer->Emit( + { + {"name", method->name()}, + {"input", QualifiedClassName(method->input_type(), *options_)}, + {"output", QualifiedClassName(method->output_type(), *options_)}, + {"index", y_absl::StrCat(i)}, + }, + R"cc( + void $classname$_Stub::$name$(::$proto_ns$::RpcController* controller, + const $input$* request, + $output$* response, ::google::protobuf::Closure* done) { + channel_->CallMethod(descriptor()->method($index$), controller, + request, response, done); + } + )cc"); } } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.h index 56982cf566b..183a4ecb1c8 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.h @@ -35,63 +35,52 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__ -#include <map> #include <string> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/cpp/options.h> - -namespace google { -namespace protobuf { -namespace io { -class Printer; // printer.h -} -} // namespace protobuf -} // namespace google +#include "google/protobuf/descriptor.h" +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { namespace cpp { - class ServiceGenerator { public: // See generator.cc for the meaning of dllexport_decl. - explicit ServiceGenerator(const ServiceDescriptor* descriptor, - const std::map<TProtoStringType, TProtoStringType>& vars, - const Options& options); - ~ServiceGenerator(); - - // Header stuff. + ServiceGenerator( + const ServiceDescriptor* descriptor, + const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& vars, + const Options& options) + : descriptor_(descriptor), options_(&options), vars_(vars) { + vars_["classname"] = descriptor_->name(); + vars_["full_name"] = descriptor_->full_name(); + } + + ServiceGenerator(const ServiceGenerator&) = delete; + ServiceGenerator& operator=(const ServiceGenerator&) = delete; + ServiceGenerator(ServiceGenerator&&) = delete; + ServiceGenerator& operator=(ServiceGenerator&&) = delete; + + ~ServiceGenerator() = default; // Generate the class definitions for the service's interface and the // stub implementation. void GenerateDeclarations(io::Printer* printer); - // Source file stuff. - // Generate implementations of everything declared by // GenerateDeclarations(). void GenerateImplementation(io::Printer* printer); private: - enum RequestOrResponse { REQUEST, RESPONSE }; - enum VirtualOrNon { VIRTUAL, NON_VIRTUAL }; - - // Header stuff. - - // Generate the service abstract interface. - void GenerateInterface(io::Printer* printer); - - // Generate the stub class definition. - void GenerateStubDefinition(io::Printer* printer); + enum RequestOrResponse { kRequest, kResponse }; + enum VirtualOrNot { kVirtual, kNonVirtual }; // Prints signatures for all methods in the - void GenerateMethodSignatures(VirtualOrNon virtual_or_non, + void GenerateMethodSignatures(VirtualOrNot virtual_or_not, io::Printer* printer); - // Source file stuff. - // Generate the default implementations of the service methods, which // produce a "not implemented" error. void GenerateNotImplementedMethods(io::Printer* printer); @@ -102,19 +91,20 @@ class ServiceGenerator { // Generate the Get{Request,Response}Prototype() methods. void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer); + // Generate the cases in CallMethod(). + void GenerateCallMethodCases(io::Printer* printer); + // Generate the stub's implementations of the service methods. void GenerateStubMethods(io::Printer* printer); const ServiceDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> vars_; - const Options& options_; + const Options* options_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars_; int index_in_metadata_; friend class FileGenerator; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator); }; - } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.cc deleted file mode 100644 index 5f30d3b511e..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.cc +++ /dev/null @@ -1,957 +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: [email protected] (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include <google/protobuf/compiler/cpp/string_field.h> - -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/cpp/helpers.h> -#include <google/protobuf/descriptor.pb.h> - - -namespace google { -namespace protobuf { -namespace compiler { -namespace cpp { - -namespace { - -void SetStringVariables(const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables, - const Options& options) { - SetCommonFieldVariables(descriptor, variables, options); - - const TProtoStringType kNS = "::" + (*variables)["proto_ns"] + "::internal::"; - const TProtoStringType kArenaStringPtr = kNS + "ArenaStringPtr"; - - (*variables)["default"] = DefaultValue(options, descriptor); - (*variables)["default_length"] = - StrCat(descriptor->default_value_string().length()); - (*variables)["default_variable_name"] = MakeDefaultName(descriptor); - (*variables)["default_variable_field"] = MakeDefaultFieldName(descriptor); - - if (descriptor->default_value_string().empty()) { - (*variables)["default_string"] = kNS + "GetEmptyStringAlreadyInited()"; - (*variables)["default_value"] = "&" + (*variables)["default_string"]; - (*variables)["lazy_variable_args"] = ""; - } else { - (*variables)["lazy_variable"] = - StrCat(QualifiedClassName(descriptor->containing_type(), options), - "::", MakeDefaultFieldName(descriptor)); - - (*variables)["default_string"] = (*variables)["lazy_variable"] + ".get()"; - (*variables)["default_value"] = "nullptr"; - (*variables)["lazy_variable_args"] = (*variables)["lazy_variable"] + ", "; - } - - (*variables)["pointer_type"] = - descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; - (*variables)["setter"] = - descriptor->type() == FieldDescriptor::TYPE_BYTES ? "SetBytes" : "Set"; - (*variables)["null_check"] = (*variables)["DCHK"] + "(value != nullptr);\n"; - // NOTE: Escaped here to unblock proto1->proto2 migration. - // TODO(liujisi): Extend this to apply for other conflicting methods. - (*variables)["release_name"] = - SafeFunctionName(descriptor->containing_type(), descriptor, "release_"); - (*variables)["full_name"] = descriptor->full_name(); - - if (options.opensource_runtime) { - (*variables)["string_piece"] = "TProtoStringType"; - } else { - (*variables)["string_piece"] = "::StringPiece"; - } -} - -} // namespace - -// =================================================================== - -StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options) - : FieldGenerator(descriptor, options), - inlined_(IsStringInlined(descriptor, options)) { - SetStringVariables(descriptor, &variables_, options); -} - -StringFieldGenerator::~StringFieldGenerator() {} - -void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const { - Formatter format(printer, variables_); - if (!inlined_) { - format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n"); - } else { - // Skips the automatic destruction; rather calls it explicitly if - // allocating arena is null. This is required to support message-owned - // arena (go/path-to-arenas) where a root proto is destroyed but - // InlinedStringField may have arena-allocated memory. - format("::$proto_ns$::internal::InlinedStringField $name$_;\n"); - } -} - -void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const { - Formatter format(printer, variables_); - if (!descriptor_->default_value_string().empty()) { - format( - "static const ::$proto_ns$::internal::LazyString" - " $default_variable_name$;\n"); - } - if (inlined_) { - // `_init_inline_xxx` is used for initializing default instances. - format("static std::true_type _init_inline_$name$_;\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. - // We aren't releasing Cord because it has too many Google-specific - // dependencies and we aren't releasing StringPiece because it's hardly - // useful outside of Google and because it would get confusing to have - // multiple instances of the StringPiece class in different libraries (PCRE - // already includes it for their C++ bindings, which came from Google). - // - // In any case, we make all the accessors private while still actually - // using a string to represent the field internally. This way, we can - // guarantee that if we do ever implement the ctype, it won't break any - // existing users who might be -- for whatever reason -- already using .proto - // files that applied the ctype. The field can still be accessed via the - // reflection interface since the reflection interface is independent of - // the string's underlying representation. - - bool unknown_ctype = descriptor_->options().ctype() != - EffectiveStringCType(descriptor_, options_); - - if (unknown_ctype) { - format.Outdent(); - format( - " private:\n" - " // Hidden due to unknown ctype option.\n"); - format.Indent(); - } - - format( - "$deprecated_attr$const TProtoStringType& ${1$$name$$}$() const;\n" - "template <typename ArgT0 = const TProtoStringType&, typename... ArgT>\n" - "$deprecated_attr$void ${1$set_$name$$}$(ArgT0&& arg0, ArgT... args);\n", - descriptor_); - format( - "$deprecated_attr$TProtoStringType* ${1$mutable_$name$$}$();\n" - "PROTOBUF_NODISCARD $deprecated_attr$TProtoStringType* " - "${1$$release_name$$}$();\n" - "$deprecated_attr$void ${1$set_allocated_$name$$}$(TProtoStringType* " - "$name$);\n", - descriptor_); - format( - "private:\n" - "const TProtoStringType& _internal_$name$() const;\n" - "inline PROTOBUF_ALWAYS_INLINE void " - "_internal_set_$name$(const TProtoStringType& value);\n" - "TProtoStringType* _internal_mutable_$name$();\n"); - if (inlined_) { - format( - "inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() " - "const;\n"); - } - format("public:\n"); - - if (unknown_ctype) { - format.Outdent(); - format(" public:\n"); - format.Indent(); - } -} - -void StringFieldGenerator::GenerateInlineAccessorDefinitions( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "inline const TProtoStringType& $classname$::$name$() const {\n" - "$annotate_get$" - " // @@protoc_insertion_point(field_get:$full_name$)\n"); - if (!descriptor_->default_value_string().empty()) { - format( - " if ($field$.IsDefault()) return " - "$default_variable_field$.get();\n"); - } - format( - " return _internal_$name$();\n" - "}\n"); - if (!inlined_) { - format( - "template <typename ArgT0, typename... ArgT>\n" - "inline PROTOBUF_ALWAYS_INLINE\n" - "void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n" - "$maybe_prepare_split_message$" - " $set_hasbit$\n" - " $field$.$setter$(static_cast<ArgT0 &&>(arg0)," - " args..., GetArenaForAllocation());\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n"); - } else { - format( - "template <typename ArgT0, typename... ArgT>\n" - "inline PROTOBUF_ALWAYS_INLINE\n" - "void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n" - "$maybe_prepare_split_message$" - " $set_hasbit$\n" - " $field$.$setter$(static_cast<ArgT0 &&>(arg0)," - " args..., GetArenaForAllocation(), _internal_$name$_donated(), " - "&$donating_states_word$, $mask_for_undonate$, this);\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "inline bool $classname$::_internal_$name$_donated() const {\n" - " bool value = $inlined_string_donated$\n" - " return value;\n" - "}\n"); - } - format( - "inline TProtoStringType* $classname$::mutable_$name$() {\n" - "$maybe_prepare_split_message$" - " TProtoStringType* _s = _internal_mutable_$name$();\n" - "$annotate_mutable$" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return _s;\n" - "}\n" - "inline const TProtoStringType& $classname$::_internal_$name$() const {\n" - " return $field$.Get();\n" - "}\n" - "inline void $classname$::_internal_set_$name$(const TProtoStringType& " - "value) {\n" - " $set_hasbit$\n"); - if (!inlined_) { - format( - " $field$.Set(value, GetArenaForAllocation());\n" - "}\n"); - } else { - format( - " $field$.Set(value, GetArenaForAllocation(),\n" - " _internal_$name$_donated(), &$donating_states_word$, " - "$mask_for_undonate$, this);\n" - "}\n"); - } - format( - "inline TProtoStringType* $classname$::_internal_mutable_$name$() {\n" - " $set_hasbit$\n"); - if (!inlined_) { - format( - " return $field$.Mutable($lazy_variable_args$" - "GetArenaForAllocation());\n" - "}\n"); - } else { - format( - " return $field$.Mutable($lazy_variable_args$" - "GetArenaForAllocation(), _internal_$name$_donated(), " - "&$donating_states_word$, $mask_for_undonate$, this);\n" - "}\n"); - } - format( - "inline TProtoStringType* $classname$::$release_name$() {\n" - "$annotate_release$" - "$maybe_prepare_split_message$" - " // @@protoc_insertion_point(field_release:$full_name$)\n"); - - if (HasHasbit(descriptor_)) { - format( - " if (!_internal_has_$name$()) {\n" - " return nullptr;\n" - " }\n" - " $clear_hasbit$\n"); - if (!inlined_) { - format(" auto* p = $field$.Release();\n"); - if (descriptor_->default_value_string().empty()) { - format( - "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n" - " if ($field$.IsDefault()) {\n" - " $field$.Set(\"\", GetArenaForAllocation());\n" - " }\n" - "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"); - } - format(" return p;\n"); - } else { - format( - " return $field$.Release(GetArenaForAllocation(), " - "_internal_$name$_donated());\n"); - } - } else { - format(" return $field$.Release();\n"); - } - - format( - "}\n" - "inline void $classname$::set_allocated_$name$(TProtoStringType* $name$) {\n" - "$maybe_prepare_split_message$" - " if ($name$ != nullptr) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n"); - if (!inlined_) { - format(" $field$.SetAllocated($name$, GetArenaForAllocation());\n"); - if (descriptor_->default_value_string().empty()) { - format( - "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n" - " if ($field$.IsDefault()) {\n" - " $field$.Set(\"\", GetArenaForAllocation());\n" - " }\n" - "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"); - } - } else { - // Currently, string fields with default value can't be inlined. - format( - " $field$.SetAllocated(nullptr, $name$, GetArenaForAllocation(), " - "_internal_$name$_donated(), &$donating_states_word$, " - "$mask_for_undonate$, this);\n"); - } - format( - "$annotate_set$" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n"); -} - -void StringFieldGenerator::GenerateNonInlineAccessorDefinitions( - io::Printer* printer) const { - Formatter format(printer, variables_); - if (!descriptor_->default_value_string().empty()) { - format( - "const ::$proto_ns$::internal::LazyString " - "$classname$::$default_variable_field$" - "{{{$default$, $default_length$}}, {nullptr}};\n"); - } -} - -void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const { - Formatter format(printer, variables_); - if (descriptor_->default_value_string().empty()) { - format("$field$.ClearToEmpty();\n"); - } else { - GOOGLE_DCHECK(!inlined_); - format( - "$field$.ClearToDefault($lazy_variable$, GetArenaForAllocation());\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 - // (given that the below methods are inlined one-liners)! - - // If we have a hasbit, then the Clear() method of the protocol buffer - // will have checked that this field is set. If so, we can avoid redundant - // checks against the default variable. - const bool must_be_present = HasHasbit(descriptor_); - - if (inlined_ && must_be_present) { - // Calling mutable_$name$() gives us a string reference and sets the has bit - // for $name$ (in proto2). We may get here when the string field is inlined - // but the string's contents have not been changed by the user, so we cannot - // make an assertion about the contents of the string and could never make - // an assertion about the string instance. - // - // For non-inlined strings, we distinguish from non-default by comparing - // instances, rather than contents. - format("$DCHK$(!$field$.IsDefault());\n"); - } - - if (descriptor_->default_value_string().empty()) { - if (must_be_present) { - format("$field$.ClearNonDefaultToEmpty();\n"); - } else { - format("$field$.ClearToEmpty();\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. - format( - "$field$.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n "); - } -} - -void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const { - Formatter format(printer, variables_); - // TODO(gpike): improve this - format("_this->_internal_set_$name$(from._internal_$name$());\n"); -} - -void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const { - Formatter format(printer, variables_); - if (!inlined_) { - format( - "::$proto_ns$::internal::ArenaStringPtr::InternalSwap(\n" - " &$field$, lhs_arena,\n" - " &other->$field$, rhs_arena\n" - ");\n"); - } else { - format( - "::$proto_ns$::internal::InlinedStringField::InternalSwap(\n" - " &$field$, lhs_arena, " - "($inlined_string_donated_array$[0] & 0x1u) == 0, this,\n" - " &other->$field$, rhs_arena, " - "(other->$inlined_string_donated_array$[0] & 0x1u) == 0, other);\n"); - } -} - -void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const { - Formatter format(printer, variables_); - if (inlined_ && descriptor_->default_value_string().empty()) { - return; - } - GOOGLE_DCHECK(!inlined_); - format("$field$.InitDefault();\n"); - if (IsString(descriptor_, options_) && - descriptor_->default_value_string().empty()) { - format( - "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n" - " $field$.Set(\"\", GetArenaForAllocation());\n" - "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"); - } -} - -void StringFieldGenerator::GenerateCreateSplitMessageCode( - io::Printer* printer) const { - GOOGLE_CHECK(ShouldSplit(descriptor_, options_)); - GOOGLE_CHECK(!inlined_); - Formatter format(printer, variables_); - format("ptr->$name$_.InitDefault();\n"); - if (IsString(descriptor_, options_) && - descriptor_->default_value_string().empty()) { - format( - "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n" - " ptr->$name$_.Set(\"\", GetArenaForAllocation());\n" - "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"); - } -} - -void StringFieldGenerator::GenerateCopyConstructorCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - GenerateConstructorCode(printer); - if (inlined_) { - format("new (&_this->$field$) ::_pbi::InlinedStringField();\n"); - } - - if (HasHasbit(descriptor_)) { - format("if (from._internal_has_$name$()) {\n"); - } else { - format("if (!from._internal_$name$().empty()) {\n"); - } - - format.Indent(); - - if (!inlined_) { - format( - "_this->$field$.Set(from._internal_$name$(), \n" - " _this->GetArenaForAllocation());\n"); - } else { - format( - "_this->$field$.Set(from._internal_$name$(),\n" - " _this->GetArenaForAllocation(), _this->_internal_$name$_donated(), " - "&_this->$donating_states_word$, $mask_for_undonate$, _this);\n"); - } - - format.Outdent(); - format("}\n"); -} - -void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const { - Formatter format(printer, variables_); - if (!inlined_) { - if (ShouldSplit(descriptor_, options_)) { - format("$cached_split_ptr$->$name$_.Destroy();\n"); - return; - } - format("$field$.Destroy();\n"); - return; - } - // Explicitly calls ~InlinedStringField as its automatic call is disabled. - // Destructor has been implicitly skipped as a union, and even the - // message-owned arena is enabled, arena could still be missing for - // Arena::CreateMessage(nullptr). - GOOGLE_DCHECK(!ShouldSplit(descriptor_, options_)); - format("$field$.~InlinedStringField();\n"); -} - -ArenaDtorNeeds StringFieldGenerator::NeedsArenaDestructor() const { - return inlined_ ? ArenaDtorNeeds::kOnDemand : ArenaDtorNeeds::kNone; -} - -void StringFieldGenerator::GenerateArenaDestructorCode( - io::Printer* printer) const { - if (!inlined_) return; - Formatter format(printer, variables_); - // _this is the object being destructed (we are inside a static method here). - format( - "if (!_this->_internal_$name$_donated()) {\n" - " _this->$field$.~InlinedStringField();\n" - "}\n"); -} - -void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const { - Formatter format(printer, variables_); - if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString( - descriptor_, options_, false, - "this->_internal_$name$().data(), " - "static_cast<int>(this->_internal_$name$().length()),\n", - format); - } - format( - "target = stream->Write$declared_type$MaybeAliased(\n" - " $number$, this->_internal_$name$(), target);\n"); -} - -void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "total_size += $tag_size$ +\n" - " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" - " this->_internal_$name$());\n"); -} - -void StringFieldGenerator::GenerateConstexprAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - if (inlined_) { - format("/*decltype($field$)*/{nullptr, false}"); - return; - } - if (descriptor_->default_value_string().empty()) { - format( - "/*decltype($field$)*/{&::_pbi::fixed_address_empty_string, " - "::_pbi::ConstantInitialized{}}"); - } else { - format("/*decltype($field$)*/{nullptr, ::_pbi::ConstantInitialized{}}"); - } -} - -void StringFieldGenerator::GenerateAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - if (ShouldSplit(descriptor_, options_)) { - GOOGLE_CHECK(!inlined_); - format("decltype(Impl_::Split::$name$_){}"); - return; - } - if (!inlined_) { - format("decltype($field$){}"); - } else { - format("decltype($field$)(arena)"); - } -} - -void StringFieldGenerator::GenerateCopyAggregateInitializer( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("decltype($field$){}"); -} - -// =================================================================== - -StringOneofFieldGenerator::StringOneofFieldGenerator( - const FieldDescriptor* descriptor, const Options& options) - : StringFieldGenerator(descriptor, options) { - SetCommonOneofFieldVariables(descriptor, &variables_); - variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true); - variables_["oneof_index"] = - StrCat(descriptor->containing_oneof()->index()); -} - -StringOneofFieldGenerator::~StringOneofFieldGenerator() {} - -void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "inline const TProtoStringType& $classname$::$name$() const {\n" - "$annotate_get$" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return _internal_$name$();\n" - "}\n" - "template <typename ArgT0, typename... ArgT>\n" - "inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field$.InitDefault();\n" - " }\n" - " $field$.$setter$(" - " static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "inline TProtoStringType* $classname$::mutable_$name$() {\n" - " TProtoStringType* _s = _internal_mutable_$name$();\n" - "$annotate_mutable$" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return _s;\n" - "}\n" - "inline const TProtoStringType& $classname$::_internal_$name$() const {\n" - " if (_internal_has_$name$()) {\n" - " return $field$.Get();\n" - " }\n" - " return $default_string$;\n" - "}\n" - "inline void $classname$::_internal_set_$name$(const TProtoStringType& " - "value) {\n" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field$.InitDefault();\n" - " }\n" - " $field$.Set(value, GetArenaForAllocation());\n" - "}\n"); - format( - "inline TProtoStringType* $classname$::_internal_mutable_$name$() {\n" - " if (!_internal_has_$name$()) {\n" - " clear_$oneof_name$();\n" - " set_has_$name$();\n" - " $field$.InitDefault();\n" - " }\n" - " return $field$.Mutable($lazy_variable_args$" - " GetArenaForAllocation());\n" - "}\n" - "inline TProtoStringType* $classname$::$release_name$() {\n" - "$annotate_release$" - " // @@protoc_insertion_point(field_release:$full_name$)\n" - " if (_internal_has_$name$()) {\n" - " clear_has_$oneof_name$();\n" - " return $field$.Release();\n" - " } else {\n" - " return nullptr;\n" - " }\n" - "}\n" - "inline void $classname$::set_allocated_$name$(TProtoStringType* $name$) {\n" - " if (has_$oneof_name$()) {\n" - " clear_$oneof_name$();\n" - " }\n" - " if ($name$ != nullptr) {\n" - " set_has_$name$();\n" - " $field$.InitAllocated($name$, GetArenaForAllocation());\n" - " }\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n"); -} - -void StringOneofFieldGenerator::GenerateClearingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$.Destroy();\n"); -} - -void StringOneofFieldGenerator::GenerateMessageClearingCode( - io::Printer* printer) const { - return GenerateClearingCode(printer); -} - -void StringOneofFieldGenerator::GenerateSwappingCode( - io::Printer* printer) const { - // Don't print any swapping code. Swapping the union will swap this field. -} - -void StringOneofFieldGenerator::GenerateConstructorCode( - io::Printer* printer) const { - // Nothing required here. -} - -// =================================================================== - -RepeatedStringFieldGenerator::RepeatedStringFieldGenerator( - const FieldDescriptor* descriptor, const Options& options) - : FieldGenerator(descriptor, options) { - SetStringVariables(descriptor, &variables_, options); -} - -RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {} - -void RepeatedStringFieldGenerator::GeneratePrivateMembers( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("::$proto_ns$::RepeatedPtrField<TProtoStringType> $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_, options_); - - if (unknown_ctype) { - format.Outdent(); - format( - " private:\n" - " // Hidden due to unknown ctype option.\n"); - format.Indent(); - } - - format( - "$deprecated_attr$const TProtoStringType& ${1$$name$$}$(int index) const;\n" - "$deprecated_attr$TProtoStringType* ${1$mutable_$name$$}$(int index);\n" - "$deprecated_attr$void ${1$set_$name$$}$(int index, const " - "TProtoStringType& value);\n" - "$deprecated_attr$void ${1$set_$name$$}$(int index, TProtoStringType&& " - "value);\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", - descriptor_); - } - format( - "$deprecated_attr$void ${1$set_$name$$}$(" - "int index, const $pointer_type$* value, size_t size);\n" - "$deprecated_attr$TProtoStringType* ${1$add_$name$$}$();\n" - "$deprecated_attr$void ${1$add_$name$$}$(const TProtoStringType& value);\n" - "$deprecated_attr$void ${1$add_$name$$}$(TProtoStringType&& value);\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", - descriptor_); - } - format( - "$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* " - "value, size_t size)" - ";\n" - "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField<TProtoStringType>& " - "${1$$name$$}$() " - "const;\n" - "$deprecated_attr$::$proto_ns$::RepeatedPtrField<TProtoStringType>* " - "${1$mutable_$name$$}$()" - ";\n" - "private:\n" - "const TProtoStringType& ${1$_internal_$name$$}$(int index) const;\n" - "TProtoStringType* _internal_add_$name$();\n" - "public:\n", - descriptor_); - - if (unknown_ctype) { - format.Outdent(); - format(" public:\n"); - format.Indent(); - } -} - -void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "inline TProtoStringType* $classname$::add_$name$() {\n" - " TProtoStringType* _s = _internal_add_$name$();\n" - "$annotate_add_mutable$" - " // @@protoc_insertion_point(field_add_mutable:$full_name$)\n" - " return _s;\n" - "}\n"); - if (options_.safe_boundary_check) { - format( - "inline const TProtoStringType& $classname$::_internal_$name$(int index) " - "const {\n" - " return $field$.InternalCheckedGet(\n" - " index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n" - "}\n"); - } else { - format( - "inline const TProtoStringType& $classname$::_internal_$name$(int index) " - "const {\n" - " return $field$.Get(index);\n" - "}\n"); - } - format( - "inline const TProtoStringType& $classname$::$name$(int index) const {\n" - "$annotate_get$" - " // @@protoc_insertion_point(field_get:$full_name$)\n" - " return _internal_$name$(index);\n" - "}\n" - "inline TProtoStringType* $classname$::mutable_$name$(int index) {\n" - "$annotate_mutable$" - " // @@protoc_insertion_point(field_mutable:$full_name$)\n" - " return $field$.Mutable(index);\n" - "}\n" - "inline void $classname$::set_$name$(int index, const TProtoStringType& " - "value) " - "{\n" - " $field$.Mutable(index)->assign(value);\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "inline void $classname$::set_$name$(int index, TProtoStringType&& value) {\n" - " $field$.Mutable(index)->assign(std::move(value));\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set:$full_name$)\n" - "}\n" - "inline void $classname$::set_$name$(int index, const char* value) {\n" - " $null_check$" - " $field$.Mutable(index)->assign(value);\n" - "$annotate_set$" - " // @@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" - " $field$.Mutable(index)->assign(value.data(), value.size());\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n" - "}\n"); - } - format( - "inline void " - "$classname$::set_$name$" - "(int index, const $pointer_type$* value, size_t size) {\n" - " $field$.Mutable(index)->assign(\n" - " reinterpret_cast<const char*>(value), size);\n" - "$annotate_set$" - " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" - "}\n" - "inline TProtoStringType* $classname$::_internal_add_$name$() {\n" - " return $field$.Add();\n" - "}\n" - "inline void $classname$::add_$name$(const TProtoStringType& value) {\n" - " $field$.Add()->assign(value);\n" - "$annotate_add$" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "inline void $classname$::add_$name$(TProtoStringType&& value) {\n" - " $field$.Add(std::move(value));\n" - "$annotate_add$" - " // @@protoc_insertion_point(field_add:$full_name$)\n" - "}\n" - "inline void $classname$::add_$name$(const char* value) {\n" - " $null_check$" - " $field$.Add()->assign(value);\n" - "$annotate_add$" - " // @@protoc_insertion_point(field_add_char:$full_name$)\n" - "}\n"); - if (!options_.opensource_runtime) { - format( - "inline void $classname$::add_$name$(StringPiece value) {\n" - " $field$.Add()->assign(value.data(), value.size());\n" - "$annotate_add$" - " // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n" - "}\n"); - } - format( - "inline void " - "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" - " $field$.Add()->assign(reinterpret_cast<const char*>(value), size);\n" - "$annotate_add$" - " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" - "}\n" - "inline const ::$proto_ns$::RepeatedPtrField<TProtoStringType>&\n" - "$classname$::$name$() const {\n" - "$annotate_list$" - " // @@protoc_insertion_point(field_list:$full_name$)\n" - " return $field$;\n" - "}\n" - "inline ::$proto_ns$::RepeatedPtrField<TProtoStringType>*\n" - "$classname$::mutable_$name$() {\n" - "$annotate_mutable_list$" - " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" - " return &$field$;\n" - "}\n"); -} - -void RepeatedStringFieldGenerator::GenerateClearingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$.Clear();\n"); -} - -void RepeatedStringFieldGenerator::GenerateMergingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("_this->$field$.MergeFrom(from.$field$);\n"); -} - -void RepeatedStringFieldGenerator::GenerateSwappingCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$.InternalSwap(&other->$field$);\n"); -} - -void RepeatedStringFieldGenerator::GenerateDestructorCode( - io::Printer* printer) const { - Formatter format(printer, variables_); - format("$field$.~RepeatedPtrField();\n"); -} - -void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n" - " const auto& s = this->_internal_$name$(i);\n"); - // format("for (const TProtoStringType& s : this->$name$()) {\n"); - format.Indent(); - if (descriptor_->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString(descriptor_, options_, false, - "s.data(), static_cast<int>(s.length()),\n", - format); - } - format.Outdent(); - format( - " target = stream->Write$declared_type$($number$, s, target);\n" - "}\n"); -} - -void RepeatedStringFieldGenerator::GenerateByteSize( - io::Printer* printer) const { - Formatter format(printer, variables_); - format( - "total_size += $tag_size$ *\n" - " ::$proto_ns$::internal::FromIntSize($field$.size());\n" - "for (int i = 0, n = $field$.size(); i < n; i++) {\n" - " total_size += " - "::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n" - " $field$.Get(i));\n" - "}\n"); -} - -} // namespace cpp -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.h deleted file mode 100644 index db5f18bfb7d..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.h +++ /dev/null @@ -1,136 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Author: [email protected] (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__ -#define GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__ - -#include <map> -#include <string> - -#include <google/protobuf/compiler/cpp/field.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace cpp { - -class StringFieldGenerator : public FieldGenerator { - public: - StringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~StringFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GeneratePrivateMembers(io::Printer* printer) const override; - void GenerateStaticMembers(io::Printer* printer) const override; - void GenerateAccessorDeclarations(io::Printer* printer) const override; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateNonInlineAccessorDefinitions( - io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateMessageClearingCode(io::Printer* printer) const override; - void GenerateMergingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override; - void GenerateCreateSplitMessageCode(io::Printer* printer) const override; - void GenerateCopyConstructorCode(io::Printer* printer) const override; - void GenerateDestructorCode(io::Printer* printer) const override; - void GenerateArenaDestructorCode(io::Printer* printer) const override; - void GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const override; - void GenerateByteSize(io::Printer* printer) const override; - void GenerateConstexprAggregateInitializer( - io::Printer* printer) const override; - void GenerateAggregateInitializer(io::Printer* printer) const override; - void GenerateCopyAggregateInitializer(io::Printer* printer) const override; - bool IsInlined() const override { return inlined_; } - ArenaDtorNeeds NeedsArenaDestructor() const override; - - private: - bool inlined_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator); -}; - -class StringOneofFieldGenerator : public StringFieldGenerator { - public: - StringOneofFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~StringOneofFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - - // StringFieldGenerator, from which we inherit, overrides this so we need to - // override it as well. - void GenerateMessageClearingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator); -}; - -class RepeatedStringFieldGenerator : public FieldGenerator { - public: - RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, - const Options& options); - ~RepeatedStringFieldGenerator() override; - - // implements FieldGenerator --------------------------------------- - void GeneratePrivateMembers(io::Printer* printer) const override; - void GenerateAccessorDeclarations(io::Printer* printer) const override; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const override; - void GenerateClearingCode(io::Printer* printer) const override; - void GenerateMergingCode(io::Printer* printer) const override; - void GenerateSwappingCode(io::Printer* printer) const override; - void GenerateConstructorCode(io::Printer* printer) const override {} - void GenerateCopyConstructorCode(io::Printer* /*printer*/) const override { - GOOGLE_CHECK(!ShouldSplit(descriptor_, options_)); - } - void GenerateDestructorCode(io::Printer* printer) const override; - void GenerateSerializeWithCachedSizesToArray( - io::Printer* printer) const override; - void GenerateByteSize(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator); -}; - -} // namespace cpp -} // namespace compiler -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc new file mode 100644 index 00000000000..77c45a8ee54 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc @@ -0,0 +1,339 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2022 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/cpp/tracker.h" + +#include <string> +#include <utility> +#include <vector> + +#include "google/protobuf/descriptor.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/substitute.h" +#include "y_absl/types/optional.h" +#include "google/protobuf/compiler/cpp/helpers.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/io/printer.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { +namespace { +using Sub = ::google::protobuf::io::Printer::Sub; + +constexpr y_absl::string_view kTracker = "Impl_::_tracker_"; +constexpr y_absl::string_view kVarPrefix = "annotate_"; +constexpr y_absl::string_view kTypeTraits = "_proto_TypeTraits"; + +struct Call { + Call(y_absl::string_view var, y_absl::string_view call) : var(var), call(call) {} + Call(y_absl::optional<int> field_index, y_absl::string_view var, + y_absl::string_view call) + : var(var), call(call), field_index(field_index) {} + + Call This(y_absl::optional<y_absl::string_view> thiz) && { + this->thiz = thiz; + return std::move(*this); + } + + template <typename... SubArgs> + Call Arg(y_absl::string_view format, const SubArgs&... args) && { + this->args.emplace_back(y_absl::Substitute(format, args...)); + return std::move(*this); + } + + Call Suppressed() && { + suppressed = true; + return std::move(*this); + } + + y_absl::string_view var; + y_absl::string_view call; + y_absl::optional<int> field_index; + y_absl::optional<y_absl::string_view> thiz = "this"; + std::vector<TProtoStringType> args; + bool suppressed = false; +}; + +std::vector<Sub> GenerateTrackerCalls( + const Options& opts, const Descriptor* message, + y_absl::optional<TProtoStringType> alt_annotation, y_absl::Span<const Call> calls) { + bool enable_tracking = HasTracker(message, opts); + const auto& forbidden = + opts.field_listener_options.forbidden_field_listener_events; + + std::vector<Sub> subs; + for (const auto& call : calls) { + TProtoStringType call_str; + if (enable_tracking && !call.suppressed && !forbidden.contains(call.var)) { + y_absl::SubstituteAndAppend(&call_str, "$0.$1", kTracker, call.call); + if (call.field_index.has_value()) { + y_absl::SubstituteAndAppend(&call_str, "<$0>", *call.field_index); + } + y_absl::StrAppend(&call_str, "("); + + y_absl::string_view arg_sep = ""; + if (call.thiz.has_value()) { + y_absl::StrAppend(&call_str, *call.thiz); + arg_sep = ", "; + } + + for (const auto& arg : call.args) { + y_absl::StrAppend(&call_str, arg_sep, arg); + arg_sep = ", "; + } + + y_absl::StrAppend(&call_str, ");"); + } else if (opts.annotate_accessor && alt_annotation.has_value()) { + call_str = *alt_annotation; + } + + if (!call_str.empty()) { + // TODO(b/245791219): Until we migrate all of the C++ backend to use + // Emit(), we need to include a newline here so that the line that follows + // the annotation is on its own line. + call_str.push_back('\n'); + } + + subs.push_back( + Sub(y_absl::StrCat(kVarPrefix, call.var), call_str).WithSuffix(";")); + } + + return subs; +} +} // namespace + +std::vector<Sub> MakeTrackerCalls(const Descriptor* message, + const Options& opts) { + y_absl::string_view extns = + IsMapEntryMessage(message) ? "_extensions_" : "_impl_._extensions_"; + + auto primitive_extn_accessor = [extns](y_absl::string_view var, + y_absl::string_view call) { + return Call(var, call) + .Arg("id.number()") + .Arg("$0::GetPtr(id.number(), $1, id.default_value_ref())", kTypeTraits, + extns); + }; + + auto index_extn_accessor = [extns](y_absl::string_view var, + y_absl::string_view call) { + return Call(var, call) + .Arg("id.number()") + .Arg("$0::GetPtr(id.number(), $1, index)", kTypeTraits, extns); + }; + + auto add_extn_accessor = [extns](y_absl::string_view var, + y_absl::string_view call) { + return Call(var, call) + .Arg("id.number()") + .Arg("$0::GetPtr(id.number(), $1, $1.ExtensionSize(id.number()) - 1)", + kTypeTraits, extns); + }; + + auto list_extn_accessor = [extns](y_absl::string_view var, + y_absl::string_view call) { + return Call(var, call) + .Arg("id.number()") + .Arg("$0::GetRepeatedPtr(id.number(), $1)", kTypeTraits, extns); + }; + + return GenerateTrackerCalls( + opts, message, y_absl::nullopt, + { + Call("serialize", "OnSerialize"), + Call("deserialize", "OnDeserialize"), + // TODO(danilak): Ideally annotate_reflection should not exist and we + // need to annotate all reflective calls on our own, however, as this + // is a cause for side effects, i.e. reading values dynamically, we + // want the users know that dynamic access can happen. + Call("reflection", "OnGetMetadata").This(y_absl::nullopt), + Call("bytesize", "OnByteSize"), + Call("mergefrom", "OnMergeFrom").This("_this").Arg("&from"), + + // "Has" is here as users calling "has" on a repeated field is a + // mistake. + primitive_extn_accessor("extension_has", "OnHasExtension"), + primitive_extn_accessor("extension_get", "OnGetExtension"), + primitive_extn_accessor("extension_mutable", "OnMutableExtension"), + primitive_extn_accessor("extension_set", "OnSetExtension"), + primitive_extn_accessor("extension_release", "OnReleaseExtension"), + + index_extn_accessor("repeated_extension_get", "OnGetExtension"), + index_extn_accessor("repeated_extension_mutable", + "OnMutableExtension"), + index_extn_accessor("repeated_extension_set", "OnSetExtension"), + + add_extn_accessor("repeated_extension_add", "OnAddExtension"), + add_extn_accessor("repeated_extension_add_mutable", + "OnAddMutableExtension"), + + list_extn_accessor("extension_repeated_size", "OnExtensionSize"), + list_extn_accessor("repeated_extension_list", "OnListExtension"), + list_extn_accessor("repeated_extension_list_mutable", + "OnMutableListExtension"), + + // Generic accessors such as "clear". + // TODO(b/190614678): Generalize clear from both repeated and non + // repeated calls, currently their underlying memory interfaces are + // very different. Or think of removing clear callback as no usages + // are needed and no memory exist + Call("extension_clear", "OnClearExtension").Suppressed(), + }); +} + +namespace { +struct Getters { + TProtoStringType base = "nullptr"; + TProtoStringType for_last = "nullptr"; + TProtoStringType for_flat = "nullptr"; +}; + +Getters RepeatedFieldGetters(const FieldDescriptor* field, + const Options& opts) { + TProtoStringType member = FieldMemberName(field, ShouldSplit(field, opts)); + + Getters getters; + if (!field->is_map() && + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + getters.base = y_absl::Substitute("&$0.Get(index)", member); + getters.for_last = y_absl::Substitute("&$0.Get($0.size() - 1)", member); + getters.for_flat = y_absl::StrCat("&", member); + } + + return getters; +} + +Getters StringFieldGetters(const FieldDescriptor* field, const Options& opts) { + TProtoStringType member = FieldMemberName(field, ShouldSplit(field, opts)); + bool is_std_string = field->options().ctype() == FieldOptions::STRING; + + Getters getters; + if (is_std_string && !field->default_value_string().empty()) { + getters.base = + y_absl::Substitute("$0.IsDefault() ? &$1.get() : $0.UnsafeGetPointer()", + member, MakeDefaultFieldName(field)); + } else { + getters.base = y_absl::StrCat("&", member); + } + + getters.for_flat = getters.base; + return getters; +} + +Getters StringOneofGetters(const FieldDescriptor* field, + const OneofDescriptor* oneof, const Options& opts) { + Y_ABSL_CHECK(oneof != nullptr); + + TProtoStringType member = FieldMemberName(field, ShouldSplit(field, opts)); + bool is_std_string = field->options().ctype() == FieldOptions::STRING; + + TProtoStringType field_ptr = member; + if (is_std_string) { + field_ptr = y_absl::Substitute("$0.UnsafeGetPointer()", member); + } + + TProtoStringType has = + y_absl::Substitute("$0_case() == k$1", oneof->name(), + UnderscoresToCamelCase(field->name(), true)); + + TProtoStringType default_field = MakeDefaultFieldName(field); + if (is_std_string) { + y_absl::StrAppend(&default_field, ".get()"); + } + + Getters getters; + if (field->default_value_string().empty() || + field->options().ctype() == FieldOptions::STRING_PIECE) { + getters.base = y_absl::Substitute("$0 ? $1 : nullptr", has, field_ptr); + } else { + getters.base = + y_absl::Substitute("$0 ? $1 : &$2", has, field_ptr, default_field); + } + + getters.for_flat = getters.base; + return getters; +} + +Getters SingularFieldGetters(const FieldDescriptor* field, + const Options& opts) { + TProtoStringType member = FieldMemberName(field, ShouldSplit(field, opts)); + + Getters getters; + getters.base = y_absl::StrCat("&", member); + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + getters.for_flat = y_absl::StrCat("&", member); + } + return getters; +} +} // namespace + +std::vector<Sub> MakeTrackerCalls(const FieldDescriptor* field, + const Options& opts) { + Getters getters; + if (field->is_repeated()) { + getters = RepeatedFieldGetters(field, opts); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + const auto* oneof = field->real_containing_oneof(); + if (oneof != nullptr) { + getters = StringOneofGetters(field, oneof, opts); + } else { + getters = StringFieldGetters(field, opts); + } + } else if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE || + IsExplicitLazy(field)) { + getters = SingularFieldGetters(field, opts); + } + + auto index = field->index(); + return GenerateTrackerCalls( + opts, field->containing_type(), + y_absl::Substitute("$0_AccessedNoStrip = true;", FieldName(field)), + { + Call(index, "get", "OnGet").Arg(getters.base), + Call(index, "set", "OnSet").Arg(getters.base), + Call(index, "has", "OnHas").Arg(getters.base), + Call(index, "mutable", "OnMutable").Arg(getters.base), + Call(index, "release", "OnRelease").Arg(getters.base), + Call(index, "clear", "OnClear").Arg(getters.for_flat), + Call(index, "size", "OnSize").Arg(getters.for_flat), + Call(index, "list", "OnList").Arg(getters.for_flat), + Call(index, "mutable_list", "OnMutableList").Arg(getters.for_flat), + Call(index, "add", "OnAdd").Arg(getters.for_last), + Call(index, "add_mutable", "OnAddMutable").Arg(getters.for_last), + }); +} +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.h b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.h new file mode 100644 index 00000000000..9f00495291e --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.h @@ -0,0 +1,58 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2022 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_CPP_TRACKER_H__ +#define GOOGLE_PROTOBUF_COMPILER_CPP_TRACKER_H__ + +#include <vector> + +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/cpp/options.h" +#include "google/protobuf/io/printer.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +// Generates printer substitutions for message-level tracker callbacks. +std::vector<google::protobuf::io::Printer::Sub> MakeTrackerCalls( + const google::protobuf::Descriptor* message, const Options& opts); + +// Generates printer substitutions for field-specific tracker callbacks. +std::vector<google::protobuf::io::Printer::Sub> MakeTrackerCalls( + const google::protobuf::FieldDescriptor* field, const Options& opts); + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CPP_TRACKER_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc index e6f5a7ab963..1fc71f3d284 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc @@ -31,10 +31,12 @@ // Author: [email protected] (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" + +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/str_split.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -54,10 +56,9 @@ void WriteDocCommentBodyImpl(io::Printer* printer, SourceLocation location) { } // XML escaping... no need for apostrophes etc as the whole text is going to be a child // node of a summary element, not part of an attribute. - comments = StringReplace(comments, "&", "&", true); - comments = StringReplace(comments, "<", "<", true); + comments = y_absl::StrReplaceAll(comments, {{"&", "&"}, {"<", "<"}}); std::vector<TProtoStringType> lines; - lines = Split(comments, "\n", false); + lines = y_absl::StrSplit(comments, "\n", y_absl::AllowEmpty()); // TODO: We really should work out which part to put in the summary and which to put in the remarks... // but that needs to be part of a bigger effort to understand the markdown better anyway. printer->Print("/// <summary>\n"); diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_doc_comment.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_doc_comment.h index 75eb0ea04d1..40c35ec0a7b 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_doc_comment.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_doc_comment.h @@ -32,8 +32,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__ -#include <google/protobuf/io/printer.h> -#include <google/protobuf/descriptor.h> +#include "google/protobuf/io/printer.h" +#include "google/protobuf/descriptor.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum.cc index c0ee9ef1910..489b3ad1bac 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -28,19 +28,21 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_enum.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> +#include <sstream> +#include <string> -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/compiler/csharp/csharp_enum.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_options.h> +#include "google/protobuf/compiler/code_generator.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/csharp_options.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -57,35 +59,42 @@ EnumGenerator::~EnumGenerator() { void EnumGenerator::Generate(io::Printer* printer) { WriteEnumDocComment(printer, descriptor_); + if (descriptor_->options().deprecated()) { + printer->Print("[global::System.ObsoleteAttribute]\n"); + } printer->Print("$access_level$ enum $name$ {\n", "access_level", class_access_level(), "name", descriptor_->name()); printer->Indent(); - std::set<TProtoStringType> used_names; - std::set<int> used_number; + y_absl::flat_hash_set<TProtoStringType> used_names; + y_absl::flat_hash_set<int> used_number; for (int i = 0; i < descriptor_->value_count(); i++) { WriteEnumValueDocComment(printer, descriptor_->value(i)); + if (descriptor_->value(i)->options().deprecated()) { + printer->Print("[global::System.ObsoleteAttribute]\n"); + } TProtoStringType original_name = descriptor_->value(i)->name(); TProtoStringType name = GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name()); // Make sure we don't get any duplicate names due to prefix removal. while (!used_names.insert(name).second) { // It's possible we'll end up giving this warning multiple times, but that's better than not at all. - GOOGLE_LOG(WARNING) << "Duplicate enum value " << name << " (originally " << original_name - << ") in " << descriptor_->name() << "; adding underscore to distinguish"; - name += "_"; + Y_ABSL_LOG(WARNING) << "Duplicate enum value " << name << " (originally " + << original_name << ") in " << descriptor_->name() + << "; adding underscore to distinguish"; + y_absl::StrAppend(&name, "_"); } int number = descriptor_->value(i)->number(); if (!used_number.insert(number).second) { printer->Print("[pbr::OriginalName(\"$original_name$\", PreferredAlias = false)] $name$ = $number$,\n", "original_name", original_name, "name", name, - "number", StrCat(number)); + "number", y_absl::StrCat(number)); } else { printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n", "original_name", original_name, "name", name, - "number", StrCat(number)); + "number", y_absl::StrCat(number)); } } printer->Outdent(); diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum.h index dcbfba36df5..73f7b713d00 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum.h @@ -33,10 +33,10 @@ #include <string> -#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> +#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/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 55fb60c504a..065e1cc5e99 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -28,18 +28,18 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_enum_field.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> +#include <sstream> -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_options.h> -#include <google/protobuf/compiler/csharp/csharp_enum_field.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/csharp_options.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum_field.h index 5d1e5f0a99a..fe2328fd5fc 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_enum_field.h @@ -31,8 +31,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__ -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/csharp/csharp_primitive_field.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/csharp/csharp_primitive_field.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 7b1806e1925..88df6e54956 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -28,22 +28,25 @@ // (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/csharp/csharp_field_base.h" + #include <cmath> #include <limits> #include <sstream> +#include <string> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/wire_format.h> +#include "google/protobuf/compiler/code_generator.h" +#include "y_absl/log/absl_log.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/names.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" -#include <google/protobuf/compiler/csharp/csharp_field_base.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_names.h> +// Must be last. +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -51,7 +54,7 @@ namespace compiler { namespace csharp { void FieldGeneratorBase::SetCommonFieldVariables( - std::map<TProtoStringType, TProtoStringType>* variables) { + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { // Note: this will be valid even though the tag emitted for packed and unpacked versions of // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which // never effects the tag size. @@ -63,13 +66,13 @@ void FieldGeneratorBase::SetCommonFieldVariables( uint tag = internal::WireFormat::MakeTag(descriptor_); uint8_t tag_array[5]; io::CodedOutputStream::WriteTagToArray(tag, tag_array); - TProtoStringType tag_bytes = StrCat(tag_array[0]); + TProtoStringType tag_bytes = y_absl::StrCat(tag_array[0]); for (int i = 1; i < part_tag_size; i++) { - tag_bytes += ", " + StrCat(tag_array[i]); + y_absl::StrAppend(&tag_bytes, ", ", tag_array[i]); } - (*variables)["tag"] = StrCat(tag); - (*variables)["tag_size"] = StrCat(tag_size); + (*variables)["tag"] = y_absl::StrCat(tag); + (*variables)["tag_size"] = y_absl::StrCat(tag_size); (*variables)["tag_bytes"] = tag_bytes; if (descriptor_->type() == FieldDescriptor::Type::TYPE_GROUP) { @@ -77,12 +80,12 @@ void FieldGeneratorBase::SetCommonFieldVariables( descriptor_->number(), internal::WireFormatLite::WIRETYPE_END_GROUP); io::CodedOutputStream::WriteTagToArray(tag, tag_array); - tag_bytes = StrCat(tag_array[0]); + tag_bytes = y_absl::StrCat(tag_array[0]); for (int i = 1; i < part_tag_size; i++) { - tag_bytes += ", " + StrCat(tag_array[i]); + y_absl::StrAppend(&tag_bytes, ", ", tag_array[i]); } - variables_["end_tag"] = StrCat(tag); + variables_["end_tag"] = y_absl::StrCat(tag); variables_["end_tag_bytes"] = tag_bytes; } @@ -97,40 +100,53 @@ void FieldGeneratorBase::SetCommonFieldVariables( (*variables)["capitalized_type_name"] = capitalized_type_name(); (*variables)["number"] = number(); if (has_default_value() && !SupportsPresenceApi(descriptor_)) { - (*variables)["name_def_message"] = - (*variables)["name"] + "_ = " + (*variables)["default_value"]; + variables->insert({"name_def_message", + y_absl::StrCat((*variables)["name"], + "_ = ", (*variables)["default_value"])}); } else { - (*variables)["name_def_message"] = (*variables)["name"] + "_"; + variables->insert( + {"name_def_message", y_absl::StrCat((*variables)["name"], "_")}); } if (SupportsPresenceApi(descriptor_)) { - (*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"]; + variables->insert({"has_property_check", + y_absl::StrCat("Has", (*variables)["property_name"])}); + variables->insert( + {"other_has_property_check", + y_absl::StrCat("other.Has", (*variables)["property_name"])}); + variables->insert({"has_not_property_check", + y_absl::StrCat("!", (*variables)["has_property_check"])}); + variables->insert( + {"other_has_not_property_check", + y_absl::StrCat("!", (*variables)["other_has_property_check"])}); if (presenceIndex_ != -1) { - TProtoStringType hasBitsNumber = StrCat(presenceIndex_ / 32); - TProtoStringType hasBitsMask = StrCat(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; + const int hasBitsNumber = presenceIndex_ / 32; + const int hasBitsMask = 1 << (presenceIndex_ % 32); + (*variables)["has_field_check"] = y_absl::StrCat( + "(_hasBits", hasBitsNumber, " & ", hasBitsMask, ") != 0"); + (*variables)["set_has_field"] = + y_absl::StrCat("_hasBits", hasBitsNumber, " |= ", hasBitsMask); + (*variables)["clear_has_field"] = + y_absl::StrCat("_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"]; + variables->insert({"has_property_check", + y_absl::StrCat((*variables)["property_name"], + " != ", (*variables)["default_value"])}); + variables->insert({"other_has_property_check", + y_absl::StrCat("other.", (*variables)["property_name"], + " != ", (*variables)["default_value"])}); } } void FieldGeneratorBase::SetCommonOneofFieldVariables( - std::map<TProtoStringType, TProtoStringType>* variables) { + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { (*variables)["oneof_name"] = oneof_name(); if (SupportsPresenceApi(descriptor_)) { - (*variables)["has_property_check"] = "Has" + property_name(); + (*variables)["has_property_check"] = y_absl::StrCat("Has", property_name()); } else { (*variables)["has_property_check"] = - oneof_name() + "Case_ == " + oneof_property_name() + - "OneofCase." + oneof_case_name(); + y_absl::StrCat(oneof_name(), "Case_ == ", oneof_property_name(), + "OneofCase.", oneof_case_name()); } (*variables)["oneof_case_name"] = oneof_case_name(); (*variables)["oneof_property_name"] = oneof_property_name(); @@ -228,7 +244,7 @@ TProtoStringType FieldGeneratorBase::type_name(const FieldDescriptor* descriptor wrapped_field->type() == FieldDescriptor::TYPE_BYTES) { return wrapped_field_type_name; } else { - return wrapped_field_type_name + "?"; + return y_absl::StrCat(wrapped_field_type_name, "?"); } } return GetClassName(descriptor->message_type()); @@ -263,7 +279,7 @@ TProtoStringType FieldGeneratorBase::type_name(const FieldDescriptor* descriptor case FieldDescriptor::TYPE_SINT64: return "long"; default: - GOOGLE_LOG(FATAL)<< "Unknown field type."; + Y_ABSL_LOG(FATAL) << "Unknown field type."; return ""; } } @@ -305,12 +321,12 @@ bool FieldGeneratorBase::has_default_value() { case FieldDescriptor::TYPE_SINT64: return descriptor_->default_value_int64() != 0L; default: - GOOGLE_LOG(FATAL)<< "Unknown field type."; + Y_ABSL_LOG(FATAL) << "Unknown field type."; return true; } } -bool AllPrintableAscii(const TProtoStringType& text) { +bool AllPrintableAscii(y_absl::string_view text) { for(int i = 0; i < text.size(); i++) { if (text[i] < 0x20 || text[i] > 0x7e) { return false; @@ -322,17 +338,19 @@ bool AllPrintableAscii(const TProtoStringType& text) { TProtoStringType FieldGeneratorBase::GetStringDefaultValueInternal(const FieldDescriptor* descriptor) { if (descriptor->default_value_string().empty()) return "\"\""; - else - return "global::System.Text.Encoding.UTF8.GetString(global::System." - "Convert.FromBase64String(\"" + - StringToBase64(descriptor->default_value_string()) + "\"), 0, " + StrCat(descriptor->default_value_string().length()) + ")"; + return y_absl::StrCat( + "global::System.Text.Encoding.UTF8.GetString(global::System." + "Convert.FromBase64String(\"", + StringToBase64(descriptor->default_value_string()), "\"), 0, ", + descriptor->default_value_string().length(), ")"); } TProtoStringType 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()) + "\")"; + return y_absl::StrCat("pb::ByteString.FromBase64(\"", + StringToBase64(descriptor->default_value_string()), + "\")"); } TProtoStringType FieldGeneratorBase::default_value() { @@ -342,8 +360,10 @@ TProtoStringType FieldGeneratorBase::default_value() { TProtoStringType FieldGeneratorBase::default_value(const FieldDescriptor* descriptor) { switch (descriptor->type()) { case FieldDescriptor::TYPE_ENUM: - return GetClassName(descriptor->default_value_enum()->type()) + "." + - GetEnumValueName(descriptor->default_value_enum()->type()->name(), descriptor->default_value_enum()->name()); + return y_absl::StrCat( + GetClassName(descriptor->default_value_enum()->type()), ".", + GetEnumValueName(descriptor->default_value_enum()->type()->name(), + descriptor->default_value_enum()->name())); case FieldDescriptor::TYPE_MESSAGE: case FieldDescriptor::TYPE_GROUP: if (IsWrapperType(descriptor)) { @@ -361,7 +381,7 @@ TProtoStringType FieldGeneratorBase::default_value(const FieldDescriptor* descri } else if (std::isnan(value)) { return "double.NaN"; } - return StrCat(value) + "D"; + return y_absl::StrCat(value, "D"); } case FieldDescriptor::TYPE_FLOAT: { float value = descriptor->default_value_float(); @@ -372,18 +392,18 @@ TProtoStringType FieldGeneratorBase::default_value(const FieldDescriptor* descri } else if (std::isnan(value)) { return "float.NaN"; } - return StrCat(value) + "F"; + return y_absl::StrCat(value, "F"); } case FieldDescriptor::TYPE_INT64: - return StrCat(descriptor->default_value_int64()) + "L"; + return y_absl::StrCat(descriptor->default_value_int64(), "L"); case FieldDescriptor::TYPE_UINT64: - return StrCat(descriptor->default_value_uint64()) + "UL"; + return y_absl::StrCat(descriptor->default_value_uint64(), "UL"); case FieldDescriptor::TYPE_INT32: - return StrCat(descriptor->default_value_int32()); + return y_absl::StrCat(descriptor->default_value_int32()); case FieldDescriptor::TYPE_FIXED64: - return StrCat(descriptor->default_value_uint64()) + "UL"; + return y_absl::StrCat(descriptor->default_value_uint64(), "UL"); case FieldDescriptor::TYPE_FIXED32: - return StrCat(descriptor->default_value_uint32()); + return y_absl::StrCat(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_BOOL: if (descriptor->default_value_bool()) { return "true"; @@ -395,23 +415,23 @@ TProtoStringType FieldGeneratorBase::default_value(const FieldDescriptor* descri case FieldDescriptor::TYPE_BYTES: return GetBytesDefaultValueInternal(descriptor); case FieldDescriptor::TYPE_UINT32: - return StrCat(descriptor->default_value_uint32()); + return y_absl::StrCat(descriptor->default_value_uint32()); case FieldDescriptor::TYPE_SFIXED32: - return StrCat(descriptor->default_value_int32()); + return y_absl::StrCat(descriptor->default_value_int32()); case FieldDescriptor::TYPE_SFIXED64: - return StrCat(descriptor->default_value_int64()) + "L"; + return y_absl::StrCat(descriptor->default_value_int64(), "L"); case FieldDescriptor::TYPE_SINT32: - return StrCat(descriptor->default_value_int32()); + return y_absl::StrCat(descriptor->default_value_int32()); case FieldDescriptor::TYPE_SINT64: - return StrCat(descriptor->default_value_int64()) + "L"; + return y_absl::StrCat(descriptor->default_value_int64(), "L"); default: - GOOGLE_LOG(FATAL)<< "Unknown field type."; + Y_ABSL_LOG(FATAL) << "Unknown field type."; return ""; } } TProtoStringType FieldGeneratorBase::number() { - return StrCat(descriptor_->number()); + return y_absl::StrCat(descriptor_->number()); } TProtoStringType FieldGeneratorBase::capitalized_type_name() { @@ -453,7 +473,7 @@ TProtoStringType FieldGeneratorBase::capitalized_type_name() { case FieldDescriptor::TYPE_SINT64: return "SInt64"; default: - GOOGLE_LOG(FATAL)<< "Unknown field type."; + Y_ABSL_LOG(FATAL) << "Unknown field type."; return ""; } } @@ -462,3 +482,5 @@ TProtoStringType FieldGeneratorBase::capitalized_type_name() { } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_field_base.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_field_base.h index e553202792f..26ce67f9678 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -32,12 +32,16 @@ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__ #include <string> -#include <google/protobuf/stubs/strutil.h> -#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> +#include "google/protobuf/compiler/code_generator.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/str_split.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 { @@ -74,7 +78,7 @@ class FieldGeneratorBase : public SourceGeneratorBase { protected: const FieldDescriptor* descriptor_; const int presenceIndex_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; void AddDeprecatedFlag(io::Printer* printer); void AddNullCheck(io::Printer* printer); @@ -82,7 +86,7 @@ class FieldGeneratorBase : public SourceGeneratorBase { void AddPublicMemberAttributes(io::Printer* printer); void SetCommonOneofFieldVariables( - std::map<TProtoStringType, TProtoStringType>* variables); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables); TProtoStringType oneof_property_name(); TProtoStringType oneof_case_name(); @@ -98,7 +102,8 @@ class FieldGeneratorBase : public SourceGeneratorBase { TProtoStringType capitalized_type_name(); private: - void SetCommonFieldVariables(std::map<TProtoStringType, TProtoStringType>* variables); + void SetCommonFieldVariables( + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables); TProtoStringType GetStringDefaultValueInternal(const FieldDescriptor* descriptor); TProtoStringType GetBytesDefaultValueInternal(const FieldDescriptor* descriptor); }; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_generator.cc index 266b073c762..8e36faeb5b0 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -28,20 +28,19 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_generator.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> +#include <sstream> -#include <google/protobuf/compiler/csharp/csharp_generator.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_names.h> -#include <google/protobuf/compiler/csharp/csharp_options.h> -#include <google/protobuf/compiler/csharp/csharp_reflection_class.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/csharp_options.h" +#include "google/protobuf/compiler/csharp/csharp_reflection_class.h" +#include "google/protobuf/compiler/csharp/names.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { @@ -70,7 +69,7 @@ bool Generator::Generate(const FileDescriptor* file, struct Options cli_options; - for (int i = 0; i < options.size(); i++) { + for (size_t i = 0; i < options.size(); i++) { if (options[i].first == "file_extension") { cli_options.file_extension = options[i].second; } else if (options[i].first == "base_namespace") { @@ -81,7 +80,7 @@ bool Generator::Generate(const FileDescriptor* file, } else if (options[i].first == "serializable") { cli_options.serializable = true; } else { - *error = "Unknown generator option: " + options[i].first; + *error = y_absl::StrCat("Unknown generator option: ", options[i].first); return false; } } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_generator.h index c82c38f23f4..2a1aefdd865 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_generator.h @@ -35,9 +35,9 @@ #include <string> -#include <google/protobuf/compiler/code_generator.h> +#include "google/protobuf/compiler/code_generator.h" -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -65,6 +65,6 @@ class PROTOC_EXPORT Generator : public CodeGenerator { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 8b5d09e5311..065eb434c72 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -32,28 +32,34 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include "google/protobuf/compiler/csharp/csharp_helpers.h" + #include <algorithm> #include <limits> -#include <vector> #include <sstream> +#include <string> +#include <vector> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_names.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> - -#include <google/protobuf/compiler/csharp/csharp_field_base.h> -#include <google/protobuf/compiler/csharp/csharp_enum_field.h> -#include <google/protobuf/compiler/csharp/csharp_map_field.h> -#include <google/protobuf/compiler/csharp/csharp_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_options.h> -#include <google/protobuf/compiler/csharp/csharp_primitive_field.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h> -#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/compiler/csharp/csharp_enum_field.h" +#include "google/protobuf/compiler/csharp/csharp_field_base.h" +#include "google/protobuf/compiler/csharp/csharp_map_field.h" +#include "google/protobuf/compiler/csharp/csharp_message_field.h" +#include "google/protobuf/compiler/csharp/csharp_options.h" +#include "google/protobuf/compiler/csharp/csharp_primitive_field.h" +#include "google/protobuf/compiler/csharp/csharp_repeated_enum_field.h" +#include "google/protobuf/compiler/csharp/csharp_repeated_message_field.h" +#include "google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h" +#include "google/protobuf/compiler/csharp/csharp_wrapper_field.h" +#include "google/protobuf/compiler/csharp/names.h" +#include "google/protobuf/descriptor.pb.h" + +// Must be last. +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -102,88 +108,10 @@ CSharpType GetCSharpType(FieldDescriptor::Type type) { // No default because we want the compiler to complain if any new // types are added. } - GOOGLE_LOG(FATAL)<< "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return (CSharpType) -1; } -TProtoStringType StripDotProto(const TProtoStringType& proto_file) { - int lastindex = proto_file.find_last_of("."); - return proto_file.substr(0, lastindex); -} - -TProtoStringType GetFileNamespace(const FileDescriptor* descriptor) { - if (descriptor->options().has_csharp_namespace()) { - return descriptor->options().csharp_namespace(); - } - return UnderscoresToCamelCase(descriptor->package(), true, true); -} - -// Returns the Pascal-cased last part of the proto file. For example, -// input of "google/protobuf/foo_bar.proto" would result in "FooBar". -TProtoStringType GetFileNameBase(const FileDescriptor* descriptor) { - TProtoStringType proto_file = descriptor->name(); - int lastslash = proto_file.find_last_of("/"); - TProtoStringType base = proto_file.substr(lastslash + 1); - return UnderscoresToPascalCase(StripDotProto(base)); -} - -TProtoStringType GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) { - // TODO: Detect collisions with existing messages, - // and append an underscore if necessary. - return GetFileNameBase(descriptor) + "Reflection"; -} - -TProtoStringType GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor) { - // TODO: Detect collisions with existing messages, - // and append an underscore if necessary. - return GetFileNameBase(descriptor) + "Extensions"; -} - -// TODO(jtattermusch): can we reuse a utility function? -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, - bool cap_next_letter, - bool preserve_period) { - TProtoStringType result; - // Note: I distrust ctype.h due to locales. - for (int i = 0; i < input.size(); i++) { - if ('a' <= input[i] && input[i] <= 'z') { - if (cap_next_letter) { - result += input[i] + ('A' - 'a'); - } else { - result += input[i]; - } - cap_next_letter = false; - } else if ('A' <= input[i] && input[i] <= 'Z') { - if (i == 0 && !cap_next_letter) { - // Force first letter to lower-case unless explicitly told to - // capitalize it. - result += input[i] + ('a' - 'A'); - } else { - // Capital letters after the first are left as-is. - result += input[i]; - } - cap_next_letter = false; - } else if ('0' <= input[i] && input[i] <= '9') { - result += input[i]; - cap_next_letter = true; - } else { - cap_next_letter = true; - if (input[i] == '.' && preserve_period) { - result += '.'; - } - } - } - // Add a trailing "_" if the name should be altered. - if (input.size() > 0 && input[input.size() - 1] == '#') { - result += '_'; - } - return result; -} - -TProtoStringType UnderscoresToPascalCase(const TProtoStringType& input) { - return UnderscoresToCamelCase(input, true); -} - // Convert a string which is expected to be SHOUTY_CASE (but may not be *precisely* shouty) // into a PascalCase string. Precise rules implemented: @@ -194,24 +122,24 @@ TProtoStringType UnderscoresToPascalCase(const TProtoStringType& input) { // Numeric Alphanumeric Upper // Lower letter Alphanumeric Same as current // Upper letter Alphanumeric Lower -TProtoStringType ShoutyToPascalCase(const TProtoStringType& input) { +TProtoStringType ShoutyToPascalCase(y_absl::string_view input) { TProtoStringType result; // Simple way of implementing "always start with upper" char previous = '_'; for (int i = 0; i < input.size(); i++) { char current = input[i]; - if (!ascii_isalnum(current)) { + if (!y_absl::ascii_isalnum(current)) { previous = current; continue; } - if (!ascii_isalnum(previous)) { - result += ascii_toupper(current); - } else if (ascii_isdigit(previous)) { - result += ascii_toupper(current); - } else if (ascii_islower(previous)) { + if (!y_absl::ascii_isalnum(previous)) { + result += y_absl::ascii_toupper(current); + } else if (y_absl::ascii_isdigit(previous)) { + result += y_absl::ascii_toupper(current); + } else if (y_absl::ascii_islower(previous)) { result += current; } else { - result += ascii_tolower(current); + result += y_absl::ascii_tolower(current); } previous = current; } @@ -224,12 +152,12 @@ TProtoStringType ShoutyToPascalCase(const TProtoStringType& input) { // (foo_bar, foobarbaz) => baz - underscore in prefix is ignored // (foobar, foo_barbaz) => baz - underscore in value is ignored // (foo, bar) => bar - prefix isn't matched; return original value -TProtoStringType TryRemovePrefix(const TProtoStringType& prefix, const TProtoStringType& value) { +TProtoStringType TryRemovePrefix(y_absl::string_view prefix, y_absl::string_view value) { // First normalize to a lower-case no-underscores prefix to match against TProtoStringType prefix_to_match = ""; for (size_t i = 0; i < prefix.size(); i++) { if (prefix[i] != '_') { - prefix_to_match += ascii_tolower(prefix[i]); + prefix_to_match += y_absl::ascii_tolower(prefix[i]); } } @@ -242,15 +170,15 @@ TProtoStringType TryRemovePrefix(const TProtoStringType& prefix, const TProtoStr if (value[value_index] == '_') { continue; } - if (ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) { + if (y_absl::ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) { // Failed to match the prefix - bail out early. - return value; + return TProtoStringType(value); } } // If we didn't finish looking through the prefix, we can't strip it. if (prefix_index < prefix_to_match.size()) { - return value; + return TProtoStringType(value); } // Step over any underscores after the prefix @@ -260,10 +188,10 @@ TProtoStringType TryRemovePrefix(const TProtoStringType& prefix, const TProtoStr // If there's nothing left (e.g. it was a prefix with only underscores afterwards), don't strip. if (value_index == value.size()) { - return value; + return TProtoStringType(value); } - return value.substr(value_index); + return TProtoStringType(value.substr(value_index)); } // Format the enum value name in a pleasant way for C#: @@ -271,13 +199,14 @@ TProtoStringType TryRemovePrefix(const TProtoStringType& prefix, const TProtoStr // - Convert to PascalCase. // For example, an enum called Color with a value of COLOR_BLUE should // result in an enum value in C# called just Blue -TProtoStringType GetEnumValueName(const TProtoStringType& enum_name, const TProtoStringType& enum_value_name) { +TProtoStringType GetEnumValueName(y_absl::string_view enum_name, + y_absl::string_view enum_value_name) { TProtoStringType stripped = TryRemovePrefix(enum_name, enum_value_name); TProtoStringType result = ShoutyToPascalCase(stripped); // Just in case we have an enum name of FOO and a value of FOO_2... make sure the returned // string is a valid identifier. - if (ascii_isdigit(result[0])) { - result = "_" + result; + if (y_absl::ascii_isdigit(result[0])) { + return y_absl::StrCat("_", result); } return result; } @@ -320,47 +249,14 @@ uint GetGroupEndTag(const Descriptor* descriptor) { return 0; } -TProtoStringType ToCSharpName(const TProtoStringType& name, const FileDescriptor* file) { - TProtoStringType result = GetFileNamespace(file); - if (!result.empty()) { - result += '.'; - } - TProtoStringType classname; - if (file->package().empty()) { - classname = name; - } else { - // Strip the proto package from full_name since we've replaced it with - // the C# namespace. - classname = name.substr(file->package().size() + 1); - } - result += StringReplace(classname, ".", ".Types.", true); - return "global::" + result; -} - -TProtoStringType GetReflectionClassName(const FileDescriptor* descriptor) { - TProtoStringType result = GetFileNamespace(descriptor); - if (!result.empty()) { - result += '.'; - } - result += GetReflectionClassUnqualifiedName(descriptor); - return "global::" + result; -} - TProtoStringType GetFullExtensionName(const FieldDescriptor* descriptor) { if (descriptor->extension_scope()) { - return GetClassName(descriptor->extension_scope()) + ".Extensions." + GetPropertyName(descriptor); - } - else { - return GetExtensionClassUnqualifiedName(descriptor->file()) + "." + GetPropertyName(descriptor); + return y_absl::StrCat(GetClassName(descriptor->extension_scope()), + ".Extensions.", GetPropertyName(descriptor)); } -} - -TProtoStringType GetClassName(const Descriptor* descriptor) { - return ToCSharpName(descriptor->full_name(), descriptor->file()); -} -TProtoStringType GetClassName(const EnumDescriptor* descriptor) { - return ToCSharpName(descriptor->full_name(), descriptor->file()); + return y_absl::StrCat(GetExtensionClassUnqualifiedName(descriptor->file()), ".", + GetPropertyName(descriptor)); } // Groups are hacky: The name of the field is just the lower-cased name @@ -375,20 +271,35 @@ TProtoStringType GetFieldName(const FieldDescriptor* descriptor) { } TProtoStringType GetFieldConstantName(const FieldDescriptor* field) { - return GetPropertyName(field) + "FieldNumber"; + return y_absl::StrCat(GetPropertyName(field), "FieldNumber"); } TProtoStringType GetPropertyName(const FieldDescriptor* descriptor) { + // Names of members declared or overridden in the message. + static const auto& reserved_member_names = *new y_absl::flat_hash_set<y_absl::string_view>({ + "Types", + "Descriptor", + "Equals", + "ToString", + "GetHashCode", + "WriteTo", + "Clone", + "CalculateSize", + "MergeFrom", + "OnConstruction", + "Parser" + }); + // TODO(jtattermusch): consider introducing csharp_property_name field option TProtoStringType property_name = UnderscoresToPascalCase(GetFieldName(descriptor)); - // Avoid either our own type name or reserved names. Note that not all names - // are reserved - a field called to_string, write_to etc would still cause a problem. + // Avoid either our own type name or reserved names. // There are various ways of ending up with naming collisions, but we try to avoid obvious - // ones. + // ones. In particular, we avoid the names of all the members we generate. + // Note that we *don't* add an underscore for MemberwiseClone or GetType. Those generate + // warnings, but not errors; changing the name now could be a breaking change. if (property_name == descriptor->containing_type()->name() - || property_name == "Types" - || property_name == "Descriptor") { - property_name += "_"; + || reserved_member_names.find(property_name) != reserved_member_names.end()) { + y_absl::StrAppend(&property_name, "_"); } return property_name; } @@ -400,40 +311,6 @@ TProtoStringType GetOneofCaseName(const FieldDescriptor* descriptor) { return property_name == "None" ? "None_" : property_name; } -TProtoStringType GetOutputFile(const FileDescriptor* descriptor, - const TProtoStringType file_extension, - const bool generate_directories, - const TProtoStringType base_namespace, - TProtoStringType* error) { - TProtoStringType relative_filename = GetFileNameBase(descriptor) + file_extension; - if (!generate_directories) { - return relative_filename; - } - TProtoStringType ns = GetFileNamespace(descriptor); - TProtoStringType namespace_suffix = ns; - if (!base_namespace.empty()) { - // Check that the base_namespace is either equal to or a leading part of - // the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't - // be regarded as a prefix of "Foo.Bar". The simplest option is to add "." - // to both. - TProtoStringType extended_ns = ns + "."; - if (extended_ns.find(base_namespace + ".") != 0) { - *error = "Namespace " + ns + " is not a prefix namespace of base namespace " + base_namespace; - return ""; // This will be ignored, because we've set an error. - } - namespace_suffix = ns.substr(base_namespace.length()); - if (namespace_suffix.find(".") == 0) { - namespace_suffix = namespace_suffix.substr(1); - } - } - - TProtoStringType namespace_dir = StringReplace(namespace_suffix, ".", "/", true); - if (!namespace_dir.empty()) { - namespace_dir += "/"; - } - return namespace_dir + relative_filename; -} - // TODO: c&p from Java protoc plugin // For encodings with fixed sizes, returns that size in bytes. Otherwise // returns -1. @@ -463,17 +340,17 @@ int GetFixedSize(FieldDescriptor::Type type) { // No default because we want the compiler to complain if any new // types are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return -1; } static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -TProtoStringType StringToBase64(const TProtoStringType& input) { +TProtoStringType StringToBase64(y_absl::string_view input) { TProtoStringType result; size_t remaining = input.size(); - const unsigned char *src = (const unsigned char*) input.c_str(); + const unsigned char* src = (const unsigned char*)input.data(); while (remaining > 2) { result += base64_chars[src[0] >> 2]; result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)]; @@ -588,7 +465,7 @@ bool IsNullable(const FieldDescriptor* descriptor) { return true; default: - GOOGLE_LOG(FATAL) << "Unknown field type."; + Y_ABSL_LOG(FATAL) << "Unknown field type."; return true; } } @@ -597,3 +474,5 @@ bool IsNullable(const FieldDescriptor* descriptor) { } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_helpers.h index 0a325464dcc..818eef1a3c4 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -36,14 +36,16 @@ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__ #include <string> -#include <google/protobuf/port.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/port_def.inc> +#include "google/protobuf/compiler/code_generator.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/compiler/csharp/names.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/port.h" +#include "google/protobuf/port_def.inc" +#include "google/protobuf/stubs/common.h" namespace google { namespace protobuf { @@ -72,15 +74,6 @@ enum CSharpType { // Converts field type to corresponding C# type. CSharpType GetCSharpType(FieldDescriptor::Type type); -TProtoStringType StripDotProto(const TProtoStringType& proto_file); - -// Gets unqualified name of the reflection class -TProtoStringType GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor); -// Gets unqualified name of the extension class -TProtoStringType GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor); - -TProtoStringType GetClassName(const EnumDescriptor* descriptor); - TProtoStringType GetFieldName(const FieldDescriptor* descriptor); TProtoStringType GetFieldConstantName(const FieldDescriptor* field); @@ -91,23 +84,13 @@ TProtoStringType GetOneofCaseName(const FieldDescriptor* descriptor); int GetFixedSize(FieldDescriptor::Type type); -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, - bool cap_next_letter, - bool preserve_period); - -inline TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, bool cap_next_letter) { - return UnderscoresToCamelCase(input, cap_next_letter, false); -} - -TProtoStringType UnderscoresToPascalCase(const TProtoStringType& 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. -TProtoStringType PROTOC_EXPORT GetEnumValueName(const TProtoStringType& enum_name, - const TProtoStringType& enum_value_name); +TProtoStringType PROTOC_EXPORT GetEnumValueName(y_absl::string_view enum_name, + y_absl::string_view enum_value_name); // TODO(jtattermusch): perhaps we could move this to strutil -TProtoStringType StringToBase64(const TProtoStringType& input); +TProtoStringType StringToBase64(y_absl::string_view input); TProtoStringType FileDescriptorToBase64(const FileDescriptor* descriptor); @@ -193,6 +176,6 @@ inline bool RequiresPresenceBit(const FieldDescriptor* descriptor) { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_map_field.cc index a13b995da8c..062e3a73b7e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_map_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_map_field.cc @@ -28,18 +28,16 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_map_field.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> +#include <sstream> -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_map_field.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -88,9 +86,8 @@ void MapFieldGenerator::GenerateMembers(io::Printer* printer) { } void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) { - printer->Print( - variables_, - "$name$_.Add(other.$name$_);\n"); + printer->Print(variables_, + "$name$_.MergeFrom(other.$name$_);\n"); } void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_map_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_map_field.h index b03f65b74a3..3fbc6e53f8c 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_map_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_map_field.h @@ -31,8 +31,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__ -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/csharp/csharp_field_base.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message.cc index e96b329cab0..d5b7f48e33d 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -28,26 +28,29 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_message.h" + #include <algorithm> -#include <map> - -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/wire_format_lite.h> - -#include <google/protobuf/compiler/csharp/csharp_options.h> -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/compiler/csharp/csharp_enum.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_message.h> -#include <google/protobuf/compiler/csharp/csharp_names.h> +#include <sstream> + +#include "google/protobuf/compiler/code_generator.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" +#include "google/protobuf/compiler/csharp/csharp_enum.h" +#include "google/protobuf/compiler/csharp/csharp_field_base.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/csharp_options.h" +#include "google/protobuf/compiler/csharp/names.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" +#include "google/protobuf/wire_format_lite.h" + +// Must be last. +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -112,7 +115,7 @@ void MessageGenerator::AddSerializableAttribute(io::Printer* printer) { } void MessageGenerator::Generate(io::Printer* printer) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["class_name"] = class_name(); vars["access_level"] = class_access_level(); @@ -161,7 +164,7 @@ void MessageGenerator::Generate(io::Printer* printer) { 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", StrCat(i)); + printer->Print("private int _hasBits$i$;\n", "i", y_absl::StrCat(i)); } WriteGeneratedCodeAttributes(printer); @@ -172,11 +175,13 @@ void MessageGenerator::Generate(io::Printer* printer) { // Access the message descriptor via the relevant file descriptor or containing message descriptor. if (!descriptor_->containing_type()) { - vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file()) - + ".Descriptor.MessageTypes[" + StrCat(descriptor_->index()) + "]"; + vars["descriptor_accessor"] = + y_absl::StrCat(GetReflectionClassName(descriptor_->file()), + ".Descriptor.MessageTypes[", descriptor_->index(), "]"); } else { - vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type()) - + ".Descriptor.NestedTypes[" + StrCat(descriptor_->index()) + "]"; + vars["descriptor_accessor"] = + y_absl::StrCat(GetClassName(descriptor_->containing_type()), + ".Descriptor.NestedTypes[", descriptor_->index(), "]"); } WriteGeneratedCodeAttributes(printer); @@ -216,7 +221,7 @@ void MessageGenerator::Generate(io::Printer* printer) { "public const int $field_constant_name$ = $index$;\n", "field_name", fieldDescriptor->name(), "field_constant_name", GetFieldConstantName(fieldDescriptor), - "index", StrCat(fieldDescriptor->number())); + "index", y_absl::StrCat(fieldDescriptor->number())); std::unique_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(fieldDescriptor)); generator->GenerateMembers(printer); @@ -240,7 +245,7 @@ void MessageGenerator::Generate(io::Printer* printer) { const FieldDescriptor* field = oneof->field(j); printer->Print("$oneof_case_name$ = $index$,\n", "oneof_case_name", GetOneofCaseName(field), - "index", StrCat(field->number())); + "index", y_absl::StrCat(field->number())); } printer->Outdent(); printer->Print("}\n"); @@ -374,7 +379,7 @@ bool MessageGenerator::HasNestedGeneratedTypes() } void MessageGenerator::GenerateCloningCode(io::Printer* printer) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; WriteGeneratedCodeAttributes(printer); vars["class_name"] = class_name(); printer->Print( @@ -382,7 +387,7 @@ void MessageGenerator::GenerateCloningCode(io::Printer* printer) { "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", StrCat(i)); + printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", y_absl::StrCat(i)); } // Clone non-oneof fields first (treating optional proto3 fields as non-oneof) for (int i = 0; i < descriptor_->field_count(); i++) { @@ -438,32 +443,30 @@ void MessageGenerator::GenerateFreezingCode(io::Printer* printer) { } void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { - std::map<TProtoStringType, TProtoStringType> vars; - vars["class_name"] = class_name(); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; + vars["class_name"] = class_name(); - // Equality - WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "public override bool Equals(object other) {\n" - " return Equals(other as $class_name$);\n" - "}\n\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "public bool Equals($class_name$ other) {\n" - " if (ReferenceEquals(other, null)) {\n" - " return false;\n" - " }\n" - " if (ReferenceEquals(other, this)) {\n" - " return true;\n" - " }\n"); - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - std::unique_ptr<FieldGeneratorBase> generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->WriteEquals(printer); - } + // Equality + WriteGeneratedCodeAttributes(printer); + printer->Print(vars, + "public override bool Equals(object other) {\n" + " return Equals(other as $class_name$);\n" + "}\n\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print(vars, + "public bool Equals($class_name$ other) {\n" + " if (ReferenceEquals(other, null)) {\n" + " return false;\n" + " }\n" + " if (ReferenceEquals(other, this)) {\n" + " return true;\n" + " }\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + std::unique_ptr<FieldGeneratorBase> generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteEquals(printer); + } for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { printer->Print("if ($property_name$Case != other.$property_name$Case) return false;\n", "property_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); @@ -605,7 +608,7 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized // for code size. - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["class_name"] = class_name(); WriteGeneratedCodeAttributes(printer); @@ -685,7 +688,7 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { } void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_parse_context) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["maybe_ref_input"] = use_parse_context ? "ref input" : "input"; printer->Print( @@ -698,7 +701,7 @@ void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_pars printer->Print( "case $end_tag$:\n" " return;\n", - "end_tag", StrCat(end_tag_)); + "end_tag", y_absl::StrCat(end_tag_)); } if (has_extension_ranges_) { printer->Print(vars, @@ -727,13 +730,13 @@ void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_pars printer->Print( "case $packed_tag$:\n", "packed_tag", - StrCat( + y_absl::StrCat( internal::WireFormatLite::MakeTag( field->number(), internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED))); } - printer->Print("case $tag$: {\n", "tag", StrCat(tag)); + printer->Print("case $tag$: {\n", "tag", y_absl::StrCat(tag)); printer->Indent(); std::unique_ptr<FieldGeneratorBase> generator( CreateFieldGeneratorInternal(field)); @@ -764,7 +767,8 @@ int MessageGenerator::GetPresenceIndex(const FieldDescriptor* descriptor) { index++; } } - GOOGLE_LOG(DFATAL)<< "Could not find presence index for field " << descriptor->name(); + Y_ABSL_DLOG(FATAL) << "Could not find presence index for field " + << descriptor->name(); return -1; } @@ -777,3 +781,5 @@ FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal( } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message.h index ef399d2ec4f..fa61b33f4b8 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message.h @@ -34,9 +34,9 @@ #include <string> #include <vector> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/csharp/csharp_source_generator_base.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 487d01ddef3..f43f2d99527 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -28,21 +28,17 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_message_field.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/wire_format_lite.h> +#include <sstream> -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_options.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/csharp_options.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -54,8 +50,8 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, const Options *options) : FieldGeneratorBase(descriptor, presenceIndex, options) { if (!SupportsPresenceApi(descriptor_)) { - variables_["has_property_check"] = name() + "_ != null"; - variables_["has_not_property_check"] = name() + "_ == null"; + variables_["has_property_check"] = y_absl::StrCat(name(), "_ != null"); + variables_["has_not_property_check"] = y_absl::StrCat(name(), "_ == null"); } } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message_field.h index 2da1d71701f..3cae2bd0b24 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -31,8 +31,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__ -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/csharp/csharp_field_base.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_names.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_names.h index cb135e1a22c..bff07d1e979 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_names.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_names.h @@ -1,109 +1,2 @@ -// 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: [email protected] (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. -// -// Provides a mechanism for mapping a descriptor to the -// fully-qualified name of the corresponding C# class. - -#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ -#define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ - -#include <string> -#include <google/protobuf/port.h> -#include <google/protobuf/stubs/common.h> - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { - -class Descriptor; -class EnumDescriptor; -class FileDescriptor; -class ServiceDescriptor; - -namespace compiler { -namespace csharp { - -// Requires: -// descriptor != NULL -// -// Returns: -// The namespace to use for given file descriptor. -TProtoStringType PROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor); - -// Requires: -// descriptor != NULL -// -// Returns: -// The fully-qualified C# class name. -TProtoStringType PROTOC_EXPORT GetClassName(const Descriptor* descriptor); - -// Requires: -// descriptor != NULL -// -// Returns: -// 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. -TProtoStringType 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 -// namespace. base_namespace can be used to strip some of the top level -// directories. E.g. for file with namespace "Bar.Foo" and base_namespace="Bar", -// the resulting file will be put under directory "Foo" (and not "Bar/Foo"). -// -// Requires: -// descriptor != NULL -// error != NULL -// -// Returns: -// 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. -TProtoStringType PROTOC_EXPORT GetOutputFile(const FileDescriptor* descriptor, - const TProtoStringType file_extension, - const bool generate_directories, - const TProtoStringType base_namespace, - TProtoStringType* error); - -} // namespace csharp -} // namespace compiler -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ +#include "names.h" +#include "names.h"
\ No newline at end of file diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index e7d51168d17..455269a8d52 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -28,19 +28,20 @@ // (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 <sstream> - -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> +#include "google/protobuf/compiler/csharp/csharp_primitive_field.h" -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_options.h> -#include <google/protobuf/compiler/csharp/csharp_primitive_field.h> +#include <sstream> +#include <string> +#include <utility> + +#include "google/protobuf/compiler/code_generator.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/csharp_options.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -54,8 +55,11 @@ PrimitiveFieldGenerator::PrimitiveFieldGenerator( is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING && descriptor->type() != FieldDescriptor::TYPE_BYTES; if (!is_value_type && !SupportsPresenceApi(descriptor_)) { - variables_["has_property_check"] = variables_["property_name"] + ".Length != 0"; - variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0"; + TProtoStringType property_name = variables_["property_name"]; + variables_["has_property_check"] = + y_absl::StrCat(property_name, ".Length != 0"); + variables_["other_has_property_check"] = + y_absl::StrCat("other.", property_name, ".Length != 0"); } } @@ -81,10 +85,12 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, "private readonly static $type_name$ $property_name$DefaultValue = $default_value$;\n\n"); + TProtoStringType property_name = variables_["property_name"]; variables_["default_value_access"] = - variables_["property_name"] + "DefaultValue"; + y_absl::StrCat(property_name, "DefaultValue"); } else { - variables_["default_value_access"] = variables_["default_value"]; + TProtoStringType default_value = variables_["default_value"]; + variables_["default_value_access"] = std::move(default_value); } // Declare the field itself. @@ -215,7 +221,7 @@ void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { } else { printer->Print( "size += $tag_size$ + $fixed_size$;\n", - "fixed_size", StrCat(fixedSize), + "fixed_size", y_absl::StrCat(fixedSize), "tag_size", variables_["tag_size"]); } printer->Outdent(); diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_primitive_field.h index e98c3698a00..0abf8278f16 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_primitive_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_primitive_field.h @@ -31,8 +31,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__ -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/csharp/csharp_field_base.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc index c142195cf53..6471da7c2c4 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc @@ -28,23 +28,24 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_reflection_class.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> +#include <sstream> +#include "google/protobuf/compiler/code_generator.h" +#include "y_absl/strings/str_join.h" +#include "google/protobuf/compiler/csharp/csharp_enum.h" +#include "google/protobuf/compiler/csharp/csharp_field_base.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/csharp_message.h" +#include "google/protobuf/compiler/csharp/csharp_options.h" +#include "google/protobuf/compiler/csharp/names.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" -#include <google/protobuf/compiler/csharp/csharp_enum.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> -#include <google/protobuf/compiler/csharp/csharp_message.h> -#include <google/protobuf/compiler/csharp/csharp_names.h> -#include <google/protobuf/compiler/csharp/csharp_options.h> -#include <google/protobuf/compiler/csharp/csharp_reflection_class.h> +// Must be last. +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -213,7 +214,7 @@ void ReflectionClassGenerator::WriteDescriptor(io::Printer* printer) { for (int i = 0; i < file_->extension_count(); i++) { extensions.push_back(GetFullExtensionName(file_->extension(i))); } - printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", ")); + printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", y_absl::StrJoin(extensions, ", ")); } else { printer->Print("null, "); @@ -265,7 +266,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript for (int i = 0; i < descriptor->field_count(); i++) { fields.push_back(GetPropertyName(descriptor->field(i))); } - printer->Print("new[]{ \"$fields$\" }, ", "fields", Join(fields, "\", \"")); + printer->Print("new[]{ \"$fields$\" }, ", "fields", y_absl::StrJoin(fields, "\", \"")); } else { printer->Print("null, "); @@ -278,7 +279,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript for (int i = 0; i < descriptor->oneof_decl_count(); i++) { oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true)); } - printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", Join(oneofs, "\", \"")); + printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", y_absl::StrJoin(oneofs, "\", \"")); } else { printer->Print("null, "); @@ -291,7 +292,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript for (int i = 0; i < descriptor->enum_type_count(); i++) { enums.push_back(GetClassName(descriptor->enum_type(i))); } - printer->Print("new[]{ typeof($enums$) }, ", "enums", Join(enums, "), typeof(")); + printer->Print("new[]{ typeof($enums$) }, ", "enums", y_absl::StrJoin(enums, "), typeof(")); } else { printer->Print("null, "); @@ -303,7 +304,7 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript for (int i = 0; i < descriptor->extension_count(); i++) { extensions.push_back(GetFullExtensionName(descriptor->extension(i))); } - printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", ")); + printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", y_absl::StrJoin(extensions, ", ")); } else { printer->Print("null, "); @@ -328,3 +329,5 @@ void ReflectionClassGenerator::WriteGeneratedCodeInfo(const Descriptor* descript } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_reflection_class.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_reflection_class.h index 392e559ddfb..11de54ea275 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_reflection_class.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_reflection_class.h @@ -33,10 +33,10 @@ #include <string> -#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> +#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/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index 04bc7bbb1bd..1a9fd1d893e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -28,18 +28,18 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_repeated_enum_field.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/wire_format.h> +#include <sstream> -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/wire_format.h" +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h index 6d6717cc022..448805b956d 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -31,8 +31,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__ -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/csharp/csharp_field_base.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 8a93cd13cfc..6ac7e2d6a04 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -28,19 +28,19 @@ // (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/csharp/csharp_repeated_message_field.h" + #include <sstream> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> - -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_message_field.h> -#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/csharp_message_field.h" +#include "google/protobuf/compiler/csharp/csharp_wrapper_field.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h index ea252ced34a..1acf10e09cd 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -31,8 +31,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__ -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/csharp/csharp_field_base.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index 0eacf91ce6c..df97ccf3db9 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -28,18 +28,18 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/wire_format.h> +#include <sstream> -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/wire_format.h" +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h index 2b470e12c9d..3b5b1c035dd 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -31,8 +31,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__ -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/csharp/csharp_field_base.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc index 91af159a7b7..f0fb30cceec 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -28,18 +28,18 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_source_generator_base.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> +#include <sstream> -#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_names.h> -#include <google/protobuf/compiler/csharp/csharp_options.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/names.h" +#include "google/protobuf/compiler/csharp/csharp_options.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h index 9206cd33092..d719cb5b7ad 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -33,8 +33,8 @@ #include <string> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/io/printer.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc index e638dd862ae..2dac8f52fd4 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc @@ -28,18 +28,18 @@ // (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 <sstream> +#include "google/protobuf/compiler/csharp/csharp_wrapper_field.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> +#include <sstream> -#include <google/protobuf/compiler/csharp/csharp_doc_comment.h> -#include <google/protobuf/compiler/csharp/csharp_helpers.h> -#include <google/protobuf/compiler/csharp/csharp_options.h> -#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/csharp/csharp_doc_comment.h" +#include "google/protobuf/compiler/csharp/csharp_helpers.h" +#include "google/protobuf/compiler/csharp/csharp_options.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { @@ -49,8 +49,8 @@ namespace csharp { WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor, int presenceIndex, const Options *options) : FieldGeneratorBase(descriptor, presenceIndex, options) { - variables_["has_property_check"] = name() + "_ != null"; - variables_["has_not_property_check"] = name() + "_ == null"; + variables_["has_property_check"] = y_absl::StrCat(name(), "_ != null"); + variables_["has_not_property_check"] = y_absl::StrCat(name(), "_ == null"); const FieldDescriptor* wrapped_field = descriptor->message_type()->field(0); is_value_type = wrapped_field->type() != FieldDescriptor::TYPE_STRING && wrapped_field->type() != FieldDescriptor::TYPE_BYTES; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h index cc8a3137d6e..6b15aa0eb08 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h @@ -31,8 +31,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__ -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/csharp/csharp_field_base.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/csharp/csharp_field_base.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/names.cc b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/names.cc new file mode 100644 index 00000000000..0caa5f3f4c7 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/names.cc @@ -0,0 +1,223 @@ +// 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: [email protected] (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include "google/protobuf/compiler/csharp/names.h" + +#include <string> + +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/strip.h" +#include "google/protobuf/compiler/csharp/names.h" +#include "google/protobuf/descriptor.pb.h" + +// Must be last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +namespace { + +y_absl::string_view StripDotProto(y_absl::string_view proto_file) { + int lastindex = proto_file.find_last_of('.'); + return proto_file.substr(0, lastindex); +} + +// Returns the Pascal-cased last part of the proto file. For example, +// input of "google/protobuf/foo_bar.proto" would result in "FooBar". +TProtoStringType GetFileNameBase(const FileDescriptor* descriptor) { + TProtoStringType proto_file = descriptor->name(); + int lastslash = proto_file.find_last_of('/'); + TProtoStringType base = proto_file.substr(lastslash + 1); + return UnderscoresToPascalCase(StripDotProto(base)); +} + +TProtoStringType ToCSharpName(y_absl::string_view name, const FileDescriptor* file) { + TProtoStringType result = GetFileNamespace(file); + if (!result.empty()) { + result += '.'; + } + y_absl::string_view classname; + if (file->package().empty()) { + classname = name; + } else { + // Strip the proto package from full_name since we've replaced it with + // the C# namespace. + classname = name.substr(file->package().size() + 1); + } + return y_absl::StrCat("global::", result, + y_absl::StrReplaceAll(classname, {{".", ".Types."}})); +} + +} // namespace + +TProtoStringType GetFileNamespace(const FileDescriptor* descriptor) { + if (descriptor->options().has_csharp_namespace()) { + return descriptor->options().csharp_namespace(); + } + return UnderscoresToCamelCase(descriptor->package(), true, true); +} + +TProtoStringType GetClassName(const Descriptor* descriptor) { + return ToCSharpName(descriptor->full_name(), descriptor->file()); +} + +TProtoStringType GetClassName(const EnumDescriptor* descriptor) { + return ToCSharpName(descriptor->full_name(), descriptor->file()); +} + +TProtoStringType GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) { + // TODO: Detect collisions with existing messages, + // and append an underscore if necessary. + return y_absl::StrCat(GetFileNameBase(descriptor), "Reflection"); +} + +TProtoStringType GetReflectionClassName(const FileDescriptor* descriptor) { + TProtoStringType result = GetFileNamespace(descriptor); + if (!result.empty()) { + result += '.'; + } + return y_absl::StrCat("global::", result, + GetReflectionClassUnqualifiedName(descriptor)); +} + +TProtoStringType GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor) { + // TODO: Detect collisions with existing messages, + // and append an underscore if necessary. + return y_absl::StrCat(GetFileNameBase(descriptor), "Extensions"); +} + +TProtoStringType GetOutputFile(const FileDescriptor* descriptor, + y_absl::string_view file_extension, + bool generate_directories, + y_absl::string_view base_namespace, + TProtoStringType* error) { + TProtoStringType relative_filename = + y_absl::StrCat(GetFileNameBase(descriptor), file_extension); + if (!generate_directories) { + return relative_filename; + } + TProtoStringType ns = GetFileNamespace(descriptor); + y_absl::string_view namespace_suffix = ns; + if (!base_namespace.empty()) { + // Check that the base_namespace is either equal to or a leading part of + // the file namespace. This isn't just a simple prefix; "Foo.B" shouldn't + // be regarded as a prefix of "Foo.Bar". The simplest option is to add "." + // to both. + if (!y_absl::ConsumePrefix(&namespace_suffix, base_namespace) || + (!namespace_suffix.empty() && + !y_absl::ConsumePrefix(&namespace_suffix, "."))) { + *error = y_absl::StrCat("Namespace ", ns, + " is not a prefix namespace of base namespace ", + base_namespace); + return ""; // This will be ignored, because we've set an error. + } + } + + return y_absl::StrCat(y_absl::StrReplaceAll(namespace_suffix, {{".", "/"}}), + namespace_suffix.empty() ? "" : "/", relative_filename); +} + +TProtoStringType UnderscoresToPascalCase(y_absl::string_view input) { + return UnderscoresToCamelCase(input, true); +} + +// TODO(jtattermusch): can we reuse a utility function? +TProtoStringType UnderscoresToCamelCase(y_absl::string_view input, + bool cap_next_letter, bool preserve_period) { + TProtoStringType result; + + // Note: I distrust ctype.h due to locales. + for (int i = 0; i < input.size(); i++) { + if ('a' <= input[i] && input[i] <= 'z') { + if (cap_next_letter) { + result += input[i] + ('A' - 'a'); + } else { + result += input[i]; + } + cap_next_letter = false; + } else if ('A' <= input[i] && input[i] <= 'Z') { + if (i == 0 && !cap_next_letter) { + // Force first letter to lower-case unless explicitly told to + // capitalize it. + result += input[i] + ('a' - 'A'); + } else { + // Capital letters after the first are left as-is. + result += input[i]; + } + cap_next_letter = false; + } else if ('0' <= input[i] && input[i] <= '9') { + result += input[i]; + cap_next_letter = true; + } else { + cap_next_letter = true; + if (input[i] == '.' && preserve_period) { + result += '.'; + } + } + } + // Add a trailing "_" if the name should be altered. + if (input.size() > 0 && input[input.size() - 1] == '#') { + result += '_'; + } + + // https://github.com/protocolbuffers/protobuf/issues/8101 + // To avoid generating invalid identifiers - if the input string + // starts with _<digit> (or multiple underscores then digit) then + // we need to preserve the underscore as an identifier cannot start + // with a digit. + // This check is being done after the loop rather than before + // to handle the case where there are multiple underscores before the + // first digit. We let them all be consumed so we can see if we would + // start with a digit. + // Note: not preserving leading underscores for all otherwise valid identifiers + // so as to not break anything that relies on the existing behaviour + if (result.size() > 0 && ('0' <= result[0] && result[0] <= '9') + && input.size() > 0 && input[0] == '_') + { + result.insert(static_cast<size_t>(0), 1, '_'); + } + return result; +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/csharp/names.h b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/names.h new file mode 100644 index 00000000000..2adb32e5cd4 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/csharp/names.h @@ -0,0 +1,150 @@ +// 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: [email protected] (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// Provides a mechanism for mapping a descriptor to the +// fully-qualified name of the corresponding C# class. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ + +#include <string> +#include "util/generic/string.h" + +#include "y_absl/strings/string_view.h" +#include "google/protobuf/port_def.inc" + +using TProtoStringType = TString; + +namespace google { +namespace protobuf { + +class Descriptor; +class EnumDescriptor; +class FileDescriptor; +class ServiceDescriptor; + +namespace compiler { +namespace csharp { + +// Requires: +// descriptor != NULL +// +// Returns: +// The namespace to use for given file descriptor. +TProtoStringType PROTOC_EXPORT GetFileNamespace(const FileDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// +// Returns: +// The fully-qualified C# class name. +TProtoStringType PROTOC_EXPORT GetClassName(const Descriptor* descriptor); + +// Requires: +// descriptor != NULL +// +// Returns: +// The fully-qualified C# enum class name. +TProtoStringType GetClassName(const EnumDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// +// Returns: +// The unqualified name of the C# class that provides access to the file +// descriptor. Proto compiler generates +// such class for each .proto file processed. +TProtoStringType GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor); + +// Gets unqualified name of the extension class +// Requires: +// descriptor != NULL +// +// Returns: +// The unqualified name of the generated C# extensions class that provide +// access to extensions. Proto compiler generates such class for each +// .proto file processed that contains extensions. +TProtoStringType GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor); + +// Requires: +// descriptor != NULL +// +// Returns: +// 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. +TProtoStringType 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 +// namespace. base_namespace can be used to strip some of the top level +// directories. E.g. for file with namespace "Bar.Foo" and base_namespace="Bar", +// the resulting file will be put under directory "Foo" (and not "Bar/Foo"). +// +// Requires: +// descriptor != NULL +// error != NULL +// +// Returns: +// 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. +TProtoStringType PROTOC_EXPORT GetOutputFile(const FileDescriptor* descriptor, + y_absl::string_view file_extension, + bool generate_directories, + y_absl::string_view base_namespace, + TProtoStringType* error); + +TProtoStringType UnderscoresToPascalCase(y_absl::string_view 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. +TProtoStringType PROTOC_EXPORT UnderscoresToCamelCase(y_absl::string_view input, + bool cap_next_letter, + bool preserve_period); + +inline TProtoStringType UnderscoresToCamelCase(y_absl::string_view input, + bool cap_next_letter) { + return UnderscoresToCamelCase(input, cap_next_letter, false); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/importer.cc b/contrib/libs/protoc/src/google/protobuf/compiler/importer.cc index 80bb1270ef6..91f1caddb31 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/importer.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/importer.cc @@ -32,6 +32,8 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include "google/protobuf/compiler/importer.h" + #ifdef _MSC_VER #include <direct.h> #else @@ -44,13 +46,18 @@ #include <algorithm> #include <memory> - -#include <google/protobuf/compiler/importer.h> -#include <google/protobuf/compiler/parser.h> -#include <google/protobuf/io/tokenizer.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/io/io_win32.h> +#include <vector> + +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_join.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/compiler/parser.h" +#include "google/protobuf/io/io_win32.h" +#include "google/protobuf/io/tokenizer.h" +#include "google/protobuf/io/zero_copy_stream_impl.h" #ifdef _WIN32 #include <ctype.h> @@ -70,7 +77,7 @@ using google::protobuf::io::win32::open; // Returns true if the text looks like a Windows-style absolute path, starting // with a drive letter. Example: "C:\foo". TODO(kenton): Share this with // copy in command_line_interface.cc? -static bool IsWindowsAbsolutePath(const TProtoStringType& text) { +static bool IsWindowsAbsolutePath(y_absl::string_view text) { #if defined(_WIN32) || defined(__CYGWIN__) return text.size() >= 3 && text[1] == ':' && isalpha(text[0]) && (text[2] == '/' || text[2] == '\\') && text.find_last_of(':') == 1; @@ -98,9 +105,10 @@ class SourceTreeDescriptorDatabase::SingleFileErrorCollector bool had_errors() { return had_errors_; } // implements ErrorCollector --------------------------------------- - void AddError(int line, int column, const TProtoStringType& message) override { + void RecordError(int line, int column, y_absl::string_view message) override { if (multi_file_error_collector_ != nullptr) { - multi_file_error_collector_->AddError(filename_, line, column, message); + multi_file_error_collector_->RecordError(filename_, line, column, + message); } had_errors_ = true; } @@ -140,8 +148,8 @@ bool SourceTreeDescriptorDatabase::FindFileByName(const TProtoStringType& filena return true; } if (error_collector_ != nullptr) { - error_collector_->AddError(filename, -1, 0, - source_tree_->GetLastErrorMessage()); + error_collector_->RecordError(filename, -1, 0, + source_tree_->GetLastErrorMessage()); } return false; } @@ -183,10 +191,10 @@ SourceTreeDescriptorDatabase::ValidationErrorCollector:: SourceTreeDescriptorDatabase::ValidationErrorCollector:: ~ValidationErrorCollector() {} -void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddError( - const TProtoStringType& filename, const TProtoStringType& element_name, +void SourceTreeDescriptorDatabase::ValidationErrorCollector::RecordError( + y_absl::string_view filename, y_absl::string_view element_name, const Message* descriptor, ErrorLocation location, - const TProtoStringType& message) { + y_absl::string_view message) { if (owner_->error_collector_ == nullptr) return; int line, column; @@ -196,13 +204,13 @@ void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddError( } else { owner_->source_locations_.Find(descriptor, location, &line, &column); } - owner_->error_collector_->AddError(filename, line, column, message); + owner_->error_collector_->RecordError(filename, line, column, message); } -void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddWarning( - const TProtoStringType& filename, const TProtoStringType& element_name, +void SourceTreeDescriptorDatabase::ValidationErrorCollector::RecordWarning( + y_absl::string_view filename, y_absl::string_view element_name, const Message* descriptor, ErrorLocation location, - const TProtoStringType& message) { + y_absl::string_view message) { if (owner_->error_collector_ == nullptr) return; int line, column; @@ -212,7 +220,7 @@ void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddWarning( } else { owner_->source_locations_.Find(descriptor, location, &line, &column); } - owner_->error_collector_->AddWarning(filename, line, column, message); + owner_->error_collector_->RecordWarning(filename, line, column, message); } // =================================================================== @@ -251,10 +259,6 @@ DiskSourceTree::DiskSourceTree() {} DiskSourceTree::~DiskSourceTree() {} -static inline char LastChar(const TProtoStringType& str) { - return str[str.size() - 1]; -} - // Given a path, returns an equivalent path with these changes: // - On Windows, any backslashes are replaced with forward slashes. // - Any instances of the directory "." are removed. @@ -274,45 +278,39 @@ static inline char LastChar(const TProtoStringType& str) { // then if foo/bar is a symbolic link, foo/bar/baz.proto will canonicalize // to a path which does not appear to be under foo, and thus the compiler // will complain that baz.proto is not inside the --proto_path. -static TProtoStringType CanonicalizePath(TProtoStringType path) { +static TProtoStringType CanonicalizePath(y_absl::string_view path) { #ifdef _WIN32 // The Win32 API accepts forward slashes as a path delimiter even though // backslashes are standard. Let's avoid confusion and use only forward // slashes. - if (HasPrefixString(path, "\\\\")) { + TProtoStringType path_str; + if (y_absl::StartsWith(path, "\\\\")) { // Avoid converting two leading backslashes. - path = "\\\\" + StringReplace(path.substr(2), "\\", "/", true); + path_str = y_absl::StrCat("\\\\", + y_absl::StrReplaceAll(path.substr(2), {{"\\", "/"}})); } else { - path = StringReplace(path, "\\", "/", true); + path_str = y_absl::StrReplaceAll(path, {{"\\", "/"}}); } + path = path_str; #endif - std::vector<TProtoStringType> canonical_parts; - std::vector<TProtoStringType> parts = Split( - path, "/", true); // Note: Removes empty parts. - for (const TProtoStringType& part : parts) { + std::vector<y_absl::string_view> canonical_parts; + if (!path.empty() && path.front() == '/') canonical_parts.push_back(""); + for (y_absl::string_view part : y_absl::StrSplit(path, '/', y_absl::SkipEmpty())) { if (part == ".") { // Ignore. } else { canonical_parts.push_back(part); } } - TProtoStringType result = Join(canonical_parts, "/"); - if (!path.empty() && path[0] == '/') { - // Restore leading slash. - result = '/' + result; - } - if (!path.empty() && LastChar(path) == '/' && !result.empty() && - LastChar(result) != '/') { - // Restore trailing slash. - result += '/'; - } - return result; + if (!path.empty() && path.back() == '/') canonical_parts.push_back(""); + + return y_absl::StrJoin(canonical_parts, "/"); } -static inline bool ContainsParentReference(const TProtoStringType& path) { - return path == ".." || HasPrefixString(path, "../") || - HasSuffixString(path, "/..") || path.find("/../") != TProtoStringType::npos; +static inline bool ContainsParentReference(y_absl::string_view path) { + return path == ".." || y_absl::StartsWith(path, "../") || + y_absl::EndsWith(path, "/..") || y_absl::StrContains(path, "/../"); } // Maps a file from an old location to a new one. Typically, old_prefix is @@ -332,28 +330,28 @@ static inline bool ContainsParentReference(const TProtoStringType& path) { // assert(!ApplyMapping("foo/bar", "baz", "qux", &result)); // assert(!ApplyMapping("foo/bar", "baz", "qux", &result)); // assert(!ApplyMapping("foobar", "foo", "baz", &result)); -static bool ApplyMapping(const TProtoStringType& filename, - const TProtoStringType& old_prefix, - const TProtoStringType& new_prefix, TProtoStringType* result) { +static bool ApplyMapping(y_absl::string_view filename, + y_absl::string_view old_prefix, + y_absl::string_view new_prefix, TProtoStringType* result) { if (old_prefix.empty()) { // old_prefix matches any relative path. if (ContainsParentReference(filename)) { // We do not allow the file name to use "..". return false; } - if (HasPrefixString(filename, "/") || IsWindowsAbsolutePath(filename)) { + if (y_absl::StartsWith(filename, "/") || IsWindowsAbsolutePath(filename)) { // This is an absolute path, so it isn't matched by the empty string. return false; } - result->assign(new_prefix); + result->assign(TProtoStringType(new_prefix)); if (!result->empty()) result->push_back('/'); - result->append(filename); + result->append(TProtoStringType(filename)); return true; - } else if (HasPrefixString(filename, old_prefix)) { + } else if (y_absl::StartsWith(filename, old_prefix)) { // old_prefix is a prefix of the filename. Is it the whole filename? if (filename.size() == old_prefix.size()) { // Yep, it's an exact match. - *result = new_prefix; + *result = TProtoStringType(new_prefix); return true; } else { // Not an exact match. Is the next character a '/'? Otherwise, @@ -370,14 +368,14 @@ static bool ApplyMapping(const TProtoStringType& filename, if (after_prefix_start != -1) { // Yep. So the prefixes are directories and the filename is a file // inside them. - TProtoStringType after_prefix = filename.substr(after_prefix_start); + y_absl::string_view after_prefix = filename.substr(after_prefix_start); if (ContainsParentReference(after_prefix)) { // We do not allow the file name to use "..". return false; } - result->assign(new_prefix); + result->assign(TProtoStringType(new_prefix)); if (!result->empty()) result->push_back('/'); - result->append(after_prefix); + result->append(TProtoStringType(after_prefix)); return true; } } @@ -386,13 +384,14 @@ static bool ApplyMapping(const TProtoStringType& filename, return false; } -void DiskSourceTree::MapPath(const TProtoStringType& virtual_path, - const TProtoStringType& disk_path) { - mappings_.push_back(Mapping(virtual_path, CanonicalizePath(disk_path))); +void DiskSourceTree::MapPath(y_absl::string_view virtual_path, + y_absl::string_view disk_path) { + mappings_.push_back( + Mapping(TProtoStringType(virtual_path), CanonicalizePath(disk_path))); } DiskSourceTree::DiskFileToVirtualFileResult -DiskSourceTree::DiskFileToVirtualFile(const TProtoStringType& disk_file, +DiskSourceTree::DiskFileToVirtualFile(y_absl::string_view disk_file, TProtoStringType* virtual_file, TProtoStringType* shadowing_disk_file) { int mapping_index = -1; @@ -436,7 +435,7 @@ DiskSourceTree::DiskFileToVirtualFile(const TProtoStringType& disk_file, return SUCCESS; } -bool DiskSourceTree::VirtualFileToDiskFile(const TProtoStringType& virtual_file, +bool DiskSourceTree::VirtualFileToDiskFile(y_absl::string_view virtual_file, TProtoStringType* disk_file) { std::unique_ptr<io::ZeroCopyInputStream> stream( OpenVirtualFile(virtual_file, disk_file)); @@ -452,7 +451,7 @@ TProtoStringType DiskSourceTree::GetLastErrorMessage() { } io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( - const TProtoStringType& virtual_file, TProtoStringType* disk_file) { + y_absl::string_view virtual_file, TProtoStringType* disk_file) { if (virtual_file != CanonicalizePath(virtual_file) || ContainsParentReference(virtual_file)) { // We do not allow importing of paths containing things like ".." or @@ -479,7 +478,7 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( if (errno == EACCES) { // The file exists but is not readable. last_error_message_ = - "Read access is denied for file: " + temp_disk_file; + y_absl::StrCat("Read access is denied for file: ", temp_disk_file); return nullptr; } } @@ -489,11 +488,11 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( } io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile( - const TProtoStringType& filename) { + y_absl::string_view filename) { struct stat sb; int ret = 0; do { - ret = stat(filename.c_str(), &sb); + ret = stat(TProtoStringType(filename).c_str(), &sb); } while (ret != 0 && errno == EINTR); #if defined(_WIN32) if (ret == 0 && sb.st_mode & S_IFDIR) { @@ -508,7 +507,7 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile( #endif int file_descriptor; do { - file_descriptor = open(filename.c_str(), O_RDONLY); + file_descriptor = open(TProtoStringType(filename).c_str(), O_RDONLY); } while (file_descriptor < 0 && errno == EINTR); if (file_descriptor >= 0) { io::FileInputStream* result = new io::FileInputStream(file_descriptor); diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/importer.h b/contrib/libs/protoc/src/google/protobuf/compiler/importer.h index c13821a2430..64cbdb0d230 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/importer.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/importer.h @@ -37,17 +37,17 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__ #define GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__ -#include <set> #include <string> #include <utility> #include <vector> -#include <google/protobuf/compiler/parser.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor_database.h> +#include "y_absl/strings/string_view.h" +#include "google/protobuf/compiler/parser.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor_database.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -129,14 +129,14 @@ class PROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase { ~ValidationErrorCollector() override; // implements ErrorCollector --------------------------------------- - void AddError(const TProtoStringType& filename, const TProtoStringType& element_name, - const Message* descriptor, ErrorLocation location, - const TProtoStringType& message) override; + void RecordError(y_absl::string_view filename, y_absl::string_view element_name, + const Message* descriptor, ErrorLocation location, + y_absl::string_view message) override; - void AddWarning(const TProtoStringType& filename, - const TProtoStringType& element_name, const Message* descriptor, - ErrorLocation location, - const TProtoStringType& message) override; + void RecordWarning(y_absl::string_view filename, + y_absl::string_view element_name, + const Message* descriptor, ErrorLocation location, + y_absl::string_view message) override; private: SourceTreeDescriptorDatabase* owner_; @@ -159,6 +159,8 @@ class PROTOBUF_EXPORT SourceTreeDescriptorDatabase : public DescriptorDatabase { class PROTOBUF_EXPORT Importer { public: Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector); + Importer(const Importer&) = delete; + Importer& operator=(const Importer&) = delete; ~Importer(); // Import the given file and build a FileDescriptor representing it. If @@ -188,27 +190,43 @@ class PROTOBUF_EXPORT Importer { private: SourceTreeDescriptorDatabase database_; DescriptorPool pool_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Importer); }; // If the importer encounters problems while trying to import the proto files, // it reports them to a MultiFileErrorCollector. class PROTOBUF_EXPORT MultiFileErrorCollector { public: - inline MultiFileErrorCollector() {} + MultiFileErrorCollector() {} + MultiFileErrorCollector(const MultiFileErrorCollector&) = delete; + MultiFileErrorCollector& operator=(const MultiFileErrorCollector&) = delete; 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 RecordError(y_absl::string_view filename, int line, int column, + y_absl::string_view message) { + PROTOBUF_IGNORE_DEPRECATION_START + AddError(TProtoStringType(filename), line, column, TProtoStringType(message)); + PROTOBUF_IGNORE_DEPRECATION_STOP + } + virtual void RecordWarning(y_absl::string_view filename, int line, int column, + y_absl::string_view message) { + PROTOBUF_IGNORE_DEPRECATION_START + AddWarning(TProtoStringType(filename), line, column, TProtoStringType(message)); + PROTOBUF_IGNORE_DEPRECATION_STOP + } + + // These should never be called directly, but if a legacy class overrides + // them they'll get routed to by the Record* methods. + virtual void AddError(const TProtoStringType& filename, int line, int column, - const TProtoStringType& message) = 0; + const TProtoStringType& message) { + Y_ABSL_LOG(FATAL) << "AddError or RecordError must be implemented."; + } - virtual void AddWarning(const TProtoStringType& /* filename */, int /* line */, - int /* column */, const TProtoStringType& /* message */) {} - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector); + virtual void AddWarning(const TProtoStringType& filename, int line, int column, + const TProtoStringType& message) {} }; // Abstract interface which represents a directory tree containing proto files. @@ -217,7 +235,9 @@ class PROTOBUF_EXPORT MultiFileErrorCollector { // below. class PROTOBUF_EXPORT SourceTree { public: - inline SourceTree() {} + SourceTree() {} + SourceTree(const SourceTree&) = delete; + SourceTree& operator=(const SourceTree&) = delete; virtual ~SourceTree(); // Open the given file and return a stream that reads it, or NULL if not @@ -232,9 +252,6 @@ class PROTOBUF_EXPORT SourceTree { // better error reporting. // TODO(xiaofeng): change this to a pure virtual function. virtual TProtoStringType GetLastErrorMessage(); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree); }; // An implementation of SourceTree which loads files from locations on disk. @@ -243,6 +260,8 @@ class PROTOBUF_EXPORT SourceTree { class PROTOBUF_EXPORT DiskSourceTree : public SourceTree { public: DiskSourceTree(); + DiskSourceTree(const DiskSourceTree&) = delete; + DiskSourceTree& operator=(const DiskSourceTree&) = delete; ~DiskSourceTree() override; // Map a path on disk to a location in the SourceTree. The path may be @@ -261,7 +280,7 @@ class PROTOBUF_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 TProtoStringType& virtual_path, const TProtoStringType& disk_path); + void MapPath(y_absl::string_view virtual_path, y_absl::string_view disk_path); // Return type for DiskFileToVirtualFile(). enum DiskFileToVirtualFileResult { @@ -292,13 +311,13 @@ class PROTOBUF_EXPORT DiskSourceTree : public SourceTree { // * NO_MAPPING: Indicates that no mapping was found which contains this // file. DiskFileToVirtualFileResult DiskFileToVirtualFile( - const TProtoStringType& disk_file, TProtoStringType* virtual_file, + y_absl::string_view disk_file, TProtoStringType* virtual_file, TProtoStringType* 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 TProtoStringType& virtual_file, + bool VirtualFileToDiskFile(y_absl::string_view virtual_file, TProtoStringType* disk_file); // implements SourceTree ------------------------------------------- @@ -311,28 +330,26 @@ class PROTOBUF_EXPORT DiskSourceTree : public SourceTree { TProtoStringType virtual_path; TProtoStringType disk_path; - inline Mapping(const TProtoStringType& virtual_path_param, - const TProtoStringType& disk_path_param) - : virtual_path(virtual_path_param), disk_path(disk_path_param) {} + inline Mapping(TProtoStringType virtual_path_param, TProtoStringType disk_path_param) + : virtual_path(std::move(virtual_path_param)), + disk_path(std::move(disk_path_param)) {} }; std::vector<Mapping> mappings_; TProtoStringType 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 TProtoStringType& virtual_file, + io::ZeroCopyInputStream* OpenVirtualFile(y_absl::string_view virtual_file, TProtoStringType* disk_file); // Like Open() but given the actual on-disk path. - io::ZeroCopyInputStream* OpenDiskFile(const TProtoStringType& filename); - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DiskSourceTree); + io::ZeroCopyInputStream* OpenDiskFile(y_absl::string_view filename); }; } // namespace compiler } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/context.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/context.cc index 463aa1f5abc..839fb6e2f59 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/context.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/context.cc @@ -28,14 +28,18 @@ // (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/java/context.h> +#include "google/protobuf/compiler/java/context.h" -#include <google/protobuf/descriptor.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/field.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/stubs/map_util.h> +#include <string> + +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/strip.h" +#include "google/protobuf/compiler/java/field.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.h" namespace google { namespace protobuf { @@ -43,7 +47,7 @@ namespace compiler { namespace java { Context::Context(const FileDescriptor* file, const Options& options) - : name_resolver_(new ClassNameResolver), options_(options) { + : name_resolver_(new ClassNameResolver(options)), options_(options) { InitializeFieldGeneratorInfo(file); } @@ -54,11 +58,17 @@ ClassNameResolver* Context::GetNameResolver() const { } namespace { +bool EqualWithSuffix(y_absl::string_view name1, y_absl::string_view suffix, + y_absl::string_view name2) { + if (!y_absl::ConsumeSuffix(&name2, suffix)) return false; + return name1 == name2; +} + // Whether two fields have conflicting accessors (assuming name1 and name2 // are different). name1 and name2 are field1 and field2's camel-case name // respectively. -bool IsConflicting(const FieldDescriptor* field1, const TProtoStringType& name1, - const FieldDescriptor* field2, const TProtoStringType& name2, +bool IsConflicting(const FieldDescriptor* field1, y_absl::string_view name1, + const FieldDescriptor* field2, y_absl::string_view name2, TProtoStringType* info) { if (field1->is_repeated()) { if (field2->is_repeated()) { @@ -66,16 +76,18 @@ bool IsConflicting(const FieldDescriptor* field1, const TProtoStringType& name1, return false; } else { // field1 is repeated, and field2 is not. - if (name1 + "Count" == name2) { - *info = "both repeated field \"" + field1->name() + "\" and singular " + - "field \"" + field2->name() + "\" generate the method \"" + - "get" + name1 + "Count()\""; + if (EqualWithSuffix(name1, "Count", name2)) { + *info = y_absl::StrCat("both repeated field \"", field1->name(), + "\" and singular ", "field \"", field2->name(), + "\" generate the method \"", "get", name1, + "Count()\""); return true; } - if (name1 + "List" == name2) { - *info = "both repeated field \"" + field1->name() + "\" and singular " + - "field \"" + field2->name() + "\" generate the method \"" + - "get" + name1 + "List()\""; + if (EqualWithSuffix(name1, "List", name2)) { + *info = + y_absl::StrCat("both repeated field \"", field1->name(), + "\" and singular ", "field \"", field2->name(), + "\" generate the method \"", "get", name1, "List()\""); return true; } // Well, there are obviously many more conflicting cases, but it probably @@ -131,15 +143,15 @@ void Context::InitializeFieldGeneratorInfoForFields( std::vector<TProtoStringType> conflict_reason(fields.size()); for (int i = 0; i < fields.size(); ++i) { const FieldDescriptor* field = fields[i]; - const TProtoStringType& name = UnderscoresToCapitalizedCamelCase(field); + const TProtoStringType& name = CapitalizedFieldName(field); for (int j = i + 1; j < fields.size(); ++j) { const FieldDescriptor* other = fields[j]; - const TProtoStringType& other_name = UnderscoresToCapitalizedCamelCase(other); + const TProtoStringType& other_name = CapitalizedFieldName(other); if (name == other_name) { is_conflict[i] = is_conflict[j] = true; conflict_reason[i] = conflict_reason[j] = - "capitalized name of field \"" + field->name() + - "\" conflicts with field \"" + other->name() + "\""; + y_absl::StrCat("capitalized name of field \"", field->name(), + "\" conflicts with field \"", other->name(), "\""); } else if (IsConflicting(field, name, other, other_name, &conflict_reason[j])) { is_conflict[i] = is_conflict[j] = true; @@ -147,20 +159,21 @@ void Context::InitializeFieldGeneratorInfoForFields( } } if (is_conflict[i]) { - GOOGLE_LOG(WARNING) << "field \"" << field->full_name() << "\" is conflicting " - << "with another field: " << conflict_reason[i]; + Y_ABSL_LOG(WARNING) << "field \"" << field->full_name() + << "\" is conflicting " + << "with another field: " << conflict_reason[i]; } } for (int i = 0; i < fields.size(); ++i) { const FieldDescriptor* field = fields[i]; FieldGeneratorInfo info; info.name = CamelCaseFieldName(field); - info.capitalized_name = UnderscoresToCapitalizedCamelCase(field); + info.capitalized_name = CapitalizedFieldName(field); // For fields conflicting with some other fields, we append the field // number to their field names in generated code to avoid conflicts. if (is_conflict[i]) { - info.name += StrCat(field->number()); - info.capitalized_name += StrCat(field->number()); + y_absl::StrAppend(&info.name, field->number()); + y_absl::StrAppend(&info.capitalized_name, field->number()); info.disambiguated_reason = conflict_reason[i]; } field_generator_info_map_[field] = info; @@ -169,24 +182,22 @@ void Context::InitializeFieldGeneratorInfoForFields( const FieldGeneratorInfo* Context::GetFieldGeneratorInfo( const FieldDescriptor* field) const { - const FieldGeneratorInfo* result = - FindOrNull(field_generator_info_map_, field); - if (result == NULL) { - GOOGLE_LOG(FATAL) << "Can not find FieldGeneratorInfo for field: " - << field->full_name(); + auto it = field_generator_info_map_.find(field); + if (it == field_generator_info_map_.end()) { + Y_ABSL_LOG(FATAL) << "Can not find FieldGeneratorInfo for field: " + << field->full_name(); } - return result; + return &it->second; } const OneofGeneratorInfo* Context::GetOneofGeneratorInfo( const OneofDescriptor* oneof) const { - const OneofGeneratorInfo* result = - FindOrNull(oneof_generator_info_map_, oneof); - if (result == NULL) { - GOOGLE_LOG(FATAL) << "Can not find OneofGeneratorInfo for oneof: " - << oneof->name(); + auto it = oneof_generator_info_map_.find(oneof); + if (it == oneof_generator_info_map_.end()) { + Y_ABSL_LOG(FATAL) << "Can not find OneofGeneratorInfo for oneof: " + << oneof->name(); } - return result; + return &it->second; } // Does this message class have generated parsing, serialization, and other diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/context.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/context.h index c224ab73f5e..57b994a8e33 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/context.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/context.h @@ -31,12 +31,13 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ -#include <map> #include <memory> #include <vector> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/java/options.h> +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/options.h" +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -65,6 +66,8 @@ struct OneofGeneratorInfo; class Context { public: Context(const FileDescriptor* file, const Options& options); + Context(const Context&) = delete; + Context& operator=(const Context&) = delete; ~Context(); // Get the name resolver associated with this context. The resolver @@ -97,14 +100,27 @@ class Context { const std::vector<const FieldDescriptor*>& fields); std::unique_ptr<ClassNameResolver> name_resolver_; - std::map<const FieldDescriptor*, FieldGeneratorInfo> + y_absl::flat_hash_map<const FieldDescriptor*, FieldGeneratorInfo> field_generator_info_map_; - std::map<const OneofDescriptor*, OneofGeneratorInfo> + y_absl::flat_hash_map<const OneofDescriptor*, OneofGeneratorInfo> oneof_generator_info_map_; Options options_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context); }; +template <typename Descriptor> +void MaybePrintGeneratedAnnotation(Context* context, io::Printer* printer, + Descriptor* descriptor, bool immutable, + const TProtoStringType& suffix = "") { + if (IsOwnFile(descriptor, immutable)) { + PrintGeneratedAnnotation(printer, '$', + context->options().annotate_code + ? AnnotationFileName(descriptor, suffix) + : "", + context->options()); + } +} + + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/doc_comment.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/doc_comment.cc index ec7dce7d34e..74fb087ccf8 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/doc_comment.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/doc_comment.cc @@ -32,13 +32,14 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/doc_comment.h> +#include "google/protobuf/compiler/java/doc_comment.h" #include <vector> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/strings/str_split.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -103,26 +104,65 @@ TProtoStringType EscapeJavadoc(const TProtoStringType& input) { return result; } +static TProtoStringType EscapeKdoc(const TProtoStringType& input) { + TProtoStringType result; + result.reserve(input.size() * 2); + + char prev = 'a'; + + for (char c : input) { + switch (c) { + case '*': + // Avoid "/*". + if (prev == '/') { + result.append("*"); + } else { + result.push_back(c); + } + break; + case '/': + // Avoid "*/". + if (prev == '*') { + result.append("/"); + } else { + result.push_back(c); + } + break; + default: + result.push_back(c); + break; + } + + prev = c; + } + + return result; +} + static void WriteDocCommentBodyForLocation(io::Printer* printer, - const SourceLocation& location) { + const SourceLocation& location, + const bool kdoc) { TProtoStringType comments = location.leading_comments.empty() ? location.trailing_comments : location.leading_comments; if (!comments.empty()) { - // TODO(kenton): Ideally we should parse the comment text as Markdown and - // write it back as HTML, but this requires a Markdown parser. For now - // we just use <pre> to get fixed-width text formatting. - - // If the comment itself contains block comment start or end markers, - // HTML-escape them so that they don't accidentally close the doc comment. - comments = EscapeJavadoc(comments); + if (kdoc) { + comments = EscapeKdoc(comments); + } else { + comments = EscapeJavadoc(comments); + } - std::vector<TProtoStringType> lines = Split(comments, "\n"); + std::vector<TProtoStringType> lines = y_absl::StrSplit(comments, "\n"); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } - printer->Print(" * <pre>\n"); + if (kdoc) { + printer->Print(" * ```\n"); + } else { + printer->Print(" * <pre>\n"); + } + for (int i = 0; i < lines.size(); i++) { // Most lines should start with a space. Watch out for lines that start // with a /, since putting that right after the leading asterisk will @@ -133,18 +173,23 @@ static void WriteDocCommentBodyForLocation(io::Printer* printer, printer->Print(" *$line$\n", "line", lines[i]); } } - printer->Print( - " * </pre>\n" - " *\n"); + + if (kdoc) { + printer->Print(" * ```\n"); + } else { + printer->Print(" * </pre>\n"); + } + printer->Print(" *\n"); } } template <typename DescriptorType> static void WriteDocCommentBody(io::Printer* printer, - const DescriptorType* descriptor) { + const DescriptorType* descriptor, + const bool kdoc) { SourceLocation location; if (descriptor->GetSourceLocation(&location)) { - WriteDocCommentBodyForLocation(printer, location); + WriteDocCommentBodyForLocation(printer, location, kdoc); } } @@ -164,16 +209,36 @@ static TProtoStringType FirstLineOf(const TProtoStringType& value) { return result; } -void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) { +static void WriteDebugString(io::Printer* printer, const FieldDescriptor* field, + const bool kdoc) { + if (kdoc) { + printer->Print(" * `$def$`\n", "def", + EscapeKdoc(FirstLineOf(field->DebugString()))); + } else { + printer->Print(" * <code>$def$</code>\n", "def", + EscapeJavadoc(FirstLineOf(field->DebugString()))); + } +} + +void WriteMessageDocComment(io::Printer* printer, const Descriptor* message, + const bool kdoc) { printer->Print("/**\n"); - WriteDocCommentBody(printer, message); - printer->Print( - " * Protobuf type {@code $fullname$}\n" - " */\n", - "fullname", EscapeJavadoc(message->full_name())); + WriteDocCommentBody(printer, message, kdoc); + if (kdoc) { + printer->Print( + " * Protobuf type `$fullname$`\n" + " */\n", + "fullname", EscapeKdoc(message->full_name())); + } else { + printer->Print( + " * Protobuf type {@code $fullname$}\n" + " */\n", + "fullname", EscapeJavadoc(message->full_name())); + } } -void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) { +void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field, + const bool kdoc) { // We start the comment with the main body based on the comments from the // .proto file (if present). We then continue with the field declaration, // e.g.: @@ -181,9 +246,14 @@ void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) { // And then we end with the javadoc tags if applicable. // If the field is a group, the debug string might end with {. printer->Print("/**\n"); - WriteDocCommentBody(printer, field); - printer->Print(" * <code>$def$</code>\n", "def", - EscapeJavadoc(FirstLineOf(field->DebugString()))); + WriteDocCommentBody(printer, field, kdoc); + if (kdoc) { + printer->Print(" * `$def$`\n", "def", + EscapeKdoc(FirstLineOf(field->DebugString()))); + } else { + printer->Print(" * <code>$def$</code>\n", "def", + EscapeJavadoc(FirstLineOf(field->DebugString()))); + } printer->Print(" */\n"); } @@ -214,12 +284,11 @@ void WriteDeprecatedJavadoc(io::Printer* printer, const FieldDescriptor* field, void WriteFieldAccessorDocComment(io::Printer* printer, const FieldDescriptor* field, const FieldAccessorType type, - const bool builder) { + const bool builder, const bool kdoc) { printer->Print("/**\n"); - WriteDocCommentBody(printer, field); - printer->Print(" * <code>$def$</code>\n", "def", - EscapeJavadoc(FirstLineOf(field->DebugString()))); - WriteDeprecatedJavadoc(printer, field, type); + WriteDocCommentBody(printer, field, kdoc); + WriteDebugString(printer, field, kdoc); + if (!kdoc) WriteDeprecatedJavadoc(printer, field, type); switch (type) { case HAZZER: printer->Print(" * @return Whether the $name$ field is set.\n", "name", @@ -273,12 +342,12 @@ void WriteFieldAccessorDocComment(io::Printer* printer, void WriteFieldEnumValueAccessorDocComment(io::Printer* printer, const FieldDescriptor* field, const FieldAccessorType type, - const bool builder) { + const bool builder, + const bool kdoc) { printer->Print("/**\n"); - WriteDocCommentBody(printer, field); - printer->Print(" * <code>$def$</code>\n", "def", - EscapeJavadoc(FirstLineOf(field->DebugString()))); - WriteDeprecatedJavadoc(printer, field, type); + WriteDocCommentBody(printer, field, kdoc); + WriteDebugString(printer, field, kdoc); + if (!kdoc) WriteDeprecatedJavadoc(printer, field, type); switch (type) { case HAZZER: // Should never happen @@ -343,12 +412,12 @@ void WriteFieldEnumValueAccessorDocComment(io::Printer* printer, void WriteFieldStringBytesAccessorDocComment(io::Printer* printer, const FieldDescriptor* field, const FieldAccessorType type, - const bool builder) { + const bool builder, + const bool kdoc) { printer->Print("/**\n"); - WriteDocCommentBody(printer, field); - printer->Print(" * <code>$def$</code>\n", "def", - EscapeJavadoc(FirstLineOf(field->DebugString()))); - WriteDeprecatedJavadoc(printer, field, type); + WriteDocCommentBody(printer, field, kdoc); + WriteDebugString(printer, field, kdoc); + if (!kdoc) WriteDeprecatedJavadoc(printer, field, type); switch (type) { case HAZZER: // Should never happen @@ -399,19 +468,28 @@ void WriteFieldStringBytesAccessorDocComment(io::Printer* printer, // Enum -void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) { +void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_, + const bool kdoc) { printer->Print("/**\n"); - WriteDocCommentBody(printer, enum_); - printer->Print( - " * Protobuf enum {@code $fullname$}\n" - " */\n", - "fullname", EscapeJavadoc(enum_->full_name())); + WriteDocCommentBody(printer, enum_, kdoc); + if (kdoc) { + printer->Print( + " * Protobuf enum `$fullname$`\n" + " */\n", + "fullname", EscapeKdoc(enum_->full_name())); + } else { + printer->Print( + " * Protobuf enum {@code $fullname$}\n" + " */\n", + "fullname", EscapeJavadoc(enum_->full_name())); + } } void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value) { printer->Print("/**\n"); - WriteDocCommentBody(printer, value); + WriteDocCommentBody(printer, value, /* kdoc */ false); + printer->Print( " * <code>$def$</code>\n" " */\n", @@ -421,7 +499,7 @@ void WriteEnumValueDocComment(io::Printer* printer, void WriteServiceDocComment(io::Printer* printer, const ServiceDescriptor* service) { printer->Print("/**\n"); - WriteDocCommentBody(printer, service); + WriteDocCommentBody(printer, service, /* kdoc */ false); printer->Print( " * Protobuf service {@code $fullname$}\n" " */\n", @@ -431,7 +509,7 @@ void WriteServiceDocComment(io::Printer* printer, void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method) { printer->Print("/**\n"); - WriteDocCommentBody(printer, method); + WriteDocCommentBody(printer, method, /* kdoc */ false); printer->Print( " * <code>$def$</code>\n" " */\n", diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/doc_comment.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/doc_comment.h index 52d6f774745..2c8ecc4047e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/doc_comment.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/doc_comment.h @@ -35,10 +35,10 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ -#include <google/protobuf/descriptor.h> +#include "google/protobuf/descriptor.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -67,21 +67,27 @@ enum FieldAccessorType { LIST_MULTI_ADDER }; -void WriteMessageDocComment(io::Printer* printer, const Descriptor* message); -void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field); +void WriteMessageDocComment(io::Printer* printer, const Descriptor* message, + const bool kdoc = false); +void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field, + const bool kdoc = false); void WriteFieldAccessorDocComment(io::Printer* printer, const FieldDescriptor* field, const FieldAccessorType type, - const bool builder = false); + const bool builder = false, + const bool kdoc = false); void WriteFieldEnumValueAccessorDocComment(io::Printer* printer, const FieldDescriptor* field, const FieldAccessorType type, - const bool builder = false); + const bool builder = false, + const bool kdoc = false); void WriteFieldStringBytesAccessorDocComment(io::Printer* printer, const FieldDescriptor* field, const FieldAccessorType type, - const bool builder = false); -void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_); + const bool builder = false, + const bool kdoc = false); +void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_, + const bool kdoc = false); void WriteEnumValueDocComment(io::Printer* printer, const EnumValueDescriptor* value); void WriteServiceDocComment(io::Printer* printer, @@ -90,6 +96,7 @@ void WriteMethodDocComment(io::Printer* printer, const MethodDescriptor* method); // Exposed for testing only. +// Also called by proto1-Java code generator. PROTOC_EXPORT TProtoStringType EscapeJavadoc(const TProtoStringType& input); } // namespace java @@ -97,6 +104,6 @@ PROTOC_EXPORT TProtoStringType EscapeJavadoc(const TProtoStringType& input); } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum.cc index 5ba5e630c05..000cd54882b 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum.cc @@ -32,21 +32,21 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/enum.h> +#include "google/protobuf/compiler/java/enum.h" -#include <map> #include <string> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -80,6 +80,10 @@ EnumGenerator::~EnumGenerator() {} void EnumGenerator::Generate(io::Printer* printer) { WriteEnumDocComment(printer, descriptor_); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_); + + if (!context_->options().opensource_runtime) { + printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n"); + } printer->Print( "$deprecation$public enum $classname$\n" " implements com.google.protobuf.ProtocolMessageEnum {\n", @@ -99,10 +103,10 @@ void EnumGenerator::Generate(io::Printer* printer) { } for (int i = 0; i < canonical_values_.size(); i++) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["name"] = canonical_values_[i]->name(); - vars["index"] = StrCat(canonical_values_[i]->index()); - vars["number"] = StrCat(canonical_values_[i]->number()); + vars["index"] = y_absl::StrCat(canonical_values_[i]->index()); + vars["number"] = y_absl::StrCat(canonical_values_[i]->number()); WriteEnumValueDocComment(printer, canonical_values_[i]); if (canonical_values_[i]->options().deprecated()) { printer->Print("@java.lang.Deprecated\n"); @@ -131,7 +135,7 @@ void EnumGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- for (int i = 0; i < aliases_.size(); i++) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["classname"] = descriptor_->name(); vars["name"] = aliases_[i].value->name(); vars["canonical_name"] = aliases_[i].canonical_value->name(); @@ -142,9 +146,9 @@ void EnumGenerator::Generate(io::Printer* printer) { } for (int i = 0; i < descriptor_->value_count(); i++) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["name"] = descriptor_->value(i)->name(); - vars["number"] = StrCat(descriptor_->value(i)->number()); + vars["number"] = y_absl::StrCat(descriptor_->value(i)->number()); vars["{"] = ""; vars["}"] = ""; vars["deprecation"] = descriptor_->value(i)->options().deprecated() @@ -181,23 +185,32 @@ void EnumGenerator::Generate(io::Printer* printer) { printer->Print( " return value;\n" "}\n" - "\n" - "/**\n" - " * @param value The numeric wire value of the corresponding enum " - "entry.\n" - " * @return The enum associated with the given numeric wire value.\n" - " * @deprecated Use {@link #forNumber(int)} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public static $classname$ valueOf(int value) {\n" - " return forNumber(value);\n" - "}\n" - "\n" + "\n"); + if (context_->options().opensource_runtime) { + printer->Print( + "/**\n" + " * @param value The numeric wire value of the corresponding enum " + "entry.\n" + " * @return The enum associated with the given numeric wire value.\n" + " * @deprecated Use {@link #forNumber(int)} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public static $classname$ valueOf(int value) {\n" + " return forNumber(value);\n" + "}\n" + "\n", + "classname", descriptor_->name()); + } + printer->Print( "/**\n" " * @param value The numeric wire value of the corresponding enum " "entry.\n" " * @return The enum associated with the given numeric wire value.\n" - " */\n" + " */\n"); + if (!context_->options().opensource_runtime) { + printer->Print("@com.google.protobuf.Internal.ProtoMethodMayReturnNull\n"); + } + printer->Print( "public static $classname$ forNumber(int value) {\n" " switch (value) {\n", "classname", descriptor_->name()); @@ -207,7 +220,7 @@ void EnumGenerator::Generate(io::Printer* printer) { for (int i = 0; i < canonical_values_.size(); i++) { printer->Print("case $number$: return $name$;\n", "name", canonical_values_[i]->name(), "number", - StrCat(canonical_values_[i]->number())); + y_absl::StrCat(canonical_values_[i]->number())); } printer->Outdent(); @@ -277,7 +290,7 @@ void EnumGenerator::Generate(io::Printer* printer) { " return $file$.getDescriptor().getEnumTypes().get($index$);\n", "file", name_resolver_->GetClassName(descriptor_->file(), immutable_api_), - "index", StrCat(descriptor_->index())); + "index", y_absl::StrCat(descriptor_->index())); } else { printer->Print( " return $parent$.$descriptor$.getEnumTypes().get($index$);\n", @@ -290,7 +303,7 @@ void EnumGenerator::Generate(io::Printer* printer) { .no_standard_descriptor_accessor() ? "getDefaultInstance().getDescriptorForType()" : "getDescriptor()", - "index", StrCat(descriptor_->index())); + "index", y_absl::StrCat(descriptor_->index())); } printer->Print( @@ -394,4 +407,4 @@ bool EnumGenerator::CanUseEnumValues() { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum.h index 0a2c363b533..ae85b0c34c6 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum.h @@ -37,7 +37,8 @@ #include <string> #include <vector> -#include <google/protobuf/descriptor.h> + +#include "google/protobuf/descriptor.h" namespace google { namespace protobuf { @@ -62,6 +63,8 @@ class EnumGenerator { public: EnumGenerator(const EnumDescriptor* descriptor, bool immutable_api, Context* context); + EnumGenerator(const EnumGenerator&) = delete; + EnumGenerator& operator=(const EnumGenerator&) = delete; ~EnumGenerator(); void Generate(io::Printer* printer); @@ -88,8 +91,6 @@ class EnumGenerator { ClassNameResolver* name_resolver_; bool CanUseEnumValues(); - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field.cc index 97e1742cc90..33ed3ae00fa 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field.cc @@ -32,24 +32,24 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/enum_field.h> +#include "google/protobuf/compiler/java/enum_field.h" #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -58,62 +58,51 @@ namespace java { namespace { -void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetEnumVariables( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables, + Context* context) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["type"] = name_resolver->GetImmutableClassName(descriptor->enum_type()); - (*variables)["kt_type"] = (*variables)["type"]; + variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])}); (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->enum_type()); - (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default"] = + ImmutableDefaultValue(descriptor, name_resolver, context->options()); (*variables)["default_number"] = - StrCat(descriptor->default_value_enum()->number()); - (*variables)["tag"] = StrCat( + y_absl::StrCat(descriptor->default_value_enum()->number()); + (*variables)["tag"] = y_absl::StrCat( static_cast<arc_i32>(internal::WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = StrCat( + (*variables)["tag_size"] = y_absl::StrCat( internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["kt_deprecation"] = - descriptor->options().deprecated() - ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + - " is deprecated\") " - : ""; - (*variables)["on_changed"] = "onChanged();"; - // Use deprecated valueOf() method to be compatible with old generated code - // for v2.5.0/v2.6.1. - // TODO(xiaofeng): Use "forNumber" when we no longer support compatibility - // with v2.5.0/v2.6.1, and remove the @SuppressWarnings annotations. - (*variables)["for_number"] = "valueOf"; - + variables->insert( + {"kt_deprecation", + descriptor->options().deprecated() + ? y_absl::StrCat("@kotlin.Deprecated(message = \"Field ", + (*variables)["name"], " is deprecated\") ") + : ""}); if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; - (*variables)["set_has_field_bit_builder"] = - GenerateSetBit(builderBitIndex) + ";"; - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex) + ";"; - + y_absl::StrCat(GenerateSetBit(messageBitIndex), ";"); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); } else { (*variables)["set_has_field_bit_message"] = ""; - (*variables)["set_has_field_bit_builder"] = ""; - (*variables)["clear_has_field_bit_builder"] = ""; - - (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != " + (*variables)["default"] + - ".getNumber()"; + (*variables)["set_has_field_bit_to_local"] = ""; + variables->insert({"is_field_present_message", + y_absl::StrCat((*variables)["name"], "_ != ", + (*variables)["default"], ".getNumber()")}); } // For repeated builders, one bit is used for whether the array is immutable. @@ -121,22 +110,21 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); - // For repeated fields, one bit is used for whether the array is immutable - // in the parsing constructor. - (*variables)["get_mutable_bit_parser"] = - GenerateGetBitMutableLocal(builderBitIndex); - (*variables)["set_mutable_bit_parser"] = - GenerateSetBitMutableLocal(builderBitIndex); + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_builder"] = + y_absl::StrCat(GenerateSetBit(builderBitIndex), ";"); + (*variables)["clear_has_field_bit_builder"] = + y_absl::StrCat(GenerateClearBit(builderBitIndex), ";"); (*variables)["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(builderBitIndex); - (*variables)["set_has_field_bit_to_local"] = - GenerateSetBitToLocal(messageBitIndex); if (SupportUnknownEnumValue(descriptor->file())) { - (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED"; + variables->insert( + {"unknown", y_absl::StrCat((*variables)["type"], ".UNRECOGNIZED")}); } else { - (*variables)["unknown"] = (*variables)["default"]; + variables->insert({"unknown", (*variables)["default"]}); } } @@ -147,21 +135,30 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, ImmutableEnumFieldGenerator::ImmutableEnumFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), + message_bit_index_(messageBitIndex), + builder_bit_index_(builderBitIndex), + name_resolver_(context->GetNameResolver()) { SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), name_resolver_, - &variables_); + &variables_, context); } ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {} +int ImmutableEnumFieldGenerator::GetMessageBitIndex() const { + return message_bit_index_; +} + +int ImmutableEnumFieldGenerator::GetBuilderBitIndex() const { + return builder_bit_index_; +} + int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const { return HasHasbit(descriptor_) ? 1 : 0; } -int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { - return GetNumBitsForMessage(); -} +int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { return 1; } void ImmutableEnumFieldGenerator::GenerateInterfaceMembers( io::Printer* printer) const { @@ -180,7 +177,7 @@ void ImmutableEnumFieldGenerator::GenerateInterfaceMembers( } void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const { - printer->Print(variables_, "private int $name$_;\n"); + printer->Print(variables_, "private int $name$_ = $default_number$;\n"); PrintExtraFieldInfo(variables_, printer); if (HasHazzer(descriptor_)) { WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); @@ -204,8 +201,7 @@ void ImmutableEnumFieldGenerator::GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "@java.lang.Override $deprecation$public $type$ " "${$get$capitalized_name$$}$() {\n" - " @SuppressWarnings(\"deprecation\")\n" - " $type$ result = $type$.$for_number$($name$_);\n" + " $type$ result = $type$.forNumber($name$_);\n" " return result == null ? $unknown$ : result;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -236,9 +232,9 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public Builder " "${$set$capitalized_name$Value$}$(int value) {\n" - " $set_has_field_bit_builder$\n" " $name$_ = value;\n" - " $on_changed$\n" + " $set_has_field_bit_builder$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -247,8 +243,7 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "@java.lang.Override\n" "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " @SuppressWarnings(\"deprecation\")\n" - " $type$ result = $type$.$for_number$($name$_);\n" + " $type$ result = $type$.forNumber($name$_);\n" " return result == null ? $unknown$ : result;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -262,7 +257,7 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers( " }\n" " $set_has_field_bit_builder$\n" " $name$_ = value.getNumber();\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -273,7 +268,7 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers( "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" " $clear_has_field_bit_builder$\n" " $name$_ = $default_number$;\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -281,9 +276,9 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers( void ImmutableEnumFieldGenerator::GenerateKotlinDslMembers( io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$ var $kt_name$: $kt_type$\n" + "$kt_deprecation$public var $kt_name$: $kt_type$\n" " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" @@ -291,18 +286,31 @@ void ImmutableEnumFieldGenerator::GenerateKotlinDslMembers( " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n" " }\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print( + variables_, + "$kt_deprecation$public var $kt_name$Value: kotlin.Int\n" + " @JvmName(\"${$get$kt_capitalized_name$Value$}$\")\n" + " get() = $kt_dsl_builder$.${$get$capitalized_name$Value$}$()\n" + " @JvmName(\"${$set$kt_capitalized_name$Value$}$\")\n" + " set(value) {\n" + " $kt_dsl_builder$.${$set$capitalized_name$Value$}$(value)\n" + " }\n"); + } + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, - "fun ${$clear$kt_capitalized_name$$}$() {\n" + "public fun ${$clear$kt_capitalized_name$$}$() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" "}\n"); if (HasHazzer(descriptor_)) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, + /* builder */ false, /* kdoc */ true); printer->Print( variables_, - "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" "}\n"); } @@ -320,9 +328,7 @@ void ImmutableEnumFieldGenerator::GenerateInitializationCode( void ImmutableEnumFieldGenerator::GenerateBuilderClearCode( io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $default_number$;\n" - "$clear_has_field_bit_builder$\n"); + printer->Print(variables_, "$name$_ = $default_number$;\n"); } void ImmutableEnumFieldGenerator::GenerateMergingCode( @@ -339,47 +345,41 @@ void ImmutableEnumFieldGenerator::GenerateMergingCode( " set$capitalized_name$Value(other.get$capitalized_name$Value());\n" "}\n"); } else { - GOOGLE_LOG(FATAL) << "Can't reach here."; + Y_ABSL_LOG(FATAL) << "Can't reach here."; } } void ImmutableEnumFieldGenerator::GenerateBuildingCode( io::Printer* printer) const { - if (HasHazzer(descriptor_)) { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " result.$name$_ = $name$_;\n"); + if (GetNumBitsForMessage() > 0) { + printer->Print(variables_, " $set_has_field_bit_to_local$;\n"); } - printer->Print(variables_, "result.$name$_ = $name$_;\n"); + printer->Print("}\n"); } -void ImmutableEnumFieldGenerator::GenerateParsingCode( +void ImmutableEnumFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "$set_has_field_bit_message$\n" - "$name$_ = rawValue;\n"); + "$name$_ = input.readEnum();\n" + "$set_has_field_bit_builder$\n"); } else { printer->Print(variables_, - "int rawValue = input.readEnum();\n" - " @SuppressWarnings(\"deprecation\")\n" - "$type$ value = $type$.$for_number$(rawValue);\n" - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" + "int tmpRaw = input.readEnum();\n" + "$type$ tmpValue =\n" + " $type$.forNumber(tmpRaw);\n" + "if (tmpValue == null) {\n" + " mergeUnknownVarintField($number$, tmpRaw);\n" "} else {\n" - " $set_has_field_bit_message$\n" - " $name$_ = rawValue;\n" + " $name$_ = tmpRaw;\n" + " $set_has_field_bit_builder$\n" "}\n"); } } -void ImmutableEnumFieldGenerator::GenerateParsingDoneCode( - io::Printer* printer) const { - // noop for enums -} - void ImmutableEnumFieldGenerator::GenerateSerializationCode( io::Printer* printer) const { printer->Print(variables_, @@ -429,7 +429,7 @@ ImmutableEnumOneofFieldGenerator::~ImmutableEnumOneofFieldGenerator() {} void ImmutableEnumOneofFieldGenerator::GenerateMembers( io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" @@ -453,8 +453,7 @@ void ImmutableEnumOneofFieldGenerator::GenerateMembers( printer->Print(variables_, "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" " if ($has_oneof_case_message$) {\n" - " @SuppressWarnings(\"deprecation\")\n" - " $type$ result = $type$.$for_number$(\n" + " $type$ result = $type$.forNumber(\n" " (java.lang.Integer) $oneof_name$_);\n" " return result == null ? $unknown$ : result;\n" " }\n" @@ -465,7 +464,7 @@ void ImmutableEnumOneofFieldGenerator::GenerateMembers( void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers( io::Printer* printer) const { - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "@java.lang.Override\n" @@ -493,7 +492,7 @@ void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers( "${$set$capitalized_name$Value$}$(int value) {\n" " $set_oneof_case_message$;\n" " $oneof_name$_ = value;\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -503,14 +502,14 @@ void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers( "@java.lang.Override\n" "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" " if ($has_oneof_case_message$) {\n" - " @SuppressWarnings(\"deprecation\")\n" - " $type$ result = $type$.$for_number$(\n" + " $type$ result = $type$.forNumber(\n" " (java.lang.Integer) $oneof_name$_);\n" " return result == null ? $unknown$ : result;\n" " }\n" " return $default$;\n" "}\n"); printer->Annotate("{", "}", descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, SETTER, /* builder */ true); printer->Print(variables_, @@ -521,10 +520,11 @@ void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers( " }\n" " $set_oneof_case_message$;\n" " $oneof_name$_ = value.getNumber();\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, /* builder */ true); printer->Print( @@ -533,19 +533,21 @@ void ImmutableEnumOneofFieldGenerator::GenerateBuilderMembers( " if ($has_oneof_case_message$) {\n" " $clear_oneof_case_message$;\n" " $oneof_name$_ = null;\n" - " $on_changed$\n" + " onChanged();\n" " }\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); } +void ImmutableEnumOneofFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { + // No-op: Enum fields in oneofs are correctly cleared by clearing the oneof +} + void ImmutableEnumOneofFieldGenerator::GenerateBuildingCode( io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " result.$oneof_name$_ = $oneof_name$_;\n" - "}\n"); + // No-Op: Handled by single statement for the oneof } void ImmutableEnumOneofFieldGenerator::GenerateMergingCode( @@ -560,7 +562,7 @@ void ImmutableEnumOneofFieldGenerator::GenerateMergingCode( } } -void ImmutableEnumOneofFieldGenerator::GenerateParsingCode( +void ImmutableEnumOneofFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print(variables_, @@ -570,10 +572,10 @@ void ImmutableEnumOneofFieldGenerator::GenerateParsingCode( } else { printer->Print(variables_, "int rawValue = input.readEnum();\n" - "@SuppressWarnings(\"deprecation\")\n" - "$type$ value = $type$.$for_number$(rawValue);\n" + "$type$ value =\n" + " $type$.forNumber(rawValue);\n" "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" + " mergeUnknownVarintField($number$, rawValue);\n" "} else {\n" " $set_oneof_case_message$;\n" " $oneof_name$_ = rawValue;\n" @@ -634,11 +636,8 @@ void ImmutableEnumOneofFieldGenerator::GenerateHashCode( RepeatedImmutableEnumFieldGenerator::RepeatedImmutableEnumFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { - SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), name_resolver_, - &variables_); -} + : ImmutableEnumFieldGenerator(descriptor, messageBitIndex, builderBitIndex, + context) {} RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {} @@ -678,6 +677,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateMembers( io::Printer* printer) const { printer->Print( variables_, + "@SuppressWarnings(\"serial\")\n" "private java.util.List<java.lang.Integer> $name$_;\n" "private static final " "com.google.protobuf.Internal.ListAdapter.Converter<\n" @@ -685,8 +685,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateMembers( " new com.google.protobuf.Internal.ListAdapter.Converter<\n" " java.lang.Integer, $type$>() {\n" " public $type$ convert(java.lang.Integer from) {\n" - " @SuppressWarnings(\"deprecation\")\n" - " $type$ result = $type$.$for_number$(from);\n" + " $type$ result = $type$.forNumber(from);\n" " return result == null ? $unknown$ : result;\n" " }\n" " };\n"); @@ -802,7 +801,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( " }\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.set(index, value.getNumber());\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -816,7 +815,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( " }\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.add(value.getNumber());\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -829,7 +828,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( " for ($type$ value : values) {\n" " $name$_.add(value.getNumber());\n" " }\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -840,7 +839,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" " $name$_ = java.util.Collections.emptyList();\n" " $clear_mutable_bit_builder$;\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -870,7 +869,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( " int index, int value) {\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.set(index, value);\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -881,7 +880,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( "${$add$capitalized_name$Value$}$(int value) {\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.add(value);\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -895,7 +894,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuilderMembers( " for (int value : values) {\n" " $name$_.add(value);\n" " }\n" - " $on_changed$\n" + " onChanged();\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); @@ -935,7 +934,7 @@ void RepeatedImmutableEnumFieldGenerator::GenerateMergingCode( " ensure$capitalized_name$IsMutable();\n" " $name$_.addAll(other.$name$_);\n" " }\n" - " $on_changed$\n" + " onChanged();\n" "}\n"); } @@ -952,36 +951,29 @@ void RepeatedImmutableEnumFieldGenerator::GenerateBuildingCode( "result.$name$_ = $name$_;\n"); } -void RepeatedImmutableEnumFieldGenerator::GenerateParsingCode( +void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { // Read and store the enum if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print(variables_, - "int rawValue = input.readEnum();\n" - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "$name$_.add(rawValue);\n"); + "int tmpRaw = input.readEnum();\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(tmpRaw);\n"); } else { - printer->Print( - variables_, - "int rawValue = input.readEnum();\n" - "@SuppressWarnings(\"deprecation\")\n" - "$type$ value = $type$.$for_number$(rawValue);\n" - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n" - " if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n" - " $set_mutable_bit_parser$;\n" - " }\n" - " $name$_.add(rawValue);\n" - "}\n"); + printer->Print(variables_, + "int tmpRaw = input.readEnum();\n" + "$type$ tmpValue =\n" + " $type$.forNumber(tmpRaw);\n" + "if (tmpValue == null) {\n" + " mergeUnknownVarintField($number$, tmpRaw);\n" + "} else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(tmpRaw);\n" + "}\n"); } } -void RepeatedImmutableEnumFieldGenerator::GenerateParsingCodeFromPacked( +void RepeatedImmutableEnumFieldGenerator::GenerateBuilderParsingCodeFromPacked( io::Printer* printer) const { // Wrap GenerateParsingCode's contents with a while loop. @@ -991,23 +983,13 @@ void RepeatedImmutableEnumFieldGenerator::GenerateParsingCodeFromPacked( "while(input.getBytesUntilLimit() > 0) {\n"); printer->Indent(); - GenerateParsingCode(printer); + GenerateBuilderParsingCode(printer); printer->Outdent(); printer->Print(variables_, "}\n" "input.popLimit(oldLimit);\n"); } - -void RepeatedImmutableEnumFieldGenerator::GenerateParsingDoneCode( - io::Printer* printer) const { - printer->Print( - variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); -} - void RepeatedImmutableEnumFieldGenerator::GenerateSerializationCode( io::Printer* printer) const { if (descriptor_->is_packed()) { @@ -1085,12 +1067,12 @@ void RepeatedImmutableEnumFieldGenerator::GenerateKotlinDslMembers( " */\n" "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" " : com.google.protobuf.kotlin.DslProxy()\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$ val $kt_name$: " + "$kt_deprecation$public val $kt_name$: " "com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " @kotlin.jvm.JvmSynthetic\n" @@ -1099,70 +1081,70 @@ void RepeatedImmutableEnumFieldGenerator::GenerateKotlinDslMembers( " )\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "add(value: $kt_type$) {\n" " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(value: $kt_type$) {\n" " add(value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" " addAll(values)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "operator fun com.google.protobuf.kotlin.DslList" + "public operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "set(index: kotlin.Int, value: $kt_type$) {\n" " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "clear() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" @@ -1178,4 +1160,4 @@ TProtoStringType RepeatedImmutableEnumFieldGenerator::GetBoxedType() const { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field.h index 6cf28fb1261..60285493a37 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field.h @@ -35,10 +35,10 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__ -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -61,10 +61,15 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { explicit ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context); + ImmutableEnumFieldGenerator(const ImmutableEnumFieldGenerator&) = delete; + ImmutableEnumFieldGenerator& operator=(const ImmutableEnumFieldGenerator&) = + delete; ~ImmutableEnumFieldGenerator() override; // implements ImmutableFieldGenerator // --------------------------------------- + int GetMessageBitIndex() const override; + int GetBuilderBitIndex() const override; int GetNumBitsForMessage() const override; int GetNumBitsForBuilder() const override; void GenerateInterfaceMembers(io::Printer* printer) const override; @@ -72,10 +77,9 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { void GenerateBuilderMembers(io::Printer* printer) const override; void GenerateInitializationCode(io::Printer* printer) const override; void GenerateBuilderClearCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; - void GenerateParsingDoneCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateFieldBuilderInitializationCode( @@ -88,11 +92,10 @@ class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { protected: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + int message_bit_index_; + int builder_bit_index_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; ClassNameResolver* name_resolver_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldGenerator); }; class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator { @@ -100,27 +103,33 @@ class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator { ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context); + ImmutableEnumOneofFieldGenerator(const ImmutableEnumOneofFieldGenerator&) = + delete; + ImmutableEnumOneofFieldGenerator& operator=( + const ImmutableEnumOneofFieldGenerator&) = delete; ~ImmutableEnumOneofFieldGenerator() override; void GenerateMembers(io::Printer* printer) const override; void GenerateBuilderMembers(io::Printer* printer) const override; + void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateEqualsCode(io::Printer* printer) const override; void GenerateHashCode(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator); }; -class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { +class RepeatedImmutableEnumFieldGenerator : public ImmutableEnumFieldGenerator { public: explicit RepeatedImmutableEnumFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context); + RepeatedImmutableEnumFieldGenerator( + const RepeatedImmutableEnumFieldGenerator&) = delete; + RepeatedImmutableEnumFieldGenerator& operator=( + const RepeatedImmutableEnumFieldGenerator&) = delete; ~RepeatedImmutableEnumFieldGenerator() override; // implements ImmutableFieldGenerator --------------------------------------- @@ -133,9 +142,9 @@ class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; - void GenerateParsingCodeFromPacked(io::Printer* printer) const override; - void GenerateParsingDoneCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; + void GenerateBuilderParsingCodeFromPacked( + io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateFieldBuilderInitializationCode( @@ -145,13 +154,6 @@ class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { void GenerateKotlinDslMembers(io::Printer* printer) const override; TProtoStringType GetBoxedType() const override; - - private: - const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; - ClassNameResolver* name_resolver_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field_lite.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field_lite.cc index c90939ada6c..0aa273c9908 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field_lite.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field_lite.cc @@ -32,24 +32,24 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/enum_field_lite.h> +#include "google/protobuf/compiler/java/enum_field_lite.h" #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_join.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -65,53 +65,62 @@ bool EnableExperimentalRuntimeForLite() { #endif // !PROTOBUF_EXPERIMENT } -void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetEnumVariables( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables, + Context* context) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["type"] = name_resolver->GetImmutableClassName(descriptor->enum_type()); - (*variables)["kt_type"] = (*variables)["type"]; + variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])}); (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->enum_type()); - (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default"] = + ImmutableDefaultValue(descriptor, name_resolver, context->options()); (*variables)["default_number"] = - StrCat(descriptor->default_value_enum()->number()); - (*variables)["tag"] = StrCat( + y_absl::StrCat(descriptor->default_value_enum()->number()); + (*variables)["tag"] = y_absl::StrCat( static_cast<arc_i32>(internal::WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = StrCat( + (*variables)["tag_size"] = y_absl::StrCat( internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["kt_deprecation"] = - descriptor->options().deprecated() - ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + - " is deprecated\") " - : ""; + variables->insert( + {"kt_deprecation", + descriptor->options().deprecated() + ? y_absl::StrCat("@kotlin.Deprecated(message = \"Field ", + (*variables)["name"], " is deprecated\") ") + : ""}); (*variables)["required"] = descriptor->is_required() ? "true" : "false"; if (HasHasbit(descriptor)) { + if (!context->options().opensource_runtime) { + (*variables)["bit_field_id"] = y_absl::StrCat(messageBitIndex / 32); + (*variables)["bit_field_name"] = GetBitFieldNameForBit(messageBitIndex); + (*variables)["bit_field_mask"] = + y_absl::StrCat(1 << (messageBitIndex % 32)); + } // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; + y_absl::StrCat(GenerateSetBit(messageBitIndex), ";"); (*variables)["clear_has_field_bit_message"] = - GenerateClearBit(messageBitIndex) + ";"; + y_absl::StrCat(GenerateClearBit(messageBitIndex), ";"); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); } else { (*variables)["set_has_field_bit_message"] = ""; (*variables)["clear_has_field_bit_message"] = ""; - (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != " + (*variables)["default"] + - ".getNumber()"; + variables->insert({"is_field_present_message", + y_absl::StrCat((*variables)["name"], "_ != ", + (*variables)["default"], ".getNumber()")}); } (*variables)["get_has_field_bit_from_local"] = @@ -120,14 +129,18 @@ void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, GenerateSetBitToLocal(messageBitIndex); if (SupportUnknownEnumValue(descriptor->file())) { - (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED"; + variables->insert( + {"unknown", y_absl::StrCat((*variables)["type"], ".UNRECOGNIZED")}); } else { - (*variables)["unknown"] = (*variables)["default"]; + variables->insert({"unknown", (*variables)["default"]}); } // We use `x.getClass()` as a null check because it generates less bytecode // than an `if (x == null) { throw ... }` statement. (*variables)["null_check"] = "value.getClass();\n"; + // Calls to Annotate() use variable ranges to know which text to annotate. + (*variables)["{"] = ""; + (*variables)["}"] = ""; } } // namespace @@ -142,7 +155,7 @@ ImmutableEnumFieldLiteGenerator::ImmutableEnumFieldLiteGenerator( name_resolver_(context->GetNameResolver()) { SetEnumVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, - &variables_); + &variables_, context); } ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {} @@ -156,19 +169,37 @@ void ImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers( if (HasHazzer(descriptor_)) { WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + "$deprecation$boolean ${$has$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); } if (SupportUnknownEnumValue(descriptor_->file())) { WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Value();\n"); + "$deprecation$int ${$get$capitalized_name$Value$}$();\n"); + printer->Annotate("{", "}", descriptor_); } WriteFieldAccessorDocComment(printer, descriptor_, GETTER); - printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); + printer->Print(variables_, + "$deprecation$$type$ ${$get$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); } void ImmutableEnumFieldLiteGenerator::GenerateMembers( io::Printer* printer) const { + if (!context_->options().opensource_runtime) { + printer->Print( + variables_, + "@com.google.protobuf.ProtoField(\n" + " fieldNumber=$number$,\n" + " type=com.google.protobuf.FieldType.$annotation_field_type$,\n" + " isRequired=$required$)\n"); + if (HasHazzer(descriptor_)) { + printer->Print(variables_, + "@com.google.protobuf.ProtoPresenceCheckedField(\n" + " presenceBitsId=$bit_field_id$,\n" + " mask=$bit_field_mask$)\n"); + } + } printer->Print(variables_, "private int $name$_;\n"); PrintExtraFieldInfo(variables_, printer); if (HasHazzer(descriptor_)) { @@ -286,9 +317,9 @@ void ImmutableEnumFieldLiteGenerator::GenerateBuilderMembers( void ImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers( io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$var $kt_name$: $kt_type$\n" + "$kt_deprecation$public var $kt_name$: $kt_type$\n" " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" @@ -296,18 +327,31 @@ void ImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers( " $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n" " }\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print( + variables_, + "$kt_deprecation$public var $kt_name$Value: kotlin.Int\n" + " @JvmName(\"${$get$kt_capitalized_name$Value$}$\")\n" + " get() = $kt_dsl_builder$.${$get$capitalized_name$Value$}$()\n" + " @JvmName(\"${$set$kt_capitalized_name$Value$}$\")\n" + " set(value) {\n" + " $kt_dsl_builder$.${$set$capitalized_name$Value$}$(value)\n" + " }\n"); + } + WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, - "fun ${$clear$kt_capitalized_name$$}$() {\n" + "public fun ${$clear$kt_capitalized_name$$}$() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" "}\n"); if (HasHazzer(descriptor_)) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, + /* builder */ false, /* kdoc */ true); printer->Print( variables_, - "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" "}\n"); } @@ -356,7 +400,7 @@ ImmutableEnumOneofFieldLiteGenerator::~ImmutableEnumOneofFieldLiteGenerator() {} void ImmutableEnumOneofFieldLiteGenerator::GenerateMembers( io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "@java.lang.Override\n" @@ -432,7 +476,7 @@ void ImmutableEnumOneofFieldLiteGenerator::GenerateFieldInfo( void ImmutableEnumOneofFieldLiteGenerator::GenerateBuilderMembers( io::Printer* printer) const { - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "@java.lang.Override\n" @@ -501,7 +545,7 @@ RepeatedImmutableEnumFieldLiteGenerator:: name_resolver_(context->GetNameResolver()) { SetEnumVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), name_resolver_, - &variables_); + &variables_, context); } RepeatedImmutableEnumFieldLiteGenerator:: @@ -514,29 +558,43 @@ int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const { void RepeatedImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers( io::Printer* printer) const { WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); - printer->Print( - variables_, - "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); + printer->Print(variables_, + "$deprecation$java.util.List<$type$> " + "${$get$capitalized_name$List$}$();\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); + "$deprecation$int ${$get$capitalized_name$Count$}$();\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); + printer->Print( + variables_, + "$deprecation$$type$ ${$get$capitalized_name$$}$(int index);\n"); + printer->Annotate("{", "}", descriptor_); if (SupportUnknownEnumValue(descriptor_->file())) { WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, "$deprecation$java.util.List<java.lang.Integer>\n" - "get$capitalized_name$ValueList();\n"); + "${$get$capitalized_name$ValueList$}$();\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); - printer->Print(variables_, - "$deprecation$int get$capitalized_name$Value(int index);\n"); + printer->Print( + variables_, + "$deprecation$int ${$get$capitalized_name$Value$}$(int index);\n"); + printer->Annotate("{", "}", descriptor_); } } void RepeatedImmutableEnumFieldLiteGenerator::GenerateMembers( io::Printer* printer) const { + if (!context_->options().opensource_runtime) { + printer->Print( + variables_, + "@com.google.protobuf.ProtoField(\n" + " fieldNumber=$number$,\n" + " type=com.google.protobuf.FieldType.$annotation_field_type$)\n"); + } printer->Print( variables_, "private com.google.protobuf.Internal.IntList $name$_;\n" @@ -793,6 +851,7 @@ void RepeatedImmutableEnumFieldLiteGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public Builder " "${$add$capitalized_name$Value$}$(int value) {\n" + " copyOnWrite();\n" " instance.add$capitalized_name$Value(value);\n" " return this;\n" "}\n"); @@ -827,12 +886,12 @@ void RepeatedImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers( " */\n" "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" " : com.google.protobuf.kotlin.DslProxy()\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$ val $kt_name$: " + "$kt_deprecation$ public val $kt_name$: " "com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " @kotlin.jvm.JvmSynthetic\n" @@ -841,70 +900,70 @@ void RepeatedImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers( " )\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "add(value: $kt_type$) {\n" " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(value: $kt_type$) {\n" " add(value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" " addAll(values)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "operator fun com.google.protobuf.kotlin.DslList" + "public operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "set(index: kotlin.Int, value: $kt_type$) {\n" " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "clear() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" @@ -920,4 +979,4 @@ TProtoStringType RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field_lite.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field_lite.h index df2f6fa10a7..824affda1e6 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field_lite.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_field_lite.h @@ -36,10 +36,10 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__ #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -62,6 +62,10 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { explicit ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + ImmutableEnumFieldLiteGenerator(const ImmutableEnumFieldLiteGenerator&) = + delete; + ImmutableEnumFieldLiteGenerator& operator=( + const ImmutableEnumFieldLiteGenerator&) = delete; ~ImmutableEnumFieldLiteGenerator() override; // implements ImmutableFieldLiteGenerator @@ -79,13 +83,10 @@ class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { protected: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; const int messageBitIndex_; Context* context_; ClassNameResolver* name_resolver_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldLiteGenerator); }; class ImmutableEnumOneofFieldLiteGenerator @@ -93,15 +94,16 @@ class ImmutableEnumOneofFieldLiteGenerator public: ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + ImmutableEnumOneofFieldLiteGenerator( + const ImmutableEnumOneofFieldLiteGenerator&) = delete; + ImmutableEnumOneofFieldLiteGenerator& operator=( + const ImmutableEnumOneofFieldLiteGenerator&) = delete; ~ImmutableEnumOneofFieldLiteGenerator() override; void GenerateMembers(io::Printer* printer) const override; void GenerateBuilderMembers(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector<uint16_t>* output) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator); }; class RepeatedImmutableEnumFieldLiteGenerator @@ -109,6 +111,10 @@ class RepeatedImmutableEnumFieldLiteGenerator public: explicit RepeatedImmutableEnumFieldLiteGenerator( const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + RepeatedImmutableEnumFieldLiteGenerator( + const RepeatedImmutableEnumFieldLiteGenerator&) = delete; + RepeatedImmutableEnumFieldLiteGenerator& operator=( + const RepeatedImmutableEnumFieldLiteGenerator&) = delete; ~RepeatedImmutableEnumFieldLiteGenerator() override; // implements ImmutableFieldLiteGenerator ------------------------------------ @@ -125,11 +131,9 @@ class RepeatedImmutableEnumFieldLiteGenerator private: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; Context* context_; ClassNameResolver* name_resolver_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldLiteGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_lite.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_lite.cc index 7fdd4ab9b8b..ae07f8c66fd 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_lite.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_lite.cc @@ -32,19 +32,18 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/enum_lite.h> +#include "google/protobuf/compiler/java/enum_lite.h" -#include <map> #include <string> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/stubs/map_util.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -87,9 +86,9 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { printer->Indent(); for (int i = 0; i < canonical_values_.size(); i++) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["name"] = canonical_values_[i]->name(); - vars["number"] = StrCat(canonical_values_[i]->number()); + vars["number"] = y_absl::StrCat(canonical_values_[i]->number()); WriteEnumValueDocComment(printer, canonical_values_[i]); if (canonical_values_[i]->options().deprecated()) { printer->Print("@java.lang.Deprecated\n"); @@ -110,7 +109,7 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- for (int i = 0; i < aliases_.size(); i++) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["classname"] = descriptor_->name(); vars["name"] = aliases_[i].value->name(); vars["canonical_name"] = aliases_[i].canonical_value->name(); @@ -121,9 +120,9 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { } for (int i = 0; i < descriptor_->value_count(); i++) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["name"] = descriptor_->value(i)->name(); - vars["number"] = StrCat(descriptor_->value(i)->number()); + vars["number"] = y_absl::StrCat(descriptor_->value(i)->number()); vars["{"] = ""; vars["}"] = ""; vars["deprecation"] = descriptor_->value(i)->options().deprecated() @@ -153,17 +152,26 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { printer->Print( " return value;\n" "}\n" - "\n" - "/**\n" - " * @param value The number of the enum to look for.\n" - " * @return The enum associated with the given number.\n" - " * @deprecated Use {@link #forNumber(int)} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public static $classname$ valueOf(int value) {\n" - " return forNumber(value);\n" - "}\n" - "\n" + "\n"); + if (context_->options().opensource_runtime) { + printer->Print( + "/**\n" + " * @param value The number of the enum to look for.\n" + " * @return The enum associated with the given number.\n" + " * @deprecated Use {@link #forNumber(int)} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public static $classname$ valueOf(int value) {\n" + " return forNumber(value);\n" + "}\n" + "\n", + "classname", descriptor_->name()); + } + + if (!context_->options().opensource_runtime) { + printer->Print("@com.google.protobuf.Internal.ProtoMethodMayReturnNull\n"); + } + printer->Print( "public static $classname$ forNumber(int value) {\n" " switch (value) {\n", "classname", descriptor_->name()); @@ -173,7 +181,7 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { for (int i = 0; i < canonical_values_.size(); i++) { printer->Print("case $number$: return $name$;\n", "name", canonical_values_[i]->name(), "number", - StrCat(canonical_values_[i]->number())); + y_absl::StrCat(canonical_values_[i]->number())); } printer->Outdent(); @@ -212,6 +220,35 @@ void EnumLiteGenerator::Generate(io::Printer* printer) { " };\n" "\n", "classname", descriptor_->name()); + if (!context_->options().opensource_runtime) { + printer->Print( + "/**\n" + " * Override of toString that prints the number and name.\n" + " * This is primarily intended as a developer aid.\n" + " *\n" + " * <p>NOTE: This implementation is liable to change in the future,\n" + " * and should not be relied on in code.\n" + " */\n" + "@java.lang.Override\n" + "public java.lang.String toString() {\n" + " StringBuilder result = new StringBuilder(\"<\");\n" + " result.append(getClass().getName()).append('@')\n" + " .append(java.lang.Integer.toHexString(\n" + " java.lang.System.identityHashCode(this)));\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print( + " if (this != UNRECOGNIZED) {\n" + " result.append(\" number=\").append(getNumber());\n" + " }\n"); + } else { + printer->Print(" result.append(\" number=\").append(getNumber());\n"); + } + printer->Print( + " return result.append(\" name=\")\n" + " .append(name()).append('>').toString();\n" + "}\n" + "\n"); + } printer->Print( "private final int value;\n\n" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_lite.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_lite.h index 50f3fe7b1aa..309d539b2ea 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_lite.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/enum_lite.h @@ -37,7 +37,8 @@ #include <string> #include <vector> -#include <google/protobuf/descriptor.h> + +#include "google/protobuf/descriptor.h" namespace google { namespace protobuf { @@ -62,6 +63,8 @@ class EnumLiteGenerator { public: EnumLiteGenerator(const EnumDescriptor* descriptor, bool immutable_api, Context* context); + EnumLiteGenerator(const EnumLiteGenerator&) = delete; + EnumLiteGenerator& operator=(const EnumLiteGenerator&) = delete; ~EnumLiteGenerator(); void Generate(io::Printer* printer); @@ -86,8 +89,6 @@ class EnumLiteGenerator { Context* context_; ClassNameResolver* name_resolver_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumLiteGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/extension.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/extension.cc index 0983366c4f8..dd9e6eab186 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/extension.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/extension.cc @@ -32,17 +32,18 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/extension.h> +#include "google/protobuf/compiler/java/extension.h" -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -51,7 +52,9 @@ namespace java { ImmutableExtensionGenerator::ImmutableExtensionGenerator( const FieldDescriptor* descriptor, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), + name_resolver_(context->GetNameResolver()), + context_(context) { if (descriptor_->extension_scope() != NULL) { scope_ = name_resolver_->GetImmutableClassName(descriptor_->extension_scope()); @@ -66,19 +69,21 @@ ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {} void ExtensionGenerator::InitTemplateVars( const FieldDescriptor* descriptor, const TProtoStringType& scope, bool immutable, ClassNameResolver* name_resolver, - std::map<TProtoStringType, TProtoStringType>* vars_pointer) { - std::map<TProtoStringType, TProtoStringType>& vars = *vars_pointer; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* vars_pointer, + Context* context) { + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& vars = *vars_pointer; vars["scope"] = scope; vars["name"] = UnderscoresToCamelCaseCheckReserved(descriptor); vars["containing_type"] = name_resolver->GetClassName(descriptor->containing_type(), immutable); - vars["number"] = StrCat(descriptor->number()); + vars["number"] = y_absl::StrCat(descriptor->number()); vars["constant_name"] = FieldConstantName(descriptor); - vars["index"] = StrCat(descriptor->index()); + vars["index"] = y_absl::StrCat(descriptor->index()); vars["default"] = descriptor->is_repeated() ? "" - : DefaultValue(descriptor, immutable, name_resolver); - vars["type_constant"] = FieldTypeName(GetType(descriptor)); + : DefaultValue(descriptor, immutable, name_resolver, + context->options()); + vars["type_constant"] = TProtoStringType(FieldTypeName(GetType(descriptor))); vars["packed"] = descriptor->is_packed() ? "true" : "false"; vars["enum_map"] = "null"; vars["prototype"] = "null"; @@ -89,12 +94,12 @@ void ExtensionGenerator::InitTemplateVars( case JAVATYPE_MESSAGE: singular_type = name_resolver->GetClassName(descriptor->message_type(), immutable); - vars["prototype"] = singular_type + ".getDefaultInstance()"; + vars["prototype"] = y_absl::StrCat(singular_type, ".getDefaultInstance()"); break; case JAVATYPE_ENUM: singular_type = name_resolver->GetClassName(descriptor->enum_type(), immutable); - vars["enum_map"] = singular_type + ".internalGetValueMap()"; + vars["enum_map"] = y_absl::StrCat(singular_type, ".internalGetValueMap()"); break; case JAVATYPE_STRING: singular_type = "java.lang.String"; @@ -103,20 +108,20 @@ void ExtensionGenerator::InitTemplateVars( singular_type = immutable ? "com.google.protobuf.ByteString" : "byte[]"; break; default: - singular_type = BoxedPrimitiveTypeName(java_type); + singular_type = TProtoStringType(BoxedPrimitiveTypeName(java_type)); break; } vars["type"] = descriptor->is_repeated() - ? "java.util.List<" + singular_type + ">" + ? y_absl::StrCat("java.util.List<", singular_type, ">") : singular_type; vars["singular_type"] = singular_type; } void ImmutableExtensionGenerator::Generate(io::Printer* printer) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; const bool kUseImmutableNames = true; InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_, - &vars); + &vars, context_); printer->Print(vars, "public static final int $constant_name$ = $number$;\n"); WriteFieldDocComment(printer, descriptor_); @@ -156,7 +161,7 @@ int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( printer->Print( "$name$.internalInit(descriptor.getExtensions().get($index$));\n", "name", UnderscoresToCamelCaseCheckReserved(descriptor_), "index", - StrCat(descriptor_->index())); + y_absl::StrCat(descriptor_->index())); bytecode_estimate += 21; } return bytecode_estimate; @@ -174,4 +179,4 @@ int ImmutableExtensionGenerator::GenerateRegistrationCode( } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/extension.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/extension.h index f9bd326f9bd..752a2de8704 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/extension.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/extension.h @@ -35,10 +35,10 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ -#include <map> #include <string> -#include <google/protobuf/stubs/common.h> +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -66,6 +66,8 @@ namespace java { class ExtensionGenerator { public: explicit ExtensionGenerator() {} + ExtensionGenerator(const ExtensionGenerator&) = delete; + ExtensionGenerator& operator=(const ExtensionGenerator&) = delete; virtual ~ExtensionGenerator() {} virtual void Generate(io::Printer* printer) = 0; @@ -82,16 +84,17 @@ class ExtensionGenerator { static void InitTemplateVars( const FieldDescriptor* descriptor, const TProtoStringType& scope, bool immutable, ClassNameResolver* name_resolver, - std::map<TProtoStringType, TProtoStringType>* vars_pointer); - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* vars_pointer, + Context* context); }; class ImmutableExtensionGenerator : public ExtensionGenerator { public: explicit ImmutableExtensionGenerator(const FieldDescriptor* descriptor, Context* context); + ImmutableExtensionGenerator(const ImmutableExtensionGenerator&) = delete; + ImmutableExtensionGenerator& operator=(const ImmutableExtensionGenerator&) = + delete; ~ImmutableExtensionGenerator() override; void Generate(io::Printer* printer) override; @@ -102,9 +105,7 @@ class ImmutableExtensionGenerator : public ExtensionGenerator { const FieldDescriptor* descriptor_; ClassNameResolver* name_resolver_; TProtoStringType scope_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionGenerator); + Context* context_; }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/extension_lite.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/extension_lite.cc index d51d9d2ba8a..99345242a10 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/extension_lite.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/extension_lite.cc @@ -28,17 +28,19 @@ // (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/java/extension_lite.h> +#include "google/protobuf/compiler/java/extension_lite.h" -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include <string> + +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -47,7 +49,9 @@ namespace java { ImmutableExtensionLiteGenerator::ImmutableExtensionLiteGenerator( const FieldDescriptor* descriptor, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), + name_resolver_(context->GetNameResolver()), + context_(context) { if (descriptor_->extension_scope() != NULL) { scope_ = name_resolver_->GetImmutableClassName(descriptor_->extension_scope()); @@ -59,10 +63,10 @@ ImmutableExtensionLiteGenerator::ImmutableExtensionLiteGenerator( ImmutableExtensionLiteGenerator::~ImmutableExtensionLiteGenerator() {} void ImmutableExtensionLiteGenerator::Generate(io::Printer* printer) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; const bool kUseImmutableNames = true; InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_, - &vars); + &vars, context_); printer->Print(vars, "public static final int $constant_name$ = $number$;\n"); WriteFieldDocComment(printer, descriptor_); @@ -117,4 +121,4 @@ int ImmutableExtensionLiteGenerator::GenerateRegistrationCode( } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/extension_lite.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/extension_lite.h index 0d013c862ce..0c74bc50955 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/extension_lite.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/extension_lite.h @@ -31,11 +31,10 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__ -#include <map> #include <string> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/java/extension.h> +#include "google/protobuf/compiler/java/extension.h" +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -49,6 +48,10 @@ class ImmutableExtensionLiteGenerator : public ExtensionGenerator { public: explicit ImmutableExtensionLiteGenerator(const FieldDescriptor* descriptor, Context* context); + ImmutableExtensionLiteGenerator(const ImmutableExtensionLiteGenerator&) = + delete; + ImmutableExtensionLiteGenerator& operator=( + const ImmutableExtensionLiteGenerator&) = delete; ~ImmutableExtensionLiteGenerator() override; void Generate(io::Printer* printer) override; @@ -63,8 +66,7 @@ class ImmutableExtensionLiteGenerator : public ExtensionGenerator { const FieldDescriptor* descriptor_; ClassNameResolver* name_resolver_; TProtoStringType scope_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionLiteGenerator); + Context* context_; }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/field.cc index 84487ac7a11..4701dc63224 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/field.cc @@ -32,27 +32,28 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/field.h> +#include "google/protobuf/compiler/java/field.h" #include <memory> +#include <string> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/enum_field.h> -#include <google/protobuf/compiler/java/enum_field_lite.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/map_field.h> -#include <google/protobuf/compiler/java/map_field_lite.h> -#include <google/protobuf/compiler/java/message_field.h> -#include <google/protobuf/compiler/java/message_field_lite.h> -#include <google/protobuf/compiler/java/primitive_field.h> -#include <google/protobuf/compiler/java/primitive_field_lite.h> -#include <google/protobuf/compiler/java/string_field.h> -#include <google/protobuf/compiler/java/string_field_lite.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/enum_field.h" +#include "google/protobuf/compiler/java/enum_field_lite.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/map_field.h" +#include "google/protobuf/compiler/java/map_field_lite.h" +#include "google/protobuf/compiler/java/message_field.h" +#include "google/protobuf/compiler/java/message_field_lite.h" +#include "google/protobuf/compiler/java/primitive_field.h" +#include "google/protobuf/compiler/java/primitive_field_lite.h" +#include "google/protobuf/compiler/java/string_field.h" +#include "google/protobuf/compiler/java/string_field_lite.h" +#include "google/protobuf/io/printer.h" namespace google { @@ -185,15 +186,15 @@ static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) { // but this method should be overridden. // - This FieldGenerator doesn't support packing, and this method // should never have been called. - GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " - << "called on field generator that does not support packing."; + Y_ABSL_LOG(FATAL) << "GenerateBuilderParsingCodeFromPacked() " + << "called on field generator that does not support packing."; } } // namespace ImmutableFieldGenerator::~ImmutableFieldGenerator() {} -void ImmutableFieldGenerator::GenerateParsingCodeFromPacked( +void ImmutableFieldGenerator::GenerateBuilderParsingCodeFromPacked( io::Printer* printer) const { ReportUnexpectedPackedFieldsCall(printer); } @@ -241,16 +242,16 @@ template <> FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {} -void SetCommonFieldVariables(const FieldDescriptor* descriptor, - const FieldGeneratorInfo* info, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetCommonFieldVariables( + const FieldDescriptor* descriptor, const FieldGeneratorInfo* info, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { (*variables)["field_name"] = descriptor->name(); (*variables)["name"] = info->name; (*variables)["classname"] = descriptor->containing_type()->name(); (*variables)["capitalized_name"] = info->capitalized_name; (*variables)["disambiguated_reason"] = info->disambiguated_reason; (*variables)["constant_name"] = FieldConstantName(descriptor); - (*variables)["number"] = StrCat(descriptor->number()); + (*variables)["number"] = y_absl::StrCat(descriptor->number()); (*variables)["kt_dsl_builder"] = "_builder"; // These variables are placeholders to pick out the beginning and ends of // identifiers for annotations (when doing so with existing variables would @@ -258,46 +259,50 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, // empty string. (*variables)["{"] = ""; (*variables)["}"] = ""; - (*variables)["kt_name"] = - IsForbiddenKotlin(info->name) ? info->name + "_" : info->name; - (*variables)["kt_capitalized_name"] = IsForbiddenKotlin(info->name) - ? info->capitalized_name + "_" - : info->capitalized_name; + (*variables)["kt_name"] = IsForbiddenKotlin(info->name) + ? y_absl::StrCat(info->name, "_") + : info->name; + (*variables)["kt_capitalized_name"] = + IsForbiddenKotlin(info->name) ? y_absl::StrCat(info->capitalized_name, "_") + : info->capitalized_name; if (!descriptor->is_repeated()) { - (*variables)["annotation_field_type"] = FieldTypeName(descriptor->type()); + (*variables)["annotation_field_type"] = + TProtoStringType(FieldTypeName(descriptor->type())); } else if (GetJavaType(descriptor) == JAVATYPE_MESSAGE && IsMapEntry(descriptor->message_type())) { (*variables)["annotation_field_type"] = - TProtoStringType(FieldTypeName(descriptor->type())) + "MAP"; + y_absl::StrCat(FieldTypeName(descriptor->type()), "MAP"); } else { (*variables)["annotation_field_type"] = - TProtoStringType(FieldTypeName(descriptor->type())) + "_LIST"; + y_absl::StrCat(FieldTypeName(descriptor->type()), "_LIST"); if (descriptor->is_packed()) { - (*variables)["annotation_field_type"] = - (*variables)["annotation_field_type"] + "_PACKED"; + variables->insert( + {"annotation_field_type", + y_absl::StrCat(FieldTypeName(descriptor->type()), "_LIST_PACKED")}); } } } -void SetCommonOneofVariables(const FieldDescriptor* descriptor, - const OneofGeneratorInfo* info, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetCommonOneofVariables( + const FieldDescriptor* descriptor, const OneofGeneratorInfo* info, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { (*variables)["oneof_name"] = info->name; (*variables)["oneof_capitalized_name"] = info->capitalized_name; (*variables)["oneof_index"] = - StrCat(descriptor->containing_oneof()->index()); + y_absl::StrCat(descriptor->containing_oneof()->index()); (*variables)["oneof_stored_type"] = GetOneofStoredType(descriptor); (*variables)["set_oneof_case_message"] = - info->name + "Case_ = " + StrCat(descriptor->number()); - (*variables)["clear_oneof_case_message"] = info->name + "Case_ = 0"; + y_absl::StrCat(info->name, "Case_ = ", descriptor->number()); + (*variables)["clear_oneof_case_message"] = + y_absl::StrCat(info->name, "Case_ = 0"); (*variables)["has_oneof_case_message"] = - info->name + "Case_ == " + StrCat(descriptor->number()); + y_absl::StrCat(info->name, "Case_ == ", descriptor->number()); } -void PrintExtraFieldInfo(const std::map<TProtoStringType, TProtoStringType>& variables, - io::Printer* printer) { - const std::map<TProtoStringType, TProtoStringType>::const_iterator it = - variables.find("disambiguated_reason"); +void PrintExtraFieldInfo( + const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& variables, + io::Printer* printer) { + auto it = variables.find("disambiguated_reason"); if (it != variables.end() && !it->second.empty()) { printer->Print( variables, diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/field.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/field.h index 481fbdb4567..1229ce3a8a0 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/field.h @@ -36,13 +36,13 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ #include <cstdint> -#include <map> #include <memory> #include <string> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/descriptor.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -66,8 +66,12 @@ namespace java { class ImmutableFieldGenerator { public: ImmutableFieldGenerator() {} + ImmutableFieldGenerator(const ImmutableFieldGenerator&) = delete; + ImmutableFieldGenerator& operator=(const ImmutableFieldGenerator&) = delete; virtual ~ImmutableFieldGenerator(); + virtual int GetMessageBitIndex() const = 0; + virtual int GetBuilderBitIndex() const = 0; virtual int GetNumBitsForMessage() const = 0; virtual int GetNumBitsForBuilder() const = 0; virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0; @@ -77,9 +81,8 @@ class ImmutableFieldGenerator { virtual void GenerateBuilderClearCode(io::Printer* printer) const = 0; virtual void GenerateMergingCode(io::Printer* printer) const = 0; virtual void GenerateBuildingCode(io::Printer* printer) const = 0; - virtual void GenerateParsingCode(io::Printer* printer) const = 0; - virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const; - virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0; + virtual void GenerateBuilderParsingCode(io::Printer* printer) const = 0; + virtual void GenerateBuilderParsingCodeFromPacked(io::Printer* printer) const; virtual void GenerateSerializationCode(io::Printer* printer) const = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; virtual void GenerateFieldBuilderInitializationCode( @@ -90,14 +93,14 @@ class ImmutableFieldGenerator { virtual void GenerateHashCode(io::Printer* printer) const = 0; virtual TProtoStringType GetBoxedType() const = 0; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator); }; class ImmutableFieldLiteGenerator { public: ImmutableFieldLiteGenerator() {} + ImmutableFieldLiteGenerator(const ImmutableFieldLiteGenerator&) = delete; + ImmutableFieldLiteGenerator& operator=(const ImmutableFieldLiteGenerator&) = + delete; virtual ~ImmutableFieldLiteGenerator(); virtual int GetNumBitsForMessage() const = 0; @@ -110,9 +113,6 @@ class ImmutableFieldLiteGenerator { virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0; virtual TProtoStringType GetBoxedType() const = 0; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldLiteGenerator); }; @@ -121,6 +121,8 @@ template <typename FieldGeneratorType> class FieldGeneratorMap { public: explicit FieldGeneratorMap(const Descriptor* descriptor, Context* context); + FieldGeneratorMap(const FieldGeneratorMap&) = delete; + FieldGeneratorMap& operator=(const FieldGeneratorMap&) = delete; ~FieldGeneratorMap(); const FieldGeneratorType& get(const FieldDescriptor* field) const; @@ -128,14 +130,12 @@ class FieldGeneratorMap { private: const Descriptor* descriptor_; std::vector<std::unique_ptr<FieldGeneratorType>> field_generators_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; template <typename FieldGeneratorType> inline const FieldGeneratorType& FieldGeneratorMap<FieldGeneratorType>::get( const FieldDescriptor* field) const { - GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); + Y_ABSL_CHECK_EQ(field->containing_type(), descriptor_); return *field_generators_[field->index()]; } @@ -170,18 +170,19 @@ struct OneofGeneratorInfo { }; // Set some common variables used in variable FieldGenerators. -void SetCommonFieldVariables(const FieldDescriptor* descriptor, - const FieldGeneratorInfo* info, - std::map<TProtoStringType, TProtoStringType>* variables); +void SetCommonFieldVariables( + const FieldDescriptor* descriptor, const FieldGeneratorInfo* info, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables); // Set some common oneof variables used in OneofFieldGenerators. -void SetCommonOneofVariables(const FieldDescriptor* descriptor, - const OneofGeneratorInfo* info, - std::map<TProtoStringType, TProtoStringType>* variables); +void SetCommonOneofVariables( + const FieldDescriptor* descriptor, const OneofGeneratorInfo* info, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables); // Print useful comments before a field's accessors. -void PrintExtraFieldInfo(const std::map<TProtoStringType, TProtoStringType>& variables, - io::Printer* printer); +void PrintExtraFieldInfo( + const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& variables, + io::Printer* printer); } // namespace java } // namespace compiler diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/file.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/file.cc index 401599765bc..da961fc0886 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/file.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/file.cc @@ -32,30 +32,32 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/file.h> +#include "google/protobuf/compiler/java/file.h" #include <memory> -#include <set> - -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/dynamic_message.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/enum.h> -#include <google/protobuf/compiler/java/enum_lite.h> -#include <google/protobuf/compiler/java/extension.h> -#include <google/protobuf/compiler/java/generator_factory.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/message.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/compiler/java/service.h> -#include <google/protobuf/compiler/java/shared_code_generator.h> -#include <google/protobuf/descriptor.pb.h> +#include <vector> + +#include "y_absl/container/btree_set.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/enum.h" +#include "google/protobuf/compiler/java/enum_lite.h" +#include "google/protobuf/compiler/java/extension.h" +#include "google/protobuf/compiler/java/generator_factory.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/message.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/compiler/java/service.h" +#include "google/protobuf/compiler/java/shared_code_generator.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/dynamic_message.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -76,8 +78,8 @@ struct FieldDescriptorCompare { } }; -typedef std::set<const FieldDescriptor*, FieldDescriptorCompare> - FieldDescriptorSet; +using FieldDescriptorSet = + y_absl::btree_set<const FieldDescriptor*, FieldDescriptorCompare>; // Recursively searches the given message to collect extensions. // Returns true if all the extensions can be recognized. The extensions will be @@ -131,7 +133,7 @@ void CollectExtensions(const FileDescriptorProto& file_proto, // builder-pool to find out all extensions. const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName( file_proto.GetDescriptor()->full_name()); - GOOGLE_CHECK(file_proto_desc) + Y_ABSL_CHECK(file_proto_desc) << "Find unknown fields in FileDescriptorProto when building " << file_proto.name() << ". It's likely that those fields are custom options, however, " @@ -140,14 +142,14 @@ void CollectExtensions(const FileDescriptorProto& file_proto, DynamicMessageFactory factory; std::unique_ptr<Message> dynamic_file_proto( factory.GetPrototype(file_proto_desc)->New()); - GOOGLE_CHECK(dynamic_file_proto.get() != NULL); - GOOGLE_CHECK(dynamic_file_proto->ParseFromString(file_data)); + Y_ABSL_CHECK(dynamic_file_proto.get() != NULL); + Y_ABSL_CHECK(dynamic_file_proto->ParseFromString(file_data)); // Collect the extensions again from the dynamic message. There should be no // more unknown fields this time, i.e. all the custom options should be // parsed as extensions now. extensions->clear(); - GOOGLE_CHECK(CollectExtensions(*dynamic_file_proto, extensions)) + Y_ABSL_CHECK(CollectExtensions(*dynamic_file_proto, extensions)) << "Find unknown fields in FileDescriptorProto when building " << file_proto.name() << ". It's likely that those fields are custom options, however, " @@ -175,10 +177,10 @@ void MaybeRestartJavaMethod(io::Printer* printer, int* bytecode_estimate, if ((*bytecode_estimate) > bytesPerMethod) { ++(*method_num); - printer->Print(chain_statement, "method_num", StrCat(*method_num)); + printer->Print(chain_statement, "method_num", y_absl::StrCat(*method_num)); printer->Outdent(); printer->Print("}\n"); - printer->Print(method_decl, "method_num", StrCat(*method_num)); + printer->Print(method_decl, "method_num", y_absl::StrCat(*method_num)); printer->Indent(); *bytecode_estimate = 0; } @@ -188,7 +190,7 @@ void MaybeRestartJavaMethod(io::Printer* printer, int* bytecode_estimate, FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options, bool immutable_api) : file_(file), - java_package_(FileJavaPackage(file, immutable_api)), + java_package_(FileJavaPackage(file, immutable_api, options)), message_generators_(file->message_type_count()), extension_generators_(file->extension_count()), context_(new Context(file, options)), @@ -196,7 +198,7 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options, options_(options), immutable_api_(immutable_api) { classname_ = name_resolver_->GetFileClassName(file, immutable_api); - generator_factory_.reset(new ImmutableGeneratorFactory(context_.get())); + generator_factory_.reset(new ImmutableGeneratorFactory(context_.get())); for (int i = 0; i < file_->message_type_count(); ++i) { message_generators_[i].reset( generator_factory_->NewMessageGenerator(file_->message_type(i))); @@ -232,7 +234,7 @@ bool FileGenerator::Validate(TProtoStringType* error) { // because filenames are case-insensitive on those platforms. if (name_resolver_->HasConflictingClassName( file_, classname_, NameEquality::EQUAL_IGNORE_CASE)) { - GOOGLE_LOG(WARNING) + Y_ABSL_LOG(WARNING) << file_->name() << ": The file's outer class name, \"" << classname_ << "\", matches the name of one of the types declared inside it when " << "case is ignored. This can cause compilation issues on Windows / " @@ -244,7 +246,7 @@ bool FileGenerator::Validate(TProtoStringType* error) { // Print a warning if optimize_for = LITE_RUNTIME is used. if (file_->options().optimize_for() == FileOptions::LITE_RUNTIME && !options_.enforce_lite) { - GOOGLE_LOG(WARNING) + Y_ABSL_LOG(WARNING) << "The optimize_for = LITE_RUNTIME option is no longer supported by " << "protobuf Java code generator and is ignored--protoc will always " << "generate full runtime code for Java. To use Java Lite runtime, " @@ -271,8 +273,13 @@ void FileGenerator::Generate(io::Printer* printer) { "package", java_package_); } PrintGeneratedAnnotation( - printer, '$', options_.annotate_code ? classname_ + ".java.pb.meta" : ""); + printer, '$', + options_.annotate_code ? y_absl::StrCat(classname_, ".java.pb.meta") : "", + options_); + if (!options_.opensource_runtime) { + printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n"); + } printer->Print( "$deprecation$public final class $classname$ {\n" " private $ctor$() {}\n", @@ -401,11 +408,14 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( " descriptor;\n" "static {\n", // TODO(dweis): Mark this as final. - "final", ""); + "final", options_.opensource_runtime ? "" : "final"); printer->Indent(); - SharedCodeGenerator shared_code_generator(file_, options_); - shared_code_generator.GenerateDescriptors(printer); + if (options_.opensource_runtime) { + SharedCodeGenerator shared_code_generator(file_, options_); + shared_code_generator.GenerateDescriptors(printer); + } else { + } int bytecode_estimate = 0; int method_num = 0; @@ -449,16 +459,16 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( FieldDescriptorSet extensions; CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); - if (extensions.size() > 0) { + if (!extensions.empty()) { // Must construct an ExtensionRegistry containing all existing extensions // and use it to parse the descriptor data again to recognize extensions. printer->Print( "com.google.protobuf.ExtensionRegistry registry =\n" " com.google.protobuf.ExtensionRegistry.newInstance();\n"); FieldDescriptorSet::iterator it; - for (it = extensions.begin(); it != extensions.end(); it++) { + for (const FieldDescriptor* field : extensions) { std::unique_ptr<ExtensionGenerator> generator( - generator_factory_->NewExtensionGenerator(*it)); + generator_factory_->NewExtensionGenerator(field)); bytecode_estimate += generator->GenerateRegistrationCode(printer); MaybeRestartJavaMethod( printer, &bytecode_estimate, &method_num, @@ -499,8 +509,8 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable( printer->Print( "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n", - "immutable_package", FileJavaPackage(file_, true), "descriptor_classname", - name_resolver_->GetDescriptorClassName(file_)); + "immutable_package", FileJavaPackage(file_, true, options_), + "descriptor_classname", name_resolver_->GetDescriptorClassName(file_)); for (int i = 0; i < file_->message_type_count(); i++) { message_generators_[i]->GenerateStaticVariableInitializers(printer); @@ -518,7 +528,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable( FieldDescriptorSet extensions; CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); - if (extensions.size() > 0) { + if (!extensions.empty()) { // Try to load immutable messages' outer class. Its initialization code // will take care of interpreting custom options. printer->Print( @@ -539,17 +549,18 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable( "com.google.protobuf.ExtensionRegistry registry =\n" " com.google.protobuf.ExtensionRegistry.newInstance();\n" "com.google.protobuf.MessageLite defaultExtensionInstance = null;\n"); - FieldDescriptorSet::iterator it; - for (it = extensions.begin(); it != extensions.end(); it++) { - const FieldDescriptor* field = *it; + + for (const FieldDescriptor* field : extensions) { TProtoStringType scope; if (field->extension_scope() != NULL) { - scope = name_resolver_->GetMutableClassName(field->extension_scope()) + - ".getDescriptor()"; + scope = y_absl::StrCat( + name_resolver_->GetMutableClassName(field->extension_scope()), + ".getDescriptor()"); } else { - scope = FileJavaPackage(field->file(), true) + "." + - name_resolver_->GetDescriptorClassName(field->file()) + - ".descriptor"; + scope = + y_absl::StrCat(FileJavaPackage(field->file(), true, options_), ".", + name_resolver_->GetDescriptorClassName(field->file()), + ".descriptor"); } if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { printer->Print( @@ -560,11 +571,11 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable( " $scope$.getExtensions().get($index$),\n" " (com.google.protobuf.Message) defaultExtensionInstance);\n" "}\n", - "scope", scope, "index", StrCat(field->index()), "class", + "scope", scope, "index", y_absl::StrCat(field->index()), "class", name_resolver_->GetImmutableClassName(field->message_type())); } else { printer->Print("registry.add($scope$.getExtensions().get($index$));\n", - "scope", scope, "index", StrCat(field->index())); + "scope", scope, "index", y_absl::StrCat(field->index())); } } printer->Print( @@ -598,9 +609,9 @@ static void GenerateSibling( GeneratorClass* generator, void (GeneratorClass::*pfn)(io::Printer* printer)) { TProtoStringType filename = - package_dir + descriptor->name() + name_suffix + ".java"; + y_absl::StrCat(package_dir, descriptor->name(), name_suffix, ".java"); file_list->push_back(filename); - TProtoStringType info_full_path = filename + ".pb.meta"; + TProtoStringType info_full_path = y_absl::StrCat(filename, ".pb.meta"); GeneratedCodeInfo annotations; io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( &annotations); @@ -682,6 +693,23 @@ TProtoStringType FileGenerator::GetKotlinClassname() { return name_resolver_->GetFileClassName(file_, immutable_api_, true); } +void FileGenerator::GenerateKotlin(io::Printer* printer) { + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n", + "filename", file_->name()); + printer->Print( + "// Generated files should ignore deprecation warnings\n" + "@file:Suppress(\"DEPRECATION\")\n"); + if (!java_package_.empty()) { + printer->Print( + "package $package$;\n" + "\n", + "package", EscapeKotlinKeywords(java_package_)); + } +} + void FileGenerator::GenerateKotlinSiblings( const TProtoStringType& package_dir, GeneratorContext* context, std::vector<TProtoStringType>* file_list, @@ -692,9 +720,10 @@ void FileGenerator::GenerateKotlinSiblings( auto open_file = [context](const TProtoStringType& filename) { return std::unique_ptr<io::ZeroCopyOutputStream>(context->Open(filename)); }; - TProtoStringType filename = package_dir + descriptor->name() + "Kt.kt"; + TProtoStringType filename = + y_absl::StrCat(package_dir, descriptor->name(), "Kt.kt"); file_list->push_back(filename); - TProtoStringType info_full_path = filename + ".pb.meta"; + TProtoStringType info_full_path = y_absl::StrCat(filename, ".pb.meta"); GeneratedCodeInfo annotations; io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( &annotations); @@ -704,15 +733,18 @@ void FileGenerator::GenerateKotlinSiblings( options_.annotate_code ? &annotation_collector : nullptr); printer.Print( - "//Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "// source: $filename$\n" "\n", "filename", descriptor->file()->name()); + printer.Print( + "// Generated files should ignore deprecation warnings\n" + "@file:Suppress(\"DEPRECATION\")\n"); if (!java_package_.empty()) { printer.Print( "package $package$;\n" "\n", - "package", java_package_); + "package", EscapeKotlinKeywords(java_package_)); } generator->GenerateKotlinMembers(&printer); @@ -736,4 +768,4 @@ bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor, } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/file.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/file.h index 0063a18816a..c8934c4bfe2 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/file.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/file.h @@ -39,8 +39,8 @@ #include <string> #include <vector> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/java/options.h> +#include "google/protobuf/compiler/java/options.h" +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -70,6 +70,8 @@ class FileGenerator { public: FileGenerator(const FileDescriptor* file, const Options& options, bool immutable_api = true); + FileGenerator(const FileGenerator&) = delete; + FileGenerator& operator=(const FileGenerator&) = delete; ~FileGenerator(); // Checks for problems that would otherwise lead to cryptic compile errors. @@ -80,6 +82,7 @@ class FileGenerator { void Generate(io::Printer* printer); TProtoStringType GetKotlinClassname(); + void GenerateKotlin(io::Printer* printer); void GenerateKotlinSiblings(const TProtoStringType& package_dir, GeneratorContext* generator_context, std::vector<TProtoStringType>* file_list, @@ -114,8 +117,6 @@ class FileGenerator { ClassNameResolver* name_resolver_; const Options options_; bool immutable_api_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/generator.cc index 03be2a417eb..cac13d8cbce 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/generator.cc @@ -32,23 +32,22 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/generator.h> +#include "google/protobuf/compiler/java/generator.h" + +#include <utility> +#include <vector> #include <memory> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/stringprintf.h> -#include <google/protobuf/compiler/java/file.h> -#include <google/protobuf/compiler/java/generator_factory.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/compiler/java/options.h> -#include <google/protobuf/compiler/java/shared_code_generator.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/strings/str_format.h" +#include "google/protobuf/compiler/java/file.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/compiler/java/options.h" +#include "google/protobuf/compiler/java/shared_code_generator.h" +#include "google/protobuf/descriptor.pb.h" -#include <google/protobuf/stubs/strutil.h> namespace google { namespace protobuf { @@ -74,25 +73,27 @@ bool JavaGenerator::Generate(const FileDescriptor* file, ParseGeneratorParameter(parameter, &options); Options file_options; - for (int i = 0; i < options.size(); i++) { - if (options[i].first == "output_list_file") { - file_options.output_list_file = options[i].second; - } else if (options[i].first == "immutable") { + file_options.opensource_runtime = opensource_runtime_; + + for (auto& option : options) { + if (option.first == "output_list_file") { + file_options.output_list_file = option.second; + } else if (option.first == "immutable") { file_options.generate_immutable_code = true; - } else if (options[i].first == "mutable") { + } else if (option.first == "mutable") { file_options.generate_mutable_code = true; - } else if (options[i].first == "shared") { + } else if (option.first == "shared") { file_options.generate_shared_code = true; - } else if (options[i].first == "lite") { + } else if (option.first == "lite") { // Note: Java Lite does not guarantee API/ABI stability. We may choose to // break existing API in order to boost performance / reduce code size. file_options.enforce_lite = true; - } else if (options[i].first == "annotate_code") { + } else if (option.first == "annotate_code") { file_options.annotate_code = true; - } else if (options[i].first == "annotation_list_file") { - file_options.annotation_list_file = options[i].second; + } else if (option.first == "annotation_list_file") { + file_options.annotation_list_file = option.second; } else { - *error = "Unknown generator option: " + options[i].first; + *error = y_absl::StrCat("Unknown generator option: ", option.first); return false; } } @@ -117,35 +118,31 @@ bool JavaGenerator::Generate(const FileDescriptor* file, std::vector<TProtoStringType> all_annotations; - std::vector<FileGenerator*> file_generators; + std::vector<std::unique_ptr<FileGenerator>> file_generators; if (file_options.generate_immutable_code) { - file_generators.push_back(new FileGenerator(file, file_options, - /* immutable = */ true)); + file_generators.emplace_back( + std::make_unique<FileGenerator>(file, file_options, + /* immutable = */ true)); } if (file_options.generate_mutable_code) { - file_generators.push_back(new FileGenerator(file, file_options, - /* mutable = */ false)); + file_generators.emplace_back( + std::make_unique<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) { - delete file_generators[j]; - } + for (auto& file_generator : file_generators) { + if (!file_generator->Validate(error)) { return false; } } - for (int i = 0; i < file_generators.size(); ++i) { - FileGenerator* file_generator = file_generators[i]; - + for (auto& file_generator : file_generators) { TProtoStringType package_dir = JavaPackageToDir(file_generator->java_package()); - TProtoStringType java_filename = package_dir; - java_filename += file_generator->classname(); - java_filename += ".java"; + TProtoStringType java_filename = + y_absl::StrCat(package_dir, file_generator->classname(), ".java"); all_files.push_back(java_filename); - TProtoStringType info_full_path = java_filename + ".pb.meta"; + TProtoStringType info_full_path = y_absl::StrCat(java_filename, ".pb.meta"); if (file_options.annotate_code) { all_annotations.push_back(info_full_path); } @@ -174,9 +171,6 @@ bool JavaGenerator::Generate(const FileDescriptor* file, } - for (int i = 0; i < file_generators.size(); ++i) { - delete file_generators[i]; - } file_generators.clear(); // Generate output list if requested. diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/generator.h index e08c9807881..32225a07623 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/generator.h @@ -38,10 +38,11 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ #include <string> -#include <google/protobuf/compiler/code_generator.h> + +#include "google/protobuf/compiler/code_generator.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -55,6 +56,8 @@ namespace java { class PROTOC_EXPORT JavaGenerator : public CodeGenerator { public: JavaGenerator(); + JavaGenerator(const JavaGenerator&) = delete; + JavaGenerator& operator=(const JavaGenerator&) = delete; ~JavaGenerator() override; // implements CodeGenerator ---------------------------------------- @@ -63,8 +66,12 @@ class PROTOC_EXPORT JavaGenerator : public CodeGenerator { uint64_t GetSupportedFeatures() const override; + void set_opensource_runtime(bool opensource) { + opensource_runtime_ = opensource; + } + private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaGenerator); + bool opensource_runtime_ = PROTO2_IS_OSS; }; } // namespace java @@ -72,6 +79,6 @@ class PROTOC_EXPORT JavaGenerator : public CodeGenerator { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/generator_factory.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/generator_factory.cc index dd526ba7c73..86baf0b06d2 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/generator_factory.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/generator_factory.cc @@ -30,17 +30,17 @@ // Author: [email protected] (Pherl Liu) -#include <google/protobuf/compiler/java/generator_factory.h> +#include "google/protobuf/compiler/java/generator_factory.h" -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/enum_field.h> -#include <google/protobuf/compiler/java/extension.h> -#include <google/protobuf/compiler/java/extension_lite.h> -#include <google/protobuf/compiler/java/field.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/message.h> -#include <google/protobuf/compiler/java/message_lite.h> -#include <google/protobuf/compiler/java/service.h> +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/enum_field.h" +#include "google/protobuf/compiler/java/extension.h" +#include "google/protobuf/compiler/java/extension_lite.h" +#include "google/protobuf/compiler/java/field.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/message.h" +#include "google/protobuf/compiler/java/message_lite.h" +#include "google/protobuf/compiler/java/service.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/generator_factory.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/generator_factory.h index 807bca383a3..b2fb0546e99 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/generator_factory.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/generator_factory.h @@ -33,7 +33,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ -#include <google/protobuf/stubs/common.h> +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -59,6 +59,8 @@ namespace java { class GeneratorFactory { public: GeneratorFactory(); + GeneratorFactory(const GeneratorFactory&) = delete; + GeneratorFactory& operator=(const GeneratorFactory&) = delete; virtual ~GeneratorFactory(); virtual MessageGenerator* NewMessageGenerator( @@ -69,15 +71,15 @@ class GeneratorFactory { virtual ServiceGenerator* NewServiceGenerator( const ServiceDescriptor* descriptor) const = 0; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorFactory); }; // Factory that creates generators for immutable-default messages. class ImmutableGeneratorFactory : public GeneratorFactory { public: ImmutableGeneratorFactory(Context* context); + ImmutableGeneratorFactory(const ImmutableGeneratorFactory&) = delete; + ImmutableGeneratorFactory& operator=(const ImmutableGeneratorFactory&) = + delete; ~ImmutableGeneratorFactory() override; MessageGenerator* NewMessageGenerator( @@ -91,7 +93,6 @@ class ImmutableGeneratorFactory : public GeneratorFactory { private: Context* context_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableGeneratorFactory); }; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/helpers.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/helpers.cc index 96444c58fa3..ada6babab5b 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/helpers.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/helpers.cc @@ -32,25 +32,31 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/helpers.h> +#include "google/protobuf/compiler/java/helpers.h" #include <algorithm> #include <cstdint> #include <limits> -#include <unordered_set> #include <vector> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/stringprintf.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/compiler/java/names.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/stubs/hash.h> // for hash<T *> +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/strtod.h" +#include "google/protobuf/wire_format.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -65,78 +71,9 @@ const char kThickSeparator[] = const char kThinSeparator[] = "// -------------------------------------------------------------------\n"; -namespace { - -const char* kDefaultPackage = ""; - -// Names that should be avoided (in UpperCamelCase format). -// Using them will cause the compiler to generate accessors whose names -// collide with methods defined in base classes. -// Keep this list in sync with specialFieldNames in -// java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java -const char* kForbiddenWordList[] = { - // java.lang.Object: - "Class", - // com.google.protobuf.MessageLiteOrBuilder: - "DefaultInstanceForType", - // com.google.protobuf.MessageLite: - "ParserForType", - "SerializedSize", - // com.google.protobuf.MessageOrBuilder: - "AllFields", - "DescriptorForType", - "InitializationErrorString", - "UnknownFields", - // obsolete. kept for backwards compatibility of generated code - "CachedSize", -}; - -const std::unordered_set<TProtoStringType>* kReservedNames = - new std::unordered_set<TProtoStringType>({ - "abstract", "assert", "boolean", "break", "byte", - "case", "catch", "char", "class", "const", - "continue", "default", "do", "double", "else", - "enum", "extends", "final", "finally", "float", - "for", "goto", "if", "implements", "import", - "instanceof", "int", "interface", "long", "native", - "new", "package", "private", "protected", "public", - "return", "short", "static", "strictfp", "super", - "switch", "synchronized", "this", "throw", "throws", - "transient", "try", "void", "volatile", "while", - }); - -bool IsForbidden(const TProtoStringType& field_name) { - for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) { - if (UnderscoresToCamelCase(field_name, true) == kForbiddenWordList[i]) { - return true; - } - } - return false; -} - -TProtoStringType FieldName(const FieldDescriptor* field) { - TProtoStringType field_name; - // Groups are hacky: The name of the field is just the lower-cased name - // of the group type. In Java, though, we would like to retain the original - // capitalization of the type name. - if (GetType(field) == FieldDescriptor::TYPE_GROUP) { - field_name = field->message_type()->name(); - } else { - field_name = field->name(); - } - if (IsForbidden(field_name)) { - // Append a trailing "#" to indicate that the name should be decorated to - // avoid collision with other names. - field_name += "#"; - } - return field_name; -} - - -} // namespace - void PrintGeneratedAnnotation(io::Printer* printer, char delimiter, - const TProtoStringType& annotation_file) { + y_absl::string_view annotation_file, + Options options) { if (annotation_file.empty()) { return; } @@ -149,14 +86,14 @@ 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<TProtoStringType, TProtoStringType>& variables, - const char* var_name, - const char* terminating_string, bool enforce_lite) { +void PrintEnumVerifierLogic( + io::Printer* printer, const FieldDescriptor* descriptor, + const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& variables, + y_absl::string_view var_name, y_absl::string_view terminating_string, + bool enforce_lite) { TProtoStringType enum_verifier_string = - enforce_lite ? StrCat(var_name, ".internalGetVerifier()") - : StrCat( + enforce_lite ? y_absl::StrCat(var_name, ".internalGetVerifier()") + : y_absl::StrCat( "new com.google.protobuf.Internal.EnumVerifier() {\n" " @java.lang.Override\n" " public boolean isInRange(int number) {\n" @@ -165,14 +102,13 @@ void PrintEnumVerifierLogic(io::Printer* printer, ".forNumber(number) != null;\n" " }\n" " }"); - printer->Print( - variables, - StrCat(enum_verifier_string, terminating_string).c_str()); + printer->Print(variables, + y_absl::StrCat(enum_verifier_string, terminating_string)); } -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, +TProtoStringType UnderscoresToCamelCase(y_absl::string_view input, bool cap_next_letter) { - GOOGLE_CHECK(!input.empty()); + Y_ABSL_CHECK(!input.empty()); TProtoStringType result; // Note: I distrust ctype.h due to locales. for (int i = 0; i < input.size(); i++) { @@ -207,7 +143,7 @@ TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, return result; } -TProtoStringType ToCamelCase(const TProtoStringType& input, bool lower_first) { +TProtoStringType ToCamelCase(y_absl::string_view input, bool lower_first) { bool capitalize_next = !lower_first; TProtoStringType result; result.reserve(input.size()); @@ -216,7 +152,7 @@ TProtoStringType ToCamelCase(const TProtoStringType& input, bool lower_first) { if (i == '_') { capitalize_next = true; } else if (capitalize_next) { - result.push_back(ToUpperCh(i)); + result.push_back(y_absl::ascii_toupper(i)); capitalize_next = false; } else { result.push_back(i); @@ -225,146 +161,83 @@ TProtoStringType ToCamelCase(const TProtoStringType& input, bool lower_first) { // Lower-case the first letter. if (lower_first && !result.empty()) { - result[0] = ToLowerCh(result[0]); + result[0] = y_absl::ascii_tolower(result[0]); } return result; } -char ToUpperCh(char ch) { - return (ch >= 'a' && ch <= 'z') ? (ch - 'a' + 'A') : ch; -} - -char ToLowerCh(char ch) { - return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch; -} - -TProtoStringType UnderscoresToCamelCase(const FieldDescriptor* field) { - return UnderscoresToCamelCase(FieldName(field), false); -} - -TProtoStringType UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { - return UnderscoresToCamelCase(FieldName(field), true); -} - -TProtoStringType CapitalizedFieldName(const FieldDescriptor* field) { - return UnderscoresToCapitalizedCamelCase(field); -} - -TProtoStringType UnderscoresToCamelCase(const MethodDescriptor* method) { - return UnderscoresToCamelCase(method->name(), false); -} - -TProtoStringType UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) { - TProtoStringType name = UnderscoresToCamelCase(field); - if (kReservedNames->find(name) != kReservedNames->end()) { - return name + "_"; - } - return name; -} - // Names that should be avoided as field names in Kotlin. // All Kotlin hard keywords are in this list. -const std::unordered_set<TProtoStringType>* kKotlinForbiddenNames = - new std::unordered_set<TProtoStringType>({ - "as", "as?", "break", "class", "continue", "do", "else", - "false", "for", "fun", "if", "in", "!in", "interface", - "is", "!is", "null", "object", "package", "return", "super", - "this", "throw", "true", "try", "typealias", "typeof", "val", - "var", "when", "while", - }); - -bool IsForbiddenKotlin(const TProtoStringType& field_name) { - return kKotlinForbiddenNames->find(field_name) != - kKotlinForbiddenNames->end(); +bool IsForbiddenKotlin(y_absl::string_view field_name) { + static const auto& kKotlinForbiddenNames = + *new y_absl::flat_hash_set<y_absl::string_view>({ + "as", "as?", "break", "class", "continue", "do", + "else", "false", "for", "fun", "if", "in", + "!in", "interface", "is", "!is", "null", "object", + "package", "return", "super", "this", "throw", "true", + "try", "typealias", "typeof", "val", "var", "when", + "while", + }); + + return kKotlinForbiddenNames.contains(field_name); +} + +TProtoStringType EscapeKotlinKeywords(TProtoStringType name) { + std::vector<TProtoStringType> escaped_packages; + std::vector<TProtoStringType> packages = y_absl::StrSplit(name, "."); // NOLINT + for (y_absl::string_view package : packages) { + if (IsForbiddenKotlin(package)) { + escaped_packages.push_back(y_absl::StrCat("`", package, "`")); + } else { + escaped_packages.emplace_back(package); + } + } + return y_absl::StrJoin(escaped_packages, "."); } TProtoStringType UniqueFileScopeIdentifier(const Descriptor* descriptor) { - return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); + return y_absl::StrCat( + "static_", y_absl::StrReplaceAll(descriptor->full_name(), {{".", "_"}})); } TProtoStringType CamelCaseFieldName(const FieldDescriptor* field) { TProtoStringType fieldName = UnderscoresToCamelCase(field); if ('0' <= fieldName[0] && fieldName[0] <= '9') { - return '_' + fieldName; + return y_absl::StrCat("_", fieldName); } return fieldName; } TProtoStringType FileClassName(const FileDescriptor* file, bool immutable) { - ClassNameResolver name_resolver; - return name_resolver.GetFileClassName(file, immutable); -} - -TProtoStringType FileJavaPackage(const FileDescriptor* file, bool immutable) { - TProtoStringType result; - - if (file->options().has_java_package()) { - result = file->options().java_package(); - } else { - result = kDefaultPackage; - if (!file->package().empty()) { - if (!result.empty()) result += '.'; - result += file->package(); - } - } - - return result; -} - -TProtoStringType FileJavaPackage(const FileDescriptor* file) { - return FileJavaPackage(file, true /* immutable */); + return ClassNameResolver().GetFileClassName(file, immutable); } TProtoStringType JavaPackageToDir(TProtoStringType package_name) { - TProtoStringType package_dir = StringReplace(package_name, ".", "/", true); - if (!package_dir.empty()) package_dir += "/"; + TProtoStringType package_dir = y_absl::StrReplaceAll(package_name, {{".", "/"}}); + if (!package_dir.empty()) y_absl::StrAppend(&package_dir, "/"); return package_dir; } -TProtoStringType ClassName(const Descriptor* descriptor) { - ClassNameResolver name_resolver; - return name_resolver.GetClassName(descriptor, true); -} - -TProtoStringType ClassName(const EnumDescriptor* descriptor) { - ClassNameResolver name_resolver; - return name_resolver.GetClassName(descriptor, true); -} - -TProtoStringType ClassName(const ServiceDescriptor* descriptor) { - ClassNameResolver name_resolver; - return name_resolver.GetClassName(descriptor, true); -} - -TProtoStringType ClassName(const FileDescriptor* descriptor) { - ClassNameResolver name_resolver; - return name_resolver.GetClassName(descriptor, true); -} - - TProtoStringType ExtraMessageInterfaces(const Descriptor* descriptor) { - TProtoStringType interfaces = "// @@protoc_insertion_point(message_implements:" + - descriptor->full_name() + ")"; - return interfaces; + return y_absl::StrCat("// @@protoc_insertion_point(message_implements:", + descriptor->full_name(), ")"); } TProtoStringType ExtraBuilderInterfaces(const Descriptor* descriptor) { - TProtoStringType interfaces = "// @@protoc_insertion_point(builder_implements:" + - descriptor->full_name() + ")"; - return interfaces; + return y_absl::StrCat("// @@protoc_insertion_point(builder_implements:", + descriptor->full_name(), ")"); } TProtoStringType ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) { - TProtoStringType interfaces = "// @@protoc_insertion_point(interface_extends:" + - descriptor->full_name() + ")"; - return interfaces; + return y_absl::StrCat("// @@protoc_insertion_point(interface_extends:", + descriptor->full_name(), ")"); } TProtoStringType FieldConstantName(const FieldDescriptor* field) { - TProtoStringType name = field->name() + "_FIELD_NUMBER"; - ToUpper(&name); + TProtoStringType name = y_absl::StrCat(field->name(), "_FIELD_NUMBER"); + y_absl::AsciiStrToUpper(&name); return name; } @@ -414,11 +287,11 @@ JavaType GetJavaType(const FieldDescriptor* field) { // types are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return JAVATYPE_INT; } -const char* PrimitiveTypeName(JavaType type) { +y_absl::string_view PrimitiveTypeName(JavaType type) { switch (type) { case JAVATYPE_INT: return "int"; @@ -435,23 +308,23 @@ const char* PrimitiveTypeName(JavaType type) { case JAVATYPE_BYTES: return "com.google.protobuf.ByteString"; case JAVATYPE_ENUM: - return NULL; + return {}; case JAVATYPE_MESSAGE: - return NULL; + return {}; // No default because we want the compiler to complain if any new // JavaTypes are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + Y_ABSL_LOG(FATAL) << "Can't get here."; + return {}; } -const char* PrimitiveTypeName(const FieldDescriptor* descriptor) { +y_absl::string_view PrimitiveTypeName(const FieldDescriptor* descriptor) { return PrimitiveTypeName(GetJavaType(descriptor)); } -const char* BoxedPrimitiveTypeName(JavaType type) { +y_absl::string_view BoxedPrimitiveTypeName(JavaType type) { switch (type) { case JAVATYPE_INT: return "java.lang.Integer"; @@ -468,23 +341,23 @@ const char* BoxedPrimitiveTypeName(JavaType type) { case JAVATYPE_BYTES: return "com.google.protobuf.ByteString"; case JAVATYPE_ENUM: - return NULL; + return {}; case JAVATYPE_MESSAGE: - return NULL; + return {}; // No default because we want the compiler to complain if any new // JavaTypes are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + Y_ABSL_LOG(FATAL) << "Can't get here."; + return {}; } -const char* BoxedPrimitiveTypeName(const FieldDescriptor* descriptor) { +y_absl::string_view BoxedPrimitiveTypeName(const FieldDescriptor* descriptor) { return BoxedPrimitiveTypeName(GetJavaType(descriptor)); } -const char* KotlinTypeName(JavaType type) { +y_absl::string_view KotlinTypeName(JavaType type) { switch (type) { case JAVATYPE_INT: return "kotlin.Int"; @@ -501,16 +374,16 @@ const char* KotlinTypeName(JavaType type) { case JAVATYPE_BYTES: return "com.google.protobuf.ByteString"; case JAVATYPE_ENUM: - return NULL; + return {}; case JAVATYPE_MESSAGE: - return NULL; + return {}; // No default because we want the compiler to complain if any new // JavaTypes are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + Y_ABSL_LOG(FATAL) << "Can't get here."; + return {}; } TProtoStringType GetOneofStoredType(const FieldDescriptor* field) { @@ -519,13 +392,13 @@ TProtoStringType GetOneofStoredType(const FieldDescriptor* field) { case JAVATYPE_ENUM: return "java.lang.Integer"; case JAVATYPE_MESSAGE: - return ClassName(field->message_type()); + return ClassNameResolver().GetClassName(field->message_type(), true); default: - return BoxedPrimitiveTypeName(javaType); + return TProtoStringType(BoxedPrimitiveTypeName(javaType)); } } -const char* FieldTypeName(FieldDescriptor::Type field_type) { +y_absl::string_view FieldTypeName(FieldDescriptor::Type field_type) { switch (field_type) { case FieldDescriptor::TYPE_INT32: return "INT32"; @@ -568,11 +441,11 @@ const char* FieldTypeName(FieldDescriptor::Type field_type) { // types are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + Y_ABSL_LOG(FATAL) << "Can't get here."; + return {}; } -bool AllAscii(const TProtoStringType& text) { +bool AllAscii(y_absl::string_view text) { for (int i = 0; i < text.size(); i++) { if ((text[i] & 0x80) != 0) { return false; @@ -582,19 +455,19 @@ bool AllAscii(const TProtoStringType& text) { } TProtoStringType DefaultValue(const FieldDescriptor* field, bool immutable, - ClassNameResolver* name_resolver) { + ClassNameResolver* name_resolver, Options options) { // Switch on CppType since we need to know which default_value_* method // of FieldDescriptor to call. switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - return StrCat(field->default_value_int32()); + return y_absl::StrCat(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: // Need to print as a signed int since Java has no unsigned. - return StrCat(static_cast<arc_i32>(field->default_value_uint32())); + return y_absl::StrCat(static_cast<arc_i32>(field->default_value_uint32())); case FieldDescriptor::CPPTYPE_INT64: - return StrCat(field->default_value_int64()) + "L"; + return y_absl::StrCat(field->default_value_int64(), "L"); case FieldDescriptor::CPPTYPE_UINT64: - return StrCat(static_cast<arc_i64>(field->default_value_uint64())) + + return y_absl::StrCat(static_cast<arc_i64>(field->default_value_uint64())) + "L"; case FieldDescriptor::CPPTYPE_DOUBLE: { double value = field->default_value_double(); @@ -605,7 +478,7 @@ TProtoStringType DefaultValue(const FieldDescriptor* field, bool immutable, } else if (value != value) { return "Double.NaN"; } else { - return SimpleDtoa(value) + "D"; + return y_absl::StrCat(io::SimpleDtoa(value), "D"); } } case FieldDescriptor::CPPTYPE_FLOAT: { @@ -617,7 +490,7 @@ TProtoStringType DefaultValue(const FieldDescriptor* field, bool immutable, } else if (value != value) { return "Float.NaN"; } else { - return SimpleFtoa(value) + "F"; + return y_absl::StrCat(io::SimpleFtoa(value), "F"); } } case FieldDescriptor::CPPTYPE_BOOL: @@ -626,37 +499,40 @@ TProtoStringType DefaultValue(const FieldDescriptor* field, bool immutable, if (GetType(field) == FieldDescriptor::TYPE_BYTES) { if (field->has_default_value()) { // See comments in Internal.java for gory details. - return strings::Substitute( + return y_absl::Substitute( "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")", - CEscape(field->default_value_string())); + y_absl::CEscape(field->default_value_string())); } else { return "com.google.protobuf.ByteString.EMPTY"; } } else { if (AllAscii(field->default_value_string())) { // All chars are ASCII. In this case CEscape() works fine. - return "\"" + CEscape(field->default_value_string()) + "\""; + return y_absl::StrCat( + "\"", y_absl::CEscape(field->default_value_string()), "\""); } else { // See comments in Internal.java for gory details. - return strings::Substitute( + return y_absl::Substitute( "com.google.protobuf.Internal.stringDefaultValue(\"$0\")", - CEscape(field->default_value_string())); + y_absl::CEscape(field->default_value_string())); } } case FieldDescriptor::CPPTYPE_ENUM: - return name_resolver->GetClassName(field->enum_type(), immutable) + "." + - field->default_value_enum()->name(); + return y_absl::StrCat( + name_resolver->GetClassName(field->enum_type(), immutable), ".", + field->default_value_enum()->name()); case FieldDescriptor::CPPTYPE_MESSAGE: - return name_resolver->GetClassName(field->message_type(), immutable) + - ".getDefaultInstance()"; + return y_absl::StrCat( + name_resolver->GetClassName(field->message_type(), immutable), + ".getDefaultInstance()"); // No default because we want the compiler to complain if any new // types are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return ""; } @@ -688,7 +564,7 @@ bool IsDefaultValueJavaDefault(const FieldDescriptor* field) { // types are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return false; } @@ -697,7 +573,7 @@ bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field) { field->default_value_string() != ""; } -const char* bit_masks[] = { +constexpr y_absl::string_view bit_masks[] = { "0x00000001", "0x00000002", "0x00000004", "0x00000008", "0x00000010", "0x00000020", "0x00000040", "0x00000080", @@ -712,10 +588,7 @@ const char* bit_masks[] = { }; TProtoStringType GetBitFieldName(int index) { - TProtoStringType varName = "bitField"; - varName += StrCat(index); - varName += "_"; - return varName; + return y_absl::StrCat("bitField", index, "_"); } TProtoStringType GetBitFieldNameForBit(int bitIndex) { @@ -724,22 +597,19 @@ TProtoStringType GetBitFieldNameForBit(int bitIndex) { namespace { -TProtoStringType GenerateGetBitInternal(const TProtoStringType& prefix, int bitIndex) { - TProtoStringType varName = prefix + GetBitFieldNameForBit(bitIndex); +TProtoStringType GenerateGetBitInternal(y_absl::string_view prefix, int bitIndex) { + TProtoStringType varName = y_absl::StrCat(prefix, GetBitFieldNameForBit(bitIndex)); int bitInVarIndex = bitIndex % 32; - TProtoStringType mask = bit_masks[bitInVarIndex]; - TProtoStringType result = "((" + varName + " & " + mask + ") != 0)"; - return result; + return y_absl::StrCat("((", varName, " & ", bit_masks[bitInVarIndex], + ") != 0)"); } -TProtoStringType GenerateSetBitInternal(const TProtoStringType& prefix, int bitIndex) { - TProtoStringType varName = prefix + GetBitFieldNameForBit(bitIndex); +TProtoStringType GenerateSetBitInternal(y_absl::string_view prefix, int bitIndex) { + TProtoStringType varName = y_absl::StrCat(prefix, GetBitFieldNameForBit(bitIndex)); int bitInVarIndex = bitIndex % 32; - TProtoStringType mask = bit_masks[bitInVarIndex]; - TProtoStringType result = varName + " |= " + mask; - return result; + return y_absl::StrCat(varName, " |= ", bit_masks[bitInVarIndex]); } } // namespace @@ -756,9 +626,8 @@ TProtoStringType GenerateClearBit(int bitIndex) { TProtoStringType varName = GetBitFieldNameForBit(bitIndex); int bitInVarIndex = bitIndex % 32; - TProtoStringType mask = bit_masks[bitInVarIndex]; - TProtoStringType result = varName + " = (" + varName + " & ~" + mask + ")"; - return result; + return y_absl::StrCat(varName, " = (", varName, " & ~", + bit_masks[bitInVarIndex], ")"); } TProtoStringType GenerateGetBitFromLocal(int bitIndex) { @@ -802,11 +671,12 @@ bool IsReferenceType(JavaType type) { // JavaTypes are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return false; } -const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) { +y_absl::string_view GetCapitalizedType(const FieldDescriptor* field, + bool immutable, Options options) { switch (GetType(field)) { case FieldDescriptor::TYPE_INT32: return "Int32"; @@ -850,8 +720,8 @@ const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) { // types are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + Y_ABSL_LOG(FATAL) << "Can't get here."; + return {}; } // For encodings with fixed sizes, returns that size in bytes. Otherwise @@ -900,7 +770,7 @@ int FixedSize(FieldDescriptor::Type type) { // No default because we want the compiler to complain if any new // types are added. } - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; return -1; } @@ -923,7 +793,7 @@ 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, - std::unordered_set<const Descriptor*>* already_seen) { + y_absl::flat_hash_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. @@ -958,7 +828,7 @@ bool HasRequiredFields(const Descriptor* type, } bool HasRequiredFields(const Descriptor* type) { - std::unordered_set<const Descriptor*> already_seen; + y_absl::flat_hash_set<const Descriptor*> already_seen; return HasRequiredFields(type, &already_seen); } @@ -1036,7 +906,7 @@ int GetExperimentalJavaFieldTypeForPacked(const FieldDescriptor* field) { } else if (result > FieldDescriptor::TYPE_BYTES) { return result + 30; } else { - GOOGLE_LOG(FATAL) << field->full_name() << " can't be packed."; + Y_ABSL_LOG(FATAL) << field->full_name() << " can't be packed."; return 0; } } @@ -1103,7 +973,7 @@ void EscapeUtf16ToString(uint16_t code, TProtoStringType* output) { } else if (code >= 0x20 && code <= 0x7f) { output->push_back(static_cast<char>(code)); } else { - output->append(StringPrintf("\\u%04x", code)); + output->append(y_absl::StrFormat("\\u%04x", code)); } } @@ -1112,4 +982,4 @@ void EscapeUtf16ToString(uint16_t code, TProtoStringType* output) { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/helpers.h index 7f4c4aad144..e4fac634264 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/helpers.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/helpers.h @@ -38,10 +38,15 @@ #include <cstdint> #include <string> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/strings/string_view.h" +#include "google/protobuf/compiler/java/names.h" +#include "google/protobuf/compiler/java/options.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" + +// Must be last. +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -53,7 +58,7 @@ namespace java { extern const char kThickSeparator[]; extern const char kThinSeparator[]; -bool IsForbiddenKotlin(const TProtoStringType& field_name); +bool IsForbiddenKotlin(y_absl::string_view field_name); // If annotation_file is non-empty, prints a javax.annotation.Generated // annotation to the given Printer. annotation_file will be referenced in the @@ -64,38 +69,20 @@ bool IsForbiddenKotlin(const TProtoStringType& field_name); // 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 TProtoStringType& annotation_file = ""); + y_absl::string_view annotation_file = "", + Options options = {}); // 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<TProtoStringType, TProtoStringType>& 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. -TProtoStringType ToCamelCase(const TProtoStringType& input, bool lower_first); - -char ToUpperCh(char ch); -char ToLowerCh(char ch); +void PrintEnumVerifierLogic( + io::Printer* printer, const FieldDescriptor* descriptor, + const y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>& variables, + y_absl::string_view var_name, y_absl::string_view terminating_string, + bool enforce_lite); // Converts a name to camel-case. If cap_first_letter is true, capitalize the // first letter. -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& name, - bool cap_first_letter); -// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes -// "fooBarBaz" or "FooBarBaz", respectively. -TProtoStringType UnderscoresToCamelCase(const FieldDescriptor* field); -TProtoStringType UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); - -// Similar, but for method names. (Typically, this merely has the effect -// of lower-casing the first letter of the name.) -TProtoStringType UnderscoresToCamelCase(const MethodDescriptor* method); - -// Same as UnderscoresToCamelCase, but checks for reserved keywords -TProtoStringType UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field); +TProtoStringType ToCamelCase(y_absl::string_view input, bool lower_first); // Similar to UnderscoresToCamelCase, but guarantees that the result is a // complete Java identifier by adding a _ if needed. @@ -113,11 +100,15 @@ TProtoStringType UniqueFileScopeIdentifier(const Descriptor* descriptor); TProtoStringType FileClassName(const FileDescriptor* file, bool immutable = true); // Returns the file's Java package name. -TProtoStringType FileJavaPackage(const FileDescriptor* file, bool immutable); +TProtoStringType FileJavaPackage(const FileDescriptor* file, bool immutable, + Options options = {}); // Returns output directory for the given package name. TProtoStringType JavaPackageToDir(TProtoStringType package_name); +// Returns the name with Kotlin keywords enclosed in backticks +TProtoStringType EscapeKotlinKeywords(TProtoStringType name); + // Comma-separate list of option-specified interfaces implemented by the // Message, to follow the "implements" declaration of the Message definition. TProtoStringType ExtraMessageInterfaces(const Descriptor* descriptor); @@ -194,20 +185,8 @@ inline bool IsOwnFile(const ServiceDescriptor* descriptor, bool immutable) { // (e.g.) be "OrBuilder" for some generated interfaces. template <typename Descriptor> TProtoStringType AnnotationFileName(const Descriptor* descriptor, - const TProtoStringType& suffix) { - return descriptor->name() + suffix + ".java.pb.meta"; -} - -template <typename Descriptor> -void MaybePrintGeneratedAnnotation(Context* context, io::Printer* printer, - Descriptor* descriptor, bool immutable, - const TProtoStringType& suffix = "") { - if (IsOwnFile(descriptor, immutable)) { - PrintGeneratedAnnotation(printer, '$', - context->options().annotate_code - ? AnnotationFileName(descriptor, suffix) - : ""); - } + y_absl::string_view suffix) { + return y_absl::StrCat(descriptor->name(), suffix, ".java.pb.meta"); } // Get the unqualified name that should be used for a field's field @@ -233,28 +212,30 @@ enum JavaType { JavaType GetJavaType(const FieldDescriptor* field); -const char* PrimitiveTypeName(JavaType type); +y_absl::string_view PrimitiveTypeName(JavaType type); // Get the fully-qualified class name for a boxed primitive type, e.g. // "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message // types. -const char* BoxedPrimitiveTypeName(JavaType type); +y_absl::string_view BoxedPrimitiveTypeName(JavaType type); // Kotlin source does not distinguish between primitives and non-primitives, // but does use Kotlin-specific qualified types for them. -const char* KotlinTypeName(JavaType type); +y_absl::string_view KotlinTypeName(JavaType type); // Get the name of the java enum constant representing this type. E.g., // "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full // name is "com.google.protobuf.WireFormat.FieldType.INT32". -const char* FieldTypeName(const FieldDescriptor::Type field_type); +y_absl::string_view FieldTypeName(const FieldDescriptor::Type field_type); class ClassNameResolver; TProtoStringType DefaultValue(const FieldDescriptor* field, bool immutable, - ClassNameResolver* name_resolver); + ClassNameResolver* name_resolver, + Options options = {}); inline TProtoStringType ImmutableDefaultValue(const FieldDescriptor* field, - ClassNameResolver* name_resolver) { - return DefaultValue(field, true, name_resolver); + ClassNameResolver* name_resolver, + Options options = {}) { + return DefaultValue(field, true, name_resolver, options); } bool IsDefaultValueJavaDefault(const FieldDescriptor* field); bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field); @@ -333,7 +314,8 @@ bool IsReferenceType(JavaType type); // Returns the capitalized name for calling relative functions in // CodedInputStream -const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable); +y_absl::string_view GetCapitalizedType(const FieldDescriptor* field, + bool immutable, Options options); // For encodings with fixed sizes, returns that size in bytes. Otherwise // returns -1. @@ -471,4 +453,5 @@ std::pair<int, int> GetTableDrivenNumberOfEntriesAndLookUpStartFieldNumber( } // namespace protobuf } // namespace google +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/kotlin_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/kotlin_generator.cc index 570840cfc13..90235f6cb8e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/kotlin_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/kotlin_generator.cc @@ -28,13 +28,13 @@ // (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/java/kotlin_generator.h> +#include "google/protobuf/compiler/java/kotlin_generator.h" -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/java/file.h> -#include <google/protobuf/compiler/java/generator.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/options.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/java/file.h" +#include "google/protobuf/compiler/java/generator.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/options.h" namespace google { namespace protobuf { @@ -78,7 +78,7 @@ bool KotlinGenerator::Generate(const FileDescriptor* file, } else if (option.first == "annotation_list_file") { file_options.annotation_list_file = option.second; } else { - *error = "Unknown generator option: " + option.first; + *error = y_absl::StrCat("Unknown generator option: ", option.first); return false; } } @@ -101,11 +101,10 @@ bool KotlinGenerator::Generate(const FileDescriptor* file, return std::unique_ptr<io::ZeroCopyOutputStream>(context->Open(filename)); }; TProtoStringType package_dir = JavaPackageToDir(file_generator->java_package()); - TProtoStringType kotlin_filename = package_dir; - kotlin_filename += file_generator->GetKotlinClassname(); - kotlin_filename += ".kt"; + TProtoStringType kotlin_filename = + y_absl::StrCat(package_dir, file_generator->GetKotlinClassname(), ".kt"); all_files.push_back(kotlin_filename); - TProtoStringType info_full_path = kotlin_filename + ".pb.meta"; + TProtoStringType info_full_path = y_absl::StrCat(kotlin_filename, ".pb.meta"); if (file_options.annotate_code) { all_annotations.push_back(info_full_path); } @@ -119,6 +118,8 @@ bool KotlinGenerator::Generate(const FileDescriptor* file, output.get(), '$', file_options.annotate_code ? &annotation_collector : nullptr); + file_generator->GenerateKotlin(&printer); + file_generator->GenerateKotlinSiblings(package_dir, context, &all_files, &all_annotations); diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/kotlin_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/kotlin_generator.h index 195acb65375..91c4b836c55 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/kotlin_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/kotlin_generator.h @@ -35,10 +35,10 @@ #include <string> -#include <google/protobuf/compiler/code_generator.h> +#include "google/protobuf/compiler/code_generator.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -52,6 +52,8 @@ namespace java { class PROTOC_EXPORT KotlinGenerator : public CodeGenerator { public: KotlinGenerator(); + KotlinGenerator(const KotlinGenerator&) = delete; + KotlinGenerator& operator=(const KotlinGenerator&) = delete; ~KotlinGenerator() override; // implements CodeGenerator ---------------------------------------- @@ -59,9 +61,6 @@ class PROTOC_EXPORT KotlinGenerator : public CodeGenerator { GeneratorContext* context, TProtoStringType* error) const override; uint64_t GetSupportedFeatures() const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(KotlinGenerator); }; } // namespace java @@ -69,6 +68,6 @@ class PROTOC_EXPORT KotlinGenerator : public CodeGenerator { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field.cc index 37bad491c06..8c3be3c0966 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field.cc @@ -28,16 +28,17 @@ // (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/java/map_field.h> +#include "google/protobuf/compiler/java/map_field.h" -#include <google/protobuf/io/printer.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -47,16 +48,16 @@ namespace java { namespace { const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) { - GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); + Y_ABSL_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); const Descriptor* message = descriptor->message_type(); - GOOGLE_CHECK(message->options().map_entry()); + Y_ABSL_CHECK(message->options().map_entry()); return message->map_key(); } const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) { - GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); + Y_ABSL_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); const Descriptor* message = descriptor->message_type(); - GOOGLE_CHECK(message->options().map_entry()); + Y_ABSL_CHECK(message->options().map_entry()); return message->map_value(); } @@ -67,8 +68,8 @@ TProtoStringType TypeName(const FieldDescriptor* field, } else if (GetJavaType(field) == JAVATYPE_ENUM) { return name_resolver->GetImmutableClassName(field->enum_type()); } else { - return boxed ? BoxedPrimitiveTypeName(GetJavaType(field)) - : PrimitiveTypeName(GetJavaType(field)); + return TProtoStringType(boxed ? BoxedPrimitiveTypeName(GetJavaType(field)) + : PrimitiveTypeName(GetJavaType(field))); } } @@ -79,19 +80,19 @@ TProtoStringType KotlinTypeName(const FieldDescriptor* field, } else if (GetJavaType(field) == JAVATYPE_ENUM) { return name_resolver->GetImmutableClassName(field->enum_type()); } else { - return KotlinTypeName(GetJavaType(field)); + return TProtoStringType(KotlinTypeName(GetJavaType(field))); } } TProtoStringType WireType(const FieldDescriptor* field) { - return "com.google.protobuf.WireFormat.FieldType." + - TProtoStringType(FieldTypeName(field->type())); + return y_absl::StrCat("com.google.protobuf.WireFormat.FieldType.", + FieldTypeName(field->type())); } -void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, const FieldGeneratorInfo* info, - Context* context, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetMessageVariables( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, Context* context, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { SetCommonFieldVariables(descriptor, info, variables); ClassNameResolver* name_resolver = context->GetNameResolver(); @@ -102,7 +103,12 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, const JavaType keyJavaType = GetJavaType(key); const JavaType valueJavaType = GetJavaType(value); - TProtoStringType pass_through_nullness = "/* nullable */\n"; + // The code that generates the open-source version appears not to understand + // #else, so we have an #ifndef instead. + TProtoStringType pass_through_nullness = + context->options().opensource_runtime + ? "/* nullable */\n" + : "@com.google.protobuf.Internal.ProtoPassThroughNullness "; (*variables)["key_type"] = TypeName(key, name_resolver, false); TProtoStringType boxed_key_type = TypeName(key, name_resolver, true); @@ -113,78 +119,89 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, (*variables)["short_key_type"] = boxed_key_type.substr(boxed_key_type.rfind('.') + 1); (*variables)["key_wire_type"] = WireType(key); - (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver); + (*variables)["key_default_value"] = + DefaultValue(key, true, name_resolver, context->options()); (*variables)["key_null_check"] = IsReferenceType(keyJavaType) ? "if (key == null) { throw new NullPointerException(\"map key\"); }" : ""; (*variables)["value_null_check"] = valueJavaType != JAVATYPE_ENUM && IsReferenceType(valueJavaType) - ? "if (value == null) {\n" - " throw new NullPointerException(\"map value\");\n" - "}\n" + ? "if (value == null) { " + "throw new NullPointerException(\"map value\"); }" : ""; if (valueJavaType == JAVATYPE_ENUM) { // We store enums as Integers internally. (*variables)["value_type"] = "int"; + variables->insert( + {"value_type_pass_through_nullness", (*variables)["value_type"]}); (*variables)["boxed_value_type"] = "java.lang.Integer"; (*variables)["value_wire_type"] = WireType(value); (*variables)["value_default_value"] = - DefaultValue(value, true, name_resolver) + ".getNumber()"; + DefaultValue(value, true, name_resolver, context->options()) + + ".getNumber()"; (*variables)["value_enum_type"] = TypeName(value, name_resolver, false); - (*variables)["value_enum_type_pass_through_nullness"] = - pass_through_nullness + (*variables)["value_enum_type"]; + variables->insert( + {"value_enum_type_pass_through_nullness", + y_absl::StrCat(pass_through_nullness, (*variables)["value_enum_type"])}); if (SupportUnknownEnumValue(descriptor->file())) { // Map unknown values to a special UNRECOGNIZED value if supported. - (*variables)["unrecognized_value"] = - (*variables)["value_enum_type"] + ".UNRECOGNIZED"; + variables->insert( + {"unrecognized_value", + y_absl::StrCat((*variables)["value_enum_type"], ".UNRECOGNIZED")}); } else { // Map unknown values to the default value if we don't have UNRECOGNIZED. (*variables)["unrecognized_value"] = - DefaultValue(value, true, name_resolver); + DefaultValue(value, true, name_resolver, context->options()); } } else { (*variables)["value_type"] = TypeName(value, name_resolver, false); - (*variables)["value_type_pass_through_nullness"] = - (IsReferenceType(valueJavaType) ? pass_through_nullness : "") + - (*variables)["value_type"]; + variables->insert( + {"value_type_pass_through_nullness", + y_absl::StrCat( + (IsReferenceType(valueJavaType) ? pass_through_nullness : ""), + (*variables)["value_type"])}); (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true); (*variables)["value_wire_type"] = WireType(value); (*variables)["value_default_value"] = - DefaultValue(value, true, name_resolver); + DefaultValue(value, true, name_resolver, context->options()); } - (*variables)["type_parameters"] = - (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; + variables->insert( + {"type_parameters", y_absl::StrCat((*variables)["boxed_key_type"], ", ", + (*variables)["boxed_value_type"])}); // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["kt_deprecation"] = - descriptor->options().deprecated() - ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + - " is deprecated\") " - : ""; + variables->insert( + {"kt_deprecation", + descriptor->options().deprecated() + ? y_absl::StrCat("@kotlin.Deprecated(message = \"Field ", + (*variables)["name"], " is deprecated\") ") + : ""}); (*variables)["on_changed"] = "onChanged();"; - // For repeated fields, one bit is used for whether the array is immutable - // in the parsing constructor. - (*variables)["get_mutable_bit_parser"] = - GenerateGetBitMutableLocal(builderBitIndex); - (*variables)["set_mutable_bit_parser"] = - GenerateSetBitMutableLocal(builderBitIndex); - - (*variables)["default_entry"] = - (*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry"; - (*variables)["map_field_parameter"] = (*variables)["default_entry"]; - (*variables)["descriptor"] = - name_resolver->GetImmutableClassName(descriptor->file()) + ".internal_" + - UniqueFileScopeIdentifier(descriptor->message_type()) + "_descriptor, "; + variables->insert( + {"default_entry", y_absl::StrCat((*variables)["capitalized_name"], + "DefaultEntryHolder.defaultEntry")}); + variables->insert({"map_field_parameter", (*variables)["default_entry"]}); + (*variables)["descriptor"] = y_absl::StrCat( + name_resolver->GetImmutableClassName(descriptor->file()), ".internal_", + UniqueFileScopeIdentifier(descriptor->message_type()), "_descriptor, "); (*variables)["ver"] = GeneratedCodeVersionSuffix(); + + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_builder"] = + y_absl::StrCat(GenerateSetBit(builderBitIndex), ";"); + (*variables)["clear_has_field_bit_builder"] = + y_absl::StrCat(GenerateClearBit(builderBitIndex), ";"); } } // namespace @@ -192,7 +209,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, ImmutableMapFieldGenerator::ImmutableMapFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), + message_bit_index_(messageBitIndex), + builder_bit_index_(builderBitIndex), + name_resolver_(context->GetNameResolver()), + context_(context) { SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), context, &variables_); @@ -200,6 +221,14 @@ ImmutableMapFieldGenerator::ImmutableMapFieldGenerator( ImmutableMapFieldGenerator::~ImmutableMapFieldGenerator() {} +int ImmutableMapFieldGenerator::GetMessageBitIndex() const { + return message_bit_index_; +} + +int ImmutableMapFieldGenerator::GetBuilderBitIndex() const { + return builder_bit_index_; +} + int ImmutableMapFieldGenerator::GetNumBitsForMessage() const { return 0; } int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const { return 1; } @@ -216,14 +245,16 @@ void ImmutableMapFieldGenerator::GenerateInterfaceMembers( " $key_type$ key);\n"); printer->Annotate("{", "}", descriptor_); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { - printer->Print(variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); + } WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -261,27 +292,29 @@ void ImmutableMapFieldGenerator::GenerateInterfaceMembers( printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" + "$deprecation$$value_type_pass_through_nullness$ " + "${$get$capitalized_name$ValueOrDefault$}$(\n" " $key_type$ key,\n" - " $value_type$ defaultValue);\n"); + " $value_type_pass_through_nullness$ defaultValue);\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" - " $key_type$ key);\n"); + printer->Print( + variables_, + "$deprecation$$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" + " $key_type$ key);\n"); printer->Annotate("{", "}", descriptor_); } } else { - printer->Print(variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "java.util.Map<$type_parameters$>\n" - "${$get$capitalized_name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "java.util.Map<$type_parameters$>\n" + "${$get$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$java.util.Map<$type_parameters$>\n" @@ -289,17 +322,16 @@ void ImmutableMapFieldGenerator::GenerateInterfaceMembers( printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$\n" - "$value_type_pass_through_nullness$ " + "$deprecation$$value_type_pass_through_nullness$ " "${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" " $value_type_pass_through_nullness$ defaultValue);\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n" - " $key_type$ key);\n"); + printer->Print( + variables_, + "$deprecation$$value_type$ ${$get$capitalized_name$OrThrow$}$(\n" + " $key_type$ key);\n"); printer->Annotate("{", "}", descriptor_); } } @@ -319,6 +351,7 @@ void ImmutableMapFieldGenerator::GenerateMembers(io::Printer* printer) const { " $value_default_value$);\n" "}\n"); printer->Print(variables_, + "@SuppressWarnings(\"serial\")\n" "private com.google.protobuf.MapField<\n" " $type_parameters$> $name$_;\n" "private com.google.protobuf.MapField<$type_parameters$>\n" @@ -354,42 +387,45 @@ void ImmutableMapFieldGenerator::GenerateMembers(io::Printer* printer) const { void ImmutableMapFieldGenerator::GenerateBuilderMembers( io::Printer* printer) const { - printer->Print(variables_, - "private com.google.protobuf.MapField<\n" - " $type_parameters$> $name$_;\n" - "private com.google.protobuf.MapField<$type_parameters$>\n" - "internalGet$capitalized_name$() {\n" - " if ($name$_ == null) {\n" - " return com.google.protobuf.MapField.emptyMapField(\n" - " $map_field_parameter$);\n" - " }\n" - " return $name$_;\n" - "}\n" - "private com.google.protobuf.MapField<$type_parameters$>\n" - "internalGetMutable$capitalized_name$() {\n" - " $on_changed$;\n" - " if ($name$_ == null) {\n" - " $name$_ = com.google.protobuf.MapField.newMapField(\n" - " $map_field_parameter$);\n" - " }\n" - " if (!$name$_.isMutable()) {\n" - " $name$_ = $name$_.copy();\n" - " }\n" - " return $name$_;\n" - "}\n"); + printer->Print( + variables_, + "private com.google.protobuf.MapField<\n" + " $type_parameters$> $name$_;\n" + "$deprecation$private com.google.protobuf.MapField<$type_parameters$>\n" + " internalGet$capitalized_name$() {\n" + " if ($name$_ == null) {\n" + " return com.google.protobuf.MapField.emptyMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n" + "$deprecation$private com.google.protobuf.MapField<$type_parameters$>\n" + " internalGetMutable$capitalized_name$() {\n" + " if ($name$_ == null) {\n" + " $name$_ = com.google.protobuf.MapField.newMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " if (!$name$_.isMutable()) {\n" + " $name$_ = $name$_.copy();\n" + " }\n" + " $set_has_field_bit_builder$\n" + " $on_changed$\n" + " return $name$_;\n" + "}\n"); GenerateMapGetters(printer); - printer->Print(variables_, - "$deprecation$\n" - "public Builder ${$clear$capitalized_name$$}$() {\n" - " internalGetMutable$capitalized_name$().getMutableMap()\n" - " .clear();\n" - " return this;\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" + " $clear_has_field_bit_builder$\n" + " internalGetMutable$capitalized_name$().getMutableMap()\n" + " .clear();\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); + WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$\n" - "public Builder ${$remove$capitalized_name$$}$(\n" + "$deprecation$public Builder ${$remove$capitalized_name$$}$(\n" " $key_type$ key) {\n" " $key_null_check$\n" " internalGetMutable$capitalized_name$().getMutableMap()\n" @@ -397,19 +433,24 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers( " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); + if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { - printer->Print( - variables_, - "/**\n" - " * Use alternate mutation accessors instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$getMutable$capitalized_name$$}$() {\n" - " return internalGetAdapted$capitalized_name$Map(\n" - " internalGetMutable$capitalized_name$().getMutableMap());\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print( + variables_, + "/**\n" + " * Use alternate mutation accessors instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + " ${$getMutable$capitalized_name$$}$() {\n" + " $set_has_field_bit_builder$\n" + " return internalGetAdapted$capitalized_name$Map(\n" + " internalGetMutable$capitalized_name$().getMutableMap());\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + } + WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public Builder ${$put$capitalized_name$$}$(\n" @@ -419,9 +460,11 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers( " $value_null_check$\n" " internalGetMutable$capitalized_name$().getMutableMap()\n" " .put(key, $name$ValueConverter.doBackward(value));\n" + " $set_has_field_bit_builder$\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); + WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -430,21 +473,27 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers( " internalGetAdapted$capitalized_name$Map(\n" " internalGetMutable$capitalized_name$().getMutableMap())\n" " .putAll(values);\n" + " $set_has_field_bit_builder$\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); + if (SupportUnknownEnumValue(descriptor_->file())) { - printer->Print( - variables_, - "/**\n" - " * Use alternate mutation accessors instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" - "${$getMutable$capitalized_name$Value$}$() {\n" - " return internalGetMutable$capitalized_name$().getMutableMap();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print( + variables_, + "/**\n" + " * Use alternate mutation accessors instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" + "${$getMutable$capitalized_name$Value$}$() {\n" + " $set_has_field_bit_builder$\n" + " return internalGetMutable$capitalized_name$().getMutableMap();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + } + WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -455,9 +504,11 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers( " $value_null_check$\n" " internalGetMutable$capitalized_name$().getMutableMap()\n" " .put(key, value);\n" + " $set_has_field_bit_builder$\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); + WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -465,95 +516,107 @@ void ImmutableMapFieldGenerator::GenerateBuilderMembers( " java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n" " internalGetMutable$capitalized_name$().getMutableMap()\n" " .putAll(values);\n" + " $set_has_field_bit_builder$\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); } } else { - printer->Print( - variables_, - "/**\n" - " * Use alternate mutation accessors instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$type_parameters$>\n" - "${$getMutable$capitalized_name$$}$() {\n" - " return internalGetMutable$capitalized_name$().getMutableMap();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print( + variables_, + "/**\n" + " * Use alternate mutation accessors instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$type_parameters$>\n" + " ${$getMutable$capitalized_name$$}$() {\n" + " $set_has_field_bit_builder$\n" + " return internalGetMutable$capitalized_name$().getMutableMap();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + } + WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$" - "public Builder ${$put$capitalized_name$$}$(\n" + "$deprecation$public Builder ${$put$capitalized_name$$}$(\n" " $key_type$ key,\n" " $value_type$ value) {\n" " $key_null_check$\n" " $value_null_check$\n" " internalGetMutable$capitalized_name$().getMutableMap()\n" " .put(key, value);\n" + " $set_has_field_bit_builder$\n" " return this;\n" "}\n"); printer->Annotate("{", "}", descriptor_); + WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$\n" - "public Builder ${$putAll$capitalized_name$$}$(\n" - " java.util.Map<$type_parameters$> values) {\n" - " internalGetMutable$capitalized_name$().getMutableMap()\n" - " .putAll(values);\n" - " return this;\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n" + " java.util.Map<$type_parameters$> values) {\n" + " internalGetMutable$capitalized_name$().getMutableMap()\n" + " .putAll(values);\n" + " $set_has_field_bit_builder$\n" + " return this;\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } } void ImmutableMapFieldGenerator::GenerateMapGetters( io::Printer* printer) const { - printer->Print(variables_, - "$deprecation$\n" - "public int ${$get$capitalized_name$Count$}$() {\n" - " return internalGet$capitalized_name$().getMap().size();\n" - "}\n"); + printer->Print( + variables_, + "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n" + " return internalGet$capitalized_name$().getMap().size();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); + WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, - "$deprecation$\n" "@java.lang.Override\n" - "public boolean ${$contains$capitalized_name$$}$(\n" + "$deprecation$public boolean ${$contains$capitalized_name$$}$(\n" " $key_type$ key) {\n" " $key_null_check$\n" " return internalGet$capitalized_name$().getMap().containsKey(key);\n" "}\n"); printer->Annotate("{", "}", descriptor_); + if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { - printer->Print(variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Override\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print( + variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Override\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + } + WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "@java.lang.Override\n" - "$deprecation$\n" - "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "$deprecation$public java.util.Map<$boxed_key_type$, " + "$value_enum_type$>\n" "${$get$capitalized_name$Map$}$() {\n" " return internalGetAdapted$capitalized_name$Map(\n" " internalGet$capitalized_name$().getMap());" "}\n"); printer->Annotate("{", "}", descriptor_); + WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, "@java.lang.Override\n" - "$deprecation$\n" - "public $value_enum_type_pass_through_nullness$ " + "$deprecation$public $value_enum_type_pass_through_nullness$ " "${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" " $value_enum_type_pass_through_nullness$ defaultValue) {\n" @@ -565,12 +628,12 @@ void ImmutableMapFieldGenerator::GenerateMapGetters( " : defaultValue;\n" "}\n"); printer->Annotate("{", "}", descriptor_); + WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, "@java.lang.Override\n" - "$deprecation$\n" - "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n" + "$deprecation$public $value_enum_type$ get$capitalized_name$OrThrow(\n" " $key_type$ key) {\n" " $key_null_check$\n" " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n" @@ -581,6 +644,7 @@ void ImmutableMapFieldGenerator::GenerateMapGetters( " return $name$ValueConverter.doForward(map.get(key));\n" "}\n"); printer->Annotate("{", "}", descriptor_); + if (SupportUnknownEnumValue(descriptor_->file())) { printer->Print( variables_, @@ -595,23 +659,22 @@ void ImmutableMapFieldGenerator::GenerateMapGetters( "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$\n" - "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" - "${$get$capitalized_name$ValueMap$}$() {\n" - " return internalGet$capitalized_name$().getMap();\n" - "}\n"); + printer->Print(variables_, + "@java.lang.Override\n" + "$deprecation$public java.util.Map<$boxed_key_type$, " + "$boxed_value_type$>\n" + "${$get$capitalized_name$ValueMap$}$() {\n" + " return internalGet$capitalized_name$().getMap();\n" + "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, "@java.lang.Override\n" - "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" + "$deprecation$public $value_type_pass_through_nullness$ " + "${$get$capitalized_name$ValueOrDefault$}$(\n" " $key_type$ key,\n" - " $value_type$ defaultValue) {\n" + " $value_type_pass_through_nullness$ defaultValue) {\n" " $key_null_check$\n" " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n" " internalGet$capitalized_name$().getMap();\n" @@ -622,8 +685,8 @@ void ImmutableMapFieldGenerator::GenerateMapGetters( printer->Print( variables_, "@java.lang.Override\n" - "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n" + "$deprecation$public $value_type$ " + "${$get$capitalized_name$ValueOrThrow$}$(\n" " $key_type$ key) {\n" " $key_null_check$\n" " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n" @@ -636,22 +699,23 @@ void ImmutableMapFieldGenerator::GenerateMapGetters( printer->Annotate("{", "}", descriptor_); } } else { - printer->Print(variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Override\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$type_parameters$> " - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Override\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$type_parameters$> " + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "@java.lang.Override\n" - "$deprecation$\n" - "public java.util.Map<$type_parameters$> " + "$deprecation$public java.util.Map<$type_parameters$> " "${$get$capitalized_name$Map$}$() {\n" " return internalGet$capitalized_name$().getMap();\n" "}\n"); @@ -660,10 +724,10 @@ void ImmutableMapFieldGenerator::GenerateMapGetters( printer->Print( variables_, "@java.lang.Override\n" - "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n" + "$deprecation$public $value_type_pass_through_nullness$ " + "${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" - " $value_type$ defaultValue) {\n" + " $value_type_pass_through_nullness$ defaultValue) {\n" " $key_null_check$\n" " java.util.Map<$type_parameters$> map =\n" " internalGet$capitalized_name$().getMap();\n" @@ -671,19 +735,19 @@ void ImmutableMapFieldGenerator::GenerateMapGetters( "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "@java.lang.Override\n" - "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n" - " $key_type$ key) {\n" - " $key_null_check$\n" - " java.util.Map<$type_parameters$> map =\n" - " internalGet$capitalized_name$().getMap();\n" - " if (!map.containsKey(key)) {\n" - " throw new java.lang.IllegalArgumentException();\n" - " }\n" - " return map.get(key);\n" - "}\n"); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n" + " $key_type$ key) {\n" + " $key_null_check$\n" + " java.util.Map<$type_parameters$> map =\n" + " internalGet$capitalized_name$().getMap();\n" + " if (!map.containsKey(key)) {\n" + " throw new java.lang.IllegalArgumentException();\n" + " }\n" + " return map.get(key);\n" + "}\n"); printer->Annotate("{", "}", descriptor_); } } @@ -698,13 +762,13 @@ void ImmutableMapFieldGenerator::GenerateKotlinDslMembers( " */\n" "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" " : com.google.protobuf.kotlin.DslProxy()\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, - "$kt_deprecation$ val $kt_name$: " + "$kt_deprecation$ public val $kt_name$: " "com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " @kotlin.jvm.JvmSynthetic\n" @@ -713,57 +777,57 @@ void ImmutableMapFieldGenerator::GenerateKotlinDslMembers( " $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n" " )\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, "@JvmName(\"put$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslMap" + "public fun com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " .put(key: $kt_key_type$, value: $kt_value_type$) {\n" " $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n" " }\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@JvmName(\"set$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslMap" + "public inline operator fun com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " .set(key: $kt_key_type$, value: $kt_value_type$) {\n" " put(key, value)\n" " }\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@JvmName(\"remove$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslMap" + "public fun com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " .remove(key: $kt_key_type$) {\n" " $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n" " }\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@JvmName(\"putAll$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslMap" + "public fun com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) " "{\n" " $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n" " }\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@JvmName(\"clear$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslMap" + "public fun com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " .clear() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" @@ -782,6 +846,7 @@ void ImmutableMapFieldGenerator::GenerateInitializationCode( void ImmutableMapFieldGenerator::GenerateBuilderClearCode( io::Printer* printer) const { + // No need to clear the has-bit since we clear the bitField ints all at once. printer->Print(variables_, "internalGetMutable$capitalized_name$().clear();\n"); } @@ -790,38 +855,34 @@ void ImmutableMapFieldGenerator::GenerateMergingCode( io::Printer* printer) const { printer->Print(variables_, "internalGetMutable$capitalized_name$().mergeFrom(\n" - " other.internalGet$capitalized_name$());\n"); + " other.internalGet$capitalized_name$());\n" + "$set_has_field_bit_builder$\n"); } void ImmutableMapFieldGenerator::GenerateBuildingCode( io::Printer* printer) const { printer->Print(variables_, - "result.$name$_ = internalGet$capitalized_name$();\n" - "result.$name$_.makeImmutable();\n"); + "if ($get_has_field_bit_from_local$) {\n" + " result.$name$_ = internalGet$capitalized_name$();\n" + " result.$name$_.makeImmutable();\n" + "}\n"); } -void ImmutableMapFieldGenerator::GenerateParsingCode( +void ImmutableMapFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { - printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = com.google.protobuf.MapField.newMapField(\n" - " $map_field_parameter$);\n" - " $set_mutable_bit_parser$;\n" - "}\n"); if (!SupportUnknownEnumValue(descriptor_->file()) && GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { printer->Print( variables_, "com.google.protobuf.ByteString bytes = input.readBytes();\n" "com.google.protobuf.MapEntry<$type_parameters$>\n" - "$name$__ = $default_entry$.getParserForType().parseFrom(bytes);\n"); - printer->Print( - variables_, + "$name$__ = $default_entry$.getParserForType().parseFrom(bytes);\n" "if ($value_enum_type$.forNumber($name$__.getValue()) == null) {\n" - " unknownFields.mergeLengthDelimitedField($number$, bytes);\n" + " mergeUnknownLengthDelimitedField($number$, bytes);\n" "} else {\n" - " $name$_.getMutableMap().put(\n" + " internalGetMutable$capitalized_name$().getMutableMap().put(\n" " $name$__.getKey(), $name$__.getValue());\n" + " $set_has_field_bit_builder$\n" "}\n"); } else { printer->Print( @@ -829,16 +890,11 @@ void ImmutableMapFieldGenerator::GenerateParsingCode( "com.google.protobuf.MapEntry<$type_parameters$>\n" "$name$__ = input.readMessage(\n" " $default_entry$.getParserForType(), extensionRegistry);\n" - "$name$_.getMutableMap().put(\n" - " $name$__.getKey(), $name$__.getValue());\n"); + "internalGetMutable$capitalized_name$().getMutableMap().put(\n" + " $name$__.getKey(), $name$__.getValue());\n" + "$set_has_field_bit_builder$\n"); } } - -void ImmutableMapFieldGenerator::GenerateParsingDoneCode( - io::Printer* printer) const { - // Nothing to do here. -} - void ImmutableMapFieldGenerator::GenerateSerializationCode( io::Printer* printer) const { printer->Print(variables_, @@ -891,4 +947,4 @@ TProtoStringType ImmutableMapFieldGenerator::GetBoxedType() const { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field.h index fe0a4819a92..697deff15af 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field.h @@ -31,7 +31,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__ -#include <google/protobuf/compiler/java/field.h> +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -46,6 +46,8 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { ~ImmutableMapFieldGenerator() override; // implements ImmutableFieldGenerator --------------------------------------- + int GetMessageBitIndex() const override; + int GetBuilderBitIndex() const override; int GetNumBitsForMessage() const override; int GetNumBitsForBuilder() const override; void GenerateInterfaceMembers(io::Printer* printer) const override; @@ -55,8 +57,7 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; - void GenerateParsingDoneCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateFieldBuilderInitializationCode( @@ -69,8 +70,11 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { private: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + int message_bit_index_; + int builder_bit_index_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; ClassNameResolver* name_resolver_; + Context* context_; void GenerateMapGetters(io::Printer* printer) const; }; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field_lite.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field_lite.cc index 807743afcfc..22f4f6daf23 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field_lite.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field_lite.cc @@ -28,18 +28,19 @@ // (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/java/map_field_lite.h> +#include "google/protobuf/compiler/java/map_field_lite.h" #include <cstdint> +#include <string> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -49,16 +50,16 @@ namespace java { namespace { const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) { - GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); + Y_ABSL_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); const Descriptor* message = descriptor->message_type(); - GOOGLE_CHECK(message->options().map_entry()); + Y_ABSL_CHECK(message->options().map_entry()); return message->map_key(); } const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) { - GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); + Y_ABSL_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); const Descriptor* message = descriptor->message_type(); - GOOGLE_CHECK(message->options().map_entry()); + Y_ABSL_CHECK(message->options().map_entry()); return message->map_value(); } @@ -69,8 +70,8 @@ TProtoStringType TypeName(const FieldDescriptor* field, } else if (GetJavaType(field) == JAVATYPE_ENUM) { return name_resolver->GetImmutableClassName(field->enum_type()); } else { - return boxed ? BoxedPrimitiveTypeName(GetJavaType(field)) - : PrimitiveTypeName(GetJavaType(field)); + return TProtoStringType(boxed ? BoxedPrimitiveTypeName(GetJavaType(field)) + : PrimitiveTypeName(GetJavaType(field))); } } @@ -81,19 +82,19 @@ TProtoStringType KotlinTypeName(const FieldDescriptor* field, } else if (GetJavaType(field) == JAVATYPE_ENUM) { return name_resolver->GetImmutableClassName(field->enum_type()); } else { - return KotlinTypeName(GetJavaType(field)); + return TProtoStringType(KotlinTypeName(GetJavaType(field))); } } TProtoStringType WireType(const FieldDescriptor* field) { - return "com.google.protobuf.WireFormat.FieldType." + - TProtoStringType(FieldTypeName(field->type())); + return y_absl::StrCat("com.google.protobuf.WireFormat.FieldType.", + FieldTypeName(field->type())); } -void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, const FieldGeneratorInfo* info, - Context* context, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetMessageVariables( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, Context* context, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { SetCommonFieldVariables(descriptor, info, variables); ClassNameResolver* name_resolver = context->GetNameResolver(); @@ -104,14 +105,18 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, const JavaType keyJavaType = GetJavaType(key); const JavaType valueJavaType = GetJavaType(value); - TProtoStringType pass_through_nullness = "/* nullable */\n"; + TProtoStringType pass_through_nullness = + context->options().opensource_runtime + ? "/* nullable */\n" + : "@com.google.protobuf.Internal.ProtoPassThroughNullness "; (*variables)["key_type"] = TypeName(key, name_resolver, false); (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true); (*variables)["kt_key_type"] = KotlinTypeName(key, name_resolver); (*variables)["kt_value_type"] = KotlinTypeName(value, name_resolver); (*variables)["key_wire_type"] = WireType(key); - (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver); + (*variables)["key_default_value"] = + DefaultValue(key, true, name_resolver, context->options()); // We use `x.getClass()` as a null check because it generates less bytecode // than an `if (x == null) { throw ... }` statement. (*variables)["key_null_check"] = @@ -126,51 +131,63 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, if (GetJavaType(value) == JAVATYPE_ENUM) { // We store enums as Integers internally. (*variables)["value_type"] = "int"; + (*variables)["value_type_pass_through_nullness"] = "int"; (*variables)["boxed_value_type"] = "java.lang.Integer"; (*variables)["value_wire_type"] = WireType(value); (*variables)["value_default_value"] = - DefaultValue(value, true, name_resolver) + ".getNumber()"; + DefaultValue(value, true, name_resolver, context->options()) + + ".getNumber()"; (*variables)["value_enum_type"] = TypeName(value, name_resolver, false); - (*variables)["value_enum_type_pass_through_nullness"] = - pass_through_nullness + (*variables)["value_enum_type"]; + variables->insert( + {"value_enum_type_pass_through_nullness", + y_absl::StrCat(pass_through_nullness, (*variables)["value_enum_type"])}); if (SupportUnknownEnumValue(descriptor->file())) { // Map unknown values to a special UNRECOGNIZED value if supported. - (*variables)["unrecognized_value"] = - (*variables)["value_enum_type"] + ".UNRECOGNIZED"; + variables->insert( + {"unrecognized_value", + y_absl::StrCat((*variables)["value_enum_type"], ".UNRECOGNIZED")}); } else { // Map unknown values to the default value if we don't have UNRECOGNIZED. (*variables)["unrecognized_value"] = - DefaultValue(value, true, name_resolver); + DefaultValue(value, true, name_resolver, context->options()); } } else { (*variables)["value_type"] = TypeName(value, name_resolver, false); - (*variables)["value_type_pass_through_nullness"] = - (IsReferenceType(valueJavaType) ? pass_through_nullness : "") + - (*variables)["value_type"]; + variables->insert( + {"value_type_pass_through_nullness", + y_absl::StrCat( + (IsReferenceType(valueJavaType) ? pass_through_nullness : ""), + (*variables)["value_type"])}); (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true); (*variables)["value_wire_type"] = WireType(value); (*variables)["value_default_value"] = - DefaultValue(value, true, name_resolver); + DefaultValue(value, true, name_resolver, context->options()); } - (*variables)["type_parameters"] = - (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; + variables->insert( + {"type_parameters", y_absl::StrCat((*variables)["boxed_key_type"], ", ", + (*variables)["boxed_value_type"])}); // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["kt_deprecation"] = - descriptor->options().deprecated() - ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + - " is deprecated\") " - : ""; - - (*variables)["default_entry"] = - (*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry"; + variables->insert( + {"kt_deprecation", + descriptor->options().deprecated() + ? y_absl::StrCat("@kotlin.Deprecated(message = \"Field ", + (*variables)["name"], " is deprecated\") ") + : ""}); + + variables->insert( + {"default_entry", y_absl::StrCat((*variables)["capitalized_name"], + "DefaultEntryHolder.defaultEntry")}); + // { and } variables are used as delimiters when emitting annotations. + (*variables)["{"] = ""; + (*variables)["}"] = ""; } } // namespace @@ -201,14 +218,16 @@ void ImmutableMapFieldLiteGenerator::GenerateInterfaceMembers( " $key_type$ key);\n"); printer->Annotate("{", "}", descriptor_); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { - printer->Print(variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); + } WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -247,9 +266,10 @@ void ImmutableMapFieldLiteGenerator::GenerateInterfaceMembers( WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$\n" - "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" + "$value_type_pass_through_nullness$ " + "${$get$capitalized_name$ValueOrDefault$}$(\n" " $key_type$ key,\n" - " $value_type$ defaultValue);\n"); + " $value_type_pass_through_nullness$ defaultValue);\n"); printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -259,14 +279,16 @@ void ImmutableMapFieldLiteGenerator::GenerateInterfaceMembers( printer->Annotate("{", "}", descriptor_); } } else { - printer->Print(variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "java.util.Map<$type_parameters$>\n" - "${$get$capitalized_name$$}$();\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "java.util.Map<$type_parameters$>\n" + "${$get$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$java.util.Map<$type_parameters$>\n" @@ -303,6 +325,12 @@ void ImmutableMapFieldLiteGenerator::GenerateMembers( " $value_wire_type$,\n" " $value_default_value$);\n" "}\n"); + if (!context_->options().opensource_runtime) { + printer->Print(variables_, + "@com.google.protobuf.ProtoField(\n" + " fieldNumber=$number$,\n" + " type=com.google.protobuf.FieldType.MAP)\n"); + } printer->Print(variables_, "private com.google.protobuf.MapFieldLite<\n" " $type_parameters$> $name$_ =\n" @@ -344,16 +372,19 @@ void ImmutableMapFieldLiteGenerator::GenerateMembers( " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n" " $value_enum_type$.internalGetValueMap(),\n" " $unrecognized_value$);\n"); - printer->Print(variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print( + variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + } WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -373,9 +404,10 @@ void ImmutableMapFieldLiteGenerator::GenerateMembers( variables_, "@java.lang.Override\n" "$deprecation$\n" - "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n" + "public $value_enum_type_pass_through_nullness$ " + "${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" - " $value_enum_type$ defaultValue) {\n" + " $value_enum_type_pass_through_nullness$ defaultValue) {\n" " $key_null_check$\n" " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n" " internalGet$capitalized_name$();\n" @@ -429,9 +461,10 @@ void ImmutableMapFieldLiteGenerator::GenerateMembers( variables_, "@java.lang.Override\n" "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" + "public $value_type_pass_through_nullness$ " + "${$get$capitalized_name$ValueOrDefault$}$(\n" " $key_type$ key,\n" - " $value_type$ defaultValue) {\n" + " $value_type_pass_through_nullness$ defaultValue) {\n" " $key_null_check$\n" " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n" " internalGet$capitalized_name$();\n" @@ -456,17 +489,19 @@ void ImmutableMapFieldLiteGenerator::GenerateMembers( printer->Annotate("{", "}", descriptor_); } } else { - printer->Print(variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Override\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$type_parameters$> " - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Override\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$type_parameters$> " + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "@java.lang.Override\n" @@ -482,9 +517,10 @@ void ImmutableMapFieldLiteGenerator::GenerateMembers( variables_, "@java.lang.Override\n" "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n" + "public $value_type_pass_through_nullness$ " + "${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" - " $value_type$ defaultValue) {\n" + " $value_type_pass_through_nullness$ defaultValue) {\n" " $key_null_check$\n" " java.util.Map<$type_parameters$> map =\n" " internalGet$capitalized_name$();\n" @@ -596,16 +632,19 @@ void ImmutableMapFieldLiteGenerator::GenerateBuilderMembers( "}\n"); printer->Annotate("{", "}", descriptor_); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { - printer->Print(variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print( + variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "@java.lang.Override\n" @@ -701,9 +740,10 @@ void ImmutableMapFieldLiteGenerator::GenerateBuilderMembers( variables_, "@java.lang.Override\n" "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n" + "public $value_type_pass_through_nullness$ " + "${$get$capitalized_name$ValueOrDefault$}$(\n" " $key_type$ key,\n" - " $value_type$ defaultValue) {\n" + " $value_type_pass_through_nullness$ defaultValue) {\n" " $key_null_check$\n" " java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n" " instance.get$capitalized_name$ValueMap();\n" @@ -750,17 +790,19 @@ void ImmutableMapFieldLiteGenerator::GenerateBuilderMembers( printer->Annotate("{", "}", descriptor_); } } else { - printer->Print(variables_, - "/**\n" - " * Use {@link #get$capitalized_name$Map()} instead.\n" - " */\n" - "@java.lang.Override\n" - "@java.lang.Deprecated\n" - "public java.util.Map<$type_parameters$> " - "${$get$capitalized_name$$}$() {\n" - " return get$capitalized_name$Map();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); + if (context_->options().opensource_runtime) { + printer->Print(variables_, + "/**\n" + " * Use {@link #get$capitalized_name$Map()} instead.\n" + " */\n" + "@java.lang.Override\n" + "@java.lang.Deprecated\n" + "public java.util.Map<$type_parameters$> " + "${$get$capitalized_name$$}$() {\n" + " return get$capitalized_name$Map();\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "@java.lang.Override\n" @@ -776,9 +818,10 @@ void ImmutableMapFieldLiteGenerator::GenerateBuilderMembers( variables_, "@java.lang.Override\n" "$deprecation$\n" - "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n" + "public $value_type_pass_through_nullness$ " + "${$get$capitalized_name$OrDefault$}$(\n" " $key_type$ key,\n" - " $value_type$ defaultValue) {\n" + " $value_type_pass_through_nullness$ defaultValue) {\n" " $key_null_check$\n" " java.util.Map<$type_parameters$> map =\n" " instance.get$capitalized_name$Map();\n" @@ -838,13 +881,13 @@ void ImmutableMapFieldLiteGenerator::GenerateKotlinDslMembers( " */\n" "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" " : com.google.protobuf.kotlin.DslProxy()\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, - "$kt_deprecation$ val $kt_name$: " + "$kt_deprecation$ public val $kt_name$: " "com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " @kotlin.jvm.JvmSynthetic\n" @@ -853,57 +896,57 @@ void ImmutableMapFieldLiteGenerator::GenerateKotlinDslMembers( " $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n" " )\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, "@JvmName(\"put$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslMap" + "public fun com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " .put(key: $kt_key_type$, value: $kt_value_type$) {\n" " $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n" " }\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@JvmName(\"set$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslMap" + "public inline operator fun com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " .set(key: $kt_key_type$, value: $kt_value_type$) {\n" " put(key, value)\n" " }\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@JvmName(\"remove$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslMap" + "public fun com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " .remove(key: $kt_key_type$) {\n" " $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n" " }\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@JvmName(\"putAll$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslMap" + "public fun com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " .putAll(map: kotlin.collections.Map<$kt_key_type$, $kt_value_type$>) " "{\n" " $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n" " }\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@JvmName(\"clear$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslMap" + "public fun com.google.protobuf.kotlin.DslMap" "<$kt_key_type$, $kt_value_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " .clear() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" @@ -924,4 +967,4 @@ TProtoStringType ImmutableMapFieldLiteGenerator::GetBoxedType() const { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field_lite.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field_lite.h index de2cc510575..4f5fb4d4ac8 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field_lite.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/map_field_lite.h @@ -33,7 +33,7 @@ #include <cstdint> -#include <google/protobuf/compiler/java/field.h> +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -61,7 +61,7 @@ class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator { private: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; Context* context_; ClassNameResolver* name_resolver_; }; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/message.cc index bcd437821f3..e3a5e5e03dd 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message.cc @@ -32,32 +32,34 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/message.h> +#include "google/protobuf/compiler/java/message.h" #include <algorithm> #include <cstdint> -#include <map> #include <memory> #include <vector> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/enum.h> -#include <google/protobuf/compiler/java/extension.h> -#include <google/protobuf/compiler/java/generator_factory.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/message_builder.h> -#include <google/protobuf/compiler/java/message_builder_lite.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/enum.h" +#include "google/protobuf/compiler/java/extension.h" +#include "google/protobuf/compiler/java/generator_factory.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/message_builder.h" +#include "google/protobuf/compiler/java/message_builder_lite.h" +#include "google/protobuf/compiler/java/message_serialization.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -71,7 +73,7 @@ namespace { TProtoStringType MapValueImmutableClassdName(const Descriptor* descriptor, ClassNameResolver* name_resolver) { const FieldDescriptor* value_field = descriptor->map_value(); - GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); + Y_ABSL_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); return name_resolver->GetImmutableClassName(value_field->message_type()); } } // namespace @@ -82,7 +84,8 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor) : descriptor_(descriptor) { for (int i = 0; i < descriptor_->field_count(); i++) { if (IsRealOneof(descriptor_->field(i))) { - oneofs_.insert(descriptor_->field(i)->containing_oneof()); + const OneofDescriptor* oneof = descriptor_->field(i)->containing_oneof(); + Y_ABSL_CHECK(oneofs_.emplace(oneof->index(), oneof).first->second == oneof); } } } @@ -96,7 +99,7 @@ ImmutableMessageGenerator::ImmutableMessageGenerator( context_(context), name_resolver_(context->GetNameResolver()), field_generators_(descriptor, context_) { - GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite())) + Y_ABSL_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite())) << "Generator factory error: A non-lite message generator is used to " "generate lite messages."; } @@ -112,9 +115,9 @@ void ImmutableMessageGenerator::GenerateStaticVariables( // the outermost class in the file. This way, they will be initialized in // a deterministic order. - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - vars["index"] = StrCat(descriptor_->index()); + vars["index"] = y_absl::StrCat(descriptor_->index()); vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); if (descriptor_->containing_type() != NULL) { vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type()); @@ -156,9 +159,9 @@ void ImmutableMessageGenerator::GenerateStaticVariables( int ImmutableMessageGenerator::GenerateStaticVariableInitializers( io::Printer* printer) { int bytecode_estimate = 0; - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - vars["index"] = StrCat(descriptor_->index()); + vars["index"] = y_absl::StrCat(descriptor_->index()); vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); if (descriptor_->containing_type() != NULL) { vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type()); @@ -193,7 +196,7 @@ int ImmutableMessageGenerator::GenerateStaticVariableInitializers( void ImmutableMessageGenerator::GenerateFieldAccessorTable( io::Printer* printer, int* bytecode_estimate) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { // We can only make these package-private since the classes that use them @@ -260,6 +263,9 @@ int ImmutableMessageGenerator::GenerateFieldAccessorTableInitializer( void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { MaybePrintGeneratedAnnotation(context_, printer, descriptor_, /* immutable = */ true, "OrBuilder"); + if (!context_->options().opensource_runtime) { + printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n"); + } if (descriptor_->extension_range_count() > 0) { printer->Print( "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n" @@ -289,13 +295,14 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { field_generators_.get(descriptor_->field(i)) .GenerateInterfaceMembers(printer); } - for (auto oneof : oneofs_) { + for (auto& kv : oneofs_) { printer->Print( "\n" - "public $classname$.$oneof_capitalized_name$Case " + "$classname$.$oneof_capitalized_name$Case " "get$oneof_capitalized_name$Case();\n", "oneof_capitalized_name", - context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "classname", + context_->GetOneofGeneratorInfo(kv.second)->capitalized_name, + "classname", context_->GetNameResolver()->GetImmutableClassName(descriptor_)); } printer->Outdent(); @@ -308,7 +315,7 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { void ImmutableMessageGenerator::Generate(io::Printer* printer) { bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true); - std::map<TProtoStringType, TProtoStringType> variables; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables; variables["static"] = is_own_file ? "" : "static "; variables["classname"] = descriptor_->name(); variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_); @@ -319,6 +326,10 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { WriteMessageDocComment(printer, descriptor_); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, /* immutable = */ true); + if (!context_->options().opensource_runtime) { + printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n"); + } + // The builder_type stores the super type name of the nested Builder class. TProtoStringType builder_type; if (descriptor_->extension_range_count() > 0) { @@ -332,7 +343,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { " $classname$> implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n"); - builder_type = strings::Substitute( + builder_type = y_absl::Substitute( "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", name_resolver_->GetImmutableClassName(descriptor_), GeneratedCodeVersionSuffix()); @@ -346,7 +357,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { " $extra_interfaces$\n" " $classname$OrBuilder {\n"); builder_type = - strings::Substitute("com.google.protobuf.GeneratedMessage$0.Builder<?>", + y_absl::Substitute("com.google.protobuf.GeneratedMessage$0.Builder<?>", GeneratedCodeVersionSuffix()); } printer->Print("private static final long serialVersionUID = 0L;\n"); @@ -379,17 +390,6 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { "}\n" "\n"); - printer->Print( - "@java.lang.Override\n" - "public final com.google.protobuf.UnknownFieldSet\n" - "getUnknownFields() {\n" - " return this.unknownFields;\n" - "}\n"); - - if (context_->HasGeneratedMethods(descriptor_)) { - GenerateParsingConstructor(printer); - } - GenerateDescriptorMethods(printer); // Nested types @@ -419,59 +419,69 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { } // oneof - std::map<TProtoStringType, TProtoStringType> vars; - for (auto oneof : oneofs_) { + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name; vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(oneof)->capitalized_name; - vars["oneof_index"] = StrCat((oneof)->index()); + vars["oneof_index"] = y_absl::StrCat((oneof)->index()); + vars["{"] = ""; + vars["}"] = ""; // oneofCase_ and oneof_ printer->Print(vars, "private int $oneof_name$Case_ = 0;\n" + "@SuppressWarnings(\"serial\")\n" "private java.lang.Object $oneof_name$_;\n"); // OneofCase enum printer->Print( vars, - "public enum $oneof_capitalized_name$Case\n" + "public enum ${$$oneof_capitalized_name$Case$}$\n" // TODO(dweis): Remove EnumLite when we want to break compatibility with // 3.x users " implements com.google.protobuf.Internal.EnumLite,\n" " com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n"); + printer->Annotate("{", "}", oneof); printer->Indent(); for (int j = 0; j < (oneof)->field_count(); j++) { const FieldDescriptor* field = (oneof)->field(j); printer->Print( "$deprecation$$field_name$($field_number$),\n", "deprecation", field->options().deprecated() ? "@java.lang.Deprecated " : "", - "field_name", ToUpper(field->name()), "field_number", - StrCat(field->number())); + "field_name", y_absl::AsciiStrToUpper(field->name()), "field_number", + y_absl::StrCat(field->number())); + printer->Annotate("field_name", field); } printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name", - ToUpper(vars["oneof_name"])); + y_absl::AsciiStrToUpper(vars["oneof_name"])); printer->Print(vars, "private final int value;\n" "private $oneof_capitalized_name$Case(int value) {\n" " this.value = value;\n" "}\n"); + if (context_->options().opensource_runtime) { + printer->Print( + vars, + "/**\n" + " * @param value The number of the enum to look for.\n" + " * @return The enum associated with the given number.\n" + " * @deprecated Use {@link #forNumber(int)} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public static $oneof_capitalized_name$Case valueOf(int value) {\n" + " return forNumber(value);\n" + "}\n" + "\n"); + } printer->Print( vars, - "/**\n" - " * @param value The number of the enum to look for.\n" - " * @return The enum associated with the given number.\n" - " * @deprecated Use {@link #forNumber(int)} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public static $oneof_capitalized_name$Case valueOf(int value) {\n" - " return forNumber(value);\n" - "}\n" - "\n" "public static $oneof_capitalized_name$Case forNumber(int value) {\n" " 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", StrCat(field->number()), - "field_name", ToUpper(field->name())); + "field_number", y_absl::StrCat(field->number()), + "field_name", y_absl::AsciiStrToUpper(field->name())); } printer->Print( " case 0: return $cap_oneof_name$_NOT_SET;\n" @@ -481,17 +491,18 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { "public int getNumber() {\n" " return this.value;\n" "}\n", - "cap_oneof_name", ToUpper(vars["oneof_name"])); + "cap_oneof_name", y_absl::AsciiStrToUpper(vars["oneof_name"])); printer->Outdent(); printer->Print("};\n\n"); // oneofCase() printer->Print(vars, "public $oneof_capitalized_name$Case\n" - "get$oneof_capitalized_name$Case() {\n" + "${$get$oneof_capitalized_name$Case$}$() {\n" " return $oneof_capitalized_name$Case.forNumber(\n" " $oneof_name$Case_);\n" "}\n" "\n"); + printer->Annotate("{", "}", oneof); } if (IsAnyMessage(descriptor_)) { @@ -502,7 +513,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { 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", StrCat(descriptor_->field(i)->number())); + "number", y_absl::StrCat(descriptor_->field(i)->number())); printer->Annotate("constant_name", descriptor_->field(i)); field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); printer->Print("\n"); @@ -582,13 +593,6 @@ void ImmutableMessageGenerator::GenerateMessageSerializationMethods( std::unique_ptr<const FieldDescriptor*[]> sorted_fields( SortFieldsByNumber(descriptor_)); - std::vector<const Descriptor::ExtensionRange*> sorted_extensions; - sorted_extensions.reserve(descriptor_->extension_range_count()); - for (int i = 0; i < descriptor_->extension_range_count(); ++i) { - sorted_extensions.push_back(descriptor_->extension_range(i)); - } - std::sort(sorted_extensions.begin(), sorted_extensions.end(), - ExtensionRangeOrdering()); printer->Print( "@java.lang.Override\n" "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" @@ -623,24 +627,13 @@ void ImmutableMessageGenerator::GenerateMessageSerializationMethods( } } - // 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++]); - } - } + GenerateSerializeFieldsAndExtensions(printer, field_generators_, descriptor_, + sorted_fields.get()); if (descriptor_->options().message_set_wire_format()) { - printer->Print("unknownFields.writeAsMessageSetTo(output);\n"); + printer->Print("getUnknownFields().writeAsMessageSetTo(output);\n"); } else { - printer->Print("unknownFields.writeTo(output);\n"); + printer->Print("getUnknownFields().writeTo(output);\n"); } printer->Outdent(); @@ -669,9 +662,10 @@ void ImmutableMessageGenerator::GenerateMessageSerializationMethods( } if (descriptor_->options().message_set_wire_format()) { - printer->Print("size += unknownFields.getSerializedSizeAsMessageSet();\n"); + printer->Print( + "size += getUnknownFields().getSerializedSizeAsMessageSet();\n"); } else { - printer->Print("size += unknownFields.getSerializedSize();\n"); + printer->Print("size += getUnknownFields().getSerializedSize();\n"); } printer->Print( @@ -765,17 +759,6 @@ void ImmutableMessageGenerator::GenerateParseFromMethods(io::Printer* printer) { GeneratedCodeVersionSuffix()); } -void ImmutableMessageGenerator::GenerateSerializeOneField( - io::Printer* printer, const FieldDescriptor* field) { - field_generators_.get(field).GenerateSerializationCode(printer); -} - -void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* range) { - printer->Print("extensionWriter.writeUntil($end$, output);\n", "end", - StrCat(range->end)); -} - // =================================================================== void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { @@ -847,7 +830,7 @@ void ImmutableMessageGenerator::GenerateDescriptorMethods( printer->Print( "case $number$:\n" " return internalGet$capitalized_name$();\n", - "number", StrCat(field->number()), "capitalized_name", + "number", y_absl::StrCat(field->number()), "capitalized_name", info->capitalized_name); } printer->Print( @@ -1005,6 +988,10 @@ void ImmutableMessageGenerator::GenerateEqualsAndHashCode( printer->Print( "@java.lang.Override\n" "public boolean equals("); + if (!context_->options().opensource_runtime) { + printer->Print( + "@com.google.protobuf.Internal.ProtoMethodAcceptsNullParameter\n"); + } printer->Print("final java.lang.Object obj) {\n"); printer->Indent(); printer->Print( @@ -1012,6 +999,8 @@ void ImmutableMessageGenerator::GenerateEqualsAndHashCode( " return true;\n" "}\n" "if (!(obj instanceof $classname$)) {\n" + // don't simply return false because mutable and immutable types + // can be equal " return super.equals(obj);\n" "}\n" "$classname$ other = ($classname$) obj;\n" @@ -1039,7 +1028,8 @@ void ImmutableMessageGenerator::GenerateEqualsAndHashCode( } // Compare oneofs. - for (auto oneof : oneofs_) { + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; printer->Print( "if (!get$oneof_capitalized_name$Case().equals(" "other.get$oneof_capitalized_name$Case())) return false;\n", @@ -1051,7 +1041,7 @@ void ImmutableMessageGenerator::GenerateEqualsAndHashCode( for (int j = 0; j < (oneof)->field_count(); j++) { const FieldDescriptor* field = (oneof)->field(j); printer->Print("case $field_number$:\n", "field_number", - StrCat(field->number())); + y_absl::StrCat(field->number())); printer->Indent(); field_generators_.get(field).GenerateEqualsCode(printer); printer->Print("break;\n"); @@ -1068,7 +1058,8 @@ void ImmutableMessageGenerator::GenerateEqualsAndHashCode( // false for non-canonical ordering when running in LITE_RUNTIME but it's // the best we can do. printer->Print( - "if (!unknownFields.equals(other.unknownFields)) return false;\n"); + "if (!getUnknownFields().equals(other.getUnknownFields())) return " + "false;\n"); if (descriptor_->extension_range_count() > 0) { printer->Print( "if (!getExtensionFields().equals(other.getExtensionFields()))\n" @@ -1118,14 +1109,15 @@ void ImmutableMessageGenerator::GenerateEqualsAndHashCode( } // hashCode oneofs. - for (auto oneof : oneofs_) { + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name); printer->Indent(); for (int j = 0; j < (oneof)->field_count(); j++) { const FieldDescriptor* field = (oneof)->field(j); printer->Print("case $field_number$:\n", "field_number", - StrCat(field->number())); + y_absl::StrCat(field->number())); printer->Indent(); field_generators_.get(field).GenerateHashCode(printer); printer->Print("break;\n"); @@ -1142,7 +1134,7 @@ void ImmutableMessageGenerator::GenerateEqualsAndHashCode( printer->Print("hash = hashFields(hash, getExtensionFields());\n"); } - printer->Print("hash = (29 * hash) + unknownFields.hashCode();\n"); + printer->Print("hash = (29 * hash) + getUnknownFields().hashCode();\n"); printer->Print( "memoizedHashCode = hash;\n" "return hash;\n"); @@ -1168,188 +1160,32 @@ void ImmutableMessageGenerator::GenerateExtensionRegistrationCode( } // =================================================================== -void ImmutableMessageGenerator::GenerateParsingConstructor( - io::Printer* printer) { - std::unique_ptr<const FieldDescriptor*[]> sorted_fields( - SortFieldsByNumber(descriptor_)); - - printer->Print( - "private $classname$(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n", - "classname", descriptor_->name()); - printer->Indent(); - - // Initialize all fields to default. - printer->Print( - "this();\n" - "if (extensionRegistry == null) {\n" - " throw new java.lang.NullPointerException();\n" - "}\n"); - - // Use builder bits to track mutable repeated fields. - int totalBuilderBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const ImmutableFieldGenerator& field = - field_generators_.get(descriptor_->field(i)); - totalBuilderBits += field.GetNumBitsForBuilder(); - } - int totalBuilderInts = (totalBuilderBits + 31) / 32; - for (int i = 0; i < totalBuilderInts; i++) { - printer->Print("int mutable_$bit_field_name$ = 0;\n", "bit_field_name", - GetBitFieldName(i)); - } - - printer->Print( - "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" - " com.google.protobuf.UnknownFieldSet.newBuilder();\n"); - - printer->Print("try {\n"); - printer->Indent(); - - printer->Print( - "boolean done = false;\n" - "while (!done) {\n"); - printer->Indent(); - - printer->Print( - "int tag = input.readTag();\n" - "switch (tag) {\n"); - printer->Indent(); - - printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " done = true;\n" - " break;\n"); - - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = sorted_fields[i]; - arc_ui32 tag = WireFormatLite::MakeTag( - field->number(), WireFormat::WireTypeForFieldType(field->type())); - - printer->Print("case $tag$: {\n", "tag", - StrCat(static_cast<arc_i32>(tag))); - printer->Indent(); - - field_generators_.get(field).GenerateParsingCode(printer); - - printer->Outdent(); - printer->Print( - " break;\n" - "}\n"); - - if (field->is_packable()) { - // To make packed = true wire compatible, we generate parsing code from a - // packed version of this field regardless of field->options().packed(). - arc_ui32 packed_tag = WireFormatLite::MakeTag( - field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED); - printer->Print("case $tag$: {\n", "tag", - StrCat(static_cast<arc_i32>(packed_tag))); - printer->Indent(); - - field_generators_.get(field).GenerateParsingCodeFromPacked(printer); - - printer->Outdent(); - printer->Print( - " break;\n" - "}\n"); - } - } - - printer->Print( - "default: {\n" - " if (!parseUnknownField(\n" - " input, unknownFields, extensionRegistry, tag)) {\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 e.setUnfinishedMessage(this);\n" - "} catch (com.google.protobuf.UninitializedMessageException e) {\n" - " throw " - "e.asInvalidProtocolBufferException().setUnfinishedMessage(this);\n" - "} catch (java.io.IOException e) {\n" - " throw new com.google.protobuf.InvalidProtocolBufferException(\n" - " e).setUnfinishedMessage(this);\n" - "} finally {\n"); - printer->Indent(); - - // Make repeated field list immutable. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = sorted_fields[i]; - field_generators_.get(field).GenerateParsingDoneCode(printer); - } - - // Make unknown fields immutable. - printer->Print("this.unknownFields = unknownFields.build();\n"); - - // Make extensions immutable. - printer->Print("makeExtensionsImmutable();\n"); - - printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\n" // finally - "}\n"); -} - -// =================================================================== void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { printer->Print( "$visibility$ static final com.google.protobuf.Parser<$classname$>\n" - " PARSER = new com.google.protobuf.AbstractParser<$classname$>() {\n", - "visibility", - ExposePublicParser(descriptor_->file()) ? "@java.lang.Deprecated public" - : "private", - "classname", descriptor_->name()); - printer->Indent(); - printer->Print( - "@java.lang.Override\n" - "public $classname$ parsePartialFrom(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n", - "classname", descriptor_->name()); - if (context_->HasGeneratedMethods(descriptor_)) { - printer->Print(" return new $classname$(input, extensionRegistry);\n", - "classname", descriptor_->name()); - } else { - // When parsing constructor isn't generated, use builder to parse - // messages. Note, will fallback to use reflection based mergeFieldFrom() - // in AbstractMessage.Builder. - printer->Indent(); - printer->Print( - "Builder builder = newBuilder();\n" - "try {\n" - " builder.mergeFrom(input, extensionRegistry);\n" - "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw e.setUnfinishedMessage(builder.buildPartial());\n" - "} catch (java.io.IOException e) {\n" - " throw new com.google.protobuf.InvalidProtocolBufferException(\n" - " e.getMessage()).setUnfinishedMessage(\n" - " builder.buildPartial());\n" - "}\n" - "return builder.buildPartial();\n"); - printer->Outdent(); - } - printer->Print("}\n"); - printer->Outdent(); - printer->Print( + " PARSER = new com.google.protobuf.AbstractParser<$classname$>() {\n" + " @java.lang.Override\n" + " public $classname$ parsePartialFrom(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " Builder builder = newBuilder();\n" + " try {\n" + " builder.mergeFrom(input, extensionRegistry);\n" + " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" + " throw e.setUnfinishedMessage(builder.buildPartial());\n" + " } catch (com.google.protobuf.UninitializedMessageException e) {\n" + " throw " + "e.asInvalidProtocolBufferException().setUnfinishedMessage(builder." + "buildPartial());\n" + " } catch (java.io.IOException e) {\n" + " throw new com.google.protobuf.InvalidProtocolBufferException(e)\n" + " .setUnfinishedMessage(builder.buildPartial());\n" + " }\n" + " return builder.buildPartial();\n" + " }\n" "};\n" - "\n"); - - printer->Print( + "\n" "public static com.google.protobuf.Parser<$classname$> parser() {\n" " return PARSER;\n" "}\n" @@ -1359,6 +1195,9 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { " return PARSER;\n" "}\n" "\n", + "visibility", + ExposePublicParser(descriptor_->file()) ? "@java.lang.Deprecated public" + : "private", "classname", descriptor_->name()); } @@ -1413,10 +1252,10 @@ void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const { "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" "@com.google.protobuf.kotlin.ProtoDslMarker\n"); printer->Print( - "class Dsl private constructor(\n" + "public class Dsl private constructor(\n" " private val _builder: $message$.Builder\n" ") {\n" - " companion object {\n" + " public companion object {\n" " @kotlin.jvm.JvmSynthetic\n" " @kotlin.PublishedApi\n" " internal fun _create(builder: $message$.Builder): Dsl = " @@ -1426,7 +1265,8 @@ void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const { " @kotlin.jvm.JvmSynthetic\n" " @kotlin.PublishedApi\n" " internal fun _build(): $message$ = _builder.build()\n", - "message", name_resolver_->GetClassName(descriptor_, true)); + "message", + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); printer->Indent(); @@ -1436,18 +1276,19 @@ void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const { .GenerateKotlinDslMembers(printer); } - for (auto oneof : oneofs_) { + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; printer->Print( - "val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n" + "public val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n" " @JvmName(\"get$oneof_capitalized_name$Case\")\n" " get() = _builder.get$oneof_capitalized_name$Case()\n\n" - "fun clear$oneof_capitalized_name$() {\n" + "public fun clear$oneof_capitalized_name$() {\n" " _builder.clear$oneof_capitalized_name$()\n" "}\n", "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name, "oneof_capitalized_name", context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message", - name_resolver_->GetClassName(descriptor_, true)); + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); } if (descriptor_->extension_range_count() > 0) { @@ -1460,19 +1301,27 @@ void ImmutableMessageGenerator::GenerateKotlinDsl(io::Printer* printer) const { void ImmutableMessageGenerator::GenerateKotlinMembers( io::Printer* printer) const { + printer->Print("@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n", + "camelcase_name", + name_resolver_->GetKotlinFactoryName(descriptor_)); + + printer->Print( - "@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n" - "inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> " + "public inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> " "kotlin.Unit): " "$message$ " "=\n" " $message_kt$.Dsl._create($message$.newBuilder()).apply { block() " "}._build()\n", "camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_), - "message_kt", name_resolver_->GetKotlinExtensionsClassName(descriptor_), - "message", name_resolver_->GetClassName(descriptor_, true)); - - printer->Print("object $name$Kt {\n", "name", descriptor_->name()); + "message_kt", + EscapeKotlinKeywords( + name_resolver_->GetKotlinExtensionsClassName(descriptor_)), + "message", + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); + + WriteMessageDocComment(printer, descriptor_, /* kdoc */ true); + printer->Print("public object $name$Kt {\n", "name", descriptor_->name()); printer->Indent(); GenerateKotlinDsl(printer); for (int i = 0; i < descriptor_->nested_type_count(); i++) { @@ -1486,15 +1335,19 @@ void ImmutableMessageGenerator::GenerateKotlinMembers( void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers( io::Printer* printer) const { + printer->Print("@kotlin.jvm.JvmSynthetic\n"); + + printer->Print( - "@kotlin.jvm.JvmSynthetic\n" - "inline fun $message$.copy(block: $message_kt$.Dsl.() -> " - "kotlin.Unit): " - "$message$ =\n" + "public inline fun $message$.copy(block: $message_kt$.Dsl.() -> " + "kotlin.Unit): $message$ =\n" " $message_kt$.Dsl._create(this.toBuilder()).apply { block() " "}._build()\n\n", - "message", name_resolver_->GetClassName(descriptor_, true), "message_kt", - name_resolver_->GetKotlinExtensionsClassName(descriptor_)); + "message", + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)), + "message_kt", + EscapeKotlinKeywords( + name_resolver_->GetKotlinExtensionsClassName(descriptor_))); for (int i = 0; i < descriptor_->nested_type_count(); i++) { if (IsMapEntry(descriptor_->nested_type(i))) continue; @@ -1505,34 +1358,39 @@ void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers( GenerateKotlinOrNull(printer); } -void ImmutableMessageGenerator::GenerateKotlinOrNull(io::Printer* printer) const { +void ImmutableMessageGenerator::GenerateKotlinOrNull( + io::Printer* printer) const { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->has_presence() && GetJavaType(field) == JAVATYPE_MESSAGE) { printer->Print( - "val $full_classname$OrBuilder.$camelcase_name$OrNull: $full_name$?\n" + "public val $full_classname$OrBuilder.$camelcase_name$OrNull: " + "$full_name$?\n" " get() = if (has$name$()) get$name$() else null\n\n", - "full_classname", name_resolver_->GetClassName(descriptor_, true), + "full_classname", + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)), "camelcase_name", context_->GetFieldGeneratorInfo(field)->name, "full_name", - name_resolver_->GetImmutableClassName(field->message_type()), "name", - context_->GetFieldGeneratorInfo(field)->capitalized_name); + EscapeKotlinKeywords( + name_resolver_->GetImmutableClassName(field->message_type())), + "name", context_->GetFieldGeneratorInfo(field)->capitalized_name); } } } void ImmutableMessageGenerator::GenerateKotlinExtensions( io::Printer* printer) const { - TProtoStringType message_name = name_resolver_->GetClassName(descriptor_, true); + TProtoStringType message_name = + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)); printer->Print( "@Suppress(\"UNCHECKED_CAST\")\n" "@kotlin.jvm.JvmSynthetic\n" - "operator fun <T : kotlin.Any> get(extension: " + "public operator fun <T : kotlin.Any> get(extension: " "com.google.protobuf.ExtensionLite<$message$, T>): T {\n" " return if (extension.isRepeated) {\n" " get(extension as com.google.protobuf.ExtensionLite<$message$, " - "List<*>>) as T\n" + "kotlin.collections.List<*>>) as T\n" " } else {\n" " _builder.getExtension(extension)\n" " }\n" @@ -1544,8 +1402,9 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n" - "operator fun <E : kotlin.Any> get(\n" - " extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n" + "public operator fun <E : kotlin.Any> get(\n" + " extension: com.google.protobuf.ExtensionLite<$message$, " + "kotlin.collections.List<E>>\n" "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n" " return com.google.protobuf.kotlin.ExtensionList(extension, " "_builder.getExtension(extension))\n" @@ -1554,7 +1413,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "operator fun contains(extension: " + "public operator fun contains(extension: " "com.google.protobuf.ExtensionLite<$message$, *>): " "Boolean {\n" " return _builder.hasExtension(extension)\n" @@ -1563,7 +1422,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "fun clear(extension: " + "public fun clear(extension: " "com.google.protobuf.ExtensionLite<$message$, *>) " "{\n" " _builder.clearExtension(extension)\n" @@ -1572,8 +1431,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.PublishedApi\n" - "internal fun <T : kotlin.Any> setExtension(extension: " + "public fun <T : kotlin.Any> setExtension(extension: " "com.google.protobuf.ExtensionLite<$message$, T>, " "value: T) {\n" " _builder.setExtension(extension, value)\n" @@ -1583,7 +1441,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun <T : Comparable<T>> set(\n" + "public inline operator fun <T : Comparable<T>> set(\n" " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" " value: T\n" ") {\n" @@ -1594,7 +1452,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun set(\n" + "public inline operator fun set(\n" " extension: com.google.protobuf.ExtensionLite<$message$, " "com.google.protobuf.ByteString>,\n" " value: com.google.protobuf.ByteString\n" @@ -1606,7 +1464,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun <T : com.google.protobuf.MessageLite> set(\n" + "public inline operator fun <T : com.google.protobuf.MessageLite> set(\n" " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" " value: T\n" ") {\n" @@ -1616,7 +1474,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "fun <E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, " + "public fun <E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, " "$message$>.add(value: E) {\n" " _builder.addExtension(this.extension, value)\n" "}\n\n", @@ -1625,7 +1483,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun <E : kotlin.Any> " + "public inline operator fun <E : kotlin.Any> " "com.google.protobuf.kotlin.ExtensionList<E, " "$message$>.plusAssign" "(value: E) {\n" @@ -1635,7 +1493,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "fun <E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, " + "public fun <E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, " "$message$>.addAll(values: Iterable<E>) {\n" " for (value in values) {\n" " add(value)\n" @@ -1646,7 +1504,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun <E : kotlin.Any> " + "public inline operator fun <E : kotlin.Any> " "com.google.protobuf.kotlin.ExtensionList<E, " "$message$>.plusAssign(values: " "Iterable<E>) {\n" @@ -1656,7 +1514,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "operator fun <E : kotlin.Any> " + "public operator fun <E : kotlin.Any> " "com.google.protobuf.kotlin.ExtensionList<E, " "$message$>.set(index: Int, value: " "E) {\n" @@ -1667,7 +1525,7 @@ void ImmutableMessageGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline fun com.google.protobuf.kotlin.ExtensionList<*, " + "public inline fun com.google.protobuf.kotlin.ExtensionList<*, " "$message$>.clear() {\n" " clear(extension)\n" "}\n\n", @@ -1722,12 +1580,19 @@ void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) { " defaultInstance.getDescriptorForType().getFullName());\n" "}\n" "\n" + "public boolean isSameTypeAs(com.google.protobuf.Message message) {\n" + " return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n" + " message.getDescriptorForType().getFullName());\n" + "}\n" + "\n" + "@SuppressWarnings(\"serial\")\n" "private volatile com.google.protobuf.Message cachedUnpackValue;\n" "\n" "@java.lang.SuppressWarnings(\"unchecked\")\n" "public <T extends com.google.protobuf.Message> T unpack(\n" " java.lang.Class<T> clazz)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n"); + printer->Print( " boolean invalidClazz = false;\n" " if (cachedUnpackValue != null) {\n" " if (cachedUnpackValue.getClass() == clazz) {\n" @@ -1745,7 +1610,30 @@ void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) { " .parseFrom(getValue());\n" " cachedUnpackValue = result;\n" " return result;\n" - "}\n"); + "}\n" + "\n" + "@java.lang.SuppressWarnings(\"unchecked\")\n" + "public <T extends com.google.protobuf.Message> T unpackSameTypeAs(" + "T message)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n"); + printer->Print( + " boolean invalidValue = false;\n" + " if (cachedUnpackValue != null) {\n" + " if (cachedUnpackValue.getClass() == message.getClass()) {\n" + " return (T) cachedUnpackValue;\n" + " }\n" + " invalidValue = true;\n" + " }\n" + " if (invalidValue || !isSameTypeAs(message)) {\n" + " throw new com.google.protobuf.InvalidProtocolBufferException(\n" + " \"Type of the Any message does not match the given " + "exemplar.\");\n" + " }\n" + " T result = (T) message.getParserForType().parseFrom(getValue());\n" + " cachedUnpackValue = result;\n" + " return result;\n" + "}\n" + "\n"); } } // namespace java @@ -1753,4 +1641,4 @@ void ImmutableMessageGenerator::GenerateAnyMethods(io::Printer* printer) { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/message.h index 2dbd0dd9bc0..37263fa628f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message.h @@ -35,10 +35,10 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "y_absl/container/btree_map.h" +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -64,6 +64,8 @@ static const int kMaxStaticSize = 1 << 15; // aka 32k class MessageGenerator { public: explicit MessageGenerator(const Descriptor* descriptor); + MessageGenerator(const MessageGenerator&) = delete; + MessageGenerator& operator=(const MessageGenerator&) = delete; virtual ~MessageGenerator(); // All static variables have to be declared at the top-level of the file @@ -92,15 +94,15 @@ class MessageGenerator { protected: const Descriptor* descriptor_; - std::set<const OneofDescriptor*> oneofs_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); + y_absl::btree_map<int, const OneofDescriptor*> oneofs_; }; class ImmutableMessageGenerator : public MessageGenerator { public: ImmutableMessageGenerator(const Descriptor* descriptor, Context* context); + ImmutableMessageGenerator(const ImmutableMessageGenerator&) = delete; + ImmutableMessageGenerator& operator=(const ImmutableMessageGenerator&) = + delete; ~ImmutableMessageGenerator() override; void Generate(io::Printer* printer) override; @@ -123,10 +125,6 @@ class ImmutableMessageGenerator : public MessageGenerator { void GenerateMessageSerializationMethods(io::Printer* printer); void GenerateParseFromMethods(io::Printer* printer); - void GenerateSerializeOneField(io::Printer* printer, - const FieldDescriptor* field); - void GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* range); void GenerateBuilder(io::Printer* printer); void GenerateIsInitialized(io::Printer* printer); @@ -143,8 +141,6 @@ class ImmutableMessageGenerator : public MessageGenerator { Context* context_; ClassNameResolver* name_resolver_; FieldGeneratorMap<ImmutableFieldGenerator> field_generators_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder.cc index 3bbb7ae3829..80064a9bf75 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder.cc @@ -32,42 +32,64 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/message_builder.h> +#include "google/protobuf/compiler/java/message_builder.h" #include <algorithm> -#include <map> #include <memory> #include <vector> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/enum.h> -#include <google/protobuf/compiler/java/extension.h> -#include <google/protobuf/compiler/java/generator_factory.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/container/btree_set.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/enum.h" +#include "google/protobuf/compiler/java/extension.h" +#include "google/protobuf/compiler/java/generator_factory.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { namespace compiler { namespace java { +using internal::WireFormat; +using internal::WireFormatLite; + namespace { TProtoStringType MapValueImmutableClassdName(const Descriptor* descriptor, ClassNameResolver* name_resolver) { const FieldDescriptor* value_field = descriptor->map_value(); - GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); + Y_ABSL_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); return name_resolver->GetImmutableClassName(value_field->message_type()); } + +bool BitfieldTracksMutability(const FieldDescriptor* const descriptor) { + if (!descriptor->is_repeated() || IsMapField(descriptor)) { + return false; + } + // TODO(b/255468704): update this to migrate repeated fields to use + // ProtobufList (which tracks immutability internally). That allows us to use + // the presence bit to skip work on the repeated field if it is not populated. + // Once all repeated fields are held in ProtobufLists, this method shouldn't + // be needed. + switch (descriptor->type()) { + case FieldDescriptor::TYPE_STRING: + return false; + default: + return true; + } +} } // namespace MessageBuilderGenerator::MessageBuilderGenerator(const Descriptor* descriptor, @@ -76,12 +98,13 @@ MessageBuilderGenerator::MessageBuilderGenerator(const Descriptor* descriptor, context_(context), name_resolver_(context->GetNameResolver()), field_generators_(descriptor, context_) { - GOOGLE_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite())) + Y_ABSL_CHECK(HasDescriptorMethods(descriptor->file(), context->EnforceLite())) << "Generator factory error: A non-lite message generator is used to " "generate lite messages."; for (int i = 0; i < descriptor_->field_count(); i++) { if (IsRealOneof(descriptor_->field(i))) { - oneofs_.insert(descriptor_->field(i)->containing_oneof()); + const OneofDescriptor* oneof = descriptor_->field(i)->containing_oneof(); + Y_ABSL_CHECK(oneofs_.emplace(oneof->index(), oneof).first->second == oneof); } } } @@ -122,12 +145,13 @@ void MessageBuilderGenerator::Generate(io::Printer* printer) { } // oneof - std::map<TProtoStringType, TProtoStringType> vars; - for (auto oneof : oneofs_) { + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name; vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(oneof)->capitalized_name; - vars["oneof_index"] = StrCat(oneof->index()); + vars["oneof_index"] = y_absl::StrCat(oneof->index()); // oneofCase_ and oneof_ printer->Print(vars, "private int $oneof_name$Case_ = 0;\n" @@ -142,12 +166,11 @@ void MessageBuilderGenerator::Generate(io::Printer* printer) { "\n" "public Builder clear$oneof_capitalized_name$() {\n" " $oneof_name$Case_ = 0;\n" - " $oneof_name$_ = null;\n"); - printer->Print(" onChanged();\n"); - printer->Print( - " return this;\n" - "}\n" - "\n"); + " $oneof_name$_ = null;\n" + " onChanged();\n" + " return this;\n" + "}\n" + "\n"); } // Integers for bit fields. @@ -168,24 +191,26 @@ void MessageBuilderGenerator::Generate(io::Printer* printer) { .GenerateBuilderMembers(printer); } - // 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 - // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release - // we changed all generated code to subclass GeneratedMessageV3). - printer->Print( - "@java.lang.Override\n" - "public final Builder setUnknownFields(\n" - " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" - " return super.setUnknownFields(unknownFields);\n" - "}\n" - "\n" - "@java.lang.Override\n" - "public final Builder mergeUnknownFields(\n" - " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" - " return super.mergeUnknownFields(unknownFields);\n" - "}\n" - "\n"); + if (context_->options().opensource_runtime) { + // 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 + // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release + // we changed all generated code to subclass GeneratedMessageV3). + printer->Print( + "@java.lang.Override\n" + "public final Builder setUnknownFields(\n" + " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" + " return super.setUnknownFields(unknownFields);\n" + "}\n" + "\n" + "@java.lang.Override\n" + "public final Builder mergeUnknownFields(\n" + " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" + " return super.mergeUnknownFields(unknownFields);\n" + "}\n" + "\n"); + } printer->Print( "\n" @@ -231,7 +256,7 @@ void MessageBuilderGenerator::GenerateDescriptorMethods(io::Printer* printer) { printer->Print( "case $number$:\n" " return internalGet$capitalized_name$();\n", - "number", StrCat(field->number()), "capitalized_name", + "number", y_absl::StrCat(field->number()), "capitalized_name", info->capitalized_name); } printer->Print( @@ -256,7 +281,7 @@ void MessageBuilderGenerator::GenerateDescriptorMethods(io::Printer* printer) { printer->Print( "case $number$:\n" " return internalGetMutable$capitalized_name$();\n", - "number", StrCat(field->number()), "capitalized_name", + "number", y_absl::StrCat(field->number()), "capitalized_name", info->capitalized_name); } printer->Print( @@ -288,43 +313,63 @@ void MessageBuilderGenerator::GenerateDescriptorMethods(io::Printer* printer) { void MessageBuilderGenerator::GenerateCommonBuilderMethods( io::Printer* printer) { + // Decide if we really need to have the "maybeForceBuilderInitialization()" + // method. + // TODO(b/249158148): Remove the need for this entirely + bool need_maybe_force_builder_init = false; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (descriptor_->field(i)->message_type() != nullptr && + !IsRealOneof(descriptor_->field(i)) && + HasHasbit(descriptor_->field(i))) { + need_maybe_force_builder_init = true; + break; + } + } + + const char* force_builder_init = need_maybe_force_builder_init + ? " maybeForceBuilderInitialization();" + : ""; + printer->Print( "// Construct using $classname$.newBuilder()\n" "private Builder() {\n" - " maybeForceBuilderInitialization();\n" + "$force_builder_init$\n" "}\n" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "force_builder_init", force_builder_init); printer->Print( "private Builder(\n" " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n" " super(parent);\n" - " maybeForceBuilderInitialization();\n" + "$force_builder_init$\n" "}\n", "classname", name_resolver_->GetImmutableClassName(descriptor_), "ver", - GeneratedCodeVersionSuffix()); + GeneratedCodeVersionSuffix(), "force_builder_init", force_builder_init); - printer->Print( - "private void maybeForceBuilderInitialization() {\n" - " if (com.google.protobuf.GeneratedMessage$ver$\n" - " .alwaysUseFieldBuilders) {\n", - "ver", GeneratedCodeVersionSuffix()); + if (need_maybe_force_builder_init) { + printer->Print( + "private void maybeForceBuilderInitialization() {\n" + " if (com.google.protobuf.GeneratedMessage$ver$\n" + " .alwaysUseFieldBuilders) {\n", + "ver", GeneratedCodeVersionSuffix()); - printer->Indent(); - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!IsRealOneof(descriptor_->field(i))) { - field_generators_.get(descriptor_->field(i)) - .GenerateFieldBuilderInitializationCode(printer); + printer->Indent(); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!IsRealOneof(descriptor_->field(i))) { + field_generators_.get(descriptor_->field(i)) + .GenerateFieldBuilderInitializationCode(printer); + } } - } - printer->Outdent(); - printer->Outdent(); + printer->Outdent(); + printer->Outdent(); - printer->Print( - " }\n" - "}\n"); + printer->Print( + " }\n" + "}\n"); + } printer->Print( "@java.lang.Override\n" @@ -332,19 +377,22 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods( " super.clear();\n"); printer->Indent(); + int totalBuilderInts = (descriptor_->field_count() + 31) / 32; + for (int i = 0; i < totalBuilderInts; i++) { + printer->Print("$bit_field_name$ = 0;\n", "bit_field_name", + GetBitFieldName(i)); + } for (int i = 0; i < descriptor_->field_count(); i++) { - if (!IsRealOneof(descriptor_->field(i))) { - field_generators_.get(descriptor_->field(i)) - .GenerateBuilderClearCode(printer); - } + field_generators_.get(descriptor_->field(i)) + .GenerateBuilderClearCode(printer); } - for (auto oneof : oneofs_) { + for (auto& kv : oneofs_) { printer->Print( "$oneof_name$Case_ = 0;\n" "$oneof_name$_ = null;\n", - "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name); + "oneof_name", context_->GetOneofGeneratorInfo(kv.second)->name); } printer->Outdent(); @@ -385,134 +433,7 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods( "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); - printer->Print( - "@java.lang.Override\n" - "public $classname$ buildPartial() {\n" - " $classname$ result = new $classname$(this);\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - printer->Indent(); - - int totalBuilderBits = 0; - int totalMessageBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const ImmutableFieldGenerator& field = - field_generators_.get(descriptor_->field(i)); - totalBuilderBits += field.GetNumBitsForBuilder(); - totalMessageBits += field.GetNumBitsForMessage(); - } - int totalBuilderInts = (totalBuilderBits + 31) / 32; - int totalMessageInts = (totalMessageBits + 31) / 32; - - // Local vars for from and to bit fields to avoid accessing the builder and - // message over and over for these fields. Seems to provide a slight - // perforamance improvement in micro benchmark and this is also what proto1 - // code does. - for (int i = 0; i < totalBuilderInts; i++) { - printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - for (int i = 0; i < totalMessageInts; i++) { - printer->Print("int to_$bit_field_name$ = 0;\n", "bit_field_name", - GetBitFieldName(i)); - } - - // Output generation code for each field. - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); - } - - // Copy the bit field results to the generated message - for (int i = 0; i < totalMessageInts; i++) { - printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - - for (auto oneof : oneofs_) { - printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n", - "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name); - } - - printer->Outdent(); - - printer->Print(" onBuilt();\n"); - - printer->Print( - " return result;\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - // 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 - // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release - // we changed all generated code to subclass GeneratedMessageV3). - printer->Print( - "@java.lang.Override\n" - "public Builder clone() {\n" - " return super.clone();\n" - "}\n" - "@java.lang.Override\n" - "public Builder setField(\n" - " com.google.protobuf.Descriptors.FieldDescriptor field,\n" - " java.lang.Object value) {\n" - " return super.setField(field, value);\n" - "}\n" - "@java.lang.Override\n" - "public Builder clearField(\n" - " com.google.protobuf.Descriptors.FieldDescriptor field) {\n" - " return super.clearField(field);\n" - "}\n" - "@java.lang.Override\n" - "public Builder clearOneof(\n" - " com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n" - " return super.clearOneof(oneof);\n" - "}\n" - "@java.lang.Override\n" - "public Builder setRepeatedField(\n" - " com.google.protobuf.Descriptors.FieldDescriptor field,\n" - " int index, java.lang.Object value) {\n" - " return super.setRepeatedField(field, index, value);\n" - "}\n" - "@java.lang.Override\n" - "public Builder addRepeatedField(\n" - " com.google.protobuf.Descriptors.FieldDescriptor field,\n" - " java.lang.Object value) {\n" - " return super.addRepeatedField(field, value);\n" - "}\n"); - - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "@java.lang.Override\n" - "public <Type> Builder setExtension(\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" - " $classname$, Type> extension,\n" - " Type value) {\n" - " return super.setExtension(extension, value);\n" - "}\n" - "@java.lang.Override\n" - "public <Type> Builder setExtension(\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" - " $classname$, java.util.List<Type>> extension,\n" - " int index, Type value) {\n" - " return super.setExtension(extension, index, value);\n" - "}\n" - "@java.lang.Override\n" - "public <Type> Builder addExtension(\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" - " $classname$, java.util.List<Type>> extension,\n" - " Type value) {\n" - " return super.addExtension(extension, value);\n" - "}\n" - "@java.lang.Override\n" - "public <Type> Builder clearExtension(\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" - " $classname$, ?> extension) {\n" - " return super.clearExtension(extension);\n" - "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } + GenerateBuildPartial(printer); // ----------------------------------------------------------------- @@ -546,7 +467,8 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods( } // Merge oneof fields. - for (auto oneof : oneofs_) { + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; printer->Print("switch (other.get$oneof_capitalized_name$Case()) {\n", "oneof_capitalized_name", context_->GetOneofGeneratorInfo(oneof)->capitalized_name); @@ -554,7 +476,7 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods( for (int j = 0; j < oneof->field_count(); j++) { const FieldDescriptor* field = oneof->field(j); printer->Print("case $field_name$: {\n", "field_name", - ToUpper(field->name())); + y_absl::AsciiStrToUpper(field->name())); printer->Indent(); field_generators_.get(field).GenerateMergingCode(printer); printer->Print("break;\n"); @@ -566,7 +488,7 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods( " break;\n" "}\n", "cap_oneof_name", - ToUpper(context_->GetOneofGeneratorInfo(oneof)->name)); + y_absl::AsciiStrToUpper(context_->GetOneofGeneratorInfo(oneof)->name)); printer->Outdent(); printer->Print("}\n"); } @@ -578,7 +500,7 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods( printer->Print(" this.mergeExtensionFields(other);\n"); } - printer->Print(" this.mergeUnknownFields(other.unknownFields);\n"); + printer->Print(" this.mergeUnknownFields(other.getUnknownFields());\n"); printer->Print(" onChanged();\n"); @@ -589,6 +511,154 @@ void MessageBuilderGenerator::GenerateCommonBuilderMethods( } } +void MessageBuilderGenerator::GenerateBuildPartial(io::Printer* printer) { + printer->Print( + "@java.lang.Override\n" + "public $classname$ buildPartial() {\n" + " $classname$ result = new $classname$(this);\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Indent(); + + // Handle the repeated fields first so that the "mutable bits" are cleared. + bool has_repeated_fields = false; + for (int i = 0; i < descriptor_->field_count(); ++i) { + if (BitfieldTracksMutability(descriptor_->field(i))) { + has_repeated_fields = true; + printer->Print("buildPartialRepeatedFields(result);\n"); + break; + } + } + + // One buildPartial#() per from_bit_field + int totalBuilderInts = (descriptor_->field_count() + 31) / 32; + if (totalBuilderInts > 0) { + for (int i = 0; i < totalBuilderInts; ++i) { + printer->Print( + "if ($bit_field_name$ != 0) { buildPartial$piece$(result); }\n", + "bit_field_name", GetBitFieldName(i), "piece", y_absl::StrCat(i)); + } + } + + if (!oneofs_.empty()) { + printer->Print("buildPartialOneofs(result);\n"); + } + + printer->Outdent(); + printer->Print( + " onBuilt();\n" + " return result;\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + // Build Repeated Fields + if (has_repeated_fields) { + printer->Print( + "private void buildPartialRepeatedFields($classname$ result) {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); ++i) { + if (BitfieldTracksMutability(descriptor_->field(i))) { + const ImmutableFieldGenerator& field = + field_generators_.get(descriptor_->field(i)); + field.GenerateBuildingCode(printer); + } + } + printer->Outdent(); + printer->Print("}\n\n"); + } + + // Build non-oneof fields + int start_field = 0; + for (int i = 0; i < totalBuilderInts; i++) { + start_field = GenerateBuildPartialPiece(printer, i, start_field); + } + + // Build Oneofs + if (!oneofs_.empty()) { + printer->Print("private void buildPartialOneofs($classname$ result) {\n", + "classname", + name_resolver_->GetImmutableClassName(descriptor_)); + printer->Indent(); + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; + printer->Print( + "result.$oneof_name$Case_ = $oneof_name$Case_;\n" + "result.$oneof_name$_ = this.$oneof_name$_;\n", + "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name); + for (int i = 0; i < oneof->field_count(); ++i) { + if (oneof->field(i)->message_type() != nullptr) { + const ImmutableFieldGenerator& field = + field_generators_.get(oneof->field(i)); + field.GenerateBuildingCode(printer); + } + } + } + printer->Outdent(); + printer->Print("}\n\n"); + } +} + +int MessageBuilderGenerator::GenerateBuildPartialPiece(io::Printer* printer, + int piece, + int first_field) { + printer->Print( + "private void buildPartial$piece$($classname$ result) {\n" + " int from_$bit_field_name$ = $bit_field_name$;\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), "piece", + y_absl::StrCat(piece), "bit_field_name", GetBitFieldName(piece)); + printer->Indent(); + y_absl::btree_set<int> declared_to_bitfields; + + int bit = 0; + int next = first_field; + for (; bit < 32 && next < descriptor_->field_count(); ++next) { + const ImmutableFieldGenerator& field = + field_generators_.get(descriptor_->field(next)); + bit += field.GetNumBitsForBuilder(); + + // Skip oneof fields that are handled separately + if (IsRealOneof(descriptor_->field(next))) { + continue; + } + + // Skip repeated fields because they are currently handled + // in separate buildPartial sub-methods. + if (BitfieldTracksMutability(descriptor_->field(next))) { + continue; + } + // Skip fields without presence bits in the builder + if (field.GetNumBitsForBuilder() == 0) { + continue; + } + + // Track message bits if necessary + if (field.GetNumBitsForMessage() > 0) { + int to_bitfield = field.GetMessageBitIndex() / 32; + if (declared_to_bitfields.count(to_bitfield) == 0) { + printer->Print("int to_$bit_field_name$ = 0;\n", "bit_field_name", + GetBitFieldName(to_bitfield)); + declared_to_bitfields.insert(to_bitfield); + } + } + + // Copy the field from the builder to the message + field.GenerateBuildingCode(printer); + } + + // Copy the bit field results to the generated message + for (int to_bitfield : declared_to_bitfields) { + printer->Print("result.$bit_field_name$ |= to_$bit_field_name$;\n", + "bit_field_name", GetBitFieldName(to_bitfield)); + } + + printer->Outdent(); + printer->Print("}\n\n"); + + return next; +} + // =================================================================== void MessageBuilderGenerator::GenerateBuilderParsingMethods( @@ -599,20 +669,92 @@ void MessageBuilderGenerator::GenerateBuilderParsingMethods( " com.google.protobuf.CodedInputStream input,\n" " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" - " $classname$ parsedMessage = null;\n" + " if (extensionRegistry == null) {\n" + " throw new java.lang.NullPointerException();\n" + " }\n" " try {\n" - " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n" + " boolean done = false;\n" + " while (!done) {\n" + " int tag = input.readTag();\n" + " switch (tag) {\n" + " case 0:\n" // zero signals EOF / limit reached + " done = true;\n" + " break;\n"); + printer->Indent(); // method + printer->Indent(); // try + printer->Indent(); // while + printer->Indent(); // switch + GenerateBuilderFieldParsingCases(printer); + printer->Outdent(); // switch + printer->Outdent(); // while + printer->Outdent(); // try + printer->Outdent(); // method + printer->Print( + " default: {\n" + " if (!super.parseUnknownField(input, extensionRegistry, tag)) " + "{\n" + " done = true; // was an endgroup tag\n" + " }\n" + " break;\n" + " } // default:\n" + " } // switch (tag)\n" + " } // while (!done)\n" " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " parsedMessage = ($classname$) e.getUnfinishedMessage();\n" " throw e.unwrapIOException();\n" " } finally {\n" - " if (parsedMessage != null) {\n" - " mergeFrom(parsedMessage);\n" - " }\n" - " }\n" + " onChanged();\n" + " } // finally\n" " return this;\n" - "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "}\n"); +} + +void MessageBuilderGenerator::GenerateBuilderFieldParsingCases( + io::Printer* 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]; + GenerateBuilderFieldParsingCase(printer, field); + if (field->is_packable()) { + GenerateBuilderPackedFieldParsingCase(printer, field); + } + } +} + +void MessageBuilderGenerator::GenerateBuilderFieldParsingCase( + io::Printer* printer, const FieldDescriptor* field) { + arc_ui32 tag = WireFormatLite::MakeTag( + field->number(), WireFormat::WireTypeForFieldType(field->type())); + TProtoStringType tagString = y_absl::StrCat(static_cast<arc_i32>(tag)); + printer->Print("case $tag$: {\n", "tag", tagString); + printer->Indent(); + + field_generators_.get(field).GenerateBuilderParsingCode(printer); + + printer->Outdent(); + printer->Print( + " break;\n" + "} // case $tag$\n", + "tag", tagString); +} + +void MessageBuilderGenerator::GenerateBuilderPackedFieldParsingCase( + io::Printer* printer, const FieldDescriptor* field) { + // To make packed = true wire compatible, we generate parsing code from a + // packed version of this field regardless of field->options().packed(). + arc_ui32 tag = WireFormatLite::MakeTag( + field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + TProtoStringType tagString = y_absl::StrCat(static_cast<arc_i32>(tag)); + printer->Print("case $tag$: {\n", "tag", tagString); + printer->Indent(); + + field_generators_.get(field).GenerateBuilderParsingCodeFromPacked(printer); + + printer->Outdent(); + printer->Print( + " break;\n" + "} // case $tag$\n", + "tag", tagString); } // =================================================================== @@ -714,4 +856,4 @@ void MessageBuilderGenerator::GenerateIsInitialized(io::Printer* printer) { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder.h index f9c9a00a0ca..16585da339c 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder.h @@ -35,10 +35,10 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__ -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "y_absl/container/btree_map.h" +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -63,23 +63,33 @@ class MessageBuilderGenerator { public: explicit MessageBuilderGenerator(const Descriptor* descriptor, Context* context); + MessageBuilderGenerator(const MessageBuilderGenerator&) = delete; + MessageBuilderGenerator& operator=(const MessageBuilderGenerator&) = delete; virtual ~MessageBuilderGenerator(); virtual void Generate(io::Printer* printer); private: void GenerateCommonBuilderMethods(io::Printer* printer); + void GenerateBuildPartial(io::Printer* printer); + int GenerateBuildPartialPiece(io::Printer* printer, int piece, + int first_field); + int GenerateBuildPartialPieceWithoutPresence(io::Printer* printer, int piece, + int first_field); void GenerateDescriptorMethods(io::Printer* printer); void GenerateBuilderParsingMethods(io::Printer* printer); + void GenerateBuilderFieldParsingCases(io::Printer* printer); + void GenerateBuilderFieldParsingCase(io::Printer* printer, + const FieldDescriptor* field); + void GenerateBuilderPackedFieldParsingCase(io::Printer* printer, + const FieldDescriptor* field); void GenerateIsInitialized(io::Printer* printer); const Descriptor* descriptor_; Context* context_; ClassNameResolver* name_resolver_; FieldGeneratorMap<ImmutableFieldGenerator> field_generators_; - std::set<const OneofDescriptor*> oneofs_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderGenerator); + y_absl::btree_map<int, const OneofDescriptor*> oneofs_; }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder_lite.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder_lite.cc index bf41a711075..f85341d9ce7 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder_lite.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder_lite.cc @@ -32,29 +32,30 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/message_builder_lite.h> +#include "google/protobuf/compiler/java/message_builder_lite.h" #include <algorithm> -#include <map> #include <memory> +#include <string> #include <vector> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/enum.h> -#include <google/protobuf/compiler/java/extension.h> -#include <google/protobuf/compiler/java/generator_factory.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/enum.h" +#include "google/protobuf/compiler/java/extension.h" +#include "google/protobuf/compiler/java/generator_factory.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -67,12 +68,13 @@ MessageBuilderLiteGenerator::MessageBuilderLiteGenerator( context_(context), name_resolver_(context->GetNameResolver()), field_generators_(descriptor, context_) { - GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite())) + Y_ABSL_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite())) << "Generator factory error: A lite message generator is used to " "generate non-lite messages."; for (int i = 0; i < descriptor_->field_count(); i++) { if (IsRealOneof(descriptor_->field(i))) { - oneofs_.insert(descriptor_->field(i)->containing_oneof()); + const OneofDescriptor* oneof = descriptor_->field(i)->containing_oneof(); + Y_ABSL_CHECK(oneofs_.emplace(oneof->index(), oneof).first->second == oneof); } } } @@ -81,41 +83,51 @@ MessageBuilderLiteGenerator::~MessageBuilderLiteGenerator() {} void MessageBuilderLiteGenerator::Generate(io::Printer* printer) { WriteMessageDocComment(printer, descriptor_); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars = { + {"{", ""}, + {"}", ""}, + {"classname", name_resolver_->GetImmutableClassName(descriptor_)}, + {"extra_interfaces", ExtraBuilderInterfaces(descriptor_)}, + {"extendible", + descriptor_->extension_range_count() > 0 ? "Extendable" : ""}, + }; printer->Print( - "public static final class Builder extends\n" + vars, + "public static final class ${$Builder$}$ extends\n" " com.google.protobuf.GeneratedMessageLite.$extendible$Builder<\n" " $classname$, Builder> implements\n" " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_), "extendible", - descriptor_->extension_range_count() > 0 ? "Extendable" : ""); + " $classname$OrBuilder {\n"); + printer->Annotate("{", "}", descriptor_); printer->Indent(); GenerateCommonBuilderMethods(printer); // oneof - std::map<TProtoStringType, TProtoStringType> vars; - for (auto oneof : oneofs_) { + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name; vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(oneof)->capitalized_name; - vars["oneof_index"] = StrCat(oneof->index()); + vars["oneof_index"] = y_absl::StrCat(oneof->index()); // oneofCase() and clearOneof() printer->Print(vars, "@java.lang.Override\n" "public $oneof_capitalized_name$Case\n" - " get$oneof_capitalized_name$Case() {\n" + " ${$get$oneof_capitalized_name$Case$}$() {\n" " return instance.get$oneof_capitalized_name$Case();\n" - "}\n" + "}\n"); + printer->Annotate("{", "}", oneof); + printer->Print(vars, "\n" - "public Builder clear$oneof_capitalized_name$() {\n" + "public Builder ${$clear$oneof_capitalized_name$$}$() {\n" " copyOnWrite();\n" " instance.clear$oneof_capitalized_name$();\n" " return this;\n" "}\n" "\n"); + printer->Annotate("{", "}", oneof); } for (int i = 0; i < descriptor_->field_count(); i++) { @@ -153,4 +165,4 @@ void MessageBuilderLiteGenerator::GenerateCommonBuilderMethods( } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder_lite.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder_lite.h index 0d895fcf05b..a0feece646d 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder_lite.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_builder_lite.h @@ -35,10 +35,10 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__ -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "y_absl/container/btree_map.h" +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -63,6 +63,9 @@ class MessageBuilderLiteGenerator { public: explicit MessageBuilderLiteGenerator(const Descriptor* descriptor, Context* context); + MessageBuilderLiteGenerator(const MessageBuilderLiteGenerator&) = delete; + MessageBuilderLiteGenerator& operator=(const MessageBuilderLiteGenerator&) = + delete; virtual ~MessageBuilderLiteGenerator(); virtual void Generate(io::Printer* printer); @@ -74,9 +77,7 @@ class MessageBuilderLiteGenerator { Context* context_; ClassNameResolver* name_resolver_; FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_; - std::set<const OneofDescriptor*> oneofs_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderLiteGenerator); + y_absl::btree_map<int, const OneofDescriptor*> oneofs_; }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field.cc index a16abfcb341..1a5efaa9386 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field.cc @@ -32,21 +32,21 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/message_field.h> +#include "google/protobuf/compiler/java/message_field.h" -#include <map> #include <string> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -56,15 +56,16 @@ namespace java { namespace { -void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetMessageVariables( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables, + Context* context) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["type"] = name_resolver->GetImmutableClassName(descriptor->message_type()); - (*variables)["kt_type"] = (*variables)["type"]; + variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])}); (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->message_type()); (*variables)["group_or_message"] = @@ -74,38 +75,33 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["kt_deprecation"] = - descriptor->options().deprecated() - ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + - " is deprecated\") " - : ""; + variables->insert( + {"kt_deprecation", + descriptor->options().deprecated() + ? y_absl::StrCat("@kotlin.Deprecated(message = \"Field ", + (*variables)["name"], " is deprecated\") ") + : ""}); (*variables)["on_changed"] = "onChanged();"; (*variables)["ver"] = GeneratedCodeVersionSuffix(); (*variables)["get_parser"] = - ExposePublicParser(descriptor->message_type()->file()) ? "PARSER" - : "parser()"; + ExposePublicParser(descriptor->message_type()->file()) && + context->options().opensource_runtime + ? "PARSER" + : "parser()"; if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); // Note that these have a trailing ";". - (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; - (*variables)["set_has_field_bit_builder"] = - GenerateSetBit(builderBitIndex) + ";"; - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex) + ";"; + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); } else { - (*variables)["set_has_field_bit_message"] = ""; - (*variables)["set_has_field_bit_builder"] = ""; - (*variables)["clear_has_field_bit_builder"] = ""; - - (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != null"; + (*variables)["set_has_field_bit_to_local"] = ""; + variables->insert({"is_field_present_message", + y_absl::StrCat((*variables)["name"], "_ != null")}); } // For repeated builders, one bit is used for whether the array is immutable. @@ -113,17 +109,13 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); - // For repeated fields, one bit is used for whether the array is immutable - // in the parsing constructor. - (*variables)["get_mutable_bit_parser"] = - GenerateGetBitMutableLocal(builderBitIndex); - (*variables)["set_mutable_bit_parser"] = - GenerateSetBitMutableLocal(builderBitIndex); - + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_has_field_bit_builder"] = + y_absl::StrCat(GenerateSetBit(builderBitIndex), ";"); + (*variables)["clear_has_field_bit_builder"] = + y_absl::StrCat(GenerateClearBit(builderBitIndex), ";"); (*variables)["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(builderBitIndex); - (*variables)["set_has_field_bit_to_local"] = - GenerateSetBitToLocal(messageBitIndex); } } // namespace @@ -133,21 +125,31 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, ImmutableMessageFieldGenerator::ImmutableMessageFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), + message_bit_index_(messageBitIndex), + builder_bit_index_(builderBitIndex), + name_resolver_(context->GetNameResolver()), + context_(context) { SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + name_resolver_, &variables_, context); } ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {} +int ImmutableMessageFieldGenerator::GetMessageBitIndex() const { + return message_bit_index_; +} + +int ImmutableMessageFieldGenerator::GetBuilderBitIndex() const { + return builder_bit_index_; +} + int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const { return HasHasbit(descriptor_) ? 1 : 0; } -int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { - return GetNumBitsForMessage(); -} +int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { return 1; } void ImmutableMessageFieldGenerator::GenerateInterfaceMembers( io::Printer* printer) const { @@ -180,24 +182,6 @@ void ImmutableMessageFieldGenerator::GenerateMembers( " return $get_has_field_bit_message$;\n" "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldAccessorDocComment(printer, descriptor_, GETTER); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - - WriteFieldDocComment(printer, descriptor_); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public $type$OrBuilder " - "${$get$capitalized_name$OrBuilder$}$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); } else { WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print( @@ -207,24 +191,25 @@ void ImmutableMessageFieldGenerator::GenerateMembers( " return $name$_ != null;\n" "}\n"); printer->Annotate("{", "}", descriptor_); - WriteFieldAccessorDocComment(printer, descriptor_, GETTER); - printer->Print( - variables_, - "@java.lang.Override\n" - "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "@java.lang.Override\n" - "$deprecation$public $type$OrBuilder " - "${$get$capitalized_name$OrBuilder$}$() {\n" - " return get$capitalized_name$();\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); } + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); + + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "@java.lang.Override\n" + "$deprecation$public $type$OrBuilder " + "${$get$capitalized_name$OrBuilder$}$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); } void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition( @@ -262,9 +247,6 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( // 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. - - bool has_hasbit = HasHasbit(descriptor_); - printer->Print(variables_, "private $type$ $name$_;\n"); printer->Print(variables_, @@ -279,21 +261,11 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( // boolean hasField() WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); - if (has_hasbit) { - printer->Print( - variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } else { - printer->Print( - variables_, - "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" - " return $name$Builder_ != null || $name$_ != null;\n" - "}\n"); - printer->Annotate("{", "}", descriptor_); - } + printer->Print(variables_, + "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + printer->Annotate("{", "}", descriptor_); // Field getField() WriteFieldAccessorDocComment(printer, descriptor_, GETTER); @@ -311,12 +283,12 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( "if (value == null) {\n" " throw new NullPointerException();\n" "}\n" - "$name$_ = value;\n" - "$on_changed$\n", + "$name$_ = value;\n", "$name$Builder_.setMessage(value);\n", "$set_has_field_bit_builder$\n" + "$on_changed$\n" "return this;\n"); // Field.Builder setField(Field.Builder builderForValue) @@ -326,58 +298,48 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" " $type$.Builder builderForValue)", - "$name$_ = builderForValue.build();\n" - "$on_changed$\n", + "$name$_ = builderForValue.build();\n", "$name$Builder_.setMessage(builderForValue.build());\n", "$set_has_field_bit_builder$\n" + "$on_changed$\n" "return this;\n"); - // Field.Builder mergeField(Field value) + // Message.Builder mergeField(Field value) WriteFieldDocComment(printer, descriptor_); PrintNestedBuilderFunction( printer, "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)", - - has_hasbit - ? "if ($get_has_field_bit_builder$ &&\n" - " $name$_ != null &&\n" - " $name$_ != $type$.getDefaultInstance()) {\n" - " $name$_ =\n" - " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" - "} else {\n" - " $name$_ = value;\n" - "}\n" - "$on_changed$\n" - : "if ($name$_ != null) {\n" - " $name$_ =\n" - " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" - "} else {\n" - " $name$_ = value;\n" - "}\n" - "$on_changed$\n", + "if ($get_has_field_bit_builder$ &&\n" + " $name$_ != null &&\n" + " $name$_ != $type$.getDefaultInstance()) {\n" + " get$capitalized_name$Builder().mergeFrom(value);\n" + "} else {\n" + " $name$_ = value;\n" + "}\n", "$name$Builder_.mergeFrom(value);\n", "$set_has_field_bit_builder$\n" + "$on_changed$\n" "return this;\n"); - // Field.Builder clearField() + // Message.Builder clearField() WriteFieldDocComment(printer, descriptor_); - PrintNestedBuilderFunction( - printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()", - - "$name$_ = null;\n" - "$on_changed$\n", - - has_hasbit ? "$name$Builder_.clear();\n" - : "$name$_ = null;\n" - "$name$Builder_ = null;\n", - - "$clear_has_field_bit_builder$\n" - "return this;\n"); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " $clear_has_field_bit_builder$\n" + " $name$_ = null;\n" + " if ($name$Builder_ != null) {\n" + " $name$Builder_.dispose();\n" + " $name$Builder_ = null;\n" + " }\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + // Field.Builder getFieldBuilder() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public $type$.Builder " @@ -387,6 +349,8 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( " return get$capitalized_name$FieldBuilder().getBuilder();\n" "}\n"); printer->Annotate("{", "}", descriptor_); + + // FieldOrBuilder getFieldOrBuilder() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public $type$OrBuilder " @@ -399,6 +363,8 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( " }\n" "}\n"); printer->Annotate("{", "}", descriptor_); + + // SingleFieldBuilder getFieldFieldBuilder WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -419,9 +385,9 @@ void ImmutableMessageFieldGenerator::GenerateBuilderMembers( void ImmutableMessageFieldGenerator::GenerateKotlinDslMembers( io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$var $kt_name$: $kt_type$\n" + "$kt_deprecation$public var $kt_name$: $kt_type$\n" " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" @@ -430,16 +396,17 @@ void ImmutableMessageFieldGenerator::GenerateKotlinDslMembers( " }\n"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, - "fun ${$clear$kt_capitalized_name$$}$() {\n" + "public fun ${$clear$kt_capitalized_name$$}$() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" "}\n"); - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, + /* builder */ false, /* kdoc */ true); printer->Print( variables_, - "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" "}\n"); @@ -449,16 +416,14 @@ void ImmutableMessageFieldGenerator::GenerateKotlinDslMembers( void ImmutableMessageFieldGenerator::GenerateKotlinOrNull(io::Printer* printer) const { if (descriptor_->has_optional_keyword()) { printer->Print(variables_, - "val $classname$Kt.Dsl.$name$OrNull: $kt_type$?\n" + "public val $classname$Kt.Dsl.$name$OrNull: $kt_type$?\n" " get() = $kt_dsl_builder$.$name$OrNull\n"); } } void ImmutableMessageFieldGenerator::GenerateFieldBuilderInitializationCode( io::Printer* printer) const { - if (HasHasbit(descriptor_)) { - printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n"); - } + printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n"); } void ImmutableMessageFieldGenerator::GenerateInitializationCode( @@ -466,17 +431,13 @@ void ImmutableMessageFieldGenerator::GenerateInitializationCode( void ImmutableMessageFieldGenerator::GenerateBuilderClearCode( io::Printer* printer) const { - if (HasHasbit(descriptor_)) { - PrintNestedBuilderCondition(printer, "$name$_ = null;\n", - - "$name$Builder_.clear();\n"); - printer->Print(variables_, "$clear_has_field_bit_builder$\n"); - } else { - PrintNestedBuilderCondition(printer, "$name$_ = null;\n", - - "$name$_ = null;\n" - "$name$Builder_ = null;\n"); - } + // No need to clear the has-bit since we clear the bitField ints all at once. + printer->Print(variables_, + "$name$_ = null;\n" + "if ($name$Builder_ != null) {\n" + " $name$Builder_.dispose();\n" + " $name$Builder_ = null;\n" + "}\n"); } void ImmutableMessageFieldGenerator::GenerateMergingCode( @@ -489,50 +450,32 @@ void ImmutableMessageFieldGenerator::GenerateMergingCode( void ImmutableMessageFieldGenerator::GenerateBuildingCode( io::Printer* printer) const { - if (HasHasbit(descriptor_)) { - 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"); - printer->Outdent(); - printer->Print(variables_, - " $set_has_field_bit_to_local$;\n" - "}\n"); - } else { - PrintNestedBuilderCondition(printer, "result.$name$_ = $name$_;\n", - "result.$name$_ = $name$Builder_.build();\n"); + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " result.$name$_ = $name$Builder_ == null\n" + " ? $name$_\n" + " : $name$Builder_.build();\n"); + if (GetNumBitsForMessage() > 0) { + printer->Print(variables_, " $set_has_field_bit_to_local$;\n"); } + printer->Print("}\n"); } -void ImmutableMessageFieldGenerator::GenerateParsingCode( +void ImmutableMessageFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { - printer->Print(variables_, - "$type$.Builder subBuilder = null;\n" - "if ($is_field_present_message$) {\n" - " subBuilder = $name$_.toBuilder();\n" - "}\n"); - if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { printer->Print(variables_, - "$name$_ = input.readGroup($number$, $type$.$get_parser$,\n" - " extensionRegistry);\n"); + "input.readGroup($number$,\n" + " get$capitalized_name$FieldBuilder().getBuilder(),\n" + " extensionRegistry);\n" + "$set_has_field_bit_builder$\n"); } else { printer->Print(variables_, - "$name$_ = input.readMessage($type$.$get_parser$, " - "extensionRegistry);\n"); + "input.readMessage(\n" + " get$capitalized_name$FieldBuilder().getBuilder(),\n" + " extensionRegistry);\n" + "$set_has_field_bit_builder$\n"); } - - printer->Print(variables_, - "if (subBuilder != null) {\n" - " subBuilder.mergeFrom($name$_);\n" - " $name$_ = subBuilder.buildPartial();\n" - "}\n" - "$set_has_field_bit_message$\n"); -} - -void ImmutableMessageFieldGenerator::GenerateParsingDoneCode( - io::Printer* printer) const { - // noop for messages. } void ImmutableMessageFieldGenerator::GenerateSerializationCode( @@ -596,6 +539,7 @@ void ImmutableMessageOneofFieldGenerator::GenerateMembers( " return $has_oneof_case_message$;\n" "}\n"); printer->Annotate("{", "}", descriptor_); + WriteFieldAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, "@java.lang.Override\n" @@ -779,24 +723,28 @@ void ImmutableMessageOneofFieldGenerator::GenerateBuilderMembers( " $oneof_name$_ = null;\n" " }\n" " $set_oneof_case_message$;\n" - " $on_changed$;\n" + " $on_changed$\n" " return $name$Builder_;\n" "}\n"); printer->Annotate("{", "}", descriptor_); } -void ImmutableMessageOneofFieldGenerator::GenerateBuildingCode( +void ImmutableMessageOneofFieldGenerator::GenerateBuilderClearCode( io::Printer* printer) const { - printer->Print(variables_, "if ($has_oneof_case_message$) {\n"); - printer->Indent(); - - PrintNestedBuilderCondition( - printer, "result.$oneof_name$_ = $oneof_name$_;\n", - - "result.$oneof_name$_ = $name$Builder_.build();\n"); + // Make sure the builder gets cleared. + printer->Print(variables_, + "if ($name$Builder_ != null) {\n" + " $name$Builder_.clear();\n" + "}\n"); +} - printer->Outdent(); - printer->Print("}\n"); +void ImmutableMessageOneofFieldGenerator::GenerateBuildingCode( + io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$ &&\n" + " $name$Builder_ != null) {\n" + " result.$oneof_name$_ = $name$Builder_.build();\n" + "}\n"); } void ImmutableMessageOneofFieldGenerator::GenerateMergingCode( @@ -805,32 +753,21 @@ void ImmutableMessageOneofFieldGenerator::GenerateMergingCode( "merge$capitalized_name$(other.get$capitalized_name$());\n"); } -void ImmutableMessageOneofFieldGenerator::GenerateParsingCode( +void ImmutableMessageOneofFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { - printer->Print(variables_, - "$type$.Builder subBuilder = null;\n" - "if ($has_oneof_case_message$) {\n" - " subBuilder = (($type$) $oneof_name$_).toBuilder();\n" - "}\n"); - if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { - printer->Print( - variables_, - "$oneof_name$_ = input.readGroup($number$, $type$.$get_parser$,\n" - " extensionRegistry);\n"); + printer->Print(variables_, + "input.readGroup($number$,\n" + " get$capitalized_name$FieldBuilder().getBuilder(),\n" + " extensionRegistry);\n" + "$set_oneof_case_message$;\n"); } else { - printer->Print( - variables_, - "$oneof_name$_ =\n" - " input.readMessage($type$.$get_parser$, extensionRegistry);\n"); + printer->Print(variables_, + "input.readMessage(\n" + " get$capitalized_name$FieldBuilder().getBuilder(),\n" + " extensionRegistry);\n" + "$set_oneof_case_message$;\n"); } - - printer->Print(variables_, - "if (subBuilder != null) {\n" - " subBuilder.mergeFrom(($type$) $oneof_name$_);\n" - " $oneof_name$_ = subBuilder.buildPartial();\n" - "}\n"); - printer->Print(variables_, "$set_oneof_case_message$;\n"); } void ImmutableMessageOneofFieldGenerator::GenerateSerializationCode( @@ -857,11 +794,8 @@ void ImmutableMessageOneofFieldGenerator::GenerateSerializedSizeCode( RepeatedImmutableMessageFieldGenerator::RepeatedImmutableMessageFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); -} + : ImmutableMessageFieldGenerator(descriptor, messageBitIndex, + builderBitIndex, context) {} RepeatedImmutableMessageFieldGenerator:: ~RepeatedImmutableMessageFieldGenerator() {} @@ -904,7 +838,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateInterfaceMembers( void RepeatedImmutableMessageFieldGenerator::GenerateMembers( io::Printer* printer) const { - printer->Print(variables_, "private java.util.List<$type$> $name$_;\n"); + printer->Print(variables_, "@SuppressWarnings(\"serial\")\n" + "private java.util.List<$type$> $name$_;\n"); PrintExtraFieldInfo(variables_, printer); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -914,6 +849,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMembers( " return $name$_;\n" // note: unmodifiable list "}\n"); printer->Annotate("{", "}", descriptor_); + + // List<FieldOrBuilder> getFieldOrBuilderList() WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -923,6 +860,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMembers( " return $name$_;\n" "}\n"); printer->Annotate("{", "}", descriptor_); + + // int getFieldCount() WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -931,6 +870,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMembers( " return $name$_.size();\n" "}\n"); printer->Annotate("{", "}", descriptor_); + + // Field getField(int index) WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -939,6 +880,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateMembers( " return $name$_.get(index);\n" "}\n"); printer->Annotate("{", "}", descriptor_); + + // FieldOrBuilder getFieldOrBuilder(int index) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "@java.lang.Override\n" @@ -1164,7 +1107,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( "return this;\n"); - // Builder clearAllRepeatedField() + // Builder clearRepeatedField() WriteFieldDocComment(printer, descriptor_); PrintNestedBuilderFunction( printer, "$deprecation$public Builder ${$clear$capitalized_name$$}$()", @@ -1191,6 +1134,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( "return this;\n"); + // Field.Builder getRepeatedFieldBuilder(int index) WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -1200,6 +1144,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( "}\n"); printer->Annotate("{", "}", descriptor_); + // FieldOrBuilder getRepeatedFieldOrBuilder(int index) WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public $type$OrBuilder " @@ -1213,6 +1158,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( "}\n"); printer->Annotate("{", "}", descriptor_); + // List<FieldOrBuilder> getRepeatedFieldOrBuilderList() WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -1226,6 +1172,7 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( "}\n"); printer->Annotate("{", "}", descriptor_); + // Field.Builder addRepeatedField() WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public $type$.Builder " @@ -1234,6 +1181,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( " $type$.getDefaultInstance());\n" "}\n"); printer->Annotate("{", "}", descriptor_); + + // Field.Builder addRepeatedFieldBuilder(int index) WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -1243,6 +1192,8 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuilderMembers( " index, $type$.getDefaultInstance());\n" "}\n"); printer->Annotate("{", "}", descriptor_); + + // List<Field.Builder> getRepeatedFieldBuilderList() WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, @@ -1281,10 +1232,12 @@ void RepeatedImmutableMessageFieldGenerator::GenerateInitializationCode( void RepeatedImmutableMessageFieldGenerator::GenerateBuilderClearCode( io::Printer* printer) const { PrintNestedBuilderCondition(printer, - "$name$_ = java.util.Collections.emptyList();\n" - "$clear_mutable_bit_builder$;\n", + "$name$_ = java.util.Collections.emptyList();\n", + "$name$_ = null;\n" "$name$Builder_.clear();\n"); + + printer->Print(variables_, "$clear_mutable_bit_builder$;\n"); } void RepeatedImmutableMessageFieldGenerator::GenerateMergingCode( @@ -1339,34 +1292,25 @@ void RepeatedImmutableMessageFieldGenerator::GenerateBuildingCode( "result.$name$_ = $name$Builder_.build();\n"); } -void RepeatedImmutableMessageFieldGenerator::GenerateParsingCode( +void RepeatedImmutableMessageFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { - printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new java.util.ArrayList<$type$>();\n" - " $set_mutable_bit_parser$;\n" - "}\n"); - if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { - printer->Print( - variables_, - "$name$_.add(input.readGroup($number$, $type$.$get_parser$,\n" - " extensionRegistry));\n"); + printer->Print(variables_, + "$type$ m =\n" + " input.readGroup($number$,\n" + " $type$.$get_parser$,\n" + " extensionRegistry);\n"); } else { - printer->Print( - variables_, - "$name$_.add(\n" - " input.readMessage($type$.$get_parser$, extensionRegistry));\n"); + printer->Print(variables_, + "$type$ m =\n" + " input.readMessage(\n" + " $type$.$get_parser$,\n" + " extensionRegistry);\n"); } -} - -void RepeatedImmutableMessageFieldGenerator::GenerateParsingDoneCode( - io::Printer* printer) const { - printer->Print( - variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = java.util.Collections.unmodifiableList($name$_);\n" - "}\n"); + PrintNestedBuilderCondition(printer, + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(m);\n", + "$name$Builder_.addMessage(m);\n"); } void RepeatedImmutableMessageFieldGenerator::GenerateSerializationCode( @@ -1419,12 +1363,12 @@ void RepeatedImmutableMessageFieldGenerator::GenerateKotlinDslMembers( " */\n" "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" " : com.google.protobuf.kotlin.DslProxy()\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$ val $kt_name$: " + "$kt_deprecation$ public val $kt_name$: " "com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " @kotlin.jvm.JvmSynthetic\n" @@ -1433,70 +1377,70 @@ void RepeatedImmutableMessageFieldGenerator::GenerateKotlinDslMembers( " )\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "add(value: $kt_type$) {\n" " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(value: $kt_type$) {\n" " add(value)\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" " addAll(values)\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "operator fun com.google.protobuf.kotlin.DslList" + "public operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "set(index: kotlin.Int, value: $kt_type$) {\n" " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "clear() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" @@ -1508,4 +1452,4 @@ void RepeatedImmutableMessageFieldGenerator::GenerateKotlinDslMembers( } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field.h index 602612e4ada..6e3e2c479d0 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field.h @@ -35,10 +35,9 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__ -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -62,10 +61,16 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { int messageBitIndex, int builderBitIndex, Context* context); + ImmutableMessageFieldGenerator(const ImmutableMessageFieldGenerator&) = + delete; + ImmutableMessageFieldGenerator& operator=( + const ImmutableMessageFieldGenerator&) = delete; ~ImmutableMessageFieldGenerator() override; // implements ImmutableFieldGenerator // --------------------------------------- + int GetMessageBitIndex() const override; + int GetBuilderBitIndex() const override; int GetNumBitsForMessage() const override; int GetNumBitsForBuilder() const override; void GenerateInterfaceMembers(io::Printer* printer) const override; @@ -75,8 +80,7 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; - void GenerateParsingDoneCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateFieldBuilderInitializationCode( @@ -89,20 +93,22 @@ class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { protected: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + int message_bit_index_; + int builder_bit_index_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; ClassNameResolver* name_resolver_; + Context* context_; - void PrintNestedBuilderCondition(io::Printer* printer, - const char* regular_case, - const char* nested_builder_case) const; - void PrintNestedBuilderFunction(io::Printer* printer, - const char* method_prototype, - const char* regular_case, - const char* nested_builder_case, - const char* trailing_code) const; + virtual void PrintNestedBuilderCondition( + io::Printer* printer, const char* regular_case, + const char* nested_builder_case) const; + virtual void PrintNestedBuilderFunction(io::Printer* printer, + const char* method_prototype, + const char* regular_case, + const char* nested_builder_case, + const char* trailing_code) const; private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator); void GenerateKotlinOrNull(io::Printer* printer) const; }; @@ -112,25 +118,32 @@ class ImmutableMessageOneofFieldGenerator ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context); + ImmutableMessageOneofFieldGenerator( + const ImmutableMessageOneofFieldGenerator&) = delete; + ImmutableMessageOneofFieldGenerator& operator=( + const ImmutableMessageOneofFieldGenerator&) = delete; ~ImmutableMessageOneofFieldGenerator() override; void GenerateMembers(io::Printer* printer) const override; void GenerateBuilderMembers(io::Printer* printer) const override; + void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldGenerator); }; -class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { +class RepeatedImmutableMessageFieldGenerator + : public ImmutableMessageFieldGenerator { public: explicit RepeatedImmutableMessageFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context); + RepeatedImmutableMessageFieldGenerator( + const RepeatedImmutableMessageFieldGenerator&) = delete; + RepeatedImmutableMessageFieldGenerator& operator=( + const RepeatedImmutableMessageFieldGenerator&) = delete; ~RepeatedImmutableMessageFieldGenerator() override; // implements ImmutableFieldGenerator --------------------------------------- @@ -143,8 +156,7 @@ class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; - void GenerateParsingDoneCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateFieldBuilderInitializationCode( @@ -156,21 +168,14 @@ class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { TProtoStringType GetBoxedType() const override; protected: - const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; - ClassNameResolver* name_resolver_; - - void PrintNestedBuilderCondition(io::Printer* printer, - const char* regular_case, - const char* nested_builder_case) const; + void PrintNestedBuilderCondition( + io::Printer* printer, const char* regular_case, + const char* nested_builder_case) const override; void PrintNestedBuilderFunction(io::Printer* printer, const char* method_prototype, const char* regular_case, const char* nested_builder_case, - const char* trailing_code) const; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator); + const char* trailing_code) const override; }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field_lite.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field_lite.cc index 23d3c410f6d..08cb34094ce 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field_lite.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field_lite.cc @@ -32,22 +32,21 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/message_field_lite.h> +#include "google/protobuf/compiler/java/message_field_lite.h" #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -56,15 +55,16 @@ namespace java { namespace { -void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex, const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetMessageVariables( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables, + Context* context) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["type"] = name_resolver->GetImmutableClassName(descriptor->message_type()); - (*variables)["kt_type"] = (*variables)["type"]; + variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])}); (*variables)["mutable_type"] = name_resolver->GetMutableClassName(descriptor->message_type()); (*variables)["group_or_message"] = @@ -74,11 +74,12 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["kt_deprecation"] = - descriptor->options().deprecated() - ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + - " is deprecated\") " - : ""; + variables->insert( + {"kt_deprecation", + descriptor->options().deprecated() + ? y_absl::StrCat("@kotlin.Deprecated(message = \"Field ", + (*variables)["name"], " is deprecated\") ") + : ""}); (*variables)["required"] = descriptor->is_required() ? "true" : "false"; if (HasHasbit(descriptor)) { @@ -87,17 +88,17 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; + y_absl::StrCat(GenerateSetBit(messageBitIndex), ";"); (*variables)["clear_has_field_bit_message"] = - GenerateClearBit(messageBitIndex) + ";"; + y_absl::StrCat(GenerateClearBit(messageBitIndex), ";"); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); } else { (*variables)["set_has_field_bit_message"] = ""; (*variables)["clear_has_field_bit_message"] = ""; - (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != null"; + variables->insert({"is_field_present_message", + y_absl::StrCat((*variables)["name"], "_ != null")}); } (*variables)["get_has_field_bit_from_local"] = @@ -108,6 +109,9 @@ void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, // We use `x.getClass()` as a null check because it generates less bytecode // than an `if (x == null) { throw ... }` statement. (*variables)["null_check"] = "value.getClass();\n"; + // Annotations often use { and } to determine ranges. + (*variables)["{"] = ""; + (*variables)["}"] = ""; } } // namespace @@ -118,10 +122,11 @@ ImmutableMessageFieldLiteGenerator::ImmutableMessageFieldLiteGenerator( const FieldDescriptor* descriptor, int messageBitIndex, Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - name_resolver_(context->GetNameResolver()) { + name_resolver_(context->GetNameResolver()), + context_(context) { SetMessageVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + name_resolver_, &variables_, context); } ImmutableMessageFieldLiteGenerator::~ImmutableMessageFieldLiteGenerator() {} @@ -137,9 +142,13 @@ int ImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const { void ImmutableMessageFieldLiteGenerator::GenerateInterfaceMembers( io::Printer* printer) const { WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); - printer->Print(variables_, "$deprecation$boolean has$capitalized_name$();\n"); + printer->Print(variables_, + "$deprecation$boolean ${$has$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, GETTER); - printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); + printer->Print(variables_, + "$deprecation$$type$ ${$get$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); } void ImmutableMessageFieldLiteGenerator::GenerateMembers( @@ -288,9 +297,9 @@ void ImmutableMessageFieldLiteGenerator::GenerateBuilderMembers( void ImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers( io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$var $kt_name$: $kt_type$\n" + "$kt_deprecation$public var $kt_name$: $kt_type$\n" " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" @@ -299,16 +308,17 @@ void ImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers( " }\n"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, - "fun ${$clear$kt_capitalized_name$$}$() {\n" + "public fun ${$clear$kt_capitalized_name$$}$() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" "}\n"); - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, + /* builder */ false, /* kdoc */ true); printer->Print( variables_, - "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" "}\n"); GenerateKotlinOrNull(printer); @@ -317,7 +327,7 @@ void ImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers( void ImmutableMessageFieldLiteGenerator::GenerateKotlinOrNull(io::Printer* printer) const { if (descriptor_->has_optional_keyword()) { printer->Print(variables_, - "val $classname$Kt.Dsl.$name$OrNull: $kt_type$?\n" + "public val $classname$Kt.Dsl.$name$OrNull: $kt_type$?\n" " get() = $kt_dsl_builder$.$name$OrNull\n"); } } @@ -495,10 +505,12 @@ RepeatedImmutableMessageFieldLiteGenerator:: RepeatedImmutableMessageFieldLiteGenerator( const FieldDescriptor* descriptor, int messageBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), + name_resolver_(context->GetNameResolver()), + context_(context) { SetMessageVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + name_resolver_, &variables_, context); } RepeatedImmutableMessageFieldLiteGenerator:: @@ -517,17 +529,28 @@ void RepeatedImmutableMessageFieldLiteGenerator::GenerateInterfaceMembers( WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$java.util.List<$type$> \n" - " get$capitalized_name$List();\n"); + " ${$get$capitalized_name$List$}$();\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); + printer->Print( + variables_, + "$deprecation$$type$ ${$get$capitalized_name$$}$(int index);\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); + "$deprecation$int ${$get$capitalized_name$Count$}$();\n"); + printer->Annotate("{", "}", descriptor_); } void RepeatedImmutableMessageFieldLiteGenerator::GenerateMembers( io::Printer* printer) const { + if (!context_->options().opensource_runtime) { + printer->Print( + variables_, + "@com.google.protobuf.ProtoField(\n" + " fieldNumber=$number$,\n" + " type=com.google.protobuf.FieldType.$annotation_field_type$)\n"); + } printer->Print( variables_, "private com.google.protobuf.Internal.ProtobufList<$type$> $name$_;\n"); @@ -806,12 +829,12 @@ void RepeatedImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers( " */\n" "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" " : com.google.protobuf.kotlin.DslProxy()\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$ val $kt_name$: " + "$kt_deprecation$ public val $kt_name$: " "com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " @kotlin.jvm.JvmSynthetic\n" @@ -820,70 +843,70 @@ void RepeatedImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers( " )\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "add(value: $kt_type$) {\n" " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(value: $kt_type$) {\n" " add(value)\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" " addAll(values)\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "operator fun com.google.protobuf.kotlin.DslList" + "public operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "set(index: kotlin.Int, value: $kt_type$) {\n" " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" "}\n"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "clear() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" @@ -895,4 +918,4 @@ void RepeatedImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers( } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field_lite.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field_lite.h index 5bf9607bc8e..8bcc550f47e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field_lite.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_field_lite.h @@ -36,10 +36,9 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__ #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -62,6 +61,10 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { explicit ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + ImmutableMessageFieldLiteGenerator( + const ImmutableMessageFieldLiteGenerator&) = delete; + ImmutableMessageFieldLiteGenerator& operator=( + const ImmutableMessageFieldLiteGenerator&) = delete; ~ImmutableMessageFieldLiteGenerator() override; // implements ImmutableFieldLiteGenerator @@ -79,12 +82,12 @@ class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { protected: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; const int messageBitIndex_; ClassNameResolver* name_resolver_; + Context* context_; private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldLiteGenerator); void GenerateKotlinOrNull(io::Printer* printer) const; }; @@ -94,6 +97,10 @@ class ImmutableMessageOneofFieldLiteGenerator ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + ImmutableMessageOneofFieldLiteGenerator( + const ImmutableMessageOneofFieldLiteGenerator&) = delete; + ImmutableMessageOneofFieldLiteGenerator& operator=( + const ImmutableMessageOneofFieldLiteGenerator&) = delete; ~ImmutableMessageOneofFieldLiteGenerator() override; void GenerateMembers(io::Printer* printer) const override; @@ -101,8 +108,6 @@ class ImmutableMessageOneofFieldLiteGenerator void GenerateFieldInfo(io::Printer* printer, std::vector<uint16_t>* output) const override; - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator); }; class RepeatedImmutableMessageFieldLiteGenerator @@ -110,6 +115,10 @@ class RepeatedImmutableMessageFieldLiteGenerator public: explicit RepeatedImmutableMessageFieldLiteGenerator( const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + RepeatedImmutableMessageFieldLiteGenerator( + const RepeatedImmutableMessageFieldLiteGenerator&) = delete; + RepeatedImmutableMessageFieldLiteGenerator& operator=( + const RepeatedImmutableMessageFieldLiteGenerator&) = delete; ~RepeatedImmutableMessageFieldLiteGenerator() override; // implements ImmutableFieldLiteGenerator ------------------------------------ @@ -126,11 +135,9 @@ class RepeatedImmutableMessageFieldLiteGenerator protected: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; ClassNameResolver* name_resolver_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldLiteGenerator); + Context* context_; }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_lite.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_lite.cc index 90bd4b2382a..83065115452 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_lite.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_lite.cc @@ -32,32 +32,34 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/message_lite.h> +#include "google/protobuf/compiler/java/message_lite.h" #include <algorithm> #include <cstdint> -#include <map> #include <memory> +#include <string> #include <vector> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/enum_lite.h> -#include <google/protobuf/compiler/java/extension_lite.h> -#include <google/protobuf/compiler/java/generator_factory.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/message_builder.h> -#include <google/protobuf/compiler/java/message_builder_lite.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/enum_lite.h" +#include "google/protobuf/compiler/java/extension_lite.h" +#include "google/protobuf/compiler/java/generator_factory.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/message_builder.h" +#include "google/protobuf/compiler/java/message_builder_lite.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -74,12 +76,13 @@ ImmutableMessageLiteGenerator::ImmutableMessageLiteGenerator( context_(context), name_resolver_(context->GetNameResolver()), field_generators_(descriptor, context_) { - GOOGLE_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite())) + Y_ABSL_CHECK(!HasDescriptorMethods(descriptor->file(), context->EnforceLite())) << "Generator factory error: A lite message generator is used to " "generate non-lite messages."; for (int i = 0; i < descriptor_->field_count(); i++) { if (IsRealOneof(descriptor_->field(i))) { - oneofs_.insert(descriptor_->field(i)->containing_oneof()); + const OneofDescriptor* oneof = descriptor_->field(i)->containing_oneof(); + Y_ABSL_CHECK(oneofs_.emplace(oneof->index(), oneof).first->second == oneof); } } } @@ -114,26 +117,33 @@ int ImmutableMessageLiteGenerator::GenerateStaticVariableInitializers( void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) { MaybePrintGeneratedAnnotation(context_, printer, descriptor_, /* immutable = */ true, "OrBuilder"); + + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables = { + {"{", ""}, + {"}", ""}, + {"deprecation", + descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""}, + {"extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_)}, + {"classname", descriptor_->name()}, + }; + + if (!context_->options().opensource_runtime) { + printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n"); + } if (descriptor_->extension_range_count() > 0) { printer->Print( + variables, "$deprecation$public interface ${$$classname$OrBuilder$}$ extends \n" " $extra_interfaces$\n" " com.google.protobuf.GeneratedMessageLite.\n" " ExtendableMessageOrBuilder<\n" - " $classname$, $classname$.Builder> {\n", - "deprecation", - descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name(), "{", "", "}", ""); + " $classname$, $classname$.Builder> {\n"); } else { printer->Print( + variables, "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n" " $extra_interfaces$\n" - " com.google.protobuf.MessageLiteOrBuilder {\n", - "deprecation", - descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name(), "{", "", "}", ""); + " com.google.protobuf.MessageLiteOrBuilder {\n"); } printer->Annotate("{", "}", descriptor_); @@ -143,14 +153,17 @@ void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) { field_generators_.get(descriptor_->field(i)) .GenerateInterfaceMembers(printer); } - for (auto oneof : oneofs_) { - printer->Print( - "\n" - "public $classname$.$oneof_capitalized_name$Case " - "get$oneof_capitalized_name$Case();\n", - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "classname", - context_->GetNameResolver()->GetImmutableClassName(descriptor_)); + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; + variables["oneof_capitalized_name"] = + context_->GetOneofGeneratorInfo(oneof)->capitalized_name; + variables["classname"] = + context_->GetNameResolver()->GetImmutableClassName(descriptor_); + printer->Print(variables, + "\n" + "public ${$$classname$.$oneof_capitalized_name$Case$}$ " + "get$oneof_capitalized_name$Case();\n"); + printer->Annotate("{", "}", oneof); } printer->Outdent(); @@ -162,7 +175,8 @@ void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) { void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true); - std::map<TProtoStringType, TProtoStringType> variables; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables = {{"{", ""}, + {"}", ""}}; variables["static"] = is_own_file ? " " : " static "; variables["classname"] = descriptor_->name(); variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_); @@ -179,18 +193,18 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { printer->Print( variables, - "$deprecation$public $static$final class $classname$ extends\n" + "$deprecation$public $static$final class ${$$classname$$}$ extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" " $classname$, $classname$.Builder> implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n"); - builder_type = strings::Substitute( + builder_type = y_absl::Substitute( "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>", name_resolver_->GetImmutableClassName(descriptor_)); } else { printer->Print( variables, - "$deprecation$public $static$final class $classname$ extends\n" + "$deprecation$public $static$final class ${$$classname$$}$ extends\n" " com.google.protobuf.GeneratedMessageLite<\n" " $classname$, $classname$.Builder> implements\n" " $extra_interfaces$\n" @@ -198,6 +212,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { builder_type = "com.google.protobuf.GeneratedMessageLite.Builder"; } + printer->Annotate("{", "}", descriptor_); printer->Indent(); GenerateConstructor(printer); @@ -230,49 +245,59 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { } // oneof - std::map<TProtoStringType, TProtoStringType> vars; - for (auto oneof : oneofs_) { + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars = {{"{", ""}, + {"}", ""}}; + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name; vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo(oneof)->capitalized_name; - vars["oneof_index"] = StrCat((oneof)->index()); - // oneofCase_ and oneof_ - printer->Print(vars, - "private int $oneof_name$Case_ = 0;\n" - "private java.lang.Object $oneof_name$_;\n"); + vars["oneof_index"] = y_absl::StrCat((oneof)->index()); + if (context_->options().opensource_runtime) { + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + } // OneofCase enum - printer->Print(vars, "public enum $oneof_capitalized_name$Case {\n"); + printer->Print(vars, "public enum ${$$oneof_capitalized_name$Case$}$ {\n"); + printer->Annotate("{", "}", oneof); 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", - StrCat(field->number())); + y_absl::AsciiStrToUpper(field->name()), "field_number", + y_absl::StrCat(field->number())); + printer->Annotate("field_name", field); } printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name", - ToUpper(vars["oneof_name"])); + y_absl::AsciiStrToUpper(vars["oneof_name"])); printer->Print(vars, "private final int value;\n" "private $oneof_capitalized_name$Case(int value) {\n" " this.value = value;\n" "}\n"); + if (context_->options().opensource_runtime) { + printer->Print( + vars, + "/**\n" + " * @deprecated Use {@link #forNumber(int)} instead.\n" + " */\n" + "@java.lang.Deprecated\n" + "public static $oneof_capitalized_name$Case valueOf(int value) {\n" + " return forNumber(value);\n" + "}\n" + "\n"); + } printer->Print( vars, - "/**\n" - " * @deprecated Use {@link #forNumber(int)} instead.\n" - " */\n" - "@java.lang.Deprecated\n" - "public static $oneof_capitalized_name$Case valueOf(int value) {\n" - " return forNumber(value);\n" - "}\n" - "\n" "public static $oneof_capitalized_name$Case forNumber(int value) {\n" " 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", StrCat(field->number()), - "field_name", ToUpper(field->name())); + "field_number", y_absl::StrCat(field->number()), + "field_name", y_absl::AsciiStrToUpper(field->name())); } printer->Print( " case 0: return $cap_oneof_name$_NOT_SET;\n" @@ -284,30 +309,34 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { "public int getNumber() {\n" " return this.value;\n" "}\n", - "cap_oneof_name", ToUpper(vars["oneof_name"])); + "cap_oneof_name", y_absl::AsciiStrToUpper(vars["oneof_name"])); printer->Outdent(); printer->Print("};\n\n"); // oneofCase() printer->Print(vars, "@java.lang.Override\n" "public $oneof_capitalized_name$Case\n" - "get$oneof_capitalized_name$Case() {\n" + "${$get$oneof_capitalized_name$Case$}$() {\n" " return $oneof_capitalized_name$Case.forNumber(\n" " $oneof_name$Case_);\n" - "}\n" + "}\n"); + printer->Annotate("{", "}", oneof); + printer->Print(vars, "\n" - "private void clear$oneof_capitalized_name$() {\n" + "private void ${$clear$oneof_capitalized_name$$}$() {\n" " $oneof_name$Case_ = 0;\n" " $oneof_name$_ = null;\n" "}\n" "\n"); + printer->Annotate("{", "}", oneof); } // 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", StrCat(descriptor_->field(i)->number())); + "number", y_absl::StrCat(descriptor_->field(i)->number())); + printer->Annotate("constant_name", descriptor_->field(i)); field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); printer->Print("\n"); } @@ -496,11 +525,11 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuildMessageInfo( // Record the number of oneofs. WriteIntToUtf16CharSequence(oneofs_.size(), &chars); - for (auto oneof : oneofs_) { + for (auto& kv : oneofs_) { printer->Print( "\"$oneof_name$_\",\n" "\"$oneof_name$Case_\",\n", - "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name); + "oneof_name", context_->GetOneofGeneratorInfo(kv.second)->name); } // Integers for bit fields. @@ -734,10 +763,10 @@ void ImmutableMessageLiteGenerator::GenerateKotlinDsl( "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" "@com.google.protobuf.kotlin.ProtoDslMarker\n"); printer->Print( - "class Dsl private constructor(\n" + "public class Dsl private constructor(\n" " private val _builder: $message$.Builder\n" ") {\n" - " companion object {\n" + " public companion object {\n" " @kotlin.jvm.JvmSynthetic\n" " @kotlin.PublishedApi\n" " internal fun _create(builder: $message$.Builder): Dsl = " @@ -747,7 +776,8 @@ void ImmutableMessageLiteGenerator::GenerateKotlinDsl( " @kotlin.jvm.JvmSynthetic\n" " @kotlin.PublishedApi\n" " internal fun _build(): $message$ = _builder.build()\n", - "message", name_resolver_->GetClassName(descriptor_, true)); + "message", + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); printer->Indent(); @@ -757,18 +787,19 @@ void ImmutableMessageLiteGenerator::GenerateKotlinDsl( .GenerateKotlinDslMembers(printer); } - for (auto oneof : oneofs_) { + for (auto& kv : oneofs_) { + const OneofDescriptor* oneof = kv.second; printer->Print( - "val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n" + "public val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n" " @JvmName(\"get$oneof_capitalized_name$Case\")\n" " get() = _builder.get$oneof_capitalized_name$Case()\n\n" - "fun clear$oneof_capitalized_name$() {\n" + "public fun clear$oneof_capitalized_name$() {\n" " _builder.clear$oneof_capitalized_name$()\n" "}\n", "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name, "oneof_capitalized_name", context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message", - name_resolver_->GetClassName(descriptor_, true)); + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); } if (descriptor_->extension_range_count() > 0) { @@ -781,18 +812,24 @@ void ImmutableMessageLiteGenerator::GenerateKotlinDsl( void ImmutableMessageLiteGenerator::GenerateKotlinMembers( io::Printer* printer) const { + printer->Print("@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n", + "camelcase_name", + name_resolver_->GetKotlinFactoryName(descriptor_)); + printer->Print( - "@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n" - "inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> " - "kotlin.Unit): " - "$message$ =\n" + "public inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> " + "kotlin.Unit): $message$ =\n" " $message_kt$.Dsl._create($message$.newBuilder()).apply { block() " "}._build()\n", "camelcase_name", name_resolver_->GetKotlinFactoryName(descriptor_), - "message_kt", name_resolver_->GetKotlinExtensionsClassName(descriptor_), - "message", name_resolver_->GetClassName(descriptor_, true)); - - printer->Print("object $name$Kt {\n", "name", descriptor_->name()); + "message_kt", + EscapeKotlinKeywords( + name_resolver_->GetKotlinExtensionsClassName(descriptor_)), + "message", + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true))); + + WriteMessageDocComment(printer, descriptor_, /* kdoc */ true); + printer->Print("public object $name$Kt {\n", "name", descriptor_->name()); printer->Indent(); GenerateKotlinDsl(printer); for (int i = 0; i < descriptor_->nested_type_count(); i++) { @@ -807,13 +844,15 @@ void ImmutableMessageLiteGenerator::GenerateKotlinMembers( void ImmutableMessageLiteGenerator::GenerateTopLevelKotlinMembers( io::Printer* printer) const { printer->Print( - "inline fun $message$.copy(block: $message_kt$.Dsl.() -> " - "kotlin.Unit): " - "$message$ =\n" + "public inline fun $message$.copy(block: $message_kt$.Dsl.() -> " + "kotlin.Unit): $message$ =\n" " $message_kt$.Dsl._create(this.toBuilder()).apply { block() " "}._build()\n\n", - "message", name_resolver_->GetClassName(descriptor_, true), "message_kt", - name_resolver_->GetKotlinExtensionsClassName(descriptor_)); + "message", + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)), + "message_kt", + EscapeKotlinKeywords( + name_resolver_->GetKotlinExtensionsClassName(descriptor_))); for (int i = 0; i < descriptor_->nested_type_count(); i++) { if (IsMapEntry(descriptor_->nested_type(i))) continue; @@ -830,30 +869,33 @@ void ImmutableMessageLiteGenerator::GenerateKotlinOrNull(io::Printer* printer) c const FieldDescriptor* field = descriptor_->field(i); if (field->has_presence() && GetJavaType(field) == JAVATYPE_MESSAGE) { printer->Print( - "val $full_classname$OrBuilder.$camelcase_name$OrNull: " + "public val $full_classname$OrBuilder.$camelcase_name$OrNull: " "$full_name$?\n" " get() = if (has$name$()) get$name$() else null\n\n", - "full_classname", name_resolver_->GetClassName(descriptor_, true), + "full_classname", + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)), "camelcase_name", context_->GetFieldGeneratorInfo(field)->name, "full_name", - name_resolver_->GetImmutableClassName(field->message_type()), "name", - context_->GetFieldGeneratorInfo(field)->capitalized_name); + EscapeKotlinKeywords( + name_resolver_->GetImmutableClassName(field->message_type())), + "name", context_->GetFieldGeneratorInfo(field)->capitalized_name); } } } void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( io::Printer* printer) const { - TProtoStringType message_name = name_resolver_->GetClassName(descriptor_, true); + TProtoStringType message_name = + EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)); printer->Print( "@Suppress(\"UNCHECKED_CAST\")\n" "@kotlin.jvm.JvmSynthetic\n" - "operator fun <T : kotlin.Any> get(extension: " + "public operator fun <T : kotlin.Any> get(extension: " "com.google.protobuf.ExtensionLite<$message$, T>): T {\n" " return if (extension.isRepeated) {\n" " get(extension as com.google.protobuf.ExtensionLite<$message$, " - "List<*>>) as T\n" + "kotlin.collections.List<*>>) as T\n" " } else {\n" " _builder.getExtension(extension)\n" " }\n" @@ -865,8 +907,9 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n" - "operator fun <E : kotlin.Any> get(\n" - " extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n" + "public operator fun <E : kotlin.Any> get(\n" + " extension: com.google.protobuf.ExtensionLite<$message$, " + "kotlin.collections.List<E>>\n" "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n" " return com.google.protobuf.kotlin.ExtensionList(extension, " "_builder.getExtension(extension))\n" @@ -875,7 +918,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "operator fun contains(extension: " + "public operator fun contains(extension: " "com.google.protobuf.ExtensionLite<$message$, *>): " "Boolean {\n" " return _builder.hasExtension(extension)\n" @@ -884,7 +927,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "fun clear(extension: " + "public fun clear(extension: " "com.google.protobuf.ExtensionLite<$message$, *>) " "{\n" " _builder.clearExtension(extension)\n" @@ -893,8 +936,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "@kotlin.PublishedApi\n" - "internal fun <T : kotlin.Any> setExtension(extension: " + "public fun <T : kotlin.Any> setExtension(extension: " "com.google.protobuf.ExtensionLite<$message$, T>, " "value: T) {\n" " _builder.setExtension(extension, value)\n" @@ -904,7 +946,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun <T : Comparable<T>> set(\n" + "public inline operator fun <T : Comparable<T>> set(\n" " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" " value: T\n" ") {\n" @@ -915,7 +957,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun set(\n" + "public inline operator fun set(\n" " extension: com.google.protobuf.ExtensionLite<$message$, " "com.google.protobuf.ByteString>,\n" " value: com.google.protobuf.ByteString\n" @@ -927,7 +969,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun <T : com.google.protobuf.MessageLite> set(\n" + "public inline operator fun <T : com.google.protobuf.MessageLite> set(\n" " extension: com.google.protobuf.ExtensionLite<$message$, T>,\n" " value: T\n" ") {\n" @@ -937,7 +979,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "fun<E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, " + "public fun<E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, " "$message$>.add(value: E) {\n" " _builder.addExtension(this.extension, value)\n" "}\n\n", @@ -946,7 +988,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun <E : kotlin.Any> " + "public inline operator fun <E : kotlin.Any> " "com.google.protobuf.kotlin.ExtensionList<E, " "$message$>.plusAssign" "(value: E) {\n" @@ -956,7 +998,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "fun<E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, " + "public fun<E : kotlin.Any> com.google.protobuf.kotlin.ExtensionList<E, " "$message$>.addAll(values: Iterable<E>) {\n" " for (value in values) {\n" " add(value)\n" @@ -967,7 +1009,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun <E : kotlin.Any> " + "public inline operator fun <E : kotlin.Any> " "com.google.protobuf.kotlin.ExtensionList<E, " "$message$>.plusAssign(values: " "Iterable<E>) {\n" @@ -977,7 +1019,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" - "operator fun <E : kotlin.Any> " + "public operator fun <E : kotlin.Any> " "com.google.protobuf.kotlin.ExtensionList<E, " "$message$>.set(index: Int, value: " "E) {\n" @@ -988,7 +1030,7 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( printer->Print( "@kotlin.jvm.JvmSynthetic\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline fun com.google.protobuf.kotlin.ExtensionList<*, " + "public inline fun com.google.protobuf.kotlin.ExtensionList<*, " "$message$>.clear() {\n" " clear(extension)\n" "}\n\n", @@ -1000,4 +1042,4 @@ void ImmutableMessageLiteGenerator::GenerateKotlinExtensions( } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_lite.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_lite.h index d1e4b68949c..279404099ed 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_lite.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_lite.h @@ -35,8 +35,8 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__ -#include <google/protobuf/compiler/java/field.h> -#include <google/protobuf/compiler/java/message.h> +#include "google/protobuf/compiler/java/field.h" +#include "google/protobuf/compiler/java/message.h" namespace google { namespace protobuf { @@ -46,6 +46,9 @@ namespace java { class ImmutableMessageLiteGenerator : public MessageGenerator { public: ImmutableMessageLiteGenerator(const Descriptor* descriptor, Context* context); + ImmutableMessageLiteGenerator(const ImmutableMessageLiteGenerator&) = delete; + ImmutableMessageLiteGenerator& operator=( + const ImmutableMessageLiteGenerator&) = delete; ~ImmutableMessageLiteGenerator() override; void Generate(io::Printer* printer) override; @@ -73,8 +76,6 @@ class ImmutableMessageLiteGenerator : public MessageGenerator { Context* context_; ClassNameResolver* name_resolver_; FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageLiteGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_serialization.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_serialization.cc new file mode 100644 index 00000000000..9ecfac21d05 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_serialization.cc @@ -0,0 +1,51 @@ +// 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/java/message_serialization.h" + +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +void GenerateSerializeExtensionRange(io::Printer* printer, + const Descriptor::ExtensionRange* range) { + printer->Print("extensionWriter.writeUntil($end$, output);\n", "end", + y_absl::StrCat(range->end)); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/message_serialization.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_serialization.h new file mode 100644 index 00000000000..3b7c8461cb5 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/message_serialization.h @@ -0,0 +1,103 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_SERIALIZATION_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_SERIALIZATION_H__ + +#include <algorithm> +#include <cstddef> +#include <vector> + +#include "google/protobuf/compiler/java/field.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +// Generates code to serialize a single extension range. +void GenerateSerializeExtensionRange(io::Printer* printer, + const Descriptor::ExtensionRange* range); + +// Generates code to serialize all fields and extension ranges for the specified +// message descriptor, sorting serialization calls in increasing order by field +// number. +// +// Templatized to support different field generator implementations. +template <typename FieldGenerator> +void GenerateSerializeFieldsAndExtensions( + io::Printer* printer, + const FieldGeneratorMap<FieldGenerator>& field_generators, + const Descriptor* descriptor, const FieldDescriptor** sorted_fields) { + std::vector<const Descriptor::ExtensionRange*> sorted_extensions; + sorted_extensions.reserve(descriptor->extension_range_count()); + for (int i = 0; i < descriptor->extension_range_count(); ++i) { + sorted_extensions.push_back(descriptor->extension_range(i)); + } + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeOrdering()); + + std::size_t range_idx = 0; + + // Merge the fields and the extension ranges, both sorted by field number. + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* field = sorted_fields[i]; + + // Collapse all extension ranges up until the next field. This leads to + // shorter and more efficient codegen for messages containing a large + // number of extension ranges without fields in between them. + const Descriptor::ExtensionRange* range = nullptr; + while (range_idx < sorted_extensions.size() && + sorted_extensions[range_idx]->end <= field->number()) { + range = sorted_extensions[range_idx++]; + } + + if (range != nullptr) { + GenerateSerializeExtensionRange(printer, range); + } + field_generators.get(field).GenerateSerializationCode(printer); + } + + // After serializing all fields, serialize any remaining extensions via a + // single writeUntil call. + if (range_idx < sorted_extensions.size()) { + GenerateSerializeExtensionRange(printer, sorted_extensions.back()); + } +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_SERIALIZATION_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/name_resolver.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/name_resolver.cc index 5cadecadf36..5959805240e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/name_resolver.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/name_resolver.cc @@ -28,18 +28,21 @@ // (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/java/name_resolver.h> +#include "google/protobuf/compiler/java/name_resolver.h" -#include <map> #include <string> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/names.h> +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/names.h" + // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -56,8 +59,8 @@ const char* kOuterClassNameSuffix = "OuterClass"; // Full name : foo.Bar.Baz // Package name: foo // After strip : Bar.Baz -TProtoStringType StripPackageName(const TProtoStringType& full_name, - const FileDescriptor* file) { +y_absl::string_view StripPackageName(y_absl::string_view full_name, + const FileDescriptor* file) { if (file->package().empty()) { return full_name; } else { @@ -69,7 +72,8 @@ TProtoStringType StripPackageName(const TProtoStringType& full_name, // Get the name of a message's Java class without package name prefix. TProtoStringType ClassNameWithoutPackage(const Descriptor* descriptor, bool immutable) { - return StripPackageName(descriptor->full_name(), descriptor->file()); + return TProtoStringType( + StripPackageName(descriptor->full_name(), descriptor->file())); } TProtoStringType ClassNameWithoutPackageKotlin(const Descriptor* descriptor) { @@ -77,7 +81,7 @@ TProtoStringType ClassNameWithoutPackageKotlin(const Descriptor* descriptor) { const Descriptor* temp = descriptor->containing_type(); while (temp) { - result = temp->name() + "Kt." + result; + result = y_absl::StrCat(temp->name(), "Kt.", result); temp = temp->containing_type(); } return result; @@ -91,24 +95,24 @@ TProtoStringType ClassNameWithoutPackage(const EnumDescriptor* descriptor, if (message_descriptor == NULL) { return descriptor->name(); } else { - return ClassNameWithoutPackage(message_descriptor, immutable) + "." + - descriptor->name(); + return y_absl::StrCat(ClassNameWithoutPackage(message_descriptor, immutable), + ".", descriptor->name()); } } // Get the name of a service's Java class without package name prefix. TProtoStringType ClassNameWithoutPackage(const ServiceDescriptor* descriptor, bool immutable) { - TProtoStringType full_name = + y_absl::string_view full_name = StripPackageName(descriptor->full_name(), descriptor->file()); // We don't allow nested service definitions. - GOOGLE_CHECK(full_name.find('.') == TProtoStringType::npos); - return full_name; + Y_ABSL_CHECK(!y_absl::StrContains(full_name, '.')); + return TProtoStringType(full_name); } // Return true if a and b are equals (case insensitive). -NameEquality CheckNameEquality(const TProtoStringType& a, const TProtoStringType& b) { - if (ToUpper(a) == ToUpper(b)) { +NameEquality CheckNameEquality(y_absl::string_view a, y_absl::string_view b) { + if (y_absl::AsciiStrToUpper(a) == y_absl::AsciiStrToUpper(b)) { if (a == b) { return NameEquality::EXACT_EQUAL; } @@ -119,7 +123,7 @@ NameEquality CheckNameEquality(const TProtoStringType& a, const TProtoStringType // Check whether a given message or its nested types has the given class name. bool MessageHasConflictingClassName(const Descriptor* message, - const TProtoStringType& classname, + y_absl::string_view classname, NameEquality equality_mode) { if (CheckNameEquality(message->name(), classname) == equality_mode) { return true; @@ -141,10 +145,6 @@ bool MessageHasConflictingClassName(const Descriptor* message, } // namespace -ClassNameResolver::ClassNameResolver() {} - -ClassNameResolver::~ClassNameResolver() {} - TProtoStringType ClassNameResolver::GetFileDefaultImmutableClassName( const FileDescriptor* file) { TProtoStringType basename; @@ -182,18 +182,18 @@ TProtoStringType ClassNameResolver::GetFileClassName(const FileDescriptor* file, TProtoStringType ClassNameResolver::GetFileClassName(const FileDescriptor* file, bool immutable, bool kotlin) { if (kotlin) { - return GetFileImmutableClassName(file) + "Kt"; + return y_absl::StrCat(GetFileImmutableClassName(file), "Kt"); } else if (immutable) { return GetFileImmutableClassName(file); } else { - return "Mutable" + GetFileImmutableClassName(file); + return y_absl::StrCat("Mutable", GetFileImmutableClassName(file)); } } // Check whether there is any type defined in the proto file that has // the given class name. bool ClassNameResolver::HasConflictingClassName(const FileDescriptor* file, - const TProtoStringType& classname, + y_absl::string_view classname, NameEquality equality_mode) { for (int i = 0; i < file->enum_type_count(); i++) { if (CheckNameEquality(file->enum_type(i)->name(), classname) == @@ -217,8 +217,12 @@ bool ClassNameResolver::HasConflictingClassName(const FileDescriptor* file, } TProtoStringType ClassNameResolver::GetDescriptorClassName( - const FileDescriptor* descriptor) { - return GetFileImmutableClassName(descriptor); + const FileDescriptor* file) { + if (options_.opensource_runtime) { + return GetFileImmutableClassName(file); + } else { + return y_absl::StrCat(GetFileImmutableClassName(file), "InternalDescriptors"); + } } TProtoStringType ClassNameResolver::GetClassName(const FileDescriptor* descriptor, @@ -228,7 +232,7 @@ TProtoStringType ClassNameResolver::GetClassName(const FileDescriptor* descripto TProtoStringType ClassNameResolver::GetClassName(const FileDescriptor* descriptor, bool immutable, bool kotlin) { - TProtoStringType result = FileJavaPackage(descriptor, immutable); + TProtoStringType result = FileJavaPackage(descriptor, immutable, options_); if (!result.empty()) result += '.'; result += GetFileClassName(descriptor, immutable, kotlin); return result; @@ -237,26 +241,26 @@ TProtoStringType ClassNameResolver::GetClassName(const FileDescriptor* descripto // Get the full name of a Java class by prepending the Java package name // or outer class name. TProtoStringType ClassNameResolver::GetClassFullName( - const TProtoStringType& name_without_package, const FileDescriptor* file, + y_absl::string_view name_without_package, const FileDescriptor* file, bool immutable, bool is_own_file) { return GetClassFullName(name_without_package, file, immutable, is_own_file, false); } TProtoStringType ClassNameResolver::GetClassFullName( - const TProtoStringType& name_without_package, const FileDescriptor* file, + y_absl::string_view name_without_package, const FileDescriptor* file, bool immutable, bool is_own_file, bool kotlin) { TProtoStringType result; if (is_own_file) { - result = FileJavaPackage(file, immutable); + result = FileJavaPackage(file, immutable, options_); } else { result = GetClassName(file, immutable, kotlin); } if (!result.empty()) { - result += '.'; + y_absl::StrAppend(&result, "."); } - result += name_without_package; - if (kotlin) result += "Kt"; + y_absl::StrAppend(&result, name_without_package); + if (kotlin) y_absl::StrAppend(&result, "Kt"); return result; } @@ -298,23 +302,23 @@ TProtoStringType ClassNameResolver::GetClassName(const ServiceDescriptor* descri // Get the Java Class style full name of a message. TProtoStringType ClassNameResolver::GetJavaClassFullName( - const TProtoStringType& name_without_package, const FileDescriptor* file, + y_absl::string_view name_without_package, const FileDescriptor* file, bool immutable) { return GetJavaClassFullName(name_without_package, file, immutable, false); } TProtoStringType ClassNameResolver::GetJavaClassFullName( - const TProtoStringType& name_without_package, const FileDescriptor* file, + y_absl::string_view name_without_package, const FileDescriptor* file, bool immutable, bool kotlin) { TProtoStringType result; if (MultipleJavaFiles(file, immutable)) { - result = FileJavaPackage(file, immutable); + result = FileJavaPackage(file, immutable, options_); if (!result.empty()) result += '.'; } else { result = GetClassName(file, immutable, kotlin); if (!result.empty()) result += '$'; } - result += StringReplace(name_without_package, ".", "$", true); + result += y_absl::StrReplaceAll(name_without_package, {{".", "$"}}); return result; } @@ -325,14 +329,15 @@ TProtoStringType ClassNameResolver::GetExtensionIdentifierName( TProtoStringType ClassNameResolver::GetExtensionIdentifierName( const FieldDescriptor* descriptor, bool immutable, bool kotlin) { - return GetClassName(descriptor->containing_type(), immutable, kotlin) + "." + - descriptor->name(); + return y_absl::StrCat( + GetClassName(descriptor->containing_type(), immutable, kotlin), ".", + descriptor->name()); } TProtoStringType ClassNameResolver::GetKotlinFactoryName( const Descriptor* descriptor) { TProtoStringType name = ToCamelCase(descriptor->name(), /* lower_first = */ true); - return IsForbiddenKotlin(name) ? name + "_" : name; + return IsForbiddenKotlin(name) ? y_absl::StrCat(name, "_") : name; } TProtoStringType ClassNameResolver::GetJavaImmutableClassName( @@ -367,14 +372,14 @@ TProtoStringType ClassNameResolver::GetJavaMutableClassName( TProtoStringType ClassNameResolver::GetDowngradedFileClassName( const FileDescriptor* file) { - return "Downgraded" + GetFileClassName(file, false); + return y_absl::StrCat("Downgraded", GetFileClassName(file, false)); } TProtoStringType ClassNameResolver::GetDowngradedClassName( const Descriptor* descriptor) { - return FileJavaPackage(descriptor->file()) + "." + - GetDowngradedFileClassName(descriptor->file()) + "." + - ClassNameWithoutPackage(descriptor, false); + return y_absl::StrCat(FileJavaPackage(descriptor->file(), true, options_), ".", + GetDowngradedFileClassName(descriptor->file()), ".", + ClassNameWithoutPackage(descriptor, false)); } } // namespace java @@ -382,4 +387,4 @@ TProtoStringType ClassNameResolver::GetDowngradedClassName( } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/name_resolver.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/name_resolver.h index 9744e8739f9..3fda3a076e3 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/name_resolver.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/name_resolver.h @@ -31,13 +31,14 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ -#include <map> #include <string> -#include <google/protobuf/stubs/common.h> +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/java/options.h" +#include "google/protobuf/port.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -58,8 +59,11 @@ enum NameEquality { NO_MATCH, EXACT_EQUAL, EQUAL_IGNORE_CASE }; // Thread-safety note: This class is *not* thread-safe. class ClassNameResolver { public: - ClassNameResolver(); - ~ClassNameResolver(); + explicit ClassNameResolver(const Options& options = {}) : options_(options) {} + ~ClassNameResolver() = default; + + ClassNameResolver(const ClassNameResolver&) = delete; + ClassNameResolver& operator=(const ClassNameResolver&) = delete; // Gets the unqualified outer class name for the file. TProtoStringType GetFileClassName(const FileDescriptor* file, bool immutable); @@ -74,7 +78,7 @@ class ClassNameResolver { // Check whether there is any type defined in the proto file that has // the given class name. bool HasConflictingClassName(const FileDescriptor* file, - const TProtoStringType& classname, + y_absl::string_view classname, NameEquality equality_mode); // Gets the name of the outer class that holds descriptor information. @@ -128,25 +132,25 @@ class ClassNameResolver { // Get the full name of a Java class by prepending the Java package name // or outer class name. - TProtoStringType GetClassFullName(const TProtoStringType& name_without_package, + TProtoStringType GetClassFullName(y_absl::string_view name_without_package, const FileDescriptor* file, bool immutable, bool is_own_file); - TProtoStringType GetClassFullName(const TProtoStringType& name_without_package, + TProtoStringType GetClassFullName(y_absl::string_view name_without_package, const FileDescriptor* file, bool immutable, bool is_own_file, bool kotlin); + Options options_; + private: // Get the Java Class style full name of a message. - TProtoStringType GetJavaClassFullName(const TProtoStringType& name_without_package, + TProtoStringType GetJavaClassFullName(y_absl::string_view name_without_package, const FileDescriptor* file, bool immutable); - TProtoStringType GetJavaClassFullName(const TProtoStringType& name_without_package, + TProtoStringType GetJavaClassFullName(y_absl::string_view name_without_package, const FileDescriptor* file, bool immutable, bool kotlin); // Caches the result to provide better performance. - std::map<const FileDescriptor*, TProtoStringType> + y_absl::flat_hash_map<const FileDescriptor*, TProtoStringType> file_immutable_outer_class_names_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ClassNameResolver); }; } // namespace java @@ -154,6 +158,6 @@ class ClassNameResolver { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/names.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/names.cc new file mode 100644 index 00000000000..7b10ec5f17a --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/names.cc @@ -0,0 +1,193 @@ +// 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: [email protected] (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include "google/protobuf/compiler/java/names.h" + +#include <string> + +#include "y_absl/container/flat_hash_set.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/compiler/java/names.h" +#include "google/protobuf/compiler/java/options.h" +#include "google/protobuf/descriptor.pb.h" + +// Must be last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { + +const char* DefaultPackage(Options options) { + return options.opensource_runtime ? "" : "com.google.protos"; +} + +bool IsReservedName(y_absl::string_view name) { + static const auto& kReservedNames = + *new y_absl::flat_hash_set<y_absl::string_view>({ + "abstract", "assert", "boolean", "break", "byte", + "case", "catch", "char", "class", "const", + "continue", "default", "do", "double", "else", + "enum", "extends", "final", "finally", "float", + "for", "goto", "if", "implements", "import", + "instanceof", "int", "interface", "long", "native", + "new", "package", "private", "protected", "public", + "return", "short", "static", "strictfp", "super", + "switch", "synchronized", "this", "throw", "throws", + "transient", "try", "void", "volatile", "while", + }); + return kReservedNames.contains(name); +} + +bool IsForbidden(y_absl::string_view field_name) { + // Names that should be avoided (in UpperCamelCase format). + // Using them will cause the compiler to generate accessors whose names + // collide with methods defined in base classes. + // Keep this list in sync with specialFieldNames in + // java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java + static const auto& kForbiddenNames = + *new y_absl::flat_hash_set<y_absl::string_view>({ + // java.lang.Object: + "Class", + // com.google.protobuf.MessageLiteOrBuilder: + "DefaultInstanceForType", + // com.google.protobuf.MessageLite: + "ParserForType", + "SerializedSize", + // com.google.protobuf.MessageOrBuilder: + "AllFields", + "DescriptorForType", + "InitializationErrorString", + "UnknownFields", + // obsolete. kept for backwards compatibility of generated code + "CachedSize", + }); + return kForbiddenNames.contains(UnderscoresToCamelCase(field_name, true)); +} + +TProtoStringType FieldName(const FieldDescriptor* field) { + TProtoStringType field_name; + // Groups are hacky: The name of the field is just the lower-cased name + // of the group type. In Java, though, we would like to retain the original + // capitalization of the type name. + if (GetType(field) == FieldDescriptor::TYPE_GROUP) { + field_name = field->message_type()->name(); + } else { + field_name = field->name(); + } + if (IsForbidden(field_name)) { + // Append a trailing "#" to indicate that the name should be decorated to + // avoid collision with other names. + y_absl::StrAppend(&field_name, "#"); + } + return field_name; +} + +} // namespace + +TProtoStringType ClassName(const Descriptor* descriptor) { + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); +} + +TProtoStringType ClassName(const EnumDescriptor* descriptor) { + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); +} + +TProtoStringType ClassName(const ServiceDescriptor* descriptor) { + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); +} + +TProtoStringType ClassName(const FileDescriptor* descriptor) { + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); +} + +TProtoStringType FileJavaPackage(const FileDescriptor* file, bool immutable, + Options options) { + TProtoStringType result; + + if (file->options().has_java_package()) { + result = file->options().java_package(); + } else { + result = DefaultPackage(options); + if (!file->package().empty()) { + if (!result.empty()) result += '.'; + result += file->package(); + } + } + + return result; +} + +TProtoStringType FileJavaPackage(const FileDescriptor* file, Options options) { + return FileJavaPackage(file, true /* immutable */, options); +} + +TProtoStringType CapitalizedFieldName(const FieldDescriptor* field) { + return UnderscoresToCamelCase(FieldName(field), true); +} + +TProtoStringType UnderscoresToCamelCase(const FieldDescriptor* field) { + return UnderscoresToCamelCase(FieldName(field), false); +} + +TProtoStringType UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { + return UnderscoresToCamelCase(FieldName(field), true); +} + +TProtoStringType UnderscoresToCamelCase(const MethodDescriptor* method) { + return UnderscoresToCamelCase(method->name(), false); +} + +TProtoStringType UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) { + TProtoStringType name = UnderscoresToCamelCase(field); + if (IsReservedName(name)) { + y_absl::StrAppend(&name, "_"); + } + return name; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/names.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/names.h index 9aeddc81cc2..2f7f1b802ed 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/names.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/names.h @@ -40,6 +40,12 @@ #include <string> +#include "google/protobuf/descriptor.h" +#include "google/protobuf/compiler/java/options.h" + +// Must be last. +#include "google/protobuf/port_def.inc" + namespace google { namespace protobuf { @@ -85,7 +91,8 @@ TProtoStringType ClassName(const ServiceDescriptor* descriptor); // // Returns: // Java package name. -TProtoStringType FileJavaPackage(const FileDescriptor* descriptor); +TProtoStringType FileJavaPackage(const FileDescriptor* descriptor, + Options options = {}); // Requires: // descriptor != NULL @@ -93,8 +100,36 @@ TProtoStringType FileJavaPackage(const FileDescriptor* descriptor); // Capitalized camel case name field name. TProtoStringType CapitalizedFieldName(const FieldDescriptor* descriptor); +// Returns: +// Converts a name to camel-case. If cap_first_letter is true, capitalize the +// first letter. +TProtoStringType UnderscoresToCamelCase(y_absl::string_view input, + bool cap_next_letter); +// Requires: +// field != NULL +// Returns: +// Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes +// "fooBarBaz" or "FooBarBaz", respectively. +TProtoStringType UnderscoresToCamelCase(const FieldDescriptor* field); + +// Requires: +// method != NULL +// Returns: +// Similar, but for method names. (Typically, this merely has the effect +// of lower-casing the first letter of the name.) +TProtoStringType UnderscoresToCamelCase(const MethodDescriptor* method); + +// Requires: +// field != NULL +// Returns: +// Same as UnderscoresToCamelCase, but checks for reserved keywords +TProtoStringType UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field); + + } // namespace java } // namespace compiler } // namespace protobuf } // namespace google + +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/options.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/options.h index 1454c232068..09364d72d70 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/options.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/options.h @@ -32,6 +32,11 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__ #include <string> +#include "util/generic/string.h" + +#include "google/protobuf/port_def.inc" + +using TProtoStringType = TString; namespace google { namespace protobuf { @@ -54,6 +59,7 @@ struct Options { // When set, the protoc will generate the current files and all the transitive // dependencies as lite runtime. bool enforce_lite; + bool opensource_runtime = PROTO2_IS_OSS; // If true, we should build .meta files and emit @Generated annotations into // generated code. bool annotate_code; @@ -70,4 +76,5 @@ struct Options { } // namespace protobuf } // namespace google +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field.cc index adb556a892a..d63cdb4ecaf 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field.cc @@ -32,21 +32,20 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/primitive_field.h> +#include "google/protobuf/compiler/java/primitive_field.h" #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" namespace google { namespace protobuf { @@ -57,71 +56,73 @@ using internal::WireFormat; namespace { -void SetPrimitiveVariables(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex, - const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetPrimitiveVariables( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables, + Context* context) { SetCommonFieldVariables(descriptor, info, variables); JavaType javaType = GetJavaType(descriptor); - (*variables)["type"] = PrimitiveTypeName(javaType); - (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType); - (*variables)["kt_type"] = KotlinTypeName(javaType); - (*variables)["field_type"] = (*variables)["type"]; + (*variables)["type"] = TProtoStringType(PrimitiveTypeName(javaType)); + (*variables)["boxed_type"] = TProtoStringType(BoxedPrimitiveTypeName(javaType)); + (*variables)["kt_type"] = TProtoStringType(KotlinTypeName(javaType)); + variables->insert({"field_type", (*variables)["type"]}); + TProtoStringType name = (*variables)["name"]; if (javaType == JAVATYPE_BOOLEAN || javaType == JAVATYPE_DOUBLE || javaType == JAVATYPE_FLOAT || javaType == JAVATYPE_INT || javaType == JAVATYPE_LONG) { TProtoStringType 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()"; + y_absl::StrCat("com.google.protobuf.Internal.", capitalized_type, "List"); + (*variables)["empty_list"] = + y_absl::StrCat("empty", capitalized_type, "List()"); + (*variables)["create_list"] = + y_absl::StrCat("new", capitalized_type, "List()"); (*variables)["mutable_copy_list"] = - "mutableCopy(" + (*variables)["name"] + "_)"; + y_absl::StrCat("mutableCopy(", name, "_)"); (*variables)["name_make_immutable"] = - (*variables)["name"] + "_.makeImmutable()"; + y_absl::StrCat(name, "_.makeImmutable()"); (*variables)["repeated_get"] = - (*variables)["name"] + "_.get" + capitalized_type; + y_absl::StrCat(name, "_.get", capitalized_type); (*variables)["repeated_add"] = - (*variables)["name"] + "_.add" + capitalized_type; + y_absl::StrCat(name, "_.add", capitalized_type); (*variables)["repeated_set"] = - (*variables)["name"] + "_.set" + capitalized_type; + y_absl::StrCat(name, "_.set", capitalized_type); } else { + TProtoStringType boxed_type = (*variables)["boxed_type"]; (*variables)["field_list_type"] = - "java.util.List<" + (*variables)["boxed_type"] + ">"; + y_absl::StrCat("java.util.List<", 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"] + "_)"; + y_absl::StrCat("new java.util.ArrayList<", boxed_type, ">()"); + (*variables)["mutable_copy_list"] = + y_absl::StrCat("new java.util.ArrayList<", boxed_type, ">(", 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)["name_make_immutable"] = y_absl::StrCat( + name, "_ = java.util.Collections.unmodifiableList(", name, "_)"); + (*variables)["repeated_get"] = y_absl::StrCat(name, "_.get"); + (*variables)["repeated_add"] = y_absl::StrCat(name, "_.add"); + (*variables)["repeated_set"] = y_absl::StrCat(name, "_.set"); } - (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default"] = + ImmutableDefaultValue(descriptor, name_resolver, context->options()); (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ? "" - : ("= " + ImmutableDefaultValue(descriptor, name_resolver)); - (*variables)["capitalized_type"] = - GetCapitalizedType(descriptor, /* immutable = */ true); + : y_absl::StrCat("= ", ImmutableDefaultValue(descriptor, name_resolver, + context->options())); + (*variables)["capitalized_type"] = TProtoStringType(GetCapitalizedType( + descriptor, /* immutable = */ true, context->options())); (*variables)["tag"] = - StrCat(static_cast<arc_i32>(WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = StrCat( + y_absl::StrCat(static_cast<arc_i32>(WireFormat::MakeTag(descriptor))); + (*variables)["tag_size"] = y_absl::StrCat( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); if (IsReferenceType(GetJavaType(descriptor))) { (*variables)["null_check"] = - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n"; + "if (value == null) { throw new NullPointerException(); }"; } else { (*variables)["null_check"] = ""; } @@ -131,52 +132,41 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["kt_deprecation"] = descriptor->options().deprecated() - ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + - " is deprecated\") " + ? y_absl::StrCat("@kotlin.Deprecated(message = \"Field ", name, + " is deprecated\") ") : ""; int fixed_size = FixedSize(GetType(descriptor)); if (fixed_size != -1) { - (*variables)["fixed_size"] = StrCat(fixed_size); + (*variables)["fixed_size"] = y_absl::StrCat(fixed_size); } (*variables)["on_changed"] = "onChanged();"; if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - // Note that these have a trailing ";". - (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; - (*variables)["set_has_field_bit_builder"] = - GenerateSetBit(builderBitIndex) + ";"; - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex) + ";"; - + (*variables)["set_has_field_bit_to_local"] = + y_absl::StrCat(GenerateSetBitToLocal(messageBitIndex), ";"); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); } else { - (*variables)["set_has_field_bit_message"] = ""; - (*variables)["set_has_field_bit_builder"] = ""; - (*variables)["clear_has_field_bit_builder"] = ""; - + (*variables)["set_has_field_bit_to_local"] = ""; switch (descriptor->type()) { case FieldDescriptor::TYPE_BYTES: (*variables)["is_field_present_message"] = - "!" + (*variables)["name"] + "_.isEmpty()"; + y_absl::StrCat("!", name, "_.isEmpty()"); break; case FieldDescriptor::TYPE_FLOAT: (*variables)["is_field_present_message"] = - "java.lang.Float.floatToRawIntBits(" + (*variables)["name"] + - "_) != 0"; + y_absl::StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0"); break; case FieldDescriptor::TYPE_DOUBLE: - (*variables)["is_field_present_message"] = - "java.lang.Double.doubleToRawLongBits(" + (*variables)["name"] + - "_) != 0"; + (*variables)["is_field_present_message"] = y_absl::StrCat( + "java.lang.Double.doubleToRawLongBits(", name, "_) != 0"); break; default: - (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != " + (*variables)["default"]; + variables->insert( + {"is_field_present_message", + y_absl::StrCat(name, "_ != ", (*variables)["default"])}); break; } } @@ -186,17 +176,15 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); - // For repeated fields, one bit is used for whether the array is immutable - // in the parsing constructor. - (*variables)["get_mutable_bit_parser"] = - GenerateGetBitMutableLocal(builderBitIndex); - (*variables)["set_mutable_bit_parser"] = - GenerateSetBitMutableLocal(builderBitIndex); - + // Always track the presence of a field explicitly in the builder, regardless + // of syntax. + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); (*variables)["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(builderBitIndex); - (*variables)["set_has_field_bit_to_local"] = - GenerateSetBitToLocal(messageBitIndex); + (*variables)["set_has_field_bit_builder"] = + y_absl::StrCat(GenerateSetBit(builderBitIndex), ";"); + (*variables)["clear_has_field_bit_builder"] = + y_absl::StrCat(GenerateClearBit(builderBitIndex), ";"); } } // namespace @@ -206,21 +194,30 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, ImmutablePrimitiveFieldGenerator::ImmutablePrimitiveFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), + message_bit_index_(messageBitIndex), + builder_bit_index_(builderBitIndex), + name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + name_resolver_, &variables_, context); } ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {} +int ImmutablePrimitiveFieldGenerator::GetMessageBitIndex() const { + return message_bit_index_; +} + +int ImmutablePrimitiveFieldGenerator::GetBuilderBitIndex() const { + return builder_bit_index_; +} + int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { return HasHasbit(descriptor_) ? 1 : 0; } -int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { - return GetNumBitsForMessage(); -} +int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { return 1; } void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers( io::Printer* printer) const { @@ -235,7 +232,7 @@ void ImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers( void ImmutablePrimitiveFieldGenerator::GenerateMembers( io::Printer* printer) const { - printer->Print(variables_, "private $field_type$ $name$_;\n"); + printer->Print(variables_, "private $field_type$ $name$_ = $default$;\n"); PrintExtraFieldInfo(variables_, printer); if (HasHazzer(descriptor_)) { WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); @@ -285,9 +282,9 @@ void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public Builder " "${$set$capitalized_name$$}$($type$ value) {\n" - "$null_check$" - " $set_has_field_bit_builder$\n" + " $null_check$\n" " $name$_ = value;\n" + " $set_has_field_bit_builder$\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -318,9 +315,9 @@ void ImmutablePrimitiveFieldGenerator::GenerateBuilderMembers( void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers( io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$var $kt_name$: $kt_type$\n" + "$kt_deprecation$public var $kt_name$: $kt_type$\n" " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" @@ -329,17 +326,18 @@ void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers( " }\n"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, - "fun ${$clear$kt_capitalized_name$$}$() {\n" + "public fun ${$clear$kt_capitalized_name$$}$() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" "}\n"); if (HasHazzer(descriptor_)) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, + /* builder */ false, /* kdoc */ true); printer->Print( variables_, - "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" "}\n"); } @@ -359,9 +357,8 @@ void ImmutablePrimitiveFieldGenerator::GenerateInitializationCode( void ImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode( io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $default$;\n" - "$clear_has_field_bit_builder$\n"); + // No need to clear the has-bit since we clear the bitField ints all at once. + printer->Print(variables_, "$name$_ = $default$;\n"); } void ImmutablePrimitiveFieldGenerator::GenerateMergingCode( @@ -381,35 +378,20 @@ void ImmutablePrimitiveFieldGenerator::GenerateMergingCode( void ImmutablePrimitiveFieldGenerator::GenerateBuildingCode( io::Printer* printer) const { - if (HasHazzer(descriptor_)) { - if (IsDefaultValueJavaDefault(descriptor_)) { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " result.$name$_ = $name$_;\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); - } else { - printer->Print(variables_, - "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_, + "if ($get_has_field_bit_from_local$) {\n" + " result.$name$_ = $name$_;\n"); + if (GetNumBitsForMessage() > 0) { + printer->Print(variables_, " $set_has_field_bit_to_local$\n"); } + printer->Print("}\n"); } -void ImmutablePrimitiveFieldGenerator::GenerateParsingCode( +void ImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { printer->Print(variables_, - "$set_has_field_bit_message$\n" - "$name$_ = input.read$capitalized_type$();\n"); -} - -void ImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode( - io::Printer* printer) const { - // noop for primitives. + "$name$_ = input.read$capitalized_type$();\n" + "$set_has_field_bit_builder$\n"); } void ImmutablePrimitiveFieldGenerator::GenerateSerializationCode( @@ -467,7 +449,7 @@ void ImmutablePrimitiveFieldGenerator::GenerateEqualsCode( case JAVATYPE_ENUM: case JAVATYPE_MESSAGE: default: - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; break; } } @@ -518,13 +500,13 @@ void ImmutablePrimitiveFieldGenerator::GenerateHashCode( case JAVATYPE_ENUM: case JAVATYPE_MESSAGE: default: - GOOGLE_LOG(FATAL) << "Can't get here."; + Y_ABSL_LOG(FATAL) << "Can't get here."; break; } } TProtoStringType ImmutablePrimitiveFieldGenerator::GetBoxedType() const { - return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); + return TProtoStringType(BoxedPrimitiveTypeName(GetJavaType(descriptor_))); } // =================================================================== @@ -545,7 +527,7 @@ ImmutablePrimitiveOneofFieldGenerator:: void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers( io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "@java.lang.Override\n" @@ -568,7 +550,7 @@ void ImmutablePrimitiveOneofFieldGenerator::GenerateMembers( void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers( io::Printer* printer) const { - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" @@ -591,7 +573,7 @@ void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public Builder " "${$set$capitalized_name$$}$($type$ value) {\n" - "$null_check$" + " $null_check$\n" " $set_oneof_case_message$;\n" " $oneof_name$_ = value;\n" " $on_changed$\n" @@ -614,12 +596,15 @@ void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderMembers( printer->Annotate("{", "}", descriptor_); } +void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { + // No-Op: When a primitive field is in a oneof, clearing the oneof clears that + // field. +} + void ImmutablePrimitiveOneofFieldGenerator::GenerateBuildingCode( io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " result.$oneof_name$_ = $oneof_name$_;\n" - "}\n"); + // no-op } void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode( @@ -628,7 +613,7 @@ void ImmutablePrimitiveOneofFieldGenerator::GenerateMergingCode( "set$capitalized_name$(other.get$capitalized_name$());\n"); } -void ImmutablePrimitiveOneofFieldGenerator::GenerateParsingCode( +void ImmutablePrimitiveOneofFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { printer->Print(variables_, "$oneof_name$_ = input.read$capitalized_type$();\n" @@ -677,11 +662,8 @@ RepeatedImmutablePrimitiveFieldGenerator:: int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); -} + : ImmutablePrimitiveFieldGenerator(descriptor, messageBitIndex, + builderBitIndex, context) {} RepeatedImmutablePrimitiveFieldGenerator:: ~RepeatedImmutablePrimitiveFieldGenerator() {} @@ -710,7 +692,8 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateInterfaceMembers( void RepeatedImmutablePrimitiveFieldGenerator::GenerateMembers( io::Printer* printer) const { - printer->Print(variables_, "private $field_list_type$ $name$_;\n"); + printer->Print(variables_, "@SuppressWarnings(\"serial\")\n" + "private $field_list_type$ $name$_;\n"); PrintExtraFieldInfo(variables_, printer); WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, @@ -760,7 +743,7 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers( " if (!$get_mutable_bit_builder$) {\n" " $name$_ = $mutable_copy_list$;\n" " $set_mutable_bit_builder$;\n" - " }\n" + " }\n" "}\n"); // Note: We return an unmodifiable list because otherwise the caller @@ -795,7 +778,7 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" " int index, $type$ value) {\n" - "$null_check$" + " $null_check$\n" " ensure$capitalized_name$IsMutable();\n" " $repeated_set$(index, value);\n" " $on_changed$\n" @@ -807,7 +790,7 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public Builder " "${$add$capitalized_name$$}$($type$ value) {\n" - "$null_check$" + " $null_check$\n" " ensure$capitalized_name$IsMutable();\n" " $repeated_add$(value);\n" " $on_changed$\n" @@ -849,12 +832,12 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers( " */\n" "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" " : com.google.protobuf.kotlin.DslProxy()\n"); - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$ val $kt_name$: " + "$kt_deprecation$ public val $kt_name$: " "com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " @kotlin.jvm.JvmSynthetic\n" @@ -863,70 +846,70 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers( " )\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "add(value: $kt_type$) {\n" " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(value: $kt_type$) {\n" " add(value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" " addAll(values)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "operator fun com.google.protobuf.kotlin.DslList" + "public operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "set(index: kotlin.Int, value: $kt_type$) {\n" " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "clear() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" @@ -945,9 +928,7 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateInitializationCode( void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderClearCode( io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $empty_list$;\n" - "$clear_mutable_bit_builder$;\n"); + printer->Print(variables_, "$name$_ = $empty_list$;\n"); } void RepeatedImmutablePrimitiveFieldGenerator::GenerateMergingCode( @@ -982,38 +963,24 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuildingCode( "result.$name$_ = $name$_;\n"); } -void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingCode( +void RepeatedImmutablePrimitiveFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = $create_list$;\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "$repeated_add$(input.read$capitalized_type$());\n"); + "$type$ v = input.read$capitalized_type$();\n" + "ensure$capitalized_name$IsMutable();\n" + "$repeated_add$(v);\n"); } -void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingCodeFromPacked( - io::Printer* printer) const { - printer->Print( - variables_, - "int length = input.readRawVarint32();\n" - "int limit = input.pushLimit(length);\n" - "if (!$get_mutable_bit_parser$ && input.getBytesUntilLimit() > 0) {\n" - " $name$_ = $create_list$;\n" - " $set_mutable_bit_parser$;\n" - "}\n" - "while (input.getBytesUntilLimit() > 0) {\n" - " $repeated_add$(input.read$capitalized_type$());\n" - "}\n" - "input.popLimit(limit);\n"); -} - -void RepeatedImmutablePrimitiveFieldGenerator::GenerateParsingDoneCode( - io::Printer* printer) const { +void RepeatedImmutablePrimitiveFieldGenerator:: + GenerateBuilderParsingCodeFromPacked(io::Printer* printer) const { printer->Print(variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name_make_immutable$; // C\n" - "}\n"); + "int length = input.readRawVarint32();\n" + "int limit = input.pushLimit(length);\n" + "ensure$capitalized_name$IsMutable();\n" + "while (input.getBytesUntilLimit() > 0) {\n" + " $repeated_add$(input.read$capitalized_type$());\n" + "}\n" + "input.popLimit(limit);\n"); } void RepeatedImmutablePrimitiveFieldGenerator::GenerateSerializationCode( @@ -1102,7 +1069,7 @@ void RepeatedImmutablePrimitiveFieldGenerator::GenerateHashCode( } TProtoStringType RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const { - return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); + return TProtoStringType(BoxedPrimitiveTypeName(GetJavaType(descriptor_))); } } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field.h index a2c00413889..dae385afa6b 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field.h @@ -35,10 +35,9 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__ -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -62,10 +61,16 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { int messageBitIndex, int builderBitIndex, Context* context); + ImmutablePrimitiveFieldGenerator(const ImmutablePrimitiveFieldGenerator&) = + delete; + ImmutablePrimitiveFieldGenerator& operator=( + const ImmutablePrimitiveFieldGenerator&) = delete; ~ImmutablePrimitiveFieldGenerator() override; // implements ImmutableFieldGenerator // --------------------------------------- + int GetMessageBitIndex() const override; + int GetBuilderBitIndex() const override; int GetNumBitsForMessage() const override; int GetNumBitsForBuilder() const override; void GenerateInterfaceMembers(io::Printer* printer) const override; @@ -75,8 +80,7 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; - void GenerateParsingDoneCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateFieldBuilderInitializationCode( @@ -89,11 +93,10 @@ class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { protected: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + int message_bit_index_; + int builder_bit_index_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; ClassNameResolver* name_resolver_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldGenerator); }; class ImmutablePrimitiveOneofFieldGenerator @@ -102,26 +105,32 @@ class ImmutablePrimitiveOneofFieldGenerator ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context); + ImmutablePrimitiveOneofFieldGenerator( + const ImmutablePrimitiveOneofFieldGenerator&) = delete; + ImmutablePrimitiveOneofFieldGenerator& operator=( + const ImmutablePrimitiveOneofFieldGenerator&) = delete; ~ImmutablePrimitiveOneofFieldGenerator() override; void GenerateMembers(io::Printer* printer) const override; void GenerateBuilderMembers(io::Printer* printer) const override; + void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldGenerator); }; class RepeatedImmutablePrimitiveFieldGenerator - : public ImmutableFieldGenerator { + : public ImmutablePrimitiveFieldGenerator { public: explicit RepeatedImmutablePrimitiveFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context); + RepeatedImmutablePrimitiveFieldGenerator( + const RepeatedImmutablePrimitiveFieldGenerator&) = delete; + RepeatedImmutablePrimitiveFieldGenerator& operator=( + const RepeatedImmutablePrimitiveFieldGenerator&) = delete; ~RepeatedImmutablePrimitiveFieldGenerator() override; // implements ImmutableFieldGenerator --------------------------------------- @@ -134,9 +143,9 @@ class RepeatedImmutablePrimitiveFieldGenerator void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; - void GenerateParsingCodeFromPacked(io::Printer* printer) const override; - void GenerateParsingDoneCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; + void GenerateBuilderParsingCodeFromPacked( + io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateFieldBuilderInitializationCode( @@ -146,13 +155,6 @@ class RepeatedImmutablePrimitiveFieldGenerator void GenerateKotlinDslMembers(io::Printer* printer) const override; TProtoStringType GetBoxedType() const override; - - private: - const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; - ClassNameResolver* name_resolver_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field_lite.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field_lite.cc index 5fd47c47e16..0d4c6334569 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field_lite.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field_lite.cc @@ -32,21 +32,19 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/primitive_field_lite.h> +#include "google/protobuf/compiler/java/primitive_field_lite.h" #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/wire_format.h" namespace google { namespace protobuf { @@ -65,65 +63,70 @@ bool EnableExperimentalRuntimeForLite() { #endif // !PROTOBUF_EXPERIMENT } -void SetPrimitiveVariables(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex, - const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetPrimitiveVariables( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables, + Context* context) { SetCommonFieldVariables(descriptor, info, variables); JavaType javaType = GetJavaType(descriptor); - (*variables)["type"] = PrimitiveTypeName(javaType); - (*variables)["boxed_type"] = BoxedPrimitiveTypeName(javaType); - (*variables)["kt_type"] = KotlinTypeName(javaType); - (*variables)["field_type"] = (*variables)["type"]; - (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["capitalized_type"] = - GetCapitalizedType(descriptor, /* immutable = */ true); + (*variables)["type"] = TProtoStringType(PrimitiveTypeName(javaType)); + (*variables)["boxed_type"] = TProtoStringType(BoxedPrimitiveTypeName(javaType)); + (*variables)["kt_type"] = TProtoStringType(KotlinTypeName(javaType)); + variables->insert({"field_type", (*variables)["type"]}); + (*variables)["default"] = + ImmutableDefaultValue(descriptor, name_resolver, context->options()); + (*variables)["capitalized_type"] = TProtoStringType(GetCapitalizedType( + descriptor, /* immutable = */ true, context->options())); (*variables)["tag"] = - StrCat(static_cast<arc_i32>(WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = StrCat( + y_absl::StrCat(static_cast<arc_i32>(WireFormat::MakeTag(descriptor))); + (*variables)["tag_size"] = y_absl::StrCat( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); (*variables)["required"] = descriptor->is_required() ? "true" : "false"; TProtoStringType capitalized_type = UnderscoresToCamelCase( PrimitiveTypeName(javaType), true /* cap_next_letter */); + TProtoStringType name = (*variables)["name"]; switch (javaType) { case JAVATYPE_INT: case JAVATYPE_LONG: case JAVATYPE_FLOAT: case JAVATYPE_DOUBLE: case JAVATYPE_BOOLEAN: - (*variables)["field_list_type"] = - "com.google.protobuf.Internal." + capitalized_type + "List"; - (*variables)["empty_list"] = "empty" + capitalized_type + "List()"; + (*variables)["field_list_type"] = y_absl::StrCat( + "com.google.protobuf.Internal.", capitalized_type, "List"); + (*variables)["empty_list"] = + y_absl::StrCat("empty", capitalized_type, "List()"); (*variables)["make_name_unmodifiable"] = - (*variables)["name"] + "_.makeImmutable()"; + y_absl::StrCat(name, "_.makeImmutable()"); (*variables)["repeated_get"] = - (*variables)["name"] + "_.get" + capitalized_type; + y_absl::StrCat(name, "_.get", capitalized_type); (*variables)["repeated_add"] = - (*variables)["name"] + "_.add" + capitalized_type; + y_absl::StrCat(name, "_.add", capitalized_type); (*variables)["repeated_set"] = - (*variables)["name"] + "_.set" + capitalized_type; + y_absl::StrCat(name, "_.set", capitalized_type); (*variables)["visit_type"] = capitalized_type; - (*variables)["visit_type_list"] = "visit" + capitalized_type + "List"; + (*variables)["visit_type_list"] = + y_absl::StrCat("visit", capitalized_type, "List"); break; default: - (*variables)["field_list_type"] = - "com.google.protobuf.Internal.ProtobufList<" + - (*variables)["boxed_type"] + ">"; + variables->insert( + {"field_list_type", + y_absl::StrCat("com.google.protobuf.Internal.ProtobufList<", + (*variables)["boxed_type"], ">")}); (*variables)["empty_list"] = "emptyProtobufList()"; (*variables)["make_name_unmodifiable"] = - (*variables)["name"] + "_.makeImmutable()"; - (*variables)["repeated_get"] = (*variables)["name"] + "_.get"; - (*variables)["repeated_add"] = (*variables)["name"] + "_.add"; - (*variables)["repeated_set"] = (*variables)["name"] + "_.set"; + y_absl::StrCat(name, "_.makeImmutable()"); + (*variables)["repeated_get"] = y_absl::StrCat(name, "_.get"); + (*variables)["repeated_add"] = y_absl::StrCat(name, "_.add"); + (*variables)["repeated_set"] = y_absl::StrCat(name, "_.set"); (*variables)["visit_type"] = "ByteString"; (*variables)["visit_type_list"] = "visitList"; } if (javaType == JAVATYPE_BYTES) { (*variables)["bytes_default"] = - ToUpper((*variables)["name"]) + "_DEFAULT_VALUE"; + y_absl::StrCat(y_absl::AsciiStrToUpper(name), "_DEFAULT_VALUE"); } if (IsReferenceType(javaType)) { @@ -140,12 +143,12 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; (*variables)["kt_deprecation"] = descriptor->options().deprecated() - ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + - " is deprecated\") " + ? y_absl::StrCat("@kotlin.Deprecated(message = \"Field ", name, + " is deprecated\") ") : ""; int fixed_size = FixedSize(GetType(descriptor)); if (fixed_size != -1) { - (*variables)["fixed_size"] = StrCat(fixed_size); + (*variables)["fixed_size"] = y_absl::StrCat(fixed_size); } if (HasHasbit(descriptor)) { @@ -154,9 +157,9 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; + y_absl::StrCat(GenerateSetBit(messageBitIndex), ";"); (*variables)["clear_has_field_bit_message"] = - GenerateClearBit(messageBitIndex) + ";"; + y_absl::StrCat(GenerateClearBit(messageBitIndex), ";"); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); } else { @@ -166,21 +169,20 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, switch (descriptor->type()) { case FieldDescriptor::TYPE_BYTES: (*variables)["is_field_present_message"] = - "!" + (*variables)["name"] + "_.isEmpty()"; + y_absl::StrCat("!", name, "_.isEmpty()"); break; case FieldDescriptor::TYPE_FLOAT: (*variables)["is_field_present_message"] = - "java.lang.Float.floatToRawIntBits(" + (*variables)["name"] + - "_) != 0"; + y_absl::StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0"); break; case FieldDescriptor::TYPE_DOUBLE: - (*variables)["is_field_present_message"] = - "java.lang.Double.doubleToRawLongBits(" + (*variables)["name"] + - "_) != 0"; + (*variables)["is_field_present_message"] = y_absl::StrCat( + "java.lang.Double.doubleToRawLongBits(", name, "_) != 0"); break; default: - (*variables)["is_field_present_message"] = - (*variables)["name"] + "_ != " + (*variables)["default"]; + variables->insert( + {"is_field_present_message", + y_absl::StrCat(name, "_ != ", (*variables)["default"])}); break; } } @@ -189,6 +191,9 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, GenerateGetBitFromLocal(builderBitIndex); (*variables)["set_has_field_bit_to_local"] = GenerateSetBitToLocal(messageBitIndex); + // Annotations often use { and } variables to denote ranges. + (*variables)["{"] = ""; + (*variables)["}"] = ""; } } // namespace @@ -199,10 +204,11 @@ 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_); + name_resolver_, &variables_, context); } ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {} @@ -219,7 +225,9 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers( "$deprecation$boolean has$capitalized_name$();\n"); } WriteFieldAccessorDocComment(printer, descriptor_, GETTER); - printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); + printer->Print(variables_, + "$deprecation$$type$ ${$get$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); } void ImmutablePrimitiveFieldLiteGenerator::GenerateMembers( @@ -231,6 +239,20 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateMembers( variables_, "private static final $field_type$ $bytes_default$ = $default$;\n"); } + if (!context_->options().opensource_runtime) { + printer->Print( + variables_, + "@com.google.protobuf.ProtoField(\n" + " fieldNumber=$number$,\n" + " type=com.google.protobuf.FieldType.$annotation_field_type$,\n" + " isRequired=$required$)\n"); + if (HasHazzer(descriptor_)) { + printer->Print(variables_, + "@com.google.protobuf.ProtoPresenceCheckedField(\n" + " presenceBitsId=$bit_field_id$,\n" + " mask=$bit_field_mask$)\n"); + } + } printer->Print(variables_, "private $field_type$ $name$_;\n"); PrintExtraFieldInfo(variables_, printer); if (HasHazzer(descriptor_)) { @@ -325,7 +347,7 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers( io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$kt_deprecation$var $kt_name$: $kt_type$\n" + "$kt_deprecation$public var $kt_name$: $kt_type$\n" " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" @@ -334,17 +356,18 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers( " }\n"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, - "fun ${$clear$kt_capitalized_name$$}$() {\n" + "public fun ${$clear$kt_capitalized_name$$}$() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" "}\n"); if (HasHazzer(descriptor_)) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, + /* builder */ false, /* kdoc */ true); printer->Print( variables_, - "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" "}\n"); } @@ -371,7 +394,7 @@ void ImmutablePrimitiveFieldLiteGenerator::GenerateInitializationCode( } TProtoStringType ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const { - return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); + return TProtoStringType(BoxedPrimitiveTypeName(GetJavaType(descriptor_))); } // =================================================================== @@ -393,7 +416,7 @@ ImmutablePrimitiveOneofFieldLiteGenerator:: void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateMembers( io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "@java.lang.Override\n" @@ -441,7 +464,7 @@ void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateFieldInfo( void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateBuilderMembers( io::Printer* printer) const { - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "@java.lang.Override\n" @@ -492,7 +515,7 @@ RepeatedImmutablePrimitiveFieldLiteGenerator:: name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + name_resolver_, &variables_, context); } RepeatedImmutablePrimitiveFieldLiteGenerator:: @@ -507,13 +530,17 @@ void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateInterfaceMembers( WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, "$deprecation$java.util.List<$boxed_type$> " - "get$capitalized_name$List();\n"); + "${$get$capitalized_name$List$}$();\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); + "$deprecation$int ${$get$capitalized_name$Count$}$();\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); - printer->Print(variables_, - "$deprecation$$type$ get$capitalized_name$(int index);\n"); + printer->Print( + variables_, + "$deprecation$$type$ ${$get$capitalized_name$$}$(int index);\n"); + printer->Annotate("{", "}", descriptor_); } void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateMembers( @@ -671,12 +698,12 @@ void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers( " */\n" "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" " : com.google.protobuf.kotlin.DslProxy()\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$kt_deprecation$ val $kt_name$: " + "$kt_deprecation$ public val $kt_name$: " "com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>\n" " @kotlin.jvm.JvmSynthetic\n" @@ -685,70 +712,70 @@ void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateKotlinDslMembers( " )\n"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "add(value: $kt_type$) {\n" " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(value: $kt_type$) {\n" " add(value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "addAll(values: kotlin.collections.Iterable<$kt_type$>) {\n" " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(values: kotlin.collections.Iterable<$kt_type$>) {\n" " addAll(values)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "operator fun com.google.protobuf.kotlin.DslList" + "public operator fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "set(index: kotlin.Int, value: $kt_type$) {\n" " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<$kt_type$, ${$$kt_capitalized_name$Proxy$}$>." "clear() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" @@ -769,7 +796,7 @@ void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateInitializationCode( } TProtoStringType RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const { - return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); + return TProtoStringType(BoxedPrimitiveTypeName(GetJavaType(descriptor_))); } } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field_lite.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field_lite.h index 1eaf8d8e092..48090484ee4 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field_lite.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/primitive_field_lite.h @@ -36,10 +36,9 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__ #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -62,6 +61,10 @@ class ImmutablePrimitiveFieldLiteGenerator public: explicit ImmutablePrimitiveFieldLiteGenerator( const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + ImmutablePrimitiveFieldLiteGenerator( + const ImmutablePrimitiveFieldLiteGenerator&) = delete; + ImmutablePrimitiveFieldLiteGenerator& operator=( + const ImmutablePrimitiveFieldLiteGenerator&) = delete; ~ImmutablePrimitiveFieldLiteGenerator() override; // implements ImmutableFieldLiteGenerator @@ -79,12 +82,10 @@ class ImmutablePrimitiveFieldLiteGenerator protected: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; const int messageBitIndex_; + Context* context_; ClassNameResolver* name_resolver_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldLiteGenerator); }; class ImmutablePrimitiveOneofFieldLiteGenerator @@ -93,6 +94,10 @@ class ImmutablePrimitiveOneofFieldLiteGenerator ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + ImmutablePrimitiveOneofFieldLiteGenerator( + const ImmutablePrimitiveOneofFieldLiteGenerator&) = delete; + ImmutablePrimitiveOneofFieldLiteGenerator& operator=( + const ImmutablePrimitiveOneofFieldLiteGenerator&) = delete; ~ImmutablePrimitiveOneofFieldLiteGenerator() override; void GenerateMembers(io::Printer* printer) const override; @@ -100,9 +105,6 @@ class ImmutablePrimitiveOneofFieldLiteGenerator void GenerateFieldInfo(io::Printer* printer, std::vector<uint16_t>* output) const override; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator); }; class RepeatedImmutablePrimitiveFieldLiteGenerator @@ -110,6 +112,10 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator public: explicit RepeatedImmutablePrimitiveFieldLiteGenerator( const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + RepeatedImmutablePrimitiveFieldLiteGenerator( + const RepeatedImmutablePrimitiveFieldLiteGenerator&) = delete; + RepeatedImmutablePrimitiveFieldLiteGenerator& operator=( + const RepeatedImmutablePrimitiveFieldLiteGenerator&) = delete; ~RepeatedImmutablePrimitiveFieldLiteGenerator() override; // implements ImmutableFieldLiteGenerator ------------------------------------ @@ -126,11 +132,9 @@ class RepeatedImmutablePrimitiveFieldLiteGenerator private: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; Context* context_; ClassNameResolver* name_resolver_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldLiteGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/service.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/service.cc index 602ab4c7b93..3f6d896c6d0 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/service.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/service.cc @@ -32,17 +32,18 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/service.h> +#include "google/protobuf/compiler/java/service.h" -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" // Must be last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -68,6 +69,10 @@ void ImmutableServiceGenerator::Generate(io::Printer* printer) { WriteServiceDocComment(printer, descriptor_); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, /* immutable = */ true); + if (!context_->options().opensource_runtime) { + printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n"); + } + printer->Print( "public $static$ abstract class $classname$\n" " implements com.google.protobuf.Service {\n", @@ -92,7 +97,7 @@ void ImmutableServiceGenerator::Generate(io::Printer* printer) { " return $file$.getDescriptor().getServices().get($index$);\n" "}\n", "file", name_resolver_->GetImmutableClassName(descriptor_->file()), - "index", StrCat(descriptor_->index())); + "index", y_absl::StrCat(descriptor_->index())); GenerateGetDescriptorForType(printer); // Generate more stuff. @@ -211,8 +216,8 @@ void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map<TProtoStringType, TProtoStringType> vars; - vars["index"] = StrCat(i); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; + vars["index"] = y_absl::StrCat(i); vars["method"] = UnderscoresToCamelCase(method); vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); vars["output"] = GetOutput(method); @@ -258,8 +263,8 @@ void ImmutableServiceGenerator::GenerateCallBlockingMethod( for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map<TProtoStringType, TProtoStringType> vars; - vars["index"] = StrCat(i); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; + vars["index"] = y_absl::StrCat(i); vars["method"] = UnderscoresToCamelCase(method); vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); vars["output"] = GetOutput(method); @@ -303,8 +308,8 @@ void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which, for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); - std::map<TProtoStringType, TProtoStringType> vars; - vars["index"] = StrCat(i); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; + vars["index"] = y_absl::StrCat(i); vars["type"] = (which == REQUEST) ? name_resolver_->GetImmutableClassName(method->input_type()) @@ -358,8 +363,8 @@ void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) { printer->Print(" {\n"); printer->Indent(); - std::map<TProtoStringType, TProtoStringType> vars; - vars["index"] = StrCat(i); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; + vars["index"] = y_absl::StrCat(i); vars["output"] = GetOutput(method); printer->Print(vars, "channel.callMethod(\n" @@ -422,8 +427,8 @@ void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) { printer->Print(" {\n"); printer->Indent(); - std::map<TProtoStringType, TProtoStringType> vars; - vars["index"] = StrCat(i); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; + vars["index"] = y_absl::StrCat(i); vars["output"] = GetOutput(method); printer->Print(vars, "return ($output$) channel.callBlockingMethod(\n" @@ -445,7 +450,7 @@ void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) { void ImmutableServiceGenerator::GenerateMethodSignature( io::Printer* printer, const MethodDescriptor* method, IsAbstract is_abstract) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["name"] = UnderscoresToCamelCase(method); vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); vars["output"] = GetOutput(method); @@ -459,7 +464,7 @@ void ImmutableServiceGenerator::GenerateMethodSignature( void ImmutableServiceGenerator::GenerateBlockingMethodSignature( io::Printer* printer, const MethodDescriptor* method) { - std::map<TProtoStringType, TProtoStringType> vars; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["method"] = UnderscoresToCamelCase(method); vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); vars["output"] = GetOutput(method); @@ -476,4 +481,4 @@ void ImmutableServiceGenerator::GenerateBlockingMethodSignature( } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/service.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/service.h index a03a3de561f..a59223c7cb9 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/service.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/service.h @@ -35,8 +35,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_SERVICE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_SERVICE_H__ -#include <map> -#include <google/protobuf/descriptor.h> +#include "google/protobuf/descriptor.h" namespace google { namespace protobuf { @@ -60,6 +59,8 @@ namespace java { class ServiceGenerator { public: explicit ServiceGenerator(const ServiceDescriptor* descriptor); + ServiceGenerator(const ServiceGenerator&) = delete; + ServiceGenerator& operator=(const ServiceGenerator&) = delete; virtual ~ServiceGenerator(); virtual void Generate(io::Printer* printer) = 0; @@ -69,15 +70,15 @@ class ServiceGenerator { protected: const ServiceDescriptor* descriptor_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator); }; class ImmutableServiceGenerator : public ServiceGenerator { public: ImmutableServiceGenerator(const ServiceDescriptor* descriptor, Context* context); + ImmutableServiceGenerator(const ImmutableServiceGenerator&) = delete; + ImmutableServiceGenerator& operator=(const ImmutableServiceGenerator&) = + delete; ~ImmutableServiceGenerator() override; void Generate(io::Printer* printer) override; @@ -128,7 +129,6 @@ class ImmutableServiceGenerator : public ServiceGenerator { Context* context_; ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableServiceGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/shared_code_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/shared_code_generator.cc index 0a8b8edb012..79c6afab4ea 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/shared_code_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/shared_code_generator.cc @@ -30,19 +30,20 @@ // Author: [email protected] (Feng Xiao) -#include <google/protobuf/compiler/java/shared_code_generator.h> +#include "google/protobuf/compiler/java/shared_code_generator.h" #include <memory> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> -#include <google/protobuf/compiler/java/names.h> -#include <google/protobuf/descriptor.pb.h> +#include "y_absl/strings/escaping.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/compiler/java/names.h" +#include "google/protobuf/compiler/retention.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { @@ -51,20 +52,22 @@ namespace java { SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file, const Options& options) - : name_resolver_(new ClassNameResolver), file_(file), options_(options) {} + : name_resolver_(new ClassNameResolver(options)), + file_(file), + options_(options) {} SharedCodeGenerator::~SharedCodeGenerator() {} void SharedCodeGenerator::Generate( GeneratorContext* context, std::vector<TProtoStringType>* file_list, std::vector<TProtoStringType>* annotation_file_list) { - TProtoStringType java_package = FileJavaPackage(file_); + TProtoStringType java_package = FileJavaPackage(file_, true, options_); TProtoStringType package_dir = JavaPackageToDir(java_package); if (HasDescriptorMethods(file_, options_.enforce_lite)) { // Generate descriptors. TProtoStringType classname = name_resolver_->GetDescriptorClassName(file_); - TProtoStringType filename = package_dir + classname + ".java"; + TProtoStringType filename = y_absl::StrCat(package_dir, classname, ".java"); file_list->push_back(filename); std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); GeneratedCodeInfo annotations; @@ -73,8 +76,8 @@ void SharedCodeGenerator::Generate( std::unique_ptr<io::Printer> printer( new io::Printer(output.get(), '$', options_.annotate_code ? &annotation_collector : NULL)); - TProtoStringType info_relative_path = classname + ".java.pb.meta"; - TProtoStringType info_full_path = filename + ".pb.meta"; + TProtoStringType info_relative_path = y_absl::StrCat(classname, ".java.pb.meta"); + TProtoStringType info_full_path = y_absl::StrCat(filename, ".pb.meta"); printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "// source: $filename$\n" @@ -87,7 +90,12 @@ void SharedCodeGenerator::Generate( "package", java_package); } PrintGeneratedAnnotation(printer.get(), '$', - options_.annotate_code ? info_relative_path : ""); + options_.annotate_code ? info_relative_path : "", + options_); + + if (!options_.opensource_runtime) { + printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n"); + } printer->Print( "public final class $classname$ {\n" " public static com.google.protobuf.Descriptors.FileDescriptor\n" @@ -127,8 +135,7 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { // This makes huge bytecode files and can easily hit the compiler's internal // code size limits (error "code to large"). String literals are apparently // embedded raw, which is what we want. - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); + FileDescriptorProto file_proto = StripSourceRetentionOptions(*file_); TProtoStringType file_data; file_proto.SerializeToString(&file_data); @@ -152,7 +159,7 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { } } printer->Print("\"$data$\"", "data", - CEscape(file_data.substr(i, kBytesPerLine))); + y_absl::CEscape(file_data.substr(i, kBytesPerLine))); } printer->Outdent(); @@ -163,14 +170,14 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { std::vector<std::pair<TProtoStringType, TProtoStringType> > dependencies; for (int i = 0; i < file_->dependency_count(); i++) { TProtoStringType filename = file_->dependency(i)->name(); - TProtoStringType package = FileJavaPackage(file_->dependency(i)); + TProtoStringType package = FileJavaPackage(file_->dependency(i), true, options_); TProtoStringType classname = name_resolver_->GetDescriptorClassName(file_->dependency(i)); TProtoStringType full_name; if (package.empty()) { full_name = classname; } else { - full_name = package + "." + classname; + full_name = y_absl::StrCat(package, ".", classname); } dependencies.push_back(std::make_pair(filename, full_name)); } @@ -180,13 +187,15 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { printer->Print( "descriptor = com.google.protobuf.Descriptors.FileDescriptor\n" " .internalBuildGeneratedFileFrom(descriptorData,\n"); - printer->Print( - " new com.google.protobuf.Descriptors.FileDescriptor[] {\n"); + if (options_.opensource_runtime) { + printer->Print( + " new com.google.protobuf.Descriptors.FileDescriptor[] {\n"); - for (int i = 0; i < dependencies.size(); i++) { - const TProtoStringType& dependency = dependencies[i].second; - printer->Print(" $dependency$.getDescriptor(),\n", "dependency", - dependency); + for (int i = 0; i < dependencies.size(); i++) { + const TProtoStringType& dependency = dependencies[i].second; + printer->Print(" $dependency$.getDescriptor(),\n", "dependency", + dependency); + } } printer->Print(" });\n"); diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/shared_code_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/shared_code_generator.h index 026124715aa..b49214bc13f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/shared_code_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/shared_code_generator.h @@ -39,8 +39,8 @@ #include <string> #include <vector> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/java/options.h> +#include "google/protobuf/compiler/java/options.h" +#include "google/protobuf/port.h" namespace google { namespace protobuf { @@ -67,6 +67,8 @@ namespace java { class SharedCodeGenerator { public: SharedCodeGenerator(const FileDescriptor* file, const Options& options); + SharedCodeGenerator(const SharedCodeGenerator&) = delete; + SharedCodeGenerator& operator=(const SharedCodeGenerator&) = delete; ~SharedCodeGenerator(); void Generate(GeneratorContext* generator_context, @@ -79,7 +81,6 @@ class SharedCodeGenerator { std::unique_ptr<ClassNameResolver> name_resolver_; const FileDescriptor* file_; const Options options_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field.cc index 066e3bd7015..62581f65b94 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field.cc @@ -33,21 +33,20 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/string_field.h> +#include "google/protobuf/compiler/java/string_field.h" #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/wire_format.h" namespace google { namespace protobuf { @@ -59,86 +58,78 @@ using internal::WireFormatLite; namespace { -void SetPrimitiveVariables(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex, - const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetPrimitiveVariables( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables, + Context* context) { SetCommonFieldVariables(descriptor, info, variables); - (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; + (*variables)["empty_list"] = + "com.google.protobuf.LazyStringArrayList.emptyList()"; - (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["default_init"] = - "= " + ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default"] = + ImmutableDefaultValue(descriptor, name_resolver, context->options()); + (*variables)["default_init"] = y_absl::StrCat( + "= ", + ImmutableDefaultValue(descriptor, name_resolver, context->options())); (*variables)["capitalized_type"] = "String"; (*variables)["tag"] = - StrCat(static_cast<arc_i32>(WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = StrCat( + y_absl::StrCat(static_cast<arc_i32>(WireFormat::MakeTag(descriptor))); + (*variables)["tag_size"] = y_absl::StrCat( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); (*variables)["null_check"] = - " if (value == null) {\n" - " throw new NullPointerException();\n" - " }\n"; - (*variables)["isStringEmpty"] = "com.google.protobuf.GeneratedMessage" + - GeneratedCodeVersionSuffix() + - ".isStringEmpty"; - (*variables)["writeString"] = "com.google.protobuf.GeneratedMessage" + - GeneratedCodeVersionSuffix() + ".writeString"; - (*variables)["computeStringSize"] = "com.google.protobuf.GeneratedMessage" + - GeneratedCodeVersionSuffix() + - ".computeStringSize"; + "if (value == null) { throw new NullPointerException(); }"; + (*variables)["isStringEmpty"] = + y_absl::StrCat("com.google.protobuf.GeneratedMessage", + GeneratedCodeVersionSuffix(), ".isStringEmpty"); + (*variables)["writeString"] = + y_absl::StrCat("com.google.protobuf.GeneratedMessage", + GeneratedCodeVersionSuffix(), ".writeString"); + (*variables)["computeStringSize"] = + y_absl::StrCat("com.google.protobuf.GeneratedMessage", + GeneratedCodeVersionSuffix(), ".computeStringSize"); // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["kt_deprecation"] = - descriptor->options().deprecated() - ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + - " is deprecated\") " - : ""; + variables->insert( + {"kt_deprecation", + descriptor->options().deprecated() + ? y_absl::StrCat("@kotlin.Deprecated(message = \"Field ", + (*variables)["name"], " is deprecated\") ") + : ""}); (*variables)["on_changed"] = "onChanged();"; if (HasHasbit(descriptor)) { // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; - (*variables)["set_has_field_bit_builder"] = - GenerateSetBit(builderBitIndex) + ";"; - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex) + ";"; + y_absl::StrCat(GenerateSetBit(messageBitIndex), ";"); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); } else { + (*variables)["get_has_field_bit_message"] = ""; + (*variables)["set_has_field_bit_to_local"] = ""; (*variables)["set_has_field_bit_message"] = ""; - (*variables)["set_has_field_bit_builder"] = ""; - (*variables)["clear_has_field_bit_builder"] = ""; - (*variables)["is_field_present_message"] = - "!" + (*variables)["isStringEmpty"] + "(" + (*variables)["name"] + "_)"; + variables->insert({"is_field_present_message", + y_absl::StrCat("!", (*variables)["isStringEmpty"], "(", + (*variables)["name"], "_)")}); } - // For repeated builders, one bit is used for whether the array is immutable. - (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); - (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); - (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); - - // For repeated fields, one bit is used for whether the array is immutable - // in the parsing constructor. - (*variables)["get_mutable_bit_parser"] = - GenerateGetBitMutableLocal(builderBitIndex); - (*variables)["set_mutable_bit_parser"] = - GenerateSetBitMutableLocal(builderBitIndex); - + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); (*variables)["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(builderBitIndex); - (*variables)["set_has_field_bit_to_local"] = - GenerateSetBitToLocal(messageBitIndex); + (*variables)["set_has_field_bit_builder"] = + y_absl::StrCat(GenerateSetBit(builderBitIndex), ";"); + (*variables)["clear_has_field_bit_builder"] = + y_absl::StrCat(GenerateClearBit(builderBitIndex), ";"); } } // namespace @@ -148,21 +139,30 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, ImmutableStringFieldGenerator::ImmutableStringFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), + message_bit_index_(messageBitIndex), + builder_bit_index_(builderBitIndex), + name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + name_resolver_, &variables_, context); } ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {} +int ImmutableStringFieldGenerator::GetMessageBitIndex() const { + return message_bit_index_; +} + +int ImmutableStringFieldGenerator::GetBuilderBitIndex() const { + return builder_bit_index_; +} + int ImmutableStringFieldGenerator::GetNumBitsForMessage() const { return HasHasbit(descriptor_) ? 1 : 0; } -int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { - return GetNumBitsForMessage(); -} +int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { return 1; } // A note about how strings are handled. This code used to just store a String // in the Message. This had two issues: @@ -194,8 +194,7 @@ int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { // separate fields but rather use dynamic type checking. // // For single fields, the logic for this is done inside the generated code. For -// repeated fields, the logic is done in LazyStringArrayList and -// UnmodifiableLazyStringList. +// repeated fields, the logic is done in LazyStringArrayList. void ImmutableStringFieldGenerator::GenerateInterfaceMembers( io::Printer* printer) const { if (HasHazzer(descriptor_)) { @@ -214,7 +213,9 @@ void ImmutableStringFieldGenerator::GenerateInterfaceMembers( void ImmutableStringFieldGenerator::GenerateMembers( io::Printer* printer) const { - printer->Print(variables_, "private volatile java.lang.Object $name$_;\n"); + printer->Print(variables_, + "@SuppressWarnings(\"serial\")\n" + "private volatile java.lang.Object $name$_ = $default$;\n"); PrintExtraFieldInfo(variables_, printer); if (HasHazzer(descriptor_)) { @@ -333,9 +334,9 @@ void ImmutableStringFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" " java.lang.String value) {\n" - "$null_check$" - " $set_has_field_bit_builder$\n" + " $null_check$\n" " $name$_ = value;\n" + " $set_has_field_bit_builder$\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -344,14 +345,14 @@ void ImmutableStringFieldGenerator::GenerateBuilderMembers( /* builder */ true); printer->Print( variables_, - "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " $clear_has_field_bit_builder$\n"); + "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"); printer->Annotate("{", "}", descriptor_); // The default value is not a simple literal so we want to avoid executing // it multiple times. Instead, get the default out of the default instance. printer->Print(variables_, " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); printer->Print(variables_, + " $clear_has_field_bit_builder$\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -362,14 +363,14 @@ void ImmutableStringFieldGenerator::GenerateBuilderMembers( variables_, "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" " com.google.protobuf.ByteString value) {\n" - "$null_check$"); + " $null_check$\n"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); } printer->Print(variables_, - " $set_has_field_bit_builder$\n" " $name$_ = value;\n" + " $set_has_field_bit_builder$\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -377,9 +378,9 @@ void ImmutableStringFieldGenerator::GenerateBuilderMembers( void ImmutableStringFieldGenerator::GenerateKotlinDslMembers( io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$var $kt_name$: kotlin.String\n" + "$kt_deprecation$public var $kt_name$: kotlin.String\n" " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" @@ -388,17 +389,18 @@ void ImmutableStringFieldGenerator::GenerateKotlinDslMembers( " }\n"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, - "fun ${$clear$kt_capitalized_name$$}$() {\n" + "public fun ${$clear$kt_capitalized_name$$}$() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" "}\n"); if (HasHazzer(descriptor_)) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, + /* builder */ false, /* kdoc */ true); printer->Print( variables_, - "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" "}\n"); } @@ -416,9 +418,7 @@ void ImmutableStringFieldGenerator::GenerateInitializationCode( void ImmutableStringFieldGenerator::GenerateBuilderClearCode( io::Printer* printer) const { - printer->Print(variables_, - "$name$_ = $default$;\n" - "$clear_has_field_bit_builder$\n"); + printer->Print(variables_, "$name$_ = $default$;\n"); } void ImmutableStringFieldGenerator::GenerateMergingCode( @@ -428,14 +428,15 @@ void ImmutableStringFieldGenerator::GenerateMergingCode( // all string fields to Strings when copying fields from a Message. printer->Print(variables_, "if (other.has$capitalized_name$()) {\n" - " $set_has_field_bit_builder$\n" " $name$_ = other.$name$_;\n" + " $set_has_field_bit_builder$\n" " $on_changed$\n" "}\n"); } else { printer->Print(variables_, "if (!other.get$capitalized_name$().isEmpty()) {\n" " $name$_ = other.$name$_;\n" + " $set_has_field_bit_builder$\n" " $on_changed$\n" "}\n"); } @@ -443,35 +444,28 @@ void ImmutableStringFieldGenerator::GenerateMergingCode( void ImmutableStringFieldGenerator::GenerateBuildingCode( io::Printer* printer) const { - if (HasHazzer(descriptor_)) { - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " result.$name$_ = $name$_;\n"); + if (GetNumBitsForMessage() > 0) { + printer->Print(variables_, " $set_has_field_bit_to_local$;\n"); } - printer->Print(variables_, "result.$name$_ = $name$_;\n"); + printer->Print("}\n"); } -void ImmutableStringFieldGenerator::GenerateParsingCode( +void ImmutableStringFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { if (CheckUtf8(descriptor_)) { printer->Print(variables_, - "java.lang.String s = input.readStringRequireUtf8();\n" - "$set_has_field_bit_message$\n" - "$name$_ = s;\n"); + "$name$_ = input.readStringRequireUtf8();\n" + "$set_has_field_bit_builder$\n"); } else { printer->Print(variables_, - "com.google.protobuf.ByteString bs = input.readBytes();\n" - "$set_has_field_bit_message$\n" - "$name$_ = bs;\n"); + "$name$_ = input.readBytes();\n" + "$set_has_field_bit_builder$\n"); } } -void ImmutableStringFieldGenerator::GenerateParsingDoneCode( - io::Printer* printer) const { - // noop for strings. -} - void ImmutableStringFieldGenerator::GenerateSerializationCode( io::Printer* printer) const { printer->Print(variables_, @@ -523,7 +517,7 @@ ImmutableStringOneofFieldGenerator::~ImmutableStringOneofFieldGenerator() {} void ImmutableStringOneofFieldGenerator::GenerateMembers( io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n" @@ -587,7 +581,7 @@ void ImmutableStringOneofFieldGenerator::GenerateMembers( void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers( io::Printer* printer) const { - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "@java.lang.Override\n" @@ -655,7 +649,7 @@ void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" " java.lang.String value) {\n" - "$null_check$" + " $null_check$\n" " $set_oneof_case_message$;\n" " $oneof_name$_ = value;\n" " $on_changed$\n" @@ -682,7 +676,7 @@ void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers( variables_, "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n" " com.google.protobuf.ByteString value) {\n" - "$null_check$"); + " $null_check$\n"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); @@ -695,6 +689,11 @@ void ImmutableStringOneofFieldGenerator::GenerateBuilderMembers( "}\n"); } +void ImmutableStringOneofFieldGenerator::GenerateBuilderClearCode( + io::Printer* printer) const { + // No-Op: String fields in oneofs are correctly cleared by clearing the oneof +} + void ImmutableStringOneofFieldGenerator::GenerateMergingCode( io::Printer* printer) const { // Allow a slight breach of abstraction here in order to avoid forcing @@ -707,13 +706,10 @@ void ImmutableStringOneofFieldGenerator::GenerateMergingCode( void ImmutableStringOneofFieldGenerator::GenerateBuildingCode( io::Printer* printer) const { - printer->Print(variables_, - "if ($has_oneof_case_message$) {\n" - " result.$oneof_name$_ = $oneof_name$_;\n" - "}\n"); + // No-Op: oneof fields are built by a single statement } -void ImmutableStringOneofFieldGenerator::GenerateParsingCode( +void ImmutableStringOneofFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { if (CheckUtf8(descriptor_)) { printer->Print(variables_, @@ -749,11 +745,8 @@ void ImmutableStringOneofFieldGenerator::GenerateSerializedSizeCode( RepeatedImmutableStringFieldGenerator::RepeatedImmutableStringFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { - SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, - context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); -} + : ImmutableStringFieldGenerator(descriptor, messageBitIndex, + builderBitIndex, context) {} RepeatedImmutableStringFieldGenerator:: ~RepeatedImmutableStringFieldGenerator() {} @@ -796,7 +789,9 @@ void RepeatedImmutableStringFieldGenerator::GenerateInterfaceMembers( void RepeatedImmutableStringFieldGenerator::GenerateMembers( io::Printer* printer) const { printer->Print(variables_, - "private com.google.protobuf.LazyStringList $name$_;\n"); + "@SuppressWarnings(\"serial\")\n" + "private com.google.protobuf.LazyStringArrayList $name$_ =\n" + " $empty_list$;\n"); PrintExtraFieldInfo(variables_, printer); WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, @@ -840,17 +835,17 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers( // memory allocations. Note, immutable is a strong guarantee here -- not // just that the list cannot be modified via the reference but that the // list can never be modified. - printer->Print( - variables_, - "private com.google.protobuf.LazyStringList $name$_ = $empty_list$;\n"); + printer->Print(variables_, + "private com.google.protobuf.LazyStringArrayList $name$_ =\n" + " $empty_list$;\n"); printer->Print( variables_, "private void ensure$capitalized_name$IsMutable() {\n" - " if (!$get_mutable_bit_builder$) {\n" + " if (!$name$_.isModifiable()) {\n" " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" - " $set_mutable_bit_builder$;\n" - " }\n" + " }\n" + " $set_has_field_bit_builder$\n" "}\n"); // Note: We return an unmodifiable list because otherwise the caller @@ -861,7 +856,8 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public com.google.protobuf.ProtocolStringList\n" " ${$get$capitalized_name$List$}$() {\n" - " return $name$_.getUnmodifiableView();\n" + " $name$_.makeImmutable();\n" + " return $name$_;\n" "}\n"); printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); @@ -891,9 +887,10 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public Builder ${$set$capitalized_name$$}$(\n" " int index, java.lang.String value) {\n" - "$null_check$" + " $null_check$\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.set(index, value);\n" + " $set_has_field_bit_builder$\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -903,9 +900,10 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, "$deprecation$public Builder ${$add$capitalized_name$$}$(\n" " java.lang.String value) {\n" - "$null_check$" + " $null_check$\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.add(value);\n" + " $set_has_field_bit_builder$\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -918,6 +916,7 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers( " ensure$capitalized_name$IsMutable();\n" " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" " values, $name$_);\n" + " $set_has_field_bit_builder$\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -927,8 +926,9 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers( printer->Print( variables_, "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n" - " $name$_ = $empty_list$;\n" - " $clear_mutable_bit_builder$;\n" + " $name$_ =\n" + " $empty_list$;\n" + " $clear_has_field_bit_builder$;\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -940,7 +940,7 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers( variables_, "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n" " com.google.protobuf.ByteString value) {\n" - "$null_check$"); + " $null_check$\n"); printer->Annotate("{", "}", descriptor_); if (CheckUtf8(descriptor_)) { printer->Print(variables_, " checkByteStringIsUtf8(value);\n"); @@ -948,6 +948,7 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuilderMembers( printer->Print(variables_, " ensure$capitalized_name$IsMutable();\n" " $name$_.add(value);\n" + " $set_has_field_bit_builder$\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -963,13 +964,14 @@ void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers( " */\n" "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" " : com.google.protobuf.kotlin.DslProxy()\n"); // property for List<String> - WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER, + /* builder */ false, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$ val $kt_name$: " + "$kt_deprecation$public val $kt_name$: " "com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n" " @kotlin.jvm.JvmSynthetic\n" @@ -979,11 +981,11 @@ void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers( // List<String>.add(String) WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "add(value: kotlin.String) {\n" " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" @@ -991,12 +993,12 @@ void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers( // List<String> += String WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(value: kotlin.String) {\n" " add(value)\n" @@ -1004,12 +1006,12 @@ void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers( // List<String>.addAll(Iterable<String>) WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n" " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" @@ -1017,13 +1019,13 @@ void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers( // List<String> += Iterable<String> WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n" " addAll(values)\n" @@ -1031,23 +1033,23 @@ void RepeatedImmutableStringFieldGenerator::GenerateKotlinDslMembers( // List<String>[Int] = String WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "operator fun com.google.protobuf.kotlin.DslList" + "public operator fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "set(index: kotlin.Int, value: kotlin.String) {\n" " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "clear() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" @@ -1061,14 +1063,16 @@ void RepeatedImmutableStringFieldGenerator:: void RepeatedImmutableStringFieldGenerator::GenerateInitializationCode( io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $empty_list$;\n"); + printer->Print(variables_, + "$name$_ =\n" + " $empty_list$;\n"); } void RepeatedImmutableStringFieldGenerator::GenerateBuilderClearCode( io::Printer* printer) const { printer->Print(variables_, - "$name$_ = $empty_list$;\n" - "$clear_mutable_bit_builder$;\n"); + "$name$_ =\n" + " $empty_list$;\n"); } void RepeatedImmutableStringFieldGenerator::GenerateMergingCode( @@ -1082,7 +1086,7 @@ void RepeatedImmutableStringFieldGenerator::GenerateMergingCode( "if (!other.$name$_.isEmpty()) {\n" " if ($name$_.isEmpty()) {\n" " $name$_ = other.$name$_;\n" - " $clear_mutable_bit_builder$;\n" + " $set_has_field_bit_builder$\n" " } else {\n" " ensure$capitalized_name$IsMutable();\n" " $name$_.addAll(other.$name$_);\n" @@ -1095,44 +1099,28 @@ void RepeatedImmutableStringFieldGenerator::GenerateBuildingCode( io::Printer* printer) const { // The code below ensures that the result has an immutable list. If our // list is immutable, we can just reuse it. If not, we make it immutable. - printer->Print(variables_, - "if ($get_mutable_bit_builder$) {\n" - " $name$_ = $name$_.getUnmodifiableView();\n" - " $clear_mutable_bit_builder$;\n" - "}\n" - "result.$name$_ = $name$_;\n"); + "if ($get_has_field_bit_from_local$) {\n" + " $name$_.makeImmutable();\n" + " result.$name$_ = $name$_;\n" + "}\n"); } -void RepeatedImmutableStringFieldGenerator::GenerateParsingCode( +void RepeatedImmutableStringFieldGenerator::GenerateBuilderParsingCode( io::Printer* printer) const { if (CheckUtf8(descriptor_)) { printer->Print(variables_, - "java.lang.String s = input.readStringRequireUtf8();\n"); + "java.lang.String s = input.readStringRequireUtf8();\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(s);\n"); } else { printer->Print(variables_, - "com.google.protobuf.ByteString bs = input.readBytes();\n"); - } - printer->Print(variables_, - "if (!$get_mutable_bit_parser$) {\n" - " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" - " $set_mutable_bit_parser$;\n" - "}\n"); - if (CheckUtf8(descriptor_)) { - printer->Print(variables_, "$name$_.add(s);\n"); - } else { - printer->Print(variables_, "$name$_.add(bs);\n"); + "com.google.protobuf.ByteString bs = input.readBytes();\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(bs);\n"); } } -void RepeatedImmutableStringFieldGenerator::GenerateParsingDoneCode( - io::Printer* printer) const { - printer->Print(variables_, - "if ($get_mutable_bit_parser$) {\n" - " $name$_ = $name$_.getUnmodifiableView();\n" - "}\n"); -} - void RepeatedImmutableStringFieldGenerator::GenerateSerializationCode( io::Printer* printer) const { printer->Print(variables_, diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field.h index 3a83f1fc2a6..e7ef4d7c061 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field.h @@ -36,10 +36,9 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__ -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -62,10 +61,15 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { explicit ImmutableStringFieldGenerator(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context); + ImmutableStringFieldGenerator(const ImmutableStringFieldGenerator&) = delete; + ImmutableStringFieldGenerator& operator=( + const ImmutableStringFieldGenerator&) = delete; ~ImmutableStringFieldGenerator() override; // implements ImmutableFieldGenerator // --------------------------------------- + int GetMessageBitIndex() const override; + int GetBuilderBitIndex() const override; int GetNumBitsForMessage() const override; int GetNumBitsForBuilder() const override; void GenerateInterfaceMembers(io::Printer* printer) const override; @@ -75,8 +79,7 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; - void GenerateParsingDoneCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateFieldBuilderInitializationCode( @@ -89,11 +92,10 @@ class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { protected: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + int message_bit_index_; + int builder_bit_index_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; ClassNameResolver* name_resolver_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldGenerator); }; class ImmutableStringOneofFieldGenerator @@ -102,25 +104,33 @@ class ImmutableStringOneofFieldGenerator ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context); + ImmutableStringOneofFieldGenerator( + const ImmutableStringOneofFieldGenerator&) = delete; + ImmutableStringOneofFieldGenerator& operator=( + const ImmutableStringOneofFieldGenerator&) = delete; ~ImmutableStringOneofFieldGenerator() override; private: void GenerateMembers(io::Printer* printer) const override; void GenerateBuilderMembers(io::Printer* printer) const override; + void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldGenerator); }; -class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { +class RepeatedImmutableStringFieldGenerator + : public ImmutableStringFieldGenerator { public: explicit RepeatedImmutableStringFieldGenerator( const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, Context* context); + RepeatedImmutableStringFieldGenerator( + const RepeatedImmutableStringFieldGenerator&) = delete; + RepeatedImmutableStringFieldGenerator& operator=( + const RepeatedImmutableStringFieldGenerator&) = delete; ~RepeatedImmutableStringFieldGenerator() override; // implements ImmutableFieldGenerator --------------------------------------- @@ -133,8 +143,7 @@ class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { void GenerateBuilderClearCode(io::Printer* printer) const override; void GenerateMergingCode(io::Printer* printer) const override; void GenerateBuildingCode(io::Printer* printer) const override; - void GenerateParsingCode(io::Printer* printer) const override; - void GenerateParsingDoneCode(io::Printer* printer) const override; + void GenerateBuilderParsingCode(io::Printer* printer) const override; void GenerateSerializationCode(io::Printer* printer) const override; void GenerateSerializedSizeCode(io::Printer* printer) const override; void GenerateFieldBuilderInitializationCode( @@ -144,13 +153,6 @@ class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { void GenerateKotlinDslMembers(io::Printer* printer) const override; TProtoStringType GetBoxedType() const override; - - private: - const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; - ClassNameResolver* name_resolver_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldGenerator); }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field_lite.cc b/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field_lite.cc index 91cb53d484f..6e57d1bbef4 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field_lite.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field_lite.cc @@ -33,21 +33,19 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include <google/protobuf/compiler/java/string_field_lite.h> +#include "google/protobuf/compiler/java/string_field_lite.h" #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/java/context.h> -#include <google/protobuf/compiler/java/doc_comment.h> -#include <google/protobuf/compiler/java/helpers.h> -#include <google/protobuf/compiler/java/name_resolver.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/java/context.h" +#include "google/protobuf/compiler/java/doc_comment.h" +#include "google/protobuf/compiler/java/helpers.h" +#include "google/protobuf/compiler/java/name_resolver.h" +#include "google/protobuf/wire_format.h" namespace google { namespace protobuf { @@ -59,23 +57,25 @@ using internal::WireFormatLite; namespace { -void SetPrimitiveVariables(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex, - const FieldGeneratorInfo* info, - ClassNameResolver* name_resolver, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetPrimitiveVariables( + const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, ClassNameResolver* name_resolver, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables, + Context* context) { SetCommonFieldVariables(descriptor, info, variables); (*variables)["empty_list"] = "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()"; - (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); - (*variables)["default_init"] = - "= " + ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default"] = + ImmutableDefaultValue(descriptor, name_resolver, context->options()); + (*variables)["default_init"] = y_absl::StrCat( + "= ", + ImmutableDefaultValue(descriptor, name_resolver, context->options())); (*variables)["capitalized_type"] = "java.lang.String"; (*variables)["tag"] = - StrCat(static_cast<arc_i32>(WireFormat::MakeTag(descriptor))); - (*variables)["tag_size"] = StrCat( + y_absl::StrCat(static_cast<arc_i32>(WireFormat::MakeTag(descriptor))); + (*variables)["tag_size"] = y_absl::StrCat( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); // We use `x.getClass()` as a null check because it generates less bytecode // than an `if (x == null) { throw ... }` statement. @@ -86,36 +86,49 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // by the proto compiler (*variables)["deprecation"] = descriptor->options().deprecated() ? "@java.lang.Deprecated " : ""; - (*variables)["kt_deprecation"] = - descriptor->options().deprecated() - ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] + - " is deprecated\") " - : ""; + variables->insert( + {"kt_deprecation", + descriptor->options().deprecated() + ? y_absl::StrCat("@kotlin.Deprecated(message = \"Field ", + (*variables)["name"], " is deprecated\") ") + : ""}); (*variables)["required"] = descriptor->is_required() ? "true" : "false"; + if (!context->options().opensource_runtime) { + (*variables)["enforce_utf8"] = CheckUtf8(descriptor) ? "true" : "false"; + } if (HasHasbit(descriptor)) { + if (!context->options().opensource_runtime) { + (*variables)["bit_field_id"] = y_absl::StrCat(messageBitIndex / 32); + (*variables)["bit_field_name"] = GetBitFieldNameForBit(messageBitIndex); + (*variables)["bit_field_mask"] = + y_absl::StrCat(1 << (messageBitIndex % 32)); + } // For singular messages and builders, one bit is used for the hasField bit. (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); // Note that these have a trailing ";". (*variables)["set_has_field_bit_message"] = - GenerateSetBit(messageBitIndex) + ";"; + y_absl::StrCat(GenerateSetBit(messageBitIndex), ";"); (*variables)["clear_has_field_bit_message"] = - GenerateClearBit(messageBitIndex) + ";"; + y_absl::StrCat(GenerateClearBit(messageBitIndex), ";"); (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); } else { (*variables)["set_has_field_bit_message"] = ""; (*variables)["clear_has_field_bit_message"] = ""; - (*variables)["is_field_present_message"] = - "!" + (*variables)["name"] + "_.isEmpty()"; + variables->insert({"is_field_present_message", + y_absl::StrCat("!", (*variables)["name"], "_.isEmpty()")}); } (*variables)["get_has_field_bit_from_local"] = GenerateGetBitFromLocal(builderBitIndex); (*variables)["set_has_field_bit_to_local"] = GenerateSetBitToLocal(messageBitIndex); + // Annotations often use { and } variables to denote text ranges. + (*variables)["{"] = ""; + (*variables)["}"] = ""; } } // namespace @@ -126,10 +139,11 @@ ImmutableStringFieldLiteGenerator::ImmutableStringFieldLiteGenerator( const FieldDescriptor* descriptor, int messageBitIndex, Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - name_resolver_(context->GetNameResolver()) { + name_resolver_(context->GetNameResolver()), + context_(context) { SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + name_resolver_, &variables_, context); } ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {} @@ -168,19 +182,38 @@ void ImmutableStringFieldLiteGenerator::GenerateInterfaceMembers( if (HasHazzer(descriptor_)) { WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + "$deprecation$boolean ${$has$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); } WriteFieldAccessorDocComment(printer, descriptor_, GETTER); - printer->Print(variables_, - "$deprecation$java.lang.String get$capitalized_name$();\n"); + printer->Print( + variables_, + "$deprecation$java.lang.String ${$get$capitalized_name$$}$();\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER); printer->Print(variables_, "$deprecation$com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes();\n"); + " ${$get$capitalized_name$Bytes$}$();\n"); + printer->Annotate("{", "}", descriptor_); } void ImmutableStringFieldLiteGenerator::GenerateMembers( io::Printer* printer) const { + if (!context_->options().opensource_runtime) { + printer->Print( + variables_, + "@com.google.protobuf.ProtoField(\n" + " fieldNumber=$number$,\n" + " type=com.google.protobuf.FieldType.$annotation_field_type$,\n" + " isRequired=$required$,\n" + " isEnforceUtf8=$enforce_utf8$)\n"); + if (HasHazzer(descriptor_)) { + printer->Print(variables_, + "@com.google.protobuf.ProtoPresenceCheckedField(\n" + " presenceBitsId=$bit_field_id$,\n" + " mask=$bit_field_mask$)\n"); + } + } printer->Print(variables_, "private java.lang.String $name$_;\n"); PrintExtraFieldInfo(variables_, printer); @@ -311,9 +344,9 @@ void ImmutableStringFieldLiteGenerator::GenerateBuilderMembers( void ImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers( io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); + WriteFieldDocComment(printer, descriptor_, /* kdoc */ true); printer->Print(variables_, - "$kt_deprecation$var $kt_name$: kotlin.String\n" + "$kt_deprecation$public var $kt_name$: kotlin.String\n" " @JvmName(\"${$get$kt_capitalized_name$$}$\")\n" " get() = $kt_dsl_builder$.${$get$capitalized_name$$}$()\n" " @JvmName(\"${$set$kt_capitalized_name$$}$\")\n" @@ -322,17 +355,18 @@ void ImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers( " }\n"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, - "fun ${$clear$kt_capitalized_name$$}$() {\n" + "public fun ${$clear$kt_capitalized_name$$}$() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" "}\n"); if (HasHazzer(descriptor_)) { - WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); + WriteFieldAccessorDocComment(printer, descriptor_, HAZZER, + /* builder */ false, /* kdoc */ true); printer->Print( variables_, - "fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" + "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n" " return $kt_dsl_builder$.${$has$capitalized_name$$}$()\n" "}\n"); } @@ -374,7 +408,7 @@ ImmutableStringOneofFieldLiteGenerator:: void ImmutableStringOneofFieldLiteGenerator::GenerateMembers( io::Printer* printer) const { PrintExtraFieldInfo(variables_, printer); - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "@java.lang.Override\n" @@ -452,7 +486,7 @@ void ImmutableStringOneofFieldLiteGenerator::GenerateFieldInfo( void ImmutableStringOneofFieldLiteGenerator::GenerateBuilderMembers( io::Printer* printer) const { - GOOGLE_DCHECK(HasHazzer(descriptor_)); + Y_ABSL_DCHECK(HasHazzer(descriptor_)); WriteFieldAccessorDocComment(printer, descriptor_, HAZZER); printer->Print(variables_, "@java.lang.Override\n" @@ -519,10 +553,12 @@ RepeatedImmutableStringFieldLiteGenerator:: RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, Context* context) - : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) { + : descriptor_(descriptor), + name_resolver_(context->GetNameResolver()), + context_(context) { SetPrimitiveVariables(descriptor, messageBitIndex, 0, context->GetFieldGeneratorInfo(descriptor), - name_resolver_, &variables_); + name_resolver_, &variables_, context); } RepeatedImmutableStringFieldLiteGenerator:: @@ -537,22 +573,34 @@ void RepeatedImmutableStringFieldLiteGenerator::GenerateInterfaceMembers( WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); printer->Print(variables_, "$deprecation$java.util.List<java.lang.String>\n" - " get$capitalized_name$List();\n"); + " ${$get$capitalized_name$List$}$();\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT); printer->Print(variables_, - "$deprecation$int get$capitalized_name$Count();\n"); + "$deprecation$int ${$get$capitalized_name$Count$}$();\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); - printer->Print( - variables_, - "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); + printer->Print(variables_, + "$deprecation$java.lang.String " + "${$get$capitalized_name$$}$(int index);\n"); + printer->Annotate("{", "}", descriptor_); WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER); printer->Print(variables_, "$deprecation$com.google.protobuf.ByteString\n" - " get$capitalized_name$Bytes(int index);\n"); + " ${$get$capitalized_name$Bytes$}$(int index);\n"); + printer->Annotate("{", "}", descriptor_); } void RepeatedImmutableStringFieldLiteGenerator::GenerateMembers( io::Printer* printer) const { + if (!context_->options().opensource_runtime) { + printer->Print( + variables_, + "@com.google.protobuf.ProtoField(\n" + " fieldNumber=$number$,\n" + " type=com.google.protobuf.FieldType.$annotation_field_type$,\n" + " isEnforceUtf8=$enforce_utf8$)\n"); + } printer->Print( variables_, "private com.google.protobuf.Internal.ProtobufList<java.lang.String> " @@ -748,14 +796,15 @@ void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers( " */\n" "@kotlin.OptIn" "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n" - "class ${$$kt_capitalized_name$Proxy$}$ private constructor()" + "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()" " : com.google.protobuf.kotlin.DslProxy()\n"); // property for List<String> - WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER); + WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER, + /* builder */ false, /* kdoc */ true); printer->Print( variables_, - "$kt_deprecation$ val $kt_name$: " + "$kt_deprecation$public val $kt_name$: " "com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>\n" "@kotlin.OptIn" @@ -766,11 +815,11 @@ void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers( // List<String>.add(String) WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "add(value: kotlin.String) {\n" " $kt_dsl_builder$.${$add$capitalized_name$$}$(value)\n" @@ -778,12 +827,12 @@ void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers( // List<String> += String WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(value: kotlin.String) {\n" " add(value)\n" @@ -791,12 +840,12 @@ void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers( // List<String>.addAll(Iterable<String>) WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "addAll(values: kotlin.collections.Iterable<kotlin.String>) {\n" " $kt_dsl_builder$.${$addAll$capitalized_name$$}$(values)\n" @@ -804,13 +853,13 @@ void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers( // List<String> += Iterable<String> WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"plusAssignAll$kt_capitalized_name$\")\n" "@Suppress(\"NOTHING_TO_INLINE\")\n" - "inline operator fun com.google.protobuf.kotlin.DslList" + "public inline operator fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "plusAssign(values: kotlin.collections.Iterable<kotlin.String>) {\n" " addAll(values)\n" @@ -818,23 +867,23 @@ void RepeatedImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers( // List<String>[Int] = String WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print( variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"set$kt_capitalized_name$\")\n" - "operator fun com.google.protobuf.kotlin.DslList" + "public operator fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "set(index: kotlin.Int, value: kotlin.String) {\n" " $kt_dsl_builder$.${$set$capitalized_name$$}$(index, value)\n" "}"); WriteFieldAccessorDocComment(printer, descriptor_, CLEARER, - /* builder */ false); + /* builder */ false, /* kdoc */ true); printer->Print(variables_, "@kotlin.jvm.JvmSynthetic\n" "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n" - "fun com.google.protobuf.kotlin.DslList" + "public fun com.google.protobuf.kotlin.DslList" "<kotlin.String, ${$$kt_capitalized_name$Proxy$}$>." "clear() {\n" " $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field_lite.h b/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field_lite.h index 73e51e32383..e65b9953d30 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field_lite.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/java/string_field_lite.h @@ -37,10 +37,9 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__ #include <cstdint> -#include <map> #include <string> -#include <google/protobuf/compiler/java/field.h> +#include "google/protobuf/compiler/java/field.h" namespace google { namespace protobuf { @@ -63,6 +62,10 @@ class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { explicit ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + ImmutableStringFieldLiteGenerator(const ImmutableStringFieldLiteGenerator&) = + delete; + ImmutableStringFieldLiteGenerator& operator=( + const ImmutableStringFieldLiteGenerator&) = delete; ~ImmutableStringFieldLiteGenerator() override; // implements ImmutableFieldLiteGenerator @@ -80,12 +83,10 @@ class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { protected: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; const int messageBitIndex_; ClassNameResolver* name_resolver_; - - private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldLiteGenerator); + Context* context_; }; class ImmutableStringOneofFieldLiteGenerator @@ -93,6 +94,10 @@ class ImmutableStringOneofFieldLiteGenerator public: ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + ImmutableStringOneofFieldLiteGenerator( + const ImmutableStringOneofFieldLiteGenerator&) = delete; + ImmutableStringOneofFieldLiteGenerator& operator=( + const ImmutableStringOneofFieldLiteGenerator&) = delete; ~ImmutableStringOneofFieldLiteGenerator() override; private: @@ -100,8 +105,6 @@ class ImmutableStringOneofFieldLiteGenerator void GenerateBuilderMembers(io::Printer* printer) const override; void GenerateFieldInfo(io::Printer* printer, std::vector<uint16_t>* output) const override; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator); }; class RepeatedImmutableStringFieldLiteGenerator @@ -109,6 +112,10 @@ class RepeatedImmutableStringFieldLiteGenerator public: explicit RepeatedImmutableStringFieldLiteGenerator( const FieldDescriptor* descriptor, int messageBitIndex, Context* context); + RepeatedImmutableStringFieldLiteGenerator( + const RepeatedImmutableStringFieldLiteGenerator&) = delete; + RepeatedImmutableStringFieldLiteGenerator& operator=( + const RepeatedImmutableStringFieldLiteGenerator&) = delete; ~RepeatedImmutableStringFieldLiteGenerator() override; // implements ImmutableFieldLiteGenerator ------------------------------------ @@ -125,10 +132,9 @@ class RepeatedImmutableStringFieldLiteGenerator private: const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; ClassNameResolver* name_resolver_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldLiteGenerator); + Context* context_; }; } // namespace java diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/main.cc b/contrib/libs/protoc/src/google/protobuf/compiler/main.cc index 39609468ab6..3f3817e4637 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/main.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/main.cc @@ -28,25 +28,27 @@ // (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/cpp/generator.h> -#include <google/protobuf/compiler/java/generator.h> -#include <google/protobuf/compiler/java/kotlin_generator.h> -#include <google/protobuf/compiler/command_line_interface.h> -#include <google/protobuf/compiler/csharp/csharp_generator.h> -#include <google/protobuf/compiler/objectivec/objectivec_generator.h> -#include <google/protobuf/compiler/php/php_generator.h> -#include <google/protobuf/compiler/python/generator.h> -#include <google/protobuf/compiler/python/pyi_generator.h> -#include <google/protobuf/compiler/ruby/ruby_generator.h> +#include "y_absl/log/initialize.h" +#include "google/protobuf/compiler/command_line_interface.h" +#include "google/protobuf/compiler/cpp/generator.h" +#include "google/protobuf/compiler/csharp/csharp_generator.h" +#include "google/protobuf/compiler/java/generator.h" +#include "google/protobuf/compiler/java/kotlin_generator.h" +#include "google/protobuf/compiler/objectivec/generator.h" +#include "google/protobuf/compiler/php/php_generator.h" +#include "google/protobuf/compiler/python/generator.h" +#include "google/protobuf/compiler/python/pyi_generator.h" +#include "google/protobuf/compiler/ruby/ruby_generator.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { namespace compiler { int ProtobufMain(int argc, char* argv[]) { + y_absl::InitializeLog(); CommandLineInterface cli; cli.AllowPlugins("protoc-"); @@ -66,6 +68,10 @@ int ProtobufMain(int argc, char* argv[]) { cli.RegisterGenerator("--java_out", "--java_opt", &java_generator, "Generate Java source file."); +#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE + java_generator.set_opensource_runtime(true); +#endif + // Proto2 Kotlin java::KotlinGenerator kt_generator; cli.RegisterGenerator("--kotlin_out", "--kotlin_opt", &kt_generator, @@ -76,6 +82,11 @@ int ProtobufMain(int argc, char* argv[]) { python::Generator py_generator; cli.RegisterGenerator("--python_out", "--python_opt", &py_generator, "Generate Python source file."); + +#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE + py_generator.set_opensource_runtime(true); +#endif + // Python pyi python::PyiGenerator pyi_generator; cli.RegisterGenerator("--pyi_out", &pyi_generator, diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/enum.cc index 39c78295768..5b23792af44 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_enum.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/enum.cc @@ -28,23 +28,38 @@ // (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 <map> +#include "google/protobuf/compiler/objectivec/enum.h" + +#include <algorithm> +#include <limits> #include <string> -#include <google/protobuf/compiler/objectivec/objectivec_enum.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> -#include <algorithm> // std::find() +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/objectivec/helpers.h" +#include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/compiler/objectivec/text_format_decode_data.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { namespace objectivec { +namespace { +TProtoStringType SafelyPrintIntToCode(int v) { + if (v == std::numeric_limits<int>::min()) { + // Some compilers try to parse -2147483648 as two tokens and then get spicy + // about the fact that +2147483648 cannot be represented as an int. + return y_absl::StrCat(v + 1, " - 1"); + } else { + return y_absl::StrCat(v); + } +} +} // namespace EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) - : descriptor_(descriptor), - name_(EnumName(descriptor_)) { + : descriptor_(descriptor), name_(EnumName(descriptor_)) { // Track the names for the enum values, and if an alias overlaps a base // value, skip making a name for it. Likewise if two alias overlap, the // first one wins. @@ -54,7 +69,7 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) // compile error is just fine. // The values are still tracked to support the reflection apis and // TextFormat handing since they are different there. - std::set<TProtoStringType> value_names; + y_absl::flat_hash_set<TProtoStringType> value_names; for (int i = 0; i < descriptor_->value_count(); i++) { const EnumValueDescriptor* value = descriptor_->value(i); @@ -65,20 +80,15 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) base_values_.push_back(value); value_names.insert(EnumValueName(value)); } else { - TProtoStringType value_name(EnumValueName(value)); - if (value_names.find(value_name) != value_names.end()) { + if (!value_names.insert(EnumValueName(value)).second) { alias_values_to_skip_.insert(value); - } else { - value_names.insert(value_name); } } all_values_.push_back(value); } } -EnumGenerator::~EnumGenerator() {} - -void EnumGenerator::GenerateHeader(io::Printer* printer) { +void EnumGenerator::GenerateHeader(io::Printer* printer) const { TProtoStringType enum_comments; SourceLocation location; if (descriptor_->GetSourceLocation(&location)) { @@ -106,45 +116,49 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) { // doesn't have to bother with the `enum_extensibility` attribute, as the // default will be what is needed. - printer->Print("$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n", - "comments", enum_comments, - "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()), - "name", name_); + printer->Print( + "$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n", + "comments", enum_comments, "deprecated_attribute", + GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()), "name", + name_); printer->Indent(); - if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { + if (!descriptor_->is_closed()) { // Include the unknown value. printer->Print( - "/**\n" - " * Value used if any message's field encounters a value that is not defined\n" - " * by this enum. The message will also have C functions to get/set the rawValue\n" - " * of the field.\n" - " **/\n" - "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n", - "name", name_); + // clang-format off + "/**\n" + " * Value used if any message's field encounters a value that is not defined\n" + " * by this enum. The message will also have C functions to get/set the rawValue\n" + " * of the field.\n" + " **/\n" + "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n", + // clang-format on + "name", name_); } for (int i = 0; i < all_values_.size(); i++) { - if (alias_values_to_skip_.find(all_values_[i]) != alias_values_to_skip_.end()) { + if (alias_values_to_skip_.find(all_values_[i]) != + alias_values_to_skip_.end()) { continue; } if (all_values_[i]->GetSourceLocation(&location)) { - TProtoStringType comments = BuildCommentsString(location, true).c_str(); + TProtoStringType comments = BuildCommentsString(location, true); if (comments.length() > 0) { if (i > 0) { printer->Print("\n"); } - printer->Print(comments.c_str()); + printer->Print(comments); } } - printer->Print( - "$name$$deprecated_attribute$ = $value$,\n", - "name", EnumValueName(all_values_[i]), - "deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]), - "value", StrCat(all_values_[i]->number())); + printer->Print("$name$$deprecated_attribute$ = $value$,\n", "name", + EnumValueName(all_values_[i]), "deprecated_attribute", + GetOptionalDeprecatedAttribute(all_values_[i]), "value", + SafelyPrintIntToCode(all_values_[i]->number())); } printer->Outdent(); printer->Print( + // clang-format off "};\n" "\n" "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n" @@ -154,11 +168,12 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) { " * the time this source was generated.\n" " **/\n" "BOOL $name$_IsValidValue(arc_i32 value);\n" + // clang-format on "\n", "name", name_); } -void EnumGenerator::GenerateSource(io::Printer* printer) { +void EnumGenerator::GenerateSource(io::Printer* printer) const { printer->Print( "#pragma mark - Enum $name$\n" "\n", @@ -184,38 +199,47 @@ void EnumGenerator::GenerateSource(io::Printer* printer) { } printer->Print( + // clang-format off "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n" " static _Atomic(GPBEnumDescriptor*) descriptor = nil;\n" - " if (!descriptor) {\n", + " if (!descriptor) {\n" + " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n", + // clang-format on "name", name_); static const int kBytesPerLine = 40; // allow for escaping - printer->Print( - " static const char *valueNames ="); + printer->Print(" static const char *valueNames ="); for (int i = 0; i < text_blob.size(); i += kBytesPerLine) { printer->Print( - "\n \"$data$\"", - "data", EscapeTrigraphs(CEscape(text_blob.substr(i, kBytesPerLine)))); + "\n \"$data$\"", "data", + EscapeTrigraphs(y_absl::CEscape(text_blob.substr(i, kBytesPerLine)))); } printer->Print( ";\n" " static const arc_i32 values[] = {\n"); for (int i = 0; i < all_values_.size(); i++) { - printer->Print(" $name$,\n", "name", EnumValueName(all_values_[i])); + printer->Print(" $name$,\n", "name", EnumValueName(all_values_[i])); } printer->Print(" };\n"); if (text_format_decode_data.num_entries() == 0) { printer->Print( + // clang-format off " GPBEnumDescriptor *worker =\n" " [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n" " valueNames:valueNames\n" " values:values\n" " count:(arc_ui32)(sizeof(values) / sizeof(arc_i32))\n" - " enumVerifier:$name$_IsValidValue];\n", - "name", name_); - } else { - printer->Print( + " enumVerifier:$name$_IsValidValue\n" + " flags:$flags$];\n", + // clang-format on + "name", name_, "flags", + (descriptor_->is_closed() + ? "GPBEnumDescriptorInitializationFlag_IsClosed" + : "GPBEnumDescriptorInitializationFlag_None")); + } else { + printer->Print( + // clang-format off " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n" " GPBEnumDescriptor *worker =\n" " [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n" @@ -223,36 +247,46 @@ void EnumGenerator::GenerateSource(io::Printer* printer) { " values:values\n" " count:(arc_ui32)(sizeof(values) / sizeof(arc_i32))\n" " enumVerifier:$name$_IsValidValue\n" + " flags:$flags$\n" " extraTextFormatInfo:extraTextFormatInfo];\n", - "name", name_, - "extraTextFormatInfo", CEscape(text_format_decode_data.Data())); - } - printer->Print( - " GPBEnumDescriptor *expected = nil;\n" - " if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {\n" - " [worker release];\n" - " }\n" - " }\n" - " return descriptor;\n" - "}\n\n"); + // clang-format on + "name", name_, "flags", + (descriptor_->is_closed() + ? "GPBEnumDescriptorInitializationFlag_IsClosed" + : "GPBEnumDescriptorInitializationFlag_None"), + "extraTextFormatInfo", y_absl::CEscape(text_format_decode_data.Data())); + } + // clang-format off + printer->Print( + " GPBEnumDescriptor *expected = nil;\n" + " if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {\n" + " [worker release];\n" + " }\n" + " }\n" + " return descriptor;\n" + "}\n\n"); + // clang-format on printer->Print( + // clang-format off "BOOL $name$_IsValidValue(arc_i32 value__) {\n" " switch (value__) {\n", + // clang-format on "name", name_); for (int i = 0; i < base_values_.size(); i++) { - printer->Print( - " case $name$:\n", - "name", EnumValueName(base_values_[i])); + printer->Print(" case $name$:\n", "name", + EnumValueName(base_values_[i])); } + // clang-format off printer->Print( " return YES;\n" " default:\n" " return NO;\n" " }\n" "}\n\n"); + // clang-format on } } // namespace objectivec } // namespace compiler diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/enum.h index 4d0404bcb32..962620febaf 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_enum.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/enum.h @@ -32,10 +32,11 @@ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__ #include <string> -#include <set> #include <vector> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/io/printer.h> + +#include "y_absl/container/flat_hash_set.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -45,13 +46,13 @@ namespace objectivec { class EnumGenerator { public: explicit EnumGenerator(const EnumDescriptor* descriptor); - ~EnumGenerator(); + ~EnumGenerator() = default; EnumGenerator(const EnumGenerator&) = delete; EnumGenerator& operator=(const EnumGenerator&) = delete; - void GenerateHeader(io::Printer* printer); - void GenerateSource(io::Printer* printer); + void GenerateHeader(io::Printer* printer) const; + void GenerateSource(io::Printer* printer) const; const TProtoStringType& name() const { return name_; } @@ -59,7 +60,7 @@ class EnumGenerator { const EnumDescriptor* descriptor_; std::vector<const EnumValueDescriptor*> base_values_; std::vector<const EnumValueDescriptor*> all_values_; - std::set<const EnumValueDescriptor*> alias_values_to_skip_; + y_absl::flat_hash_set<const EnumValueDescriptor*> alias_values_to_skip_; const TProtoStringType name_; }; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/enum_field.cc index bcecc7b3730..c470c241581 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/enum_field.cc @@ -28,12 +28,14 @@ // (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 <map> +#include "google/protobuf/compiler/objectivec/enum_field.h" + #include <string> -#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/io/printer.h> +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/objectivec/helpers.h" +#include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -42,22 +44,24 @@ namespace objectivec { namespace { -void SetEnumVariables(const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables) { - TProtoStringType type = EnumName(descriptor->enum_type()); +void SetEnumVariables( + const FieldDescriptor* descriptor, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { + const TProtoStringType type = EnumName(descriptor->enum_type()); + const TProtoStringType enum_desc_func = y_absl::StrCat(type, "_EnumDescriptor"); (*variables)["storage_type"] = type; // For non repeated fields, if it was defined in a different file, the // property decls need to use "enum NAME" rather than just "NAME" to support // the forward declaration of the enums. if (!descriptor->is_repeated() && (descriptor->file() != descriptor->enum_type()->file())) { - (*variables)["property_type"] = "enum " + type; + (*variables)["property_type"] = y_absl::StrCat("enum ", type); } - (*variables)["enum_verifier"] = type + "_IsValidValue"; - (*variables)["enum_desc_func"] = type + "_EnumDescriptor"; + (*variables)["enum_verifier"] = y_absl::StrCat(type, "_IsValidValue"); + (*variables)["enum_desc_func"] = enum_desc_func; (*variables)["dataTypeSpecific_name"] = "enumDescFunc"; - (*variables)["dataTypeSpecific_value"] = (*variables)["enum_desc_func"]; + (*variables)["dataTypeSpecific_value"] = enum_desc_func; const Descriptor* msg_descriptor = descriptor->containing_type(); (*variables)["owning_message_class"] = ClassName(msg_descriptor); @@ -69,14 +73,13 @@ EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor) SetEnumVariables(descriptor, &variables_); } -EnumFieldGenerator::~EnumFieldGenerator() {} - void EnumFieldGenerator::GenerateCFunctionDeclarations( io::Printer* printer) const { - if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { + if (descriptor_->enum_type()->is_closed()) { return; } + // clang-format off printer->Print( variables_, "/**\n" @@ -91,12 +94,16 @@ void EnumFieldGenerator::GenerateCFunctionDeclarations( " **/\n" "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, arc_i32 value);\n" "\n"); + // clang-format on } void EnumFieldGenerator::GenerateCFunctionImplementations( io::Printer* printer) const { - if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return; + if (descriptor_->enum_type()->is_closed()) { + return; + } + // clang-format off printer->Print( variables_, "arc_i32 $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n" @@ -111,13 +118,14 @@ void EnumFieldGenerator::GenerateCFunctionImplementations( " GPBSetMessageRawEnumField(message, field, value);\n" "}\n" "\n"); + // clang-format on } void EnumFieldGenerator::DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, + y_absl::btree_set<TProtoStringType>* fwd_decls, bool include_external_types) const { - SingleFieldGenerator::DetermineForwardDeclarations( - fwd_decls, include_external_types); + SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls, + include_external_types); // If it is an enum defined in a different file (and not a WKT), then we'll // need a forward declaration for it. When it is in our file, all the enums // are output before the message, so it will be declared before it is needed. @@ -126,7 +134,7 @@ void EnumFieldGenerator::DetermineForwardDeclarations( !IsProtobufLibraryBundledProtoFile(descriptor_->enum_type()->file())) { // Enum name is already in "storage_type". const TProtoStringType& name = variable("storage_type"); - fwd_decls->insert("GPB_ENUM_FWD_DECLARE(" + name + ")"); + fwd_decls->insert(y_absl::StrCat("GPB_ENUM_FWD_DECLARE(", name, ");")); } } @@ -137,14 +145,18 @@ RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( variables_["array_storage_type"] = "GPBEnumArray"; } -RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} - -void RepeatedEnumFieldGenerator::FinishInitialization(void) { +void RepeatedEnumFieldGenerator::FinishInitialization() { RepeatedFieldGenerator::FinishInitialization(); + TProtoStringType name = variables_["name"]; + TProtoStringType storage_type = variables_["storage_type"]; variables_["array_comment"] = - "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n"; + y_absl::StrCat("// |", name, "| contains |", storage_type, "|\n"); } +// NOTE: RepeatedEnumFieldGenerator::DetermineForwardDeclarations isn't needed +// because `GPBEnumArray` isn't generic (like `NSArray` would be for messages) +// and thus doesn't reference the type in the header. + } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/enum_field.h index fea75f7a848..3220df10464 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/enum_field.h @@ -31,9 +31,10 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__ -#include <map> #include <string> -#include <google/protobuf/compiler/objectivec/objectivec_field.h> + +#include "y_absl/container/btree_set.h" +#include "google/protobuf/compiler/objectivec/field.h" namespace google { namespace protobuf { @@ -47,28 +48,25 @@ class EnumFieldGenerator : public SingleFieldGenerator { EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete; public: - virtual void GenerateCFunctionDeclarations( - io::Printer* printer) const override; - virtual void GenerateCFunctionImplementations( - io::Printer* printer) const override; - virtual void DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, - bool include_external_types) const override; + void GenerateCFunctionDeclarations(io::Printer* printer) const override; + void GenerateCFunctionImplementations(io::Printer* printer) const override; + void DetermineForwardDeclarations(y_absl::btree_set<TProtoStringType>* fwd_decls, + bool include_external_types) const override; protected: explicit EnumFieldGenerator(const FieldDescriptor* descriptor); - virtual ~EnumFieldGenerator(); + ~EnumFieldGenerator() override = default; }; class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator { friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); public: - virtual void FinishInitialization() override; + void FinishInitialization() override; protected: explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor); - virtual ~RepeatedEnumFieldGenerator(); + ~RepeatedEnumFieldGenerator() override = default; }; } // namespace objectivec diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/extension.cc index dbbce48952b..4da745c9f69 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/extension.cc @@ -28,38 +28,39 @@ // (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/objectivec/extension.h" + #include <iostream> +#include <ostream> +#include <string> +#include <vector> -#include <google/protobuf/compiler/objectivec/objectivec_extension.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/io/printer.h> +#include "y_absl/container/btree_set.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/objectivec/helpers.h" +#include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { namespace objectivec { -ExtensionGenerator::ExtensionGenerator(const TProtoStringType& root_class_name, +ExtensionGenerator::ExtensionGenerator(y_absl::string_view root_class_name, const FieldDescriptor* descriptor) : method_name_(ExtensionMethodName(descriptor)), - root_class_and_method_name_(root_class_name + "_" + method_name_), + root_class_and_method_name_( + y_absl::StrCat(root_class_name, "_", method_name_)), descriptor_(descriptor) { - if (descriptor->is_map()) { - // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some - // error cases, so it seems to be ok to use as a back door for errors. - std::cerr << "error: Extension is a map<>!" - << " That used to be blocked by the compiler." << std::endl; - std::cerr.flush(); - abort(); - } + Y_ABSL_CHECK(!descriptor->is_map()) + << "error: Extension is a map<>!" + << " That used to be blocked by the compiler."; } -ExtensionGenerator::~ExtensionGenerator() {} - -void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { - std::map<TProtoStringType, TProtoStringType> vars; +void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) const { + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["method_name"] = method_name_; if (IsRetainedName(method_name_)) { vars["storage_attribute"] = " NS_RETURNS_NOT_RETAINED"; @@ -74,19 +75,23 @@ void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { } // Unlike normal message fields, check if the file for the extension was // deprecated. - vars["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()); - printer->Print(vars, - "$comments$" - "+ (GPBExtensionDescriptor *)$method_name$$storage_attribute$$deprecated_attribute$;\n"); + vars["deprecated_attribute"] = + GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()); + // clang-format off + printer->Print( + vars, + "$comments$" + "+ (GPBExtensionDescriptor *)$method_name$$storage_attribute$$deprecated_attribute$;\n"); + // clang-format on } void ExtensionGenerator::GenerateStaticVariablesInitialization( - io::Printer* printer) { - std::map<TProtoStringType, TProtoStringType> vars; + io::Printer* printer) const { + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; vars["root_class_and_method_name"] = root_class_and_method_name_; const TProtoStringType containing_type = ClassName(descriptor_->containing_type()); vars["extended_type"] = ObjCClass(containing_type); - vars["number"] = StrCat(descriptor_->number()); + vars["number"] = y_absl::StrCat(descriptor_->number()); std::vector<TProtoStringType> options; if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated"); @@ -111,30 +116,33 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( vars["default"] = DefaultValue(descriptor_); } TProtoStringType type = GetCapitalizedType(descriptor_); - vars["extension_type"] = TProtoStringType("GPBDataType") + type; + vars["extension_type"] = y_absl::StrCat("GPBDataType", type); if (objc_type == OBJECTIVECTYPE_ENUM) { vars["enum_desc_func_name"] = - EnumName(descriptor_->enum_type()) + "_EnumDescriptor"; + y_absl::StrCat(EnumName(descriptor_->enum_type()), "_EnumDescriptor"); } else { vars["enum_desc_func_name"] = "NULL"; } - printer->Print(vars, - "{\n" - " .defaultValue.$default_name$ = $default$,\n" - " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n" - " .extendedClass.clazz = $extended_type$,\n" - " .messageOrGroupClass.clazz = $type$,\n" - " .enumDescriptorFunc = $enum_desc_func_name$,\n" - " .fieldNumber = $number$,\n" - " .dataType = $extension_type$,\n" - " .options = $options$,\n" - "},\n"); + // clang-format off + printer->Print( + vars, + "{\n" + " .defaultValue.$default_name$ = $default$,\n" + " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n" + " .extendedClass.clazz = $extended_type$,\n" + " .messageOrGroupClass.clazz = $type$,\n" + " .enumDescriptorFunc = $enum_desc_func_name$,\n" + " .fieldNumber = $number$,\n" + " .dataType = $extension_type$,\n" + " .options = $options$,\n" + "},\n"); + // clang-format on } void ExtensionGenerator::DetermineObjectiveCClassDefinitions( - std::set<TProtoStringType>* fwd_decls) { + y_absl::btree_set<TProtoStringType>* fwd_decls) const { TProtoStringType extended_type = ClassName(descriptor_->containing_type()); fwd_decls->insert(ObjCClassDeclaration(extended_type)); ObjectiveCType objc_type = GetObjectiveCType(descriptor_); @@ -144,10 +152,13 @@ void ExtensionGenerator::DetermineObjectiveCClassDefinitions( } } -void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) { +void ExtensionGenerator::GenerateRegistrationSource( + io::Printer* printer) const { + // clang-format off printer->Print( "[registry addExtension:$root_class_and_method_name$];\n", "root_class_and_method_name", root_class_and_method_name_); + // clang-format on } } // namespace objectivec diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/extension.h index 04e59f9284b..1f81d82e745 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_extension.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/extension.h @@ -31,8 +31,11 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__ -#include <google/protobuf/descriptor.h> -#include <google/protobuf/io/printer.h> +#include <string> + +#include "y_absl/container/btree_set.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -41,17 +44,18 @@ namespace objectivec { class ExtensionGenerator { public: - ExtensionGenerator(const TProtoStringType& root_class_name, + ExtensionGenerator(y_absl::string_view root_class_name, const FieldDescriptor* descriptor); - ~ExtensionGenerator(); + ~ExtensionGenerator() = default; ExtensionGenerator(const ExtensionGenerator&) = delete; ExtensionGenerator& operator=(const ExtensionGenerator&) = delete; - void GenerateMembersHeader(io::Printer* printer); - void GenerateStaticVariablesInitialization(io::Printer* printer); - void GenerateRegistrationSource(io::Printer* printer); - void DetermineObjectiveCClassDefinitions(std::set<TProtoStringType>* fwd_decls); + void GenerateMembersHeader(io::Printer* printer) const; + void GenerateStaticVariablesInitialization(io::Printer* printer) const; + void GenerateRegistrationSource(io::Printer* printer) const; + void DetermineObjectiveCClassDefinitions( + y_absl::btree_set<TProtoStringType>* fwd_decls) const; private: TProtoStringType method_name_; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/field.cc index e73a664db1a..e72185e7949 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/field.cc @@ -28,16 +28,24 @@ // (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 <iostream> +#include "google/protobuf/compiler/objectivec/field.h" -#include <google/protobuf/compiler/objectivec/objectivec_field.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h> -#include <google/protobuf/compiler/objectivec/objectivec_map_field.h> -#include <google/protobuf/compiler/objectivec/objectivec_message_field.h> -#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> +#include <iostream> +#include <ostream> +#include <string> +#include <vector> + +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/objectivec/enum_field.h" +#include "google/protobuf/compiler/objectivec/helpers.h" +#include "google/protobuf/compiler/objectivec/map_field.h" +#include "google/protobuf/compiler/objectivec/message_field.h" +#include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/compiler/objectivec/primitive_field.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -46,8 +54,9 @@ namespace objectivec { namespace { -void SetCommonFieldVariables(const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetCommonFieldVariables( + const FieldDescriptor* descriptor, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { TProtoStringType camel_case_name = FieldName(descriptor); TProtoStringType raw_field_name; if (descriptor->type() == FieldDescriptor::TYPE_GROUP) { @@ -73,10 +82,11 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["capitalized_name"] = capitalized_name; (*variables)["raw_field_name"] = raw_field_name; (*variables)["field_number_name"] = - classname + "_FieldNumber_" + capitalized_name; - (*variables)["field_number"] = StrCat(descriptor->number()); + y_absl::StrCat(classname, "_FieldNumber_", capitalized_name); + (*variables)["field_number"] = y_absl::StrCat(descriptor->number()); (*variables)["field_type"] = GetCapitalizedType(descriptor); - (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor); + (*variables)["deprecated_attribute"] = + GetOptionalDeprecatedAttribute(descriptor); std::vector<TProtoStringType> field_flags; if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated"); if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired"); @@ -89,6 +99,9 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom"); if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { field_flags.push_back("GPBFieldHasEnumDescriptor"); + if (descriptor->enum_type()->is_closed()) { + field_flags.push_back("GPBFieldClosedEnum"); + } } // It will clear on a zero value if... // - not repeated/map @@ -107,18 +120,63 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["dataTypeSpecific_name"] = "clazz"; (*variables)["dataTypeSpecific_value"] = "Nil"; - (*variables)["storage_offset_value"] = - "(arc_ui32)offsetof(" + classname + "__storage_, " + camel_case_name + ")"; + (*variables)["storage_offset_value"] = y_absl::StrCat( + "(arc_ui32)offsetof(", classname, "__storage_, ", camel_case_name, ")"); (*variables)["storage_offset_comment"] = ""; // Clear some common things so they can be set just when needed. (*variables)["storage_attribute"] = ""; } +bool HasNonZeroDefaultValue(const FieldDescriptor* field) { + // Repeated fields don't have defaults. + if (field->is_repeated()) { + return false; + } + + // As much as checking field->has_default_value() seems useful, it isn't + // because of enums. proto2 syntax allows the first item in an enum (the + // default) to be non zero. So checking field->has_default_value() would + // result in missing this non zero default. See MessageWithOneBasedEnum in + // objectivec/Tests/unittest_objc.proto for a test Message to confirm this. + + // Some proto file set the default to the zero value, so make sure the value + // isn't the zero case. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return field->default_value_int32() != 0; + case FieldDescriptor::CPPTYPE_UINT32: + return field->default_value_uint32() != 0U; + case FieldDescriptor::CPPTYPE_INT64: + return field->default_value_int64() != 0LL; + case FieldDescriptor::CPPTYPE_UINT64: + return field->default_value_uint64() != 0ULL; + case FieldDescriptor::CPPTYPE_DOUBLE: + return field->default_value_double() != 0.0; + case FieldDescriptor::CPPTYPE_FLOAT: + return field->default_value_float() != 0.0f; + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool(); + case FieldDescriptor::CPPTYPE_STRING: { + const TProtoStringType& default_string = field->default_value_string(); + return default_string.length() != 0; + } + case FieldDescriptor::CPPTYPE_ENUM: + return field->default_value_enum()->number() != 0; + case FieldDescriptor::CPPTYPE_MESSAGE: + return false; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + Y_ABSL_LOG(FATAL) << "Can't get here."; + return false; +} + } // namespace FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { - FieldGenerator* result = NULL; + FieldGenerator* result = nullptr; if (field->is_repeated()) { switch (GetObjectiveCType(field)) { case OBJECTIVECTYPE_MESSAGE: { @@ -163,16 +221,11 @@ FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor) SetCommonFieldVariables(descriptor, &variables_); } -FieldGenerator::~FieldGenerator() {} - void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const { - printer->Print( - variables_, - "$field_number_name$ = $field_number$,\n"); + printer->Print(variables_, "$field_number_name$ = $field_number$,\n"); } -void FieldGenerator::GenerateCFunctionDeclarations( - io::Printer* printer) const { +void FieldGenerator::GenerateCFunctionDeclarations(io::Printer* printer) const { // Nothing } @@ -182,20 +235,21 @@ void FieldGenerator::GenerateCFunctionImplementations( } void FieldGenerator::DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, + y_absl::btree_set<TProtoStringType>* fwd_decls, bool include_external_types) const { // Nothing } void FieldGenerator::DetermineObjectiveCClassDefinitions( - std::set<TProtoStringType>* fwd_decls) const { + y_absl::btree_set<TProtoStringType>* fwd_decls) const { // Nothing } -void FieldGenerator::GenerateFieldDescription( - io::Printer* printer, bool include_default) const { +void FieldGenerator::GenerateFieldDescription(io::Printer* printer, + bool include_default) const { // Printed in the same order as the structure decl. if (include_default) { + // clang-format off printer->Print( variables_, "{\n" @@ -208,7 +262,9 @@ void FieldGenerator::GenerateFieldDescription( " .core.flags = $fieldflags$,\n" " .core.dataType = GPBDataType$field_type$,\n" "},\n"); + // clang-format on } else { + // clang-format off printer->Print( variables_, "{\n" @@ -220,43 +276,37 @@ void FieldGenerator::GenerateFieldDescription( " .flags = $fieldflags$,\n" " .dataType = GPBDataType$field_type$,\n" "},\n"); + // clang-format on } } void FieldGenerator::SetRuntimeHasBit(int has_index) { - variables_["has_index"] = StrCat(has_index); + variables_["has_index"] = y_absl::StrCat(has_index); } -void FieldGenerator::SetNoHasBit(void) { - variables_["has_index"] = "GPBNoHasBit"; -} +void FieldGenerator::SetNoHasBit() { variables_["has_index"] = "GPBNoHasBit"; } -int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const { - return 0; -} +int FieldGenerator::ExtraRuntimeHasBitsNeeded() const { return 0; } void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) { - // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some - // error cases, so it seems to be ok to use as a back door for errors. - std::cerr << "Error: should have overridden SetExtraRuntimeHasBitsBase()." << std::endl; - std::cerr.flush(); - abort(); + Y_ABSL_LOG(FATAL) + << "Error: should have overridden SetExtraRuntimeHasBitsBase()."; } void FieldGenerator::SetOneofIndexBase(int index_base) { const OneofDescriptor* oneof = descriptor_->real_containing_oneof(); - if (oneof != NULL) { + if (oneof != nullptr) { int index = oneof->index() + index_base; // Flip the sign to mark it as a oneof. - variables_["has_index"] = StrCat(-index); + variables_["has_index"] = y_absl::StrCat(-index); } } -bool FieldGenerator::WantsHasProperty(void) const { +bool FieldGenerator::WantsHasProperty() const { return descriptor_->has_presence() && !descriptor_->real_containing_oneof(); } -void FieldGenerator::FinishInitialization(void) { +void FieldGenerator::FinishInitialization() { // If "property_type" wasn't set, make it "storage_type". if ((variables_.find("property_type") == variables_.end()) && (variables_.find("storage_type") != variables_.end())) { @@ -269,8 +319,6 @@ SingleFieldGenerator::SingleFieldGenerator(const FieldDescriptor* descriptor) // Nothing } -SingleFieldGenerator::~SingleFieldGenerator() {} - void SingleFieldGenerator::GenerateFieldStorageDeclaration( io::Printer* printer) const { printer->Print(variables_, "$storage_type$ $name$;\n"); @@ -279,15 +327,19 @@ void SingleFieldGenerator::GenerateFieldStorageDeclaration( void SingleFieldGenerator::GeneratePropertyDeclaration( io::Printer* printer) const { printer->Print(variables_, "$comments$"); + // clang-format off printer->Print( variables_, - "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n" - "\n"); + "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"); + // clang-format on if (WantsHasProperty()) { + // clang-format off printer->Print( variables_, "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n"); + // clang-format on } + printer->Print("\n"); } void SingleFieldGenerator::GeneratePropertyImplementation( @@ -299,7 +351,7 @@ void SingleFieldGenerator::GeneratePropertyImplementation( } } -bool SingleFieldGenerator::RuntimeUsesHasBit(void) const { +bool SingleFieldGenerator::RuntimeUsesHasBit() const { if (descriptor_->real_containing_oneof()) { // The oneof tracks what is set instead. return false; @@ -315,8 +367,6 @@ ObjCObjFieldGenerator::ObjCObjFieldGenerator(const FieldDescriptor* descriptor) } } -ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {} - void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration( io::Printer* printer) const { printer->Print(variables_, "$storage_type$ *$name$;\n"); @@ -324,26 +374,30 @@ void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration( void ObjCObjFieldGenerator::GeneratePropertyDeclaration( io::Printer* printer) const { - // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that - // it uses pointers and deals with Objective C's rules around storage name + // it uses pointers and deals with Objective-C's rules around storage name // conventions (init*, new*, etc.) printer->Print(variables_, "$comments$"); + // clang-format off printer->Print( variables_, "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"); + // clang-format on if (WantsHasProperty()) { + // clang-format off printer->Print( variables_, "/** Test to see if @c $name$ has been set. */\n" "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n"); + // clang-format on } if (IsInitName(variables_.find("name")->second)) { // If property name starts with init we need to annotate it to get past ARC. // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 printer->Print(variables_, - "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n"); + "- ($property_type$ *)$name$ " + "GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n"); } printer->Print("\n"); } @@ -355,9 +409,7 @@ RepeatedFieldGenerator::RepeatedFieldGenerator( variables_["array_comment"] = ""; } -RepeatedFieldGenerator::~RepeatedFieldGenerator() {} - -void RepeatedFieldGenerator::FinishInitialization(void) { +void RepeatedFieldGenerator::FinishInitialization() { FieldGenerator::FinishInitialization(); if (variables_.find("array_property_type") == variables_.end()) { variables_["array_property_type"] = variable("array_storage_type"); @@ -376,30 +428,33 @@ void RepeatedFieldGenerator::GeneratePropertyImplementation( void RepeatedFieldGenerator::GeneratePropertyDeclaration( io::Printer* printer) const { - // Repeated fields don't need the has* properties, but they do expose a // *Count (to check without autocreation). So for the field property we need // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for - // dealing with needing Objective C's rules around storage name conventions + // dealing with needing Objective-C's rules around storage name conventions // (init*, new*, etc.) + // clang-format off printer->Print( variables_, "$comments$" "$array_comment$" "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n" - "/** The number of items in @c $name$ without causing the array to be created. */\n" + "/** The number of items in @c $name$ without causing the container to be created. */\n" "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n"); + // clang-format on if (IsInitName(variables_.find("name")->second)) { // If property name starts with init we need to annotate it to get past ARC. // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 + // clang-format off printer->Print(variables_, "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n"); + // clang-format on } printer->Print("\n"); } -bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const { +bool RepeatedFieldGenerator::RuntimeUsesHasBit() const { return false; // The array (or map/dict) having anything is what is used. } @@ -409,8 +464,7 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) extension_generators_(descriptor->extension_count()) { // Construct all the FieldGenerators. for (int i = 0; i < descriptor->field_count(); i++) { - field_generators_[i].reset( - FieldGenerator::Make(descriptor->field(i))); + field_generators_[i].reset(FieldGenerator::Make(descriptor->field(i))); } for (int i = 0; i < descriptor->extension_count(); i++) { extension_generators_[i].reset( @@ -418,11 +472,9 @@ FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) } } -FieldGeneratorMap::~FieldGeneratorMap() {} - const FieldGenerator& FieldGeneratorMap::get( const FieldDescriptor* field) const { - GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); + Y_ABSL_CHECK_EQ(field->containing_type(), descriptor_); return *field_generators_[field->index()]; } @@ -430,7 +482,7 @@ const FieldGenerator& FieldGeneratorMap::get_extension(int index) const { return *extension_generators_[index]; } -int FieldGeneratorMap::CalculateHasBits(void) { +int FieldGeneratorMap::CalculateHasBits() { int total_bits = 0; for (int i = 0; i < descriptor_->field_count(); i++) { if (field_generators_[i]->RuntimeUsesHasBit()) { @@ -454,7 +506,7 @@ void FieldGeneratorMap::SetOneofIndexBase(int index_base) { } } -bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const { +bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault() const { for (int i = 0; i < descriptor_->field_count(); i++) { if (HasNonZeroDefaultValue(descriptor_->field(i))) { return true; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/field.h index 3e968946fa2..04500651331 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/field.h @@ -31,10 +31,15 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__ -#include <map> +#include <memory> #include <string> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/io/printer.h> +#include <vector> + +#include "y_absl/container/btree_set.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/match.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -45,7 +50,7 @@ class FieldGenerator { public: static FieldGenerator* Make(const FieldDescriptor* field); - virtual ~FieldGenerator(); + virtual ~FieldGenerator() = default; FieldGenerator(const FieldGenerator&) = delete; FieldGenerator& operator=(const FieldGenerator&) = delete; @@ -64,21 +69,21 @@ class FieldGenerator { // Exposed for subclasses, should always call it on the parent class also. virtual void DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, + y_absl::btree_set<TProtoStringType>* fwd_decls, bool include_external_types) const; virtual void DetermineObjectiveCClassDefinitions( - std::set<TProtoStringType>* fwd_decls) const; + y_absl::btree_set<TProtoStringType>* fwd_decls) const; // Used during generation, not intended to be extended by subclasses. - void GenerateFieldDescription( - io::Printer* printer, bool include_default) const; + void GenerateFieldDescription(io::Printer* printer, + bool include_default) const; void GenerateFieldNumberConstant(io::Printer* printer) const; // Exposed to get and set the has bits information. - virtual bool RuntimeUsesHasBit(void) const = 0; + virtual bool RuntimeUsesHasBit() const = 0; void SetRuntimeHasBit(int has_index); - void SetNoHasBit(void); - virtual int ExtraRuntimeHasBitsNeeded(void) const; + void SetNoHasBit(); + virtual int ExtraRuntimeHasBitsNeeded() const; virtual void SetExtraRuntimeHasBitsBase(int index_base); void SetOneofIndexBase(int index_base); @@ -88,8 +93,7 @@ class FieldGenerator { bool needs_textformat_name_support() const { const TProtoStringType& field_flags = variable("fieldflags"); - return field_flags.find("GPBFieldTextFormatNameCustom") != - TProtoStringType::npos; + return y_absl::StrContains(field_flags, "GPBFieldTextFormatNameCustom"); } TProtoStringType generated_objc_name() const { return variable("name"); } TProtoStringType raw_field_name() const { return variable("raw_field_name"); } @@ -97,26 +101,26 @@ class FieldGenerator { protected: explicit FieldGenerator(const FieldDescriptor* descriptor); - virtual void FinishInitialization(void); - bool WantsHasProperty(void) const; + virtual void FinishInitialization(); + bool WantsHasProperty() const; const FieldDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; }; class SingleFieldGenerator : public FieldGenerator { public: - virtual ~SingleFieldGenerator(); + ~SingleFieldGenerator() override = default; SingleFieldGenerator(const SingleFieldGenerator&) = delete; SingleFieldGenerator& operator=(const SingleFieldGenerator&) = delete; - virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override; - virtual void GeneratePropertyDeclaration(io::Printer* printer) const override; + void GenerateFieldStorageDeclaration(io::Printer* printer) const override; + void GeneratePropertyDeclaration(io::Printer* printer) const override; - virtual void GeneratePropertyImplementation(io::Printer* printer) const override; + void GeneratePropertyImplementation(io::Printer* printer) const override; - virtual bool RuntimeUsesHasBit(void) const override; + bool RuntimeUsesHasBit() const override; protected: explicit SingleFieldGenerator(const FieldDescriptor* descriptor); @@ -125,13 +129,13 @@ class SingleFieldGenerator : public FieldGenerator { // Subclass with common support for when the field ends up as an ObjC Object. class ObjCObjFieldGenerator : public SingleFieldGenerator { public: - virtual ~ObjCObjFieldGenerator(); + ~ObjCObjFieldGenerator() override = default; ObjCObjFieldGenerator(const ObjCObjFieldGenerator&) = delete; ObjCObjFieldGenerator& operator=(const ObjCObjFieldGenerator&) = delete; - virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override; - virtual void GeneratePropertyDeclaration(io::Printer* printer) const override; + void GenerateFieldStorageDeclaration(io::Printer* printer) const override; + void GeneratePropertyDeclaration(io::Printer* printer) const override; protected: explicit ObjCObjFieldGenerator(const FieldDescriptor* descriptor); @@ -139,28 +143,28 @@ class ObjCObjFieldGenerator : public SingleFieldGenerator { class RepeatedFieldGenerator : public ObjCObjFieldGenerator { public: - virtual ~RepeatedFieldGenerator(); + ~RepeatedFieldGenerator() override = default; RepeatedFieldGenerator(const RepeatedFieldGenerator&) = delete; RepeatedFieldGenerator& operator=(const RepeatedFieldGenerator&) = delete; - virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override; - virtual void GeneratePropertyDeclaration(io::Printer* printer) const override; + void GenerateFieldStorageDeclaration(io::Printer* printer) const override; + void GeneratePropertyDeclaration(io::Printer* printer) const override; - virtual void GeneratePropertyImplementation(io::Printer* printer) const override; + void GeneratePropertyImplementation(io::Printer* printer) const override; - virtual bool RuntimeUsesHasBit(void) const override; + bool RuntimeUsesHasBit() const override; protected: explicit RepeatedFieldGenerator(const FieldDescriptor* descriptor); - virtual void FinishInitialization(void) override; + void FinishInitialization() override; }; // Convenience class which constructs FieldGenerators for a Descriptor. class FieldGeneratorMap { public: explicit FieldGeneratorMap(const Descriptor* descriptor); - ~FieldGeneratorMap(); + ~FieldGeneratorMap() = default; FieldGeneratorMap(const FieldGeneratorMap&) = delete; FieldGeneratorMap& operator=(const FieldGeneratorMap&) = delete; @@ -169,12 +173,12 @@ class FieldGeneratorMap { const FieldGenerator& get_extension(int index) const; // Assigns the has bits and returns the number of bits needed. - int CalculateHasBits(void); + int CalculateHasBits(); void SetOneofIndexBase(int index_base); // Check if any field of this message has a non zero default. - bool DoesAnyFieldHaveNonZeroDefault(void) const; + bool DoesAnyFieldHaveNonZeroDefault() const; private: const Descriptor* descriptor_; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/file.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/file.cc new file mode 100644 index 00000000000..06be7c9ceca --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/file.cc @@ -0,0 +1,736 @@ +// 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/objectivec/file.h" + +#include <algorithm> +#include <functional> +#include <iostream> +#include <iterator> +#include <memory> +#include <sstream> +#include <string> +#include <vector> + +#include "y_absl/container/btree_set.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_join.h" +#include "google/protobuf/compiler/objectivec/enum.h" +#include "google/protobuf/compiler/objectivec/extension.h" +#include "google/protobuf/compiler/objectivec/import_writer.h" +#include "google/protobuf/compiler/objectivec/message.h" +#include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" + +// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some +// error cases, so it seems to be ok to use as a back door for errors. + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +// This is also found in GPBBootstrap.h, and needs to be kept in sync. +const arc_i32 GOOGLE_PROTOBUF_OBJC_VERSION = 30007; + +const char* kHeaderExtension = ".pbobjc.h"; + +// Checks if a message contains any extension definitions (on the message or +// a nested message under it). +bool MessageContainsExtensions(const Descriptor* message) { + if (message->extension_count() > 0) { + return true; + } + for (int i = 0; i < message->nested_type_count(); i++) { + if (MessageContainsExtensions(message->nested_type(i))) { + return true; + } + } + return false; +} + +// Checks if the file contains any extensions definitions (at the root or +// nested under a message). +bool FileContainsExtensions(const FileDescriptor* file) { + if (file->extension_count() > 0) { + return true; + } + for (int i = 0; i < file->message_type_count(); i++) { + if (MessageContainsExtensions(file->message_type(i))) { + return true; + } + } + return false; +} + +bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) { + for (int i = 0; i < file->dependency_count(); i++) { + if (dep == file->dependency(i)) { + return true; + } + } + return false; +} + +struct FileDescriptorsOrderedByName { + inline bool operator()(const FileDescriptor* a, + const FileDescriptor* b) const { + return a->name() < b->name(); + } +}; + +void MakeDescriptors( + const Descriptor* descriptor, const TProtoStringType& file_description_name, + std::vector<std::unique_ptr<EnumGenerator>>* enum_generators, + std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators, + std::vector<std::unique_ptr<MessageGenerator>>* message_generators) { + for (int i = 0; i < descriptor->enum_type_count(); i++) { + enum_generators->emplace_back( + std::make_unique<EnumGenerator>(descriptor->enum_type(i))); + } + for (int i = 0; i < descriptor->nested_type_count(); i++) { + message_generators->emplace_back(std::make_unique<MessageGenerator>( + file_description_name, descriptor->nested_type(i))); + message_generators->back()->AddExtensionGenerators(extension_generators); + MakeDescriptors(descriptor->nested_type(i), file_description_name, + enum_generators, extension_generators, message_generators); + } +} + +} // namespace + +const FileGenerator::CommonState::MinDepsEntry& +FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensionsInternal( + const FileDescriptor* file) { + auto it = deps_info_cache.find(file); + if (it != deps_info_cache.end()) { + return it->second; + } + + y_absl::flat_hash_set<const FileDescriptor*> min_deps_collector; + y_absl::flat_hash_set<const FileDescriptor*> transitive_deps_collector; + y_absl::flat_hash_set<const FileDescriptor*> to_prune; + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + MinDepsEntry dep_info = + CollectMinimalFileDepsContainingExtensionsInternal(dep); + + // Everything the dep covered, this file will also cover. + transitive_deps_collector.insert(dep_info.transitive_deps.begin(), + dep_info.transitive_deps.end()); + // Prune everything from the dep's covered list in case another dep lists it + // as a min dep. + to_prune.insert(dep_info.transitive_deps.begin(), + dep_info.transitive_deps.end()); + + // Does the dep have any extensions... + if (dep_info.has_extensions) { + // Yes -> Add this file, prune its min_deps and add them to the covered + // deps. + min_deps_collector.insert(dep); + to_prune.insert(dep_info.min_deps.begin(), dep_info.min_deps.end()); + transitive_deps_collector.insert(dep_info.min_deps.begin(), + dep_info.min_deps.end()); + } else { + // No -> Just use its min_deps. + min_deps_collector.insert(dep_info.min_deps.begin(), + dep_info.min_deps.end()); + } + } + + const bool file_has_exts = FileContainsExtensions(file); + + // Fast path: if nothing to prune or there was only one dep, the prune work is + // a waste, skip it. + if (to_prune.empty() || file->dependency_count() == 1) { + return deps_info_cache + .insert( + {file, + {file_has_exts, min_deps_collector, transitive_deps_collector}}) + .first->second; + } + + y_absl::flat_hash_set<const FileDescriptor*> min_deps; + std::copy_if(min_deps_collector.begin(), min_deps_collector.end(), + std::inserter(min_deps, min_deps.begin()), + [&](const FileDescriptor* value) { + return to_prune.find(value) == to_prune.end(); + }); + return deps_info_cache + .insert({file, {file_has_exts, min_deps, transitive_deps_collector}}) + .first->second; +} + +// Collect the deps of the given file that contain extensions. This can be used +// to create the chain of roots that need to be wired together. +// +// NOTE: If any changes are made to this and the supporting functions, you will +// need to manually validate what the generated code is for the test files: +// objectivec/Tests/unittest_extension_chain_*.proto +// There are comments about what the expected code should be line and limited +// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports +// specifically). +std::vector<const FileDescriptor*> +FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensions( + const FileDescriptor* file) { + y_absl::flat_hash_set<const FileDescriptor*> min_deps = + CollectMinimalFileDepsContainingExtensionsInternal(file).min_deps; + // Sort the list since pointer order isn't stable across runs. + std::vector<const FileDescriptor*> result(min_deps.begin(), min_deps.end()); + std::sort(result.begin(), result.end(), FileDescriptorsOrderedByName()); + return result; +} + +FileGenerator::FileGenerator(const FileDescriptor* file, + const GenerationOptions& generation_options, + CommonState& common_state) + : file_(file), + generation_options_(generation_options), + common_state_(&common_state), + root_class_name_(FileClassName(file)), + file_description_name_(FileClassName(file) + "_FileDescription"), + is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)) { + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_.emplace_back( + std::make_unique<EnumGenerator>(file_->enum_type(i))); + } + for (int i = 0; i < file_->extension_count(); i++) { + extension_generators_.push_back(std::make_unique<ExtensionGenerator>( + root_class_name_, file_->extension(i))); + } + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_.emplace_back(std::make_unique<MessageGenerator>( + file_description_name_, file_->message_type(i))); + message_generators_.back()->AddExtensionGenerators(&extension_generators_); + MakeDescriptors(file_->message_type(i), file_description_name_, + &enum_generators_, &extension_generators_, + &message_generators_); + } +} + +void FileGenerator::GenerateHeader(io::Printer* p) const { + GenerateFile(p, GeneratedFileType::kHeader, [&] { + p->Print("CF_EXTERN_C_BEGIN\n\n"); + + y_absl::btree_set<TProtoStringType> fwd_decls; + for (const auto& generator : message_generators_) { + generator->DetermineForwardDeclarations(&fwd_decls, + /* include_external_types = */ + HeadersUseForwardDeclarations()); + } + if (!fwd_decls.empty()) { + p->Print("$fwd_decls$\n\n", "fwd_decls", y_absl::StrJoin(fwd_decls, "\n")); + } + + p->Print("NS_ASSUME_NONNULL_BEGIN\n\n"); + + for (const auto& generator : enum_generators_) { + generator->GenerateHeader(p); + } + + // For extensions to chain together, the Root gets created even if there + // are no extensions. + p->Print( + // clang-format off + "#pragma mark - $root_class_name$\n" + "\n" + "/**\n" + " * Exposes the extension registry for this file.\n" + " *\n" + " * The base class provides:\n" + " * @code\n" + " * + (GPBExtensionRegistry *)extensionRegistry;\n" + " * @endcode\n" + " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n" + " * this file and all files that it depends on.\n" + " **/\n" + "GPB_FINAL @interface $root_class_name$ : GPBRootObject\n" + "@end\n" + "\n", + // clang-format on + "root_class_name", root_class_name_); + + // The dynamic methods block is only needed if there are extensions that are + // file level scoped (not message scoped). The first + // file_->extension_count() of extension_generators_ are the file scoped + // ones. + if (file_->extension_count()) { + p->Print("@interface $root_class_name$ (DynamicMethods)\n", + "root_class_name", root_class_name_); + + for (int i = 0; i < file_->extension_count(); i++) { + extension_generators_[i]->GenerateMembersHeader(p); + } + + p->Print("@end\n\n"); + } // file_->extension_count() + + for (const auto& generator : message_generators_) { + generator->GenerateMessageHeader(p); + } + + // clang-format off + p->Print( + "NS_ASSUME_NONNULL_END\n" + "\n" + "CF_EXTERN_C_END\n"); + // clang-format on + }); +} + +void FileGenerator::GenerateSource(io::Printer* p) const { + std::vector<const FileDescriptor*> deps_with_extensions = + common_state_->CollectMinimalFileDepsContainingExtensions(file_); + GeneratedFileOptions file_options; + + // If any indirect dependency provided extensions, it needs to be directly + // imported so it can get merged into the root's extensions registry. + // See the Note by CollectMinimalFileDepsContainingExtensions before + // changing this. + for (auto& dep : deps_with_extensions) { + if (!IsDirectDependency(dep, file_)) { + file_options.extra_files_to_import.push_back(dep); + } + } + + y_absl::btree_set<TProtoStringType> fwd_decls; + for (const auto& generator : message_generators_) { + generator->DetermineObjectiveCClassDefinitions(&fwd_decls); + } + for (const auto& generator : extension_generators_) { + generator->DetermineObjectiveCClassDefinitions(&fwd_decls); + } + + // The generated code for oneof's uses direct ivar access, suppress the + // warning in case developer turn that on in the context they compile the + // generated code. + for (const auto& generator : message_generators_) { + if (generator->IncludesOneOfDefinition()) { + file_options.ignored_warnings.push_back("direct-ivar-access"); + break; + } + } + if (!fwd_decls.empty()) { + file_options.ignored_warnings.push_back("dollar-in-identifier-extension"); + } + + // Enum implementation uses atomic in the generated code, so add + // the system import as needed. + if (!enum_generators_.empty()) { + file_options.extra_system_headers.push_back("stdatomic.h"); + } + + GenerateFile(p, GeneratedFileType::kSource, file_options, [&] { + if (!fwd_decls.empty()) { + p->Print( + // clang-format off + "#pragma mark - Objective-C Class declarations\n" + "// Forward declarations of Objective-C classes that we can use as\n" + "// static values in struct initializers.\n" + "// We don't use [Foo class] because it is not a static value.\n" + "$fwd_decls$\n" + "\n", + // clang-format on + "fwd_decls", y_absl::StrJoin(fwd_decls, "\n")); + } + + PrintRootImplementation(p, deps_with_extensions); + PrintFileDescription(p); + + for (const auto& generator : enum_generators_) { + generator->GenerateSource(p); + } + for (const auto& generator : message_generators_) { + generator->GenerateSource(p); + } + }); +} + +void FileGenerator::GenerateGlobalSource(io::Printer* p) const { + std::vector<const FileDescriptor*> deps_with_extensions = + common_state_->CollectMinimalFileDepsContainingExtensions(file_); + GeneratedFileOptions file_options; + + // If any indirect dependency provided extensions, it needs to be directly + // imported so it can get merged into the root's extensions registry. + // See the Note by CollectMinimalFileDepsContainingExtensions before + // changing this. + for (auto& dep : deps_with_extensions) { + if (!IsDirectDependency(dep, file_)) { + file_options.extra_files_to_import.push_back(dep); + } + } + + y_absl::btree_set<TProtoStringType> fwd_decls; + for (const auto& generator : extension_generators_) { + generator->DetermineObjectiveCClassDefinitions(&fwd_decls); + } + + if (!fwd_decls.empty()) { + file_options.ignored_warnings.push_back("dollar-in-identifier-extension"); + } + + GenerateFile(p, GeneratedFileType::kSource, file_options, [&] { + if (!fwd_decls.empty()) { + p->Print( + // clang-format off + "#pragma mark - Objective-C Class declarations\n" + "// Forward declarations of Objective-C classes that we can use as\n" + "// static values in struct initializers.\n" + "// We don't use [Foo class] because it is not a static value.\n" + "$fwd_decls$\n" + "\n", + // clang-format on + "fwd_decls", y_absl::StrJoin(fwd_decls, "\n")); + } + + PrintRootImplementation(p, deps_with_extensions); + }); +} + +void FileGenerator::GenerateSourceForEnums(io::Printer* p) const { + // Enum implementation uses atomic in the generated code. + GeneratedFileOptions file_options; + file_options.extra_system_headers.push_back("stdatomic.h"); + + GenerateFile(p, GeneratedFileType::kSource, file_options, [&] { + for (const auto& generator : enum_generators_) { + generator->GenerateSource(p); + } + }); +} + +void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* p) const { + const auto& generator = message_generators_[idx]; + + y_absl::btree_set<TProtoStringType> fwd_decls; + generator->DetermineObjectiveCClassDefinitions(&fwd_decls); + + GeneratedFileOptions file_options; + // The generated code for oneof's uses direct ivar access, suppress the + // warning in case developer turn that on in the context they compile the + // generated code. + if (generator->IncludesOneOfDefinition()) { + file_options.ignored_warnings.push_back("direct-ivar-access"); + } + + GenerateFile(p, GeneratedFileType::kSource, file_options, [&] { + if (!fwd_decls.empty()) { + p->Print( + // clang-format off + "#pragma mark - Objective-C Class declarations\n" + "// Forward declarations of Objective-C classes that we can use as\n" + "// static values in struct initializers.\n" + "// We don't use [Foo class] because it is not a static value.\n" + "$fwd_decls$\n" + "\n", + // clang-format on + "fwd_decls", y_absl::StrJoin(fwd_decls, "\n")); + } + + PrintFileDescription(p); + generator->GenerateSource(p); + }); +} + +void FileGenerator::GenerateFile(io::Printer* p, GeneratedFileType file_type, + const GeneratedFileOptions& file_options, + std::function<void()> body) const { + ImportWriter import_writer( + generation_options_.generate_for_named_framework, + generation_options_.named_framework_to_proto_path_mappings_path, + generation_options_.runtime_import_prefix, + /* for_bundled_proto = */ is_bundled_proto_); + const TProtoStringType header_extension(kHeaderExtension); + + switch (file_type) { + case GeneratedFileType::kHeader: + // Generated files bundled with the library get minimal imports, + // everything else gets the wrapper so everything is usable. + if (is_bundled_proto_) { + import_writer.AddRuntimeImport("GPBDescriptor.h"); + import_writer.AddRuntimeImport("GPBMessage.h"); + import_writer.AddRuntimeImport("GPBRootObject.h"); + } else { + import_writer.AddRuntimeImport("GPBProtocolBuffers.h"); + } + if (HeadersUseForwardDeclarations()) { + // #import any headers for "public imports" in the proto file. + for (int i = 0; i < file_->public_dependency_count(); i++) { + import_writer.AddFile(file_->public_dependency(i), header_extension); + } + } else { + for (int i = 0; i < file_->dependency_count(); i++) { + import_writer.AddFile(file_->dependency(i), header_extension); + } + } + break; + case GeneratedFileType::kSource: + import_writer.AddRuntimeImport("GPBProtocolBuffers_RuntimeSupport.h"); + import_writer.AddFile(file_, header_extension); + if (HeadersUseForwardDeclarations()) { + // #import the headers for anything that a plain dependency of this + // proto file (that means they were just an include, not a "public" + // include). + y_absl::flat_hash_set<TProtoStringType> public_import_names; + for (int i = 0; i < file_->public_dependency_count(); i++) { + public_import_names.insert(file_->public_dependency(i)->name()); + } + for (int i = 0; i < file_->dependency_count(); i++) { + const FileDescriptor* dep = file_->dependency(i); + if (!public_import_names.contains(dep->name())) { + import_writer.AddFile(dep, header_extension); + } + } + } + break; + } + + for (const auto& dep : file_options.extra_files_to_import) { + import_writer.AddFile(dep, header_extension); + } + + p->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// $clangfmt$ off\n" + "// source: $filename$\n" + "\n", + "filename", file_->name(), "clangfmt", "clang-format"); + + import_writer.PrintRuntimeImports( + p, /* default_cpp_symbol = */ !is_bundled_proto_); + + p->Print("\n"); + + // Add some verification that the generated code matches the source the + // code is being compiled with. + // NOTE: This captures the raw numeric values at the time the generator was + // compiled, since that will be the versions for the ObjC runtime at that + // time. The constants in the generated code will then get their values at + // compile time (so checking against the headers being used to compile). + p->Print( + // clang-format off + "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n" + "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n" + "#endif\n" + "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n" + "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n" + "#endif\n" + "\n", + // clang-format on + "google_protobuf_objc_version", + y_absl::StrCat(GOOGLE_PROTOBUF_OBJC_VERSION)); + + if (!file_options.extra_system_headers.empty()) { + for (const auto& system_header : file_options.extra_system_headers) { + p->Print("#import <$header$>\n", "header", system_header); + } + p->Print("\n"); + } + + import_writer.PrintFileImports(p); + + // clang-format off + p->Print( + "// @@protoc_insertion_point(imports)\n" + "\n" + "#pragma clang diagnostic push\n" + "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"); + // clang-format on + for (const auto& warning : file_options.ignored_warnings) { + p->Print("#pragma clang diagnostic ignored \"-W$warning$\"\n", "warning", + warning); + } + p->Print("\n"); + + body(); + + p->Print( + "\n" + "#pragma clang diagnostic pop\n" + "\n" + "// @@protoc_insertion_point(global_scope)\n" + "\n" + "// $clangfmt$ on\n", + "clangfmt", "clang-format"); +} + +void FileGenerator::PrintRootImplementation( + io::Printer* p, + const std::vector<const FileDescriptor*>& deps_with_extensions) const { + p->Print( + // clang-format off + "#pragma mark - $root_class_name$\n" + "\n" + "@implementation $root_class_name$\n" + "\n", + // clang-format on + "root_class_name", root_class_name_); + + // If there were any extensions or this file has any dependencies, output a + // registry to override to create the file specific registry. + if (extension_generators_.empty() && deps_with_extensions.empty()) { + if (file_->dependency_count() == 0) { + // clang-format off + p->Print( + "// No extensions in the file and no imports, so no need to generate\n" + "// +extensionRegistry.\n"); + // clang-format on + } else { + // clang-format off + p->Print( + "// No extensions in the file and none of the imports (direct or indirect)\n" + "// defined extensions, so no need to generate +extensionRegistry.\n"); + // clang-format on + } + } else { + PrintRootExtensionRegistryImplementation(p, deps_with_extensions); + } + + p->Print("\n@end\n\n"); +} + +void FileGenerator::PrintRootExtensionRegistryImplementation( + io::Printer* p, + const std::vector<const FileDescriptor*>& deps_with_extensions) const { + // clang-format off + p->Print( + "+ (GPBExtensionRegistry*)extensionRegistry {\n" + " // This is called by +initialize so there is no need to worry\n" + " // about thread safety and initialization of registry.\n" + " static GPBExtensionRegistry* registry = nil;\n" + " if (!registry) {\n" + " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n" + " registry = [[GPBExtensionRegistry alloc] init];\n"); + // clang-format on + + p->Indent(); + p->Indent(); + + if (!extension_generators_.empty()) { + p->Print("static GPBExtensionDescription descriptions[] = {\n"); + p->Indent(); + for (const auto& generator : extension_generators_) { + generator->GenerateStaticVariablesInitialization(p); + } + p->Outdent(); + // clang-format off + p->Print( + "};\n" + "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n" + " GPBExtensionDescriptor *extension =\n" + " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]\n" + " usesClassRefs:YES];\n" + " [registry addExtension:extension];\n" + " [self globallyRegisterExtension:extension];\n" + " [extension release];\n" + "}\n"); + // clang-format on + } + + if (deps_with_extensions.empty()) { + // clang-format off + p->Print( + "// None of the imports (direct or indirect) defined extensions, so no need to add\n" + "// them to this registry.\n"); + // clang-format on + } else { + // clang-format off + p->Print( + "// Merge in the imports (direct or indirect) that defined extensions.\n"); + // clang-format on + for (const auto& dep : deps_with_extensions) { + const TProtoStringType root_class_name(FileClassName((dep))); + p->Print("[registry addExtensions:[$dependency$ extensionRegistry]];\n", + "dependency", root_class_name); + } + } + + p->Outdent(); + p->Outdent(); + + // clang-format off + p->Print( + " }\n" + " return registry;\n" + "}\n"); + // clang-format on +} + +void FileGenerator::PrintFileDescription(io::Printer* p) const { + // File descriptor only needed if there are messages to use it. + if (message_generators_.empty()) { + return; + } + + const TProtoStringType objc_prefix(FileClassPrefix(file_)); + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; + vars["file_description_name"] = file_description_name_; + vars["package_value"] = file_->package().empty() + ? "NULL" + : y_absl::StrCat("\"", file_->package(), "\""); + switch (file_->syntax()) { + case FileDescriptor::SYNTAX_UNKNOWN: + vars["syntax"] = "GPBFileSyntaxUnknown"; + break; + case FileDescriptor::SYNTAX_PROTO2: + vars["syntax"] = "GPBFileSyntaxProto2"; + break; + case FileDescriptor::SYNTAX_PROTO3: + vars["syntax"] = "GPBFileSyntaxProto3"; + break; + } + if (objc_prefix.empty() && !file_->options().has_objc_class_prefix()) { + vars["prefix_value"] = "NULL"; + } else { + vars["prefix_value"] = y_absl::StrCat("\"", objc_prefix, "\""); + } + + // clang-format off + p->Print( + vars, + "static GPBFileDescription $file_description_name$ = {\n" + " .package = $package_value$,\n" + " .prefix = $prefix_value$,\n" + " .syntax = $syntax$\n" + "};\n" + "\n"); + // clang-format on +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_file.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/file.h index de37930eb39..e83c27c2eca 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_file.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/file.h @@ -31,80 +31,108 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ -#include <map> -#include <set> +#include <functional> +#include <memory> #include <string> #include <vector> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/io/printer.h> + +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "google/protobuf/compiler/objectivec/enum.h" +#include "google/protobuf/compiler/objectivec/extension.h" +#include "google/protobuf/compiler/objectivec/message.h" +#include "google/protobuf/compiler/objectivec/options.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { namespace objectivec { -class EnumGenerator; -class ExtensionGenerator; -class MessageGenerator; - class FileGenerator { public: - struct GenerationOptions { - GenerationOptions() - // TODO(thomasvl): Eventually flip this default to false for better - // interop with Swift if proto usages span modules made from ObjC sources. - : headers_use_forward_declarations(true) {} - TProtoStringType generate_for_named_framework; - TProtoStringType named_framework_to_proto_path_mappings_path; - TProtoStringType runtime_import_prefix; - bool headers_use_forward_declarations; - }; - // Wrapper for some common state that is shared between file generations to // improve performance when more than one file is generated at a time. struct CommonState { - CommonState(); + CommonState() = default; - const std::vector<const FileDescriptor*> + std::vector<const FileDescriptor*> CollectMinimalFileDepsContainingExtensions(const FileDescriptor* file); private: struct MinDepsEntry { bool has_extensions; - std::set<const FileDescriptor*> min_deps; - // `covered_deps` are the transtive deps of `min_deps_w_exts` that also - // have extensions. - std::set<const FileDescriptor*> covered_deps; + // The minimal dependencies that cover all the dependencies with + // extensions. + y_absl::flat_hash_set<const FileDescriptor*> min_deps; + y_absl::flat_hash_set<const FileDescriptor*> transitive_deps; }; - const MinDepsEntry& CollectMinimalFileDepsContainingExtensionsInternal(const FileDescriptor* file); - std::map<const FileDescriptor*, MinDepsEntry> deps_info_cache_; + const MinDepsEntry& CollectMinimalFileDepsContainingExtensionsInternal( + const FileDescriptor* file); + y_absl::flat_hash_map<const FileDescriptor*, MinDepsEntry> deps_info_cache; }; FileGenerator(const FileDescriptor* file, const GenerationOptions& generation_options, CommonState& common_state); - ~FileGenerator(); + ~FileGenerator() = default; FileGenerator(const FileGenerator&) = delete; FileGenerator& operator=(const FileGenerator&) = delete; - void GenerateSource(io::Printer* printer); - void GenerateHeader(io::Printer* printer); + void GenerateHeader(io::Printer* p) const; + void GenerateSource(io::Printer* p) const; + + int NumEnums() const { return enum_generators_.size(); } + int NumMessages() const { return message_generators_.size(); } + + void GenerateGlobalSource(io::Printer* p) const; + void GenerateSourceForMessage(int idx, io::Printer* p) const; + void GenerateSourceForEnums(io::Printer* p) const; private: + enum class GeneratedFileType : int { kHeader, kSource }; + struct GeneratedFileOptions { + std::vector<TProtoStringType> ignored_warnings; + std::vector<const FileDescriptor*> extra_files_to_import; + std::vector<TProtoStringType> extra_system_headers; + }; + + void GenerateFile(io::Printer* p, GeneratedFileType file_type, + const GeneratedFileOptions& file_options, + std::function<void()> body) const; + void GenerateFile(io::Printer* p, GeneratedFileType file_type, + std::function<void()> body) const { + GeneratedFileOptions file_options; + GenerateFile(p, file_type, file_options, body); + } + + void PrintRootImplementation( + io::Printer* p, + const std::vector<const FileDescriptor*>& deps_with_extensions) const; + void PrintRootExtensionRegistryImplementation( + io::Printer* p, + const std::vector<const FileDescriptor*>& deps_with_extensions) const; + void PrintFileDescription(io::Printer* p) const; + + bool HeadersUseForwardDeclarations() const { + // The bundled protos (WKTs) don't make use of forward declarations. + return !is_bundled_proto_ && + generation_options_.headers_use_forward_declarations; + } + const FileDescriptor* file_; const GenerationOptions& generation_options_; - CommonState& common_state_; - TProtoStringType root_class_name_; - bool is_bundled_proto_; + mutable CommonState* common_state_; + const TProtoStringType root_class_name_; + const TProtoStringType file_description_name_; + const bool is_bundled_proto_; std::vector<std::unique_ptr<EnumGenerator>> enum_generators_; std::vector<std::unique_ptr<MessageGenerator>> message_generators_; + // The first file_->extension_count() are the extensions at file level scope. std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_; - - void PrintFileRuntimePreamble( - io::Printer* printer, - const std::vector<TProtoStringType>& headers_to_import) const; }; } // namespace objectivec diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/generator.cc index 586cdb025b2..31c99dba67a 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/generator.cc @@ -28,16 +28,24 @@ // (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/objectivec/generator.h" + #include <fstream> #include <iostream> +#include <memory> #include <string> -#include <unordered_set> -#include <google/protobuf/compiler/objectivec/objectivec_generator.h> -#include <google/protobuf/compiler/objectivec/objectivec_file.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/strutil.h> +#include <utility> +#include <vector> + +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/strip.h" +#include "google/protobuf/compiler/objectivec/file.h" +#include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { @@ -47,16 +55,17 @@ namespace objectivec { namespace { // Convert a string with "yes"/"no" (case insensitive) to a boolean, returning -// true/false for if the input string was a valid value. If the input string is -// invalid, `result` is unchanged. +// true/false for if the input string was a valid value. The empty string is +// also treated as a true value. If the input string is invalid, `result` is +// unchanged. bool StringToBool(const TProtoStringType& value, bool* result) { TProtoStringType upper_value(value); - UpperString(&upper_value); + y_absl::AsciiStrToUpper(&upper_value); if (upper_value == "NO") { *result = false; return true; } - if (upper_value == "YES") { + if (upper_value == "YES" || upper_value.empty()) { *result = true; return true; } @@ -64,15 +73,13 @@ bool StringToBool(const TProtoStringType& value, bool* result) { return false; } -} // namespace +TProtoStringType NumberedObjCMFileName(y_absl::string_view basename, int number) { + return y_absl::StrCat(basename, ".out/", number, ".pbobjc.m"); +} -ObjectiveCGenerator::ObjectiveCGenerator() {} +} // namespace -ObjectiveCGenerator::~ObjectiveCGenerator() {} - -bool ObjectiveCGenerator::HasGenerateAll() const { - return true; -} +bool ObjectiveCGenerator::HasGenerateAll() const { return true; } bool ObjectiveCGenerator::Generate(const FileDescriptor* file, const TProtoStringType& parameter, @@ -92,14 +99,15 @@ bool ObjectiveCGenerator::GenerateAll( // options along with their values. If the option appears multiple times, only // the last value will be considered. // - // e.g. protoc ... --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework + // e.g. protoc ... + // --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework Options validation_options; - FileGenerator::GenerationOptions generation_options; + GenerationOptions generation_options; std::vector<std::pair<TProtoStringType, TProtoStringType> > options; ParseGeneratorParameter(parameter, &options); - for (int i = 0; i < options.size(); i++) { + for (size_t i = 0; i < options.size(); i++) { if (options[i].first == "expected_prefixes_path") { // Path to find a file containing the expected prefixes // (objc_class_prefix "PREFIX") for proto packages (package NAME). The @@ -122,8 +130,8 @@ bool ObjectiveCGenerator::GenerateAll( // A semicolon delimited string that lists the paths of .proto files to // exclude from the package prefix validations (expected_prefixes_path). // This is provided as an "out", to skip some files being checked. - for (StringPiece split_piece : Split( - options[i].second, ";", true)) { + for (y_absl::string_view split_piece : + y_absl::StrSplit(options[i].second, ';', y_absl::SkipEmpty())) { validation_options.expected_prefixes_suppressions.push_back( TProtoStringType(split_piece)); } @@ -137,7 +145,9 @@ bool ObjectiveCGenerator::GenerateAll( // Default is "no". if (!StringToBool(options[i].second, &validation_options.prefixes_must_be_registered)) { - *error = "error: Unknown value for prefixes_must_be_registered: " + options[i].second; + *error = y_absl::StrCat( + "error: Unknown value for prefixes_must_be_registered: ", + options[i].second); return false; } } else if (options[i].first == "require_prefixes") { @@ -149,7 +159,8 @@ bool ObjectiveCGenerator::GenerateAll( // Default is "no". if (!StringToBool(options[i].second, &validation_options.require_prefixes)) { - *error = "error: Unknown value for require_prefixes: " + options[i].second; + *error = y_absl::StrCat("error: Unknown value for require_prefixes: ", + options[i].second); return false; } } else if (options[i].first == "generate_for_named_framework") { @@ -162,7 +173,8 @@ bool ObjectiveCGenerator::GenerateAll( // the "default" framework name used for everything that wasn't mapped by // the mapping file. generation_options.generate_for_named_framework = options[i].second; - } else if (options[i].first == "named_framework_to_proto_path_mappings_path") { + } else if (options[i].first == + "named_framework_to_proto_path_mappings_path") { // Path to find a file containing the list of framework names and proto // files. The generator uses this to decide if a proto file // referenced should use a framework style import vs. a user level import @@ -183,17 +195,20 @@ bool ObjectiveCGenerator::GenerateAll( // mappings file, it will use the default framework name if one was passed // with generate_for_named_framework, or the relative path to it's include // path otherwise. - generation_options.named_framework_to_proto_path_mappings_path = options[i].second; + generation_options.named_framework_to_proto_path_mappings_path = + options[i].second; } else if (options[i].first == "runtime_import_prefix") { // Path to use as a prefix on #imports of runtime provided headers in the // generated files. When integrating ObjC protos into a build system, // this can be used to avoid having to add the runtime directory to the // header search path since the generate #import will be more complete. - generation_options.runtime_import_prefix = StripSuffixString(options[i].second, "/"); + generation_options.runtime_import_prefix = + TProtoStringType(y_absl::StripSuffix(options[i].second, "/")); } else if (options[i].first == "package_to_prefix_mappings_path") { // Path to use for when loading the objc class prefix mappings to use. - // The `objc_class_prefix` file option is always honored first if one is present. - // This option also has precedent over the use_package_as_prefix option. + // The `objc_class_prefix` file option is always honored first if one is + // present. This option also has precedent over the use_package_as_prefix + // option. // // The format of the file is: // - An entry is a line of "package=prefix". @@ -215,7 +230,8 @@ bool ObjectiveCGenerator::GenerateAll( if (StringToBool(options[i].second, &value)) { SetUseProtoPackageAsDefaultPrefix(value); } else { - *error = "error: Unknown use_package_as_prefix: " + options[i].second; + *error = y_absl::StrCat("error: Unknown use_package_as_prefix: ", + options[i].second); return false; } } else if (options[i].first == "proto_package_prefix_exceptions_path") { @@ -230,25 +246,54 @@ bool ObjectiveCGenerator::GenerateAll( // - A comment can go on a line after a expected package/prefix pair. // (i.e. - "some.proto.package # comment") SetProtoPackagePrefixExceptionList(options[i].second); + } else if (options[i].first == "package_as_prefix_forced_prefix") { + // String to use as the prefix when deriving a prefix from the package + // name. So this only applies when use_package_as_prefix is also used. + SetForcedPackagePrefix(options[i].second); } else if (options[i].first == "headers_use_forward_declarations") { if (!StringToBool(options[i].second, &generation_options.headers_use_forward_declarations)) { - *error = "error: Unknown value for headers_use_forward_declarations: " + options[i].second; + *error = y_absl::StrCat( + "error: Unknown value for headers_use_forward_declarations: ", + options[i].second); + return false; + } + } else if (options[i].first == "experimental_multi_source_generation") { + // This is an experimental option, and could be removed or change at any + // time; it is not documented in the README.md for that reason. + // + // Enables a mode where each ObjC class (messages and roots) generates to + // a unique .m file; this is to explore impacts on code size when not + // compiling/linking with `-ObjC` as then only linker visible needs should + // be pulled into the builds. + if (!StringToBool( + options[i].second, + &generation_options.experimental_multi_source_generation)) { + *error = y_absl::StrCat( + "error: Unknown value for experimental_multi_source_generation: ", + options[i].second); return false; } } else { - *error = "error: Unknown generator option: " + options[i].first; + *error = + y_absl::StrCat("error: Unknown generator option: ", options[i].first); return false; } } + // Multi source generation forces off the use of fwd decls in favor of + // imports. + if (generation_options.experimental_multi_source_generation) { + generation_options.headers_use_forward_declarations = false; + } + // ----------------------------------------------------------------- // These are not official generation options and could be removed/changed in // the future and doing that won't count as a breaking change. - bool headers_only = getenv("GPB_OBJC_HEADERS_ONLY") != NULL; - std::unordered_set<TProtoStringType> skip_impls; - if (getenv("GPB_OBJC_SKIP_IMPLS_FILE") != NULL) { + bool headers_only = getenv("GPB_OBJC_HEADERS_ONLY") != nullptr; + y_absl::flat_hash_set<TProtoStringType> skip_impls; + if (getenv("GPB_OBJC_SKIP_IMPLS_FILE") != nullptr) { std::ifstream skip_file(getenv("GPB_OBJC_SKIP_IMPLS_FILE")); if (skip_file.is_open()) { std::string line; @@ -270,27 +315,83 @@ bool ObjectiveCGenerator::GenerateAll( } FileGenerator::CommonState state; - for (int i = 0; i < files.size(); i++) { - const FileDescriptor* file = files[i]; - FileGenerator file_generator(file, generation_options, state); + for (const auto& file : files) { + const FileGenerator file_generator(file, generation_options, state); TProtoStringType filepath = FilePath(file); // Generate header. { - std::unique_ptr<io::ZeroCopyOutputStream> output( - context->Open(filepath + ".pbobjc.h")); - io::Printer printer(output.get(), '$'); + auto output = + y_absl::WrapUnique(context->Open(y_absl::StrCat(filepath, ".pbobjc.h"))); + io::Printer printer(output.get()); file_generator.GenerateHeader(&printer); + if (printer.failed()) { + *error = y_absl::StrCat("error: internal error generating a header: ", + file->name()); + return false; + } } - // Generate m file. + // Generate m file(s). if (!headers_only && skip_impls.count(file->name()) == 0) { - std::unique_ptr<io::ZeroCopyOutputStream> output( - context->Open(filepath + ".pbobjc.m")); - io::Printer printer(output.get(), '$'); - file_generator.GenerateSource(&printer); - } - } + if (generation_options.experimental_multi_source_generation) { + int file_number = 0; + + // Generate the Root and FileDescriptor (if needed). + { + std::unique_ptr<io::ZeroCopyOutputStream> output( + context->Open(NumberedObjCMFileName(filepath, file_number++))); + io::Printer printer(output.get()); + file_generator.GenerateGlobalSource(&printer); + if (printer.failed()) { + *error = y_absl::StrCat( + "error: internal error generating an implementation:", + file->name()); + return false; + } + } + + // Enums only generate C functions, so they can all go in one file as + // dead stripping anything not used. + if (file_generator.NumEnums() > 0) { + std::unique_ptr<io::ZeroCopyOutputStream> output( + context->Open(NumberedObjCMFileName(filepath, file_number++))); + io::Printer printer(output.get()); + file_generator.GenerateSourceForEnums(&printer); + if (printer.failed()) { + *error = y_absl::StrCat( + "error: internal error generating an enum implementation(s):", + file->name()); + return false; + } + } + + for (int i = 0; i < file_generator.NumMessages(); ++i) { + std::unique_ptr<io::ZeroCopyOutputStream> output( + context->Open(NumberedObjCMFileName(filepath, file_number++))); + io::Printer printer(output.get()); + file_generator.GenerateSourceForMessage(i, &printer); + if (printer.failed()) { + *error = y_absl::StrCat( + "error: internal error generating an message implementation:", + file->name(), "::", i); + return false; + } + } + } else { + auto output = y_absl::WrapUnique( + context->Open(y_absl::StrCat(filepath, ".pbobjc.m"))); + io::Printer printer(output.get()); + file_generator.GenerateSource(&printer); + if (printer.failed()) { + *error = y_absl::StrCat( + "error: internal error generating an implementation:", + file->name()); + return false; + } + } + } // if (!headers_only && skip_impls.count(file->name()) == 0) + } // for(file : files) return true; } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/generator.h index cdaac67c3ba..34767e45a6a 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/generator.h @@ -34,10 +34,13 @@ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__ #include <string> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> +#include <vector> -#include <google/protobuf/port_def.inc> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" + +// Must be included last +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -50,8 +53,8 @@ namespace objectivec { // CodeGenerator with the CommandLineInterface in your main() function. class PROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { public: - ObjectiveCGenerator(); - ~ObjectiveCGenerator(); + ObjectiveCGenerator() = default; + ~ObjectiveCGenerator() override = default; ObjectiveCGenerator(const ObjectiveCGenerator&) = delete; ObjectiveCGenerator& operator=(const ObjectiveCGenerator&) = delete; @@ -74,6 +77,6 @@ class PROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/helpers.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/helpers.cc new file mode 100644 index 00000000000..4d90adeb7de --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/helpers.cc @@ -0,0 +1,399 @@ +// 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/objectivec/helpers.h" + +#include <string> +#include <vector> + +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/io/strtod.h" +#include "google/protobuf/stubs/common.h" +#include <google/protobuf/stubs/port.h> + +// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some +// error cases, so it seems to be ok to use as a back door for errors. + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +TProtoStringType EscapeTrigraphs(y_absl::string_view to_escape) { + return y_absl::StrReplaceAll(to_escape, {{"?", "\\?"}}); +} + +namespace { + +TProtoStringType GetZeroEnumNameForFlagType(const FlagType flag_type) { + switch (flag_type) { + case FLAGTYPE_DESCRIPTOR_INITIALIZATION: + return "GPBDescriptorInitializationFlag_None"; + case FLAGTYPE_EXTENSION: + return "GPBExtensionNone"; + case FLAGTYPE_FIELD: + return "GPBFieldNone"; + default: + Y_ABSL_LOG(FATAL) << "Can't get here."; + return "0"; + } +} + +TProtoStringType GetEnumNameForFlagType(const FlagType flag_type) { + switch (flag_type) { + case FLAGTYPE_DESCRIPTOR_INITIALIZATION: + return "GPBDescriptorInitializationFlags"; + case FLAGTYPE_EXTENSION: + return "GPBExtensionOptions"; + case FLAGTYPE_FIELD: + return "GPBFieldFlags"; + default: + Y_ABSL_LOG(FATAL) << "Can't get here."; + return TProtoStringType(); + } +} + +TProtoStringType HandleExtremeFloatingPoint(TProtoStringType val, bool add_float_suffix) { + if (val == "nan") { + return "NAN"; + } else if (val == "inf") { + return "INFINITY"; + } else if (val == "-inf") { + return "-INFINITY"; + } else { + // float strings with ., e or E need to have f appended + if (add_float_suffix && + (y_absl::StrContains(val, '.') || y_absl::StrContains(val, 'e') || + y_absl::StrContains(val, 'E'))) { + return y_absl::StrCat(val, "f"); + } + return val; + } +} + +} // namespace + +TProtoStringType GetCapitalizedType(const FieldDescriptor* field) { + switch (field->type()) { + case FieldDescriptor::TYPE_INT32: + return "Int32"; + case FieldDescriptor::TYPE_UINT32: + return "UInt32"; + case FieldDescriptor::TYPE_SINT32: + return "SInt32"; + case FieldDescriptor::TYPE_FIXED32: + return "Fixed32"; + case FieldDescriptor::TYPE_SFIXED32: + return "SFixed32"; + case FieldDescriptor::TYPE_INT64: + return "Int64"; + case FieldDescriptor::TYPE_UINT64: + return "UInt64"; + case FieldDescriptor::TYPE_SINT64: + return "SInt64"; + case FieldDescriptor::TYPE_FIXED64: + return "Fixed64"; + case FieldDescriptor::TYPE_SFIXED64: + return "SFixed64"; + case FieldDescriptor::TYPE_FLOAT: + return "Float"; + case FieldDescriptor::TYPE_DOUBLE: + return "Double"; + case FieldDescriptor::TYPE_BOOL: + return "Bool"; + case FieldDescriptor::TYPE_STRING: + return "String"; + case FieldDescriptor::TYPE_BYTES: + return "Bytes"; + case FieldDescriptor::TYPE_ENUM: + return "Enum"; + case FieldDescriptor::TYPE_GROUP: + return "Group"; + case FieldDescriptor::TYPE_MESSAGE: + return "Message"; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + Y_ABSL_LOG(FATAL) << "Can't get here."; + return TProtoStringType(); +} + +ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) { + switch (field_type) { + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SFIXED32: + return OBJECTIVECTYPE_INT32; + + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_FIXED32: + return OBJECTIVECTYPE_UINT32; + + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_SFIXED64: + return OBJECTIVECTYPE_INT64; + + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_FIXED64: + return OBJECTIVECTYPE_UINT64; + + case FieldDescriptor::TYPE_FLOAT: + return OBJECTIVECTYPE_FLOAT; + + case FieldDescriptor::TYPE_DOUBLE: + return OBJECTIVECTYPE_DOUBLE; + + case FieldDescriptor::TYPE_BOOL: + return OBJECTIVECTYPE_BOOLEAN; + + case FieldDescriptor::TYPE_STRING: + return OBJECTIVECTYPE_STRING; + + case FieldDescriptor::TYPE_BYTES: + return OBJECTIVECTYPE_DATA; + + case FieldDescriptor::TYPE_ENUM: + return OBJECTIVECTYPE_ENUM; + + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + return OBJECTIVECTYPE_MESSAGE; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + Y_ABSL_LOG(FATAL) << "Can't get here."; + return OBJECTIVECTYPE_INT32; +} + +TProtoStringType GPBGenericValueFieldName(const FieldDescriptor* field) { + // Returns the field within the GPBGenericValue union to use for the given + // field. + if (field->is_repeated()) { + return "valueMessage"; + } + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return "valueInt32"; + case FieldDescriptor::CPPTYPE_UINT32: + return "valueUInt32"; + case FieldDescriptor::CPPTYPE_INT64: + return "valueInt64"; + case FieldDescriptor::CPPTYPE_UINT64: + return "valueUInt64"; + case FieldDescriptor::CPPTYPE_FLOAT: + return "valueFloat"; + case FieldDescriptor::CPPTYPE_DOUBLE: + return "valueDouble"; + case FieldDescriptor::CPPTYPE_BOOL: + return "valueBool"; + case FieldDescriptor::CPPTYPE_STRING: + if (field->type() == FieldDescriptor::TYPE_BYTES) { + return "valueData"; + } else { + return "valueString"; + } + case FieldDescriptor::CPPTYPE_ENUM: + return "valueEnum"; + case FieldDescriptor::CPPTYPE_MESSAGE: + return "valueMessage"; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + Y_ABSL_LOG(FATAL) << "Can't get here."; + return TProtoStringType(); +} + +TProtoStringType DefaultValue(const FieldDescriptor* field) { + // Repeated fields don't have defaults. + if (field->is_repeated()) { + return "nil"; + } + + // Switch on cpp_type since we need to know which default_value_* method + // of FieldDescriptor to call. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + // gcc and llvm reject the decimal form of kint32min and kint64min. + if (field->default_value_int32() == INT_MIN) { + return "-0x80000000"; + } + return y_absl::StrCat(field->default_value_int32()); + case FieldDescriptor::CPPTYPE_UINT32: + return y_absl::StrCat(field->default_value_uint32(), "U"); + case FieldDescriptor::CPPTYPE_INT64: + // gcc and llvm reject the decimal form of kint32min and kint64min. + if (field->default_value_int64() == LLONG_MIN) { + return "-0x8000000000000000LL"; + } + return y_absl::StrCat(field->default_value_int64(), "LL"); + case FieldDescriptor::CPPTYPE_UINT64: + return y_absl::StrCat(field->default_value_uint64(), "ULL"); + case FieldDescriptor::CPPTYPE_DOUBLE: + return HandleExtremeFloatingPoint( + io::SimpleDtoa(field->default_value_double()), false); + case FieldDescriptor::CPPTYPE_FLOAT: + return HandleExtremeFloatingPoint( + io::SimpleFtoa(field->default_value_float()), true); + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() ? "YES" : "NO"; + case FieldDescriptor::CPPTYPE_STRING: { + const bool has_default_value = field->has_default_value(); + y_absl::string_view default_string = field->default_value_string(); + if (!has_default_value || default_string.length() == 0) { + // If the field is defined as being the empty string, + // then we will just assign to nil, as the empty string is the + // default for both strings and data. + return "nil"; + } + if (field->type() == FieldDescriptor::TYPE_BYTES) { + // We want constant fields in our data structures so we can + // declare them as static. To achieve this we cheat and stuff + // a escaped c string (prefixed with a length) into the data + // field, and cast it to an (NSData*) so it will compile. + // The runtime library knows how to handle it. + + // Must convert to a standard byte order for packing length into + // a cstring. + arc_ui32 length = ghtonl(default_string.length()); + TProtoStringType bytes((const char*)&length, sizeof(length)); + y_absl::StrAppend(&bytes, default_string); + return y_absl::StrCat("(NSData*)\"", + EscapeTrigraphs(y_absl::CEscape(bytes)), "\""); + } else { + return y_absl::StrCat( + "@\"", EscapeTrigraphs(y_absl::CEscape(default_string)), "\""); + } + } + case FieldDescriptor::CPPTYPE_ENUM: + return EnumValueName(field->default_value_enum()); + case FieldDescriptor::CPPTYPE_MESSAGE: + return "nil"; + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + Y_ABSL_LOG(FATAL) << "Can't get here."; + return TProtoStringType(); +} + +TProtoStringType BuildFlagsString(FlagType flag_type, + const std::vector<TProtoStringType>& strings) { + if (strings.empty()) { + return GetZeroEnumNameForFlagType(flag_type); + } else if (strings.size() == 1) { + return strings[0]; + } + TProtoStringType string = + y_absl::StrCat("(", GetEnumNameForFlagType(flag_type), ")("); + for (size_t i = 0; i != strings.size(); ++i) { + if (i > 0) { + string.append(" | "); + } + string.append(strings[i]); + } + string.append(")"); + return string; +} + +TProtoStringType ObjCClass(y_absl::string_view class_name) { + return y_absl::StrCat("GPBObjCClass(", class_name, ")"); +} + +TProtoStringType ObjCClassDeclaration(y_absl::string_view class_name) { + return y_absl::StrCat("GPBObjCClassDeclaration(", class_name, ");"); +} + +TProtoStringType BuildCommentsString(const SourceLocation& location, + bool prefer_single_line) { + y_absl::string_view comments = location.leading_comments.empty() + ? location.trailing_comments + : location.leading_comments; + std::vector<y_absl::string_view> lines; + lines = y_absl::StrSplit(comments, '\n', y_absl::AllowEmpty()); + while (!lines.empty() && lines.back().empty()) { + lines.pop_back(); + } + // If there are no comments, just return an empty string. + if (lines.empty()) { + return ""; + } + + TProtoStringType prefix; + TProtoStringType suffix; + TProtoStringType final_comments; + TProtoStringType epilogue; + + bool add_leading_space = false; + + if (prefer_single_line && lines.size() == 1) { + prefix = "/** "; + suffix = " */\n"; + } else { + prefix = "* "; + suffix = "\n"; + y_absl::StrAppend(&final_comments, "/**\n"); + epilogue = " **/\n"; + add_leading_space = true; + } + + for (size_t i = 0; i < lines.size(); i++) { + TProtoStringType line = y_absl::StrReplaceAll( + y_absl::StripPrefix(lines[i], " "), + {// HeaderDoc and appledoc use '\' and '@' for markers; escape them. + {"\\", "\\\\"}, + {"@", "\\@"}, + // Decouple / from * to not have inline comments inside comments. + {"/*", "/\\*"}, + {"*/", "*\\/"}}); + line = prefix + line; + y_absl::StripAsciiWhitespace(&line); + // If not a one line, need to add the first space before *, as + // y_absl::StripAsciiWhitespace would have removed it. + line = y_absl::StrCat(add_leading_space ? " " : "", line); + y_absl::StrAppend(&final_comments, line, suffix); + } + return y_absl::StrCat(final_comments, epilogue); +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/helpers.h new file mode 100644 index 00000000000..73f67e13d72 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/helpers.h @@ -0,0 +1,155 @@ +// 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. + +// Helper functions for generating ObjectiveC code. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ + +#include <string> +#include <vector> + +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// Escape C++ trigraphs by escaping question marks to "\?". +TProtoStringType EscapeTrigraphs(y_absl::string_view to_escape); + +enum ObjectiveCType { + OBJECTIVECTYPE_INT32, + OBJECTIVECTYPE_UINT32, + OBJECTIVECTYPE_INT64, + OBJECTIVECTYPE_UINT64, + OBJECTIVECTYPE_FLOAT, + OBJECTIVECTYPE_DOUBLE, + OBJECTIVECTYPE_BOOLEAN, + OBJECTIVECTYPE_STRING, + OBJECTIVECTYPE_DATA, + OBJECTIVECTYPE_ENUM, + OBJECTIVECTYPE_MESSAGE +}; + +enum FlagType { + FLAGTYPE_DESCRIPTOR_INITIALIZATION, + FLAGTYPE_EXTENSION, + FLAGTYPE_FIELD +}; + +TProtoStringType GetCapitalizedType(const FieldDescriptor* field); + +ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type); + +inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) { + return GetObjectiveCType(field->type()); +} + +inline bool IsPrimitiveType(const FieldDescriptor* field) { + ObjectiveCType type = GetObjectiveCType(field); + switch (type) { + case OBJECTIVECTYPE_INT32: + case OBJECTIVECTYPE_UINT32: + case OBJECTIVECTYPE_INT64: + case OBJECTIVECTYPE_UINT64: + case OBJECTIVECTYPE_FLOAT: + case OBJECTIVECTYPE_DOUBLE: + case OBJECTIVECTYPE_BOOLEAN: + case OBJECTIVECTYPE_ENUM: + return true; + break; + default: + return false; + } +} + +inline bool IsReferenceType(const FieldDescriptor* field) { + return !IsPrimitiveType(field); +} + +TProtoStringType GPBGenericValueFieldName(const FieldDescriptor* field); +TProtoStringType DefaultValue(const FieldDescriptor* field); + +TProtoStringType BuildFlagsString(FlagType type, + const std::vector<TProtoStringType>& strings); + +// Returns a symbol that can be used in C code to refer to an Objective-C +// class without initializing the class. +TProtoStringType ObjCClass(y_absl::string_view class_name); + +// Declares an Objective-C class without initializing the class so that it can +// be refrerred to by ObjCClass. +TProtoStringType ObjCClassDeclaration(y_absl::string_view class_name); + +// Builds HeaderDoc/appledoc style comments out of the comments in the .proto +// file. +TProtoStringType BuildCommentsString(const SourceLocation& location, + bool prefer_single_line); + +template <class TDescriptor> +TProtoStringType GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, + const FileDescriptor* file = nullptr, + bool preSpace = true, + bool postNewline = false) { + bool isDeprecated = descriptor->options().deprecated(); + // The file is only passed when checking Messages & Enums, so those types + // get tagged. At the moment, it doesn't seem to make sense to tag every + // field or enum value with when the file is deprecated. + bool isFileLevelDeprecation = false; + if (!isDeprecated && file) { + isFileLevelDeprecation = file->options().deprecated(); + isDeprecated = isFileLevelDeprecation; + } + if (isDeprecated) { + TProtoStringType message; + const FileDescriptor* sourceFile = descriptor->file(); + if (isFileLevelDeprecation) { + message = y_absl::StrCat(sourceFile->name(), " is deprecated."); + } else { + message = y_absl::StrCat(descriptor->full_name(), " is deprecated (see ", + sourceFile->name(), ")."); + } + + return y_absl::StrCat(preSpace ? " " : "", "GPB_DEPRECATED_MSG(\"", message, + "\")", postNewline ? "\n" : ""); + } else { + return ""; + } +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/import_writer.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/import_writer.cc new file mode 100644 index 00000000000..de6f6ab66c1 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/import_writer.cc @@ -0,0 +1,255 @@ +// 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/objectivec/import_writer.h" + +#include <iostream> +#include <ostream> +#include <string> +#include <vector> + +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/match.h" +#include "google/protobuf/compiler/objectivec/line_consumer.h" +#include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/io/printer.h" + +// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some +// error cases, so it seems to be ok to use as a back door for errors. + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +class ProtoFrameworkCollector : public LineConsumer { + public: + explicit ProtoFrameworkCollector( + y_absl::flat_hash_map<TProtoStringType, TProtoStringType>* + inout_proto_file_to_framework_name) + : map_(inout_proto_file_to_framework_name) {} + + bool ConsumeLine(y_absl::string_view line, TProtoStringType* out_error) override; + + private: + y_absl::flat_hash_map<TProtoStringType, TProtoStringType>* map_; +}; + +bool ProtoFrameworkCollector::ConsumeLine(y_absl::string_view line, + TProtoStringType* out_error) { + int offset = line.find(':'); + if (offset == y_absl::string_view::npos) { + *out_error = y_absl::StrCat( + "Framework/proto file mapping line without colon sign: '", line, "'."); + return false; + } + y_absl::string_view framework_name = + y_absl::StripAsciiWhitespace(line.substr(0, offset)); + y_absl::string_view proto_file_list = + y_absl::StripAsciiWhitespace(line.substr(offset + 1)); + + int start = 0; + while (start < proto_file_list.length()) { + offset = proto_file_list.find(',', start); + if (offset == y_absl::string_view::npos) { + offset = proto_file_list.length(); + } + + y_absl::string_view proto_file = y_absl::StripAsciiWhitespace( + proto_file_list.substr(start, offset - start)); + if (!proto_file.empty()) { + auto existing_entry = map_->find(proto_file); + if (existing_entry != map_->end()) { + std::cerr << "warning: duplicate proto file reference, replacing " + "framework entry for '" + << proto_file << "' with '" << framework_name << "' (was '" + << existing_entry->second << "')." << std::endl; + std::cerr.flush(); + } + + if (y_absl::StrContains(proto_file, ' ')) { + std::cerr << "note: framework mapping file had a proto file with a " + "space in, hopefully that isn't a missing comma: '" + << proto_file << "'" << std::endl; + std::cerr.flush(); + } + + (*map_)[proto_file] = TProtoStringType(framework_name); + } + + start = offset + 1; + } + + return true; +} + +} // namespace + +ImportWriter::ImportWriter( + const TProtoStringType& generate_for_named_framework, + const TProtoStringType& named_framework_to_proto_path_mappings_path, + const TProtoStringType& runtime_import_prefix, bool for_bundled_proto) + : generate_for_named_framework_(generate_for_named_framework), + named_framework_to_proto_path_mappings_path_( + named_framework_to_proto_path_mappings_path), + runtime_import_prefix_(runtime_import_prefix), + for_bundled_proto_(for_bundled_proto), + need_to_parse_mapping_file_(true) {} + +void ImportWriter::AddFile(const FileDescriptor* file, + const TProtoStringType& header_extension) { + if (IsProtobufLibraryBundledProtoFile(file)) { + // The imports of the WKTs are only needed within the library itself, + // in other cases, they get skipped because the generated code already + // import GPBProtocolBuffers.h and hence proves them. + if (for_bundled_proto_) { + protobuf_imports_.emplace_back( + y_absl::StrCat("GPB", FilePathBasename(file), header_extension)); + } + return; + } + + // Lazy parse any mappings. + if (need_to_parse_mapping_file_) { + ParseFrameworkMappings(); + } + + auto proto_lookup = proto_file_to_framework_name_.find(file->name()); + if (proto_lookup != proto_file_to_framework_name_.end()) { + other_framework_imports_.emplace_back(y_absl::StrCat( + proto_lookup->second, "/", FilePathBasename(file), header_extension)); + return; + } + + if (!generate_for_named_framework_.empty()) { + other_framework_imports_.push_back( + y_absl::StrCat(generate_for_named_framework_, "/", FilePathBasename(file), + header_extension)); + return; + } + + other_imports_.push_back(FilePath(file) + header_extension); +} + +void ImportWriter::AddRuntimeImport(const TProtoStringType& header_name) { + protobuf_imports_.push_back(header_name); +} + +void ImportWriter::PrintFileImports(io::Printer* p) const { + if (!other_framework_imports_.empty()) { + for (const auto& header : other_framework_imports_) { + p->Print("#import <$header$>\n", "header", header); + } + } + + if (!other_imports_.empty()) { + if (!other_framework_imports_.empty()) { + p->Print("\n"); + } + + for (const auto& header : other_imports_) { + p->Print("#import \"$header$\"\n", "header", header); + } + } +} + +void ImportWriter::PrintRuntimeImports(io::Printer* p, + bool default_cpp_symbol) const { + // Given an override, use that. + if (!runtime_import_prefix_.empty()) { + for (const auto& header : protobuf_imports_) { + p->Print("#import \"$import_prefix$/$header$\"\n", "header", header, + "import_prefix", runtime_import_prefix_); + } + return; + } + + // If bundled, no need to do the framework support below. + if (for_bundled_proto_) { + Y_ABSL_DCHECK(!default_cpp_symbol); + for (const auto& header : protobuf_imports_) { + p->Print("#import \"$header$\"\n", "header", header); + } + return; + } + + const TProtoStringType cpp_symbol( + ProtobufFrameworkImportSymbol(ProtobufLibraryFrameworkName)); + + if (default_cpp_symbol) { + p->Print( + // clang-format off + "// This CPP symbol can be defined to use imports that match up to the framework\n" + "// imports needed when using CocoaPods.\n" + "#if !defined($cpp_symbol$)\n" + " #define $cpp_symbol$ 0\n" + "#endif\n" + "\n", + // clang-format on + "cpp_symbol", cpp_symbol); + } + + p->Print("#if $cpp_symbol$\n", "cpp_symbol", cpp_symbol); + for (const auto& header : protobuf_imports_) { + p->Print(" #import <$framework_name$/$header$>\n", "framework_name", + ProtobufLibraryFrameworkName, "header", header); + } + p->Print("#else\n"); + for (const auto& header : protobuf_imports_) { + p->Print(" #import \"$header$\"\n", "header", header); + } + p->Print("#endif\n"); +} + +void ImportWriter::ParseFrameworkMappings() { + need_to_parse_mapping_file_ = false; + if (named_framework_to_proto_path_mappings_path_.empty()) { + return; // Nothing to do. + } + + ProtoFrameworkCollector collector(&proto_file_to_framework_name_); + TProtoStringType parse_error; + if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_, &collector, + &parse_error)) { + std::cerr << "error parsing " + << named_framework_to_proto_path_mappings_path_ << " : " + << parse_error << std::endl; + std::cerr.flush(); + } +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/import_writer.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/import_writer.h new file mode 100644 index 00000000000..d4ed37d3a85 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/import_writer.h @@ -0,0 +1,82 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_IMPORT_WRITER_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_IMPORT_WRITER_H__ + +#include <string> +#include <vector> + +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// Helper class for parsing framework import mappings and generating +// import statements. +class ImportWriter { + public: + ImportWriter(const TProtoStringType& generate_for_named_framework, + const TProtoStringType& named_framework_to_proto_path_mappings_path, + const TProtoStringType& runtime_import_prefix, + bool for_bundled_proto); + ~ImportWriter() = default; + + void AddFile(const FileDescriptor* file, const TProtoStringType& header_extension); + void AddRuntimeImport(const TProtoStringType& header_name); + + void PrintFileImports(io::Printer* p) const; + void PrintRuntimeImports(io::Printer* p, bool default_cpp_symbol) const; + + private: + void ParseFrameworkMappings(); + + const TProtoStringType generate_for_named_framework_; + const TProtoStringType named_framework_to_proto_path_mappings_path_; + const TProtoStringType runtime_import_prefix_; + y_absl::flat_hash_map<TProtoStringType, TProtoStringType> proto_file_to_framework_name_; + bool for_bundled_proto_; + bool need_to_parse_mapping_file_; + + std::vector<TProtoStringType> protobuf_imports_; + std::vector<TProtoStringType> other_framework_imports_; + std::vector<TProtoStringType> other_imports_; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_IMPORT_WRITER_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/line_consumer.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/line_consumer.cc new file mode 100644 index 00000000000..f47be8186e1 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/line_consumer.cc @@ -0,0 +1,212 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef _MSC_VER +#include <unistd.h> +#endif +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> + +#include <climits> +#include <fstream> +#include <iostream> +#include <sstream> +#include <string> +#include <vector> + +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/objectivec/line_consumer.h" +#include "google/protobuf/io/zero_copy_stream_impl.h" + +#ifdef _WIN32 +#include "google/protobuf/io/io_win32.h" +#endif + +// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some +// error cases, so it seems to be ok to use as a back door for errors. + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// <io.h> is transitively included in this file. Import the functions explicitly +// in this port namespace to avoid ambiguous definition. +namespace posix { +#ifdef _WIN32 +using google::protobuf::io::win32::open; +#else // !_WIN32 +using ::open; +#endif // _WIN32 +} // namespace posix + +namespace { + +bool ascii_isnewline(char c) { return c == '\n' || c == '\r'; } + +bool ReadLine(y_absl::string_view* input, y_absl::string_view* line) { + for (int len = 0; len < input->size(); ++len) { + if (ascii_isnewline((*input)[len])) { + *line = y_absl::string_view(input->data(), len); + ++len; // advance over the newline + *input = y_absl::string_view(input->data() + len, input->size() - len); + return true; + } + } + return false; // Ran out of input with no newline. +} + +void RemoveComment(y_absl::string_view* input) { + int offset = input->find('#'); + if (offset != y_absl::string_view::npos) { + input->remove_suffix(input->length() - offset); + } +} + +class Parser { + public: + explicit Parser(LineConsumer* line_consumer) + : line_consumer_(line_consumer), line_(0) {} + + // Feeds in some input, parse what it can, returning success/failure. Calling + // again after an error is undefined. + bool ParseChunk(y_absl::string_view chunk, TProtoStringType* out_error); + + // Should be called to finish parsing (after all input has been provided via + // successful calls to ParseChunk(), calling after a ParseChunk() failure is + // undefined). Returns success/failure. + bool Finish(TProtoStringType* out_error); + + int last_line() const { return line_; } + + private: + LineConsumer* line_consumer_; + int line_; + TProtoStringType leftover_; +}; + +bool Parser::ParseChunk(y_absl::string_view chunk, TProtoStringType* out_error) { + y_absl::string_view full_chunk; + if (!leftover_.empty()) { + leftover_ += TProtoStringType(chunk); + full_chunk = y_absl::string_view(leftover_); + } else { + full_chunk = chunk; + } + + y_absl::string_view line; + while (ReadLine(&full_chunk, &line)) { + ++line_; + RemoveComment(&line); + line = y_absl::StripAsciiWhitespace(line); + if (!line.empty() && !line_consumer_->ConsumeLine(line, out_error)) { + if (out_error->empty()) { + *out_error = "ConsumeLine failed without setting an error."; + } + leftover_.clear(); + return false; + } + } + + if (full_chunk.empty()) { + leftover_.clear(); + } else { + leftover_ = TProtoStringType(full_chunk); + } + return true; +} + +bool Parser::Finish(TProtoStringType* out_error) { + // If there is still something to go, flush it with a newline. + if (!leftover_.empty() && !ParseChunk("\n", out_error)) { + return false; + } + // This really should never fail if ParseChunk succeeded, but check to be + // sure. + if (!leftover_.empty()) { + *out_error = "ParseSimple Internal error: finished with pending data."; + return false; + } + return true; +} + +} // namespace + +bool ParseSimpleFile(y_absl::string_view path, LineConsumer* line_consumer, + TProtoStringType* out_error) { + int fd; + do { + fd = posix::open(TProtoStringType(path).c_str(), O_RDONLY); + } while (fd < 0 && errno == EINTR); + if (fd < 0) { + *out_error = + y_absl::StrCat("error: Unable to open \"", path, "\", ", strerror(errno)); + return false; + } + io::FileInputStream file_stream(fd); + file_stream.SetCloseOnDelete(true); + + return ParseSimpleStream(file_stream, path, line_consumer, out_error); +} + +bool ParseSimpleStream(io::ZeroCopyInputStream& input_stream, + y_absl::string_view stream_name, + LineConsumer* line_consumer, TProtoStringType* out_error) { + TProtoStringType local_error; + Parser parser(line_consumer); + const void* buf; + int buf_len; + while (input_stream.Next(&buf, &buf_len)) { + if (buf_len == 0) { + continue; + } + + if (!parser.ParseChunk( + y_absl::string_view(static_cast<const char*>(buf), buf_len), + &local_error)) { + *out_error = y_absl::StrCat("error: ", stream_name, " Line ", + parser.last_line(), ", ", local_error); + return false; + } + } + if (!parser.Finish(&local_error)) { + *out_error = y_absl::StrCat("error: ", stream_name, " Line ", + parser.last_line(), ", ", local_error); + return false; + } + return true; +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/line_consumer.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/line_consumer.h new file mode 100644 index 00000000000..668fdb1d126 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/line_consumer.h @@ -0,0 +1,74 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_LINE_CONSUMER_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_LINE_CONSUMER_H__ + +#include <string> +#include <vector> + +#include "google/protobuf/io/zero_copy_stream.h" + +// Must be included last +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// TODO(b/250947994): PROTOC_EXPORT is only used to allow the CMake build to +// find/link these in the unittest, this is not public api. + +// Helper for parsing simple files. +class PROTOC_EXPORT LineConsumer { + public: + LineConsumer() = default; + virtual ~LineConsumer() = default; + virtual bool ConsumeLine(y_absl::string_view line, TProtoStringType* out_error) = 0; +}; + +bool PROTOC_EXPORT ParseSimpleFile(y_absl::string_view path, + LineConsumer* line_consumer, + TProtoStringType* out_error); + +bool PROTOC_EXPORT ParseSimpleStream(io::ZeroCopyInputStream& input_stream, + y_absl::string_view stream_name, + LineConsumer* line_consumer, + TProtoStringType* out_error); + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_LINE_CONSUMER_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/map_field.cc index 933f0ce73d1..96b777027c6 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/map_field.cc @@ -28,12 +28,16 @@ // (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 <map> +#include "google/protobuf/compiler/objectivec/map_field.h" + #include <string> +#include <vector> -#include <google/protobuf/compiler/objectivec/objectivec_map_field.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/io/printer.h> +#include "y_absl/container/btree_set.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/match.h" +#include "google/protobuf/compiler/objectivec/helpers.h" +#include "google/protobuf/compiler/objectivec/names.h" namespace google { namespace protobuf { @@ -75,16 +79,15 @@ const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) { // Some compilers report reaching end of function even though all cases of // the enum are handed in the switch. - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + Y_ABSL_LOG(FATAL) << "Can't get here."; + return nullptr; } } // namespace MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor) : RepeatedFieldGenerator(descriptor) { - const FieldDescriptor* key_descriptor = - descriptor->message_type()->map_key(); + const FieldDescriptor* key_descriptor = descriptor->message_type()->map_key(); const FieldDescriptor* value_descriptor = descriptor->message_type()->map_value(); value_field_generator_.reset(FieldGenerator::Make(value_descriptor)); @@ -96,21 +99,24 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor) // Build custom field flags. std::vector<TProtoStringType> field_flags; - field_flags.push_back("GPBFieldMapKey" + GetCapitalizedType(key_descriptor)); + field_flags.push_back( + y_absl::StrCat("GPBFieldMapKey", GetCapitalizedType(key_descriptor))); // Pull over the current text format custom name values that was calculated. - if (variables_["fieldflags"].find("GPBFieldTextFormatNameCustom") != - TProtoStringType::npos) { + if (y_absl::StrContains(variables_["fieldflags"], + "GPBFieldTextFormatNameCustom")) { field_flags.push_back("GPBFieldTextFormatNameCustom"); } // Pull over some info from the value's flags. const TProtoStringType& value_field_flags = value_field_generator_->variable("fieldflags"); - if (value_field_flags.find("GPBFieldHasDefaultValue") != TProtoStringType::npos) { + if (y_absl::StrContains(value_field_flags, "GPBFieldHasDefaultValue")) { field_flags.push_back("GPBFieldHasDefaultValue"); } - if (value_field_flags.find("GPBFieldHasEnumDescriptor") != - TProtoStringType::npos) { + if (y_absl::StrContains(value_field_flags, "GPBFieldHasEnumDescriptor")) { field_flags.push_back("GPBFieldHasEnumDescriptor"); + if (y_absl::StrContains(value_field_flags, "GPBFieldClosedEnum")) { + field_flags.push_back("GPBFieldClosedEnum"); + } } variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); @@ -124,18 +130,17 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor) value_is_object_type) { variables_["array_storage_type"] = "NSMutableDictionary"; variables_["array_property_type"] = - "NSMutableDictionary<NSString*, " + - value_field_generator_->variable("storage_type") + "*>"; + y_absl::StrCat("NSMutableDictionary<NSString*, ", + value_field_generator_->variable("storage_type"), "*>"); } else { - TProtoStringType class_name("GPB"); - class_name += MapEntryTypeName(key_descriptor, true); - class_name += MapEntryTypeName(value_descriptor, false); - class_name += "Dictionary"; + TProtoStringType class_name = + y_absl::StrCat("GPB", MapEntryTypeName(key_descriptor, true), + MapEntryTypeName(value_descriptor, false), "Dictionary"); variables_["array_storage_type"] = class_name; if (value_is_object_type) { variables_["array_property_type"] = - class_name + "<" + - value_field_generator_->variable("storage_type") + "*>"; + y_absl::StrCat(class_name, "<", + value_field_generator_->variable("storage_type"), "*>"); } } @@ -145,48 +150,57 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor) value_field_generator_->variable("dataTypeSpecific_value"); } -MapFieldGenerator::~MapFieldGenerator() {} - -void MapFieldGenerator::FinishInitialization(void) { +void MapFieldGenerator::FinishInitialization() { RepeatedFieldGenerator::FinishInitialization(); // Use the array_comment support in RepeatedFieldGenerator to output what the // values in the map are. const FieldDescriptor* value_descriptor = descriptor_->message_type()->map_value(); if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_ENUM) { + TProtoStringType name = variables_["name"]; variables_["array_comment"] = - "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n"; + y_absl::StrCat("// |", name, "| values are |", + value_field_generator_->variable("storage_type"), "|\n"); } } void MapFieldGenerator::DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, + y_absl::btree_set<TProtoStringType>* fwd_decls, bool include_external_types) const { - RepeatedFieldGenerator::DetermineForwardDeclarations( - fwd_decls, include_external_types); + RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls, + include_external_types); const FieldDescriptor* value_descriptor = descriptor_->message_type()->map_value(); + // NOTE: Maps with values of enums don't have to worry about adding the + // forward declaration because `GPB*EnumDictionary` isn't generic to the + // specific enum (like say `NSDictionary<String, MyMessage>`) and thus doesn't + // reference the type in the header. + if (GetObjectiveCType(value_descriptor) != OBJECTIVECTYPE_MESSAGE) { + return; + } + + const Descriptor* value_msg_descriptor = value_descriptor->message_type(); + // Within a file there is no requirement on the order of the messages, so // local references need a forward declaration. External files (not WKTs), // need one when requested. - if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE && - ((include_external_types && - !IsProtobufLibraryBundledProtoFile(value_descriptor->file())) || - descriptor_->file() == value_descriptor->file())) { + if ((include_external_types && + !IsProtobufLibraryBundledProtoFile(value_msg_descriptor->file())) || + descriptor_->file() == value_msg_descriptor->file()) { const TProtoStringType& value_storage_type = value_field_generator_->variable("storage_type"); - fwd_decls->insert("@class " + value_storage_type); + fwd_decls->insert(y_absl::StrCat("@class ", value_storage_type, ";")); } } void MapFieldGenerator::DetermineObjectiveCClassDefinitions( - std::set<TProtoStringType>* fwd_decls) const { + y_absl::btree_set<TProtoStringType>* fwd_decls) const { // Class name is already in "storage_type". const FieldDescriptor* value_descriptor = descriptor_->message_type()->map_value(); if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) { - fwd_decls->insert(ObjCClassDeclaration( - value_field_generator_->variable("storage_type"))); + fwd_decls->insert( + ObjCClassDeclaration(value_field_generator_->variable("storage_type"))); } } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/map_field.h index a75aa961d8f..d3ceb070d33 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_map_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/map_field.h @@ -31,9 +31,11 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__ -#include <map> +#include <memory> #include <string> -#include <google/protobuf/compiler/objectivec/objectivec_field.h> + +#include "y_absl/container/btree_set.h" +#include "google/protobuf/compiler/objectivec/field.h" namespace google { namespace protobuf { @@ -44,20 +46,19 @@ class MapFieldGenerator : public RepeatedFieldGenerator { friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); public: - virtual void FinishInitialization(void) override; + void FinishInitialization() override; MapFieldGenerator(const MapFieldGenerator&) = delete; MapFieldGenerator& operator=(const MapFieldGenerator&) = delete; protected: explicit MapFieldGenerator(const FieldDescriptor* descriptor); - virtual ~MapFieldGenerator(); + ~MapFieldGenerator() override = default; - virtual void DetermineObjectiveCClassDefinitions( - std::set<TProtoStringType>* fwd_decls) const override; - virtual void DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, - bool include_external_types) const override; + void DetermineObjectiveCClassDefinitions( + y_absl::btree_set<TProtoStringType>* fwd_decls) const override; + void DetermineForwardDeclarations(y_absl::btree_set<TProtoStringType>* fwd_decls, + bool include_external_types) const override; private: std::unique_ptr<FieldGenerator> value_field_generator_; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/message.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/message.cc new file mode 100644 index 00000000000..089314d3611 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/message.cc @@ -0,0 +1,631 @@ +// 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/objectivec/message.h" + +#include <algorithm> +#include <iostream> +#include <memory> +#include <sstream> +#include <string> +#include <vector> + +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/objectivec/extension.h" +#include "google/protobuf/compiler/objectivec/helpers.h" +#include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/compiler/objectivec/oneof.h" +#include "google/protobuf/compiler/objectivec/text_format_decode_data.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +bool IsMapEntryMessage(const Descriptor* descriptor) { + return descriptor->options().map_entry(); +} + +struct FieldOrderingByNumber { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + return a->number() < b->number(); + } +}; + +int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) { + // The first item in the object structure is our uint32[] for has bits. + // We then want to order things to make the instances as small as + // possible. So we follow the has bits with: + // 1. Anything always 4 bytes - float, *32, enums + // 2. Anything that is always a pointer (they will be 8 bytes on 64 bit + // builds and 4 bytes on 32bit builds. + // 3. Anything always 8 bytes - double, *64 + // + // NOTE: Bools aren't listed, they were stored in the has bits. + // + // Why? Using 64bit builds as an example, this means worse case, we have + // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes + // are wasted before the 4 byte values. Then if we have an odd number of + // those 4 byte values, the 8 byte values will be pushed down by 32bits to + // keep them aligned. But the structure will end 8 byte aligned, so no + // waste on the end. If you did the reverse order, you could waste 4 bytes + // before the first 8 byte value (after the has array), then a single + // bool on the end would need 7 bytes of padding to make the overall + // structure 8 byte aligned; so 11 bytes, wasted total. + + // Anything repeated is a GPB*Array/NSArray, so pointer. + if (descriptor->is_repeated()) { + return 3; + } + + switch (descriptor->type()) { + // All always 8 bytes. + case FieldDescriptor::TYPE_DOUBLE: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_SFIXED64: + case FieldDescriptor::TYPE_FIXED64: + return 4; + + // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes + // depending on the build architecture. + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + return 3; + + // All always 4 bytes (enums are int32s). + case FieldDescriptor::TYPE_FLOAT: + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_SFIXED32: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_ENUM: + return 2; + + // 0 bytes. Stored in the has bits. + case FieldDescriptor::TYPE_BOOL: + return 99; // End of the list (doesn't really matter). + } + + // Some compilers report reaching end of function even though all cases of + // the enum are handed in the switch. + Y_ABSL_LOG(FATAL) << "Can't get here."; + return 0; +} + +struct FieldOrderingByStorageSize { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + // Order by grouping. + const int order_group_a = OrderGroupForFieldDescriptor(a); + const int order_group_b = OrderGroupForFieldDescriptor(b); + if (order_group_a != order_group_b) { + return order_group_a < order_group_b; + } + // Within the group, order by field number (provides stable ordering). + return a->number() < b->number(); + } +}; + +struct ExtensionRangeOrdering { + bool operator()(const Descriptor::ExtensionRange* a, + const Descriptor::ExtensionRange* b) const { + return a->start < b->start; + } +}; + +// This is a reduced case of Descriptor::ExtensionRange with just start and end. +struct SimpleExtensionRange { + SimpleExtensionRange(int start, int end) : start(start), end(end){}; + int start; // inclusive + int end; // exclusive + + // Descriptors expose extension ranges in the order they were defined in the + // file, but this reorders and merges the ranges that are contiguous (i.e. - + // [(21,30),(10,20)] -> [(10,30)]) + static std::vector<SimpleExtensionRange> Normalize( + const Descriptor* descriptor) { + std::vector<const Descriptor::ExtensionRange*> sorted_extensions; + sorted_extensions.reserve(descriptor->extension_range_count()); + for (int i = 0; i < descriptor->extension_range_count(); ++i) { + sorted_extensions.push_back(descriptor->extension_range(i)); + } + + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeOrdering()); + + std::vector<SimpleExtensionRange> result; + result.reserve(sorted_extensions.size()); + for (const auto ext : sorted_extensions) { + if (!result.empty() && result.back().end == ext->start) { + result.back().end = ext->end; + } else { + result.emplace_back(ext->start, ext->end); + } + } + return result; + } +}; + +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor*[descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + std::sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); + return fields; +} + +// Sort the fields of the given Descriptor by storage size into a new[]'d +// array and return it. +const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor*[descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + std::sort(fields, fields + descriptor->field_count(), + FieldOrderingByStorageSize()); + return fields; +} + +} // namespace + +MessageGenerator::MessageGenerator(const TProtoStringType& file_description_name, + const Descriptor* descriptor) + : file_description_name_(file_description_name), + descriptor_(descriptor), + field_generators_(descriptor), + class_name_(ClassName(descriptor_)), + deprecated_attribute_(GetOptionalDeprecatedAttribute( + descriptor, descriptor->file(), false, true)) { + for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { + oneof_generators_.push_back( + std::make_unique<OneofGenerator>(descriptor_->oneof_decl(i))); + } + + // Assign has bits: + // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing + // who needs has bits and assigning them. + // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative + // index that groups all the elements in the oneof. + size_t num_has_bits = field_generators_.CalculateHasBits(); + size_t sizeof_has_storage = (num_has_bits + 31) / 32; + if (sizeof_has_storage == 0) { + // In the case where no field needs has bits, don't let the _has_storage_ + // end up as zero length (zero length arrays are sort of a grey area + // since it has to be at the start of the struct). This also ensures a + // field with only oneofs keeps the required negative indices they need. + sizeof_has_storage = 1; + } + // Tell all the fields the oneof base. + for (const auto& generator : oneof_generators_) { + generator->SetOneofIndexBase(sizeof_has_storage); + } + field_generators_.SetOneofIndexBase(sizeof_has_storage); + // sizeof_has_storage needs enough bits for the single fields that aren't in + // any oneof, and then one int32 for each oneof (to store the field number). + sizeof_has_storage += oneof_generators_.size(); + + sizeof_has_storage_ = sizeof_has_storage; +} + +void MessageGenerator::AddExtensionGenerators( + std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators->push_back(std::make_unique<ExtensionGenerator>( + class_name_, descriptor_->extension(i))); + extension_generators_.push_back(extension_generators->back().get()); + } +} + +void MessageGenerator::DetermineForwardDeclarations( + y_absl::btree_set<TProtoStringType>* fwd_decls, + bool include_external_types) const { + if (IsMapEntryMessage(descriptor_)) { + return; + } + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + field_generators_.get(fieldDescriptor) + .DetermineForwardDeclarations(fwd_decls, include_external_types); + } +} + +void MessageGenerator::DetermineObjectiveCClassDefinitions( + y_absl::btree_set<TProtoStringType>* fwd_decls) const { + if (!IsMapEntryMessage(descriptor_)) { + // Forward declare this class, as a linker symbol, so the symbol can be used + // to reference the class instead of calling +class later. + fwd_decls->insert(ObjCClassDeclaration(class_name_)); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + field_generators_.get(fieldDescriptor) + .DetermineObjectiveCClassDefinitions(fwd_decls); + } + } + + const Descriptor* containing_descriptor = descriptor_->containing_type(); + if (containing_descriptor != nullptr) { + TProtoStringType containing_class = ClassName(containing_descriptor); + fwd_decls->insert(ObjCClassDeclaration(containing_class)); + } +} + +void MessageGenerator::GenerateMessageHeader(io::Printer* printer) const { + // This a a map entry message, just recurse and do nothing directly. + if (IsMapEntryMessage(descriptor_)) { + return; + } + + printer->Print( + // clang-format off + "#pragma mark - $classname$\n" + "\n", + // clang-format on + "classname", class_name_); + + if (descriptor_->field_count()) { + std::unique_ptr<const FieldDescriptor*[]> sorted_fields( + SortFieldsByNumber(descriptor_)); + + printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", "classname", + class_name_); + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(sorted_fields[i]) + .GenerateFieldNumberConstant(printer); + } + + printer->Outdent(); + printer->Print("};\n\n"); + } + + for (const auto& generator : oneof_generators_) { + generator->GenerateCaseEnum(printer); + } + + TProtoStringType message_comments; + SourceLocation location; + if (descriptor_->GetSourceLocation(&location)) { + message_comments = BuildCommentsString(location, false); + } else { + message_comments = ""; + } + + printer->Print( + // clang-format off + "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n", + // clang-format on + "classname", class_name_, "deprecated_attribute", deprecated_attribute_, + "comments", message_comments); + + std::vector<char> seen_oneofs(oneof_generators_.size(), 0); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const OneofDescriptor* oneof = field->real_containing_oneof(); + if (oneof) { + const int oneof_index = oneof->index(); + if (!seen_oneofs[oneof_index]) { + seen_oneofs[oneof_index] = 1; + oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( + printer); + } + } + field_generators_.get(field).GeneratePropertyDeclaration(printer); + } + + printer->Print("@end\n\n"); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateCFunctionDeclarations(printer); + } + + if (!oneof_generators_.empty()) { + for (const auto& generator : oneof_generators_) { + generator->GenerateClearFunctionDeclaration(printer); + } + printer->Print("\n"); + } + + if (descriptor_->extension_count() > 0) { + printer->Print("@interface $classname$ (DynamicMethods)\n\n", "classname", + class_name_); + for (const auto generator : extension_generators_) { + generator->GenerateMembersHeader(printer); + } + printer->Print("@end\n\n"); + } +} + +void MessageGenerator::GenerateSource(io::Printer* printer) const { + if (IsMapEntryMessage(descriptor_)) { + return; + } + printer->Print( + // clang-format off + "#pragma mark - $classname$\n" + "\n", + // clang-format on + "classname", class_name_); + + if (!deprecated_attribute_.empty()) { + // No warnings when compiling the impl of this deprecated class. + // clang-format off + printer->Print( + "#pragma clang diagnostic push\n" + "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n" + "\n"); + // clang-format on + } + + printer->Print("@implementation $classname$\n\n", "classname", class_name_); + + for (const auto& generator : oneof_generators_) { + generator->GeneratePropertyImplementation(printer); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GeneratePropertyImplementation(printer); + } + + std::unique_ptr<const FieldDescriptor*[]> sorted_fields( + SortFieldsByNumber(descriptor_)); + std::unique_ptr<const FieldDescriptor*[]> size_order_fields( + SortFieldsByStorageSize(descriptor_)); + + std::vector<SimpleExtensionRange> sorted_extensions( + SimpleExtensionRange::Normalize(descriptor_)); + + printer->Print( + // clang-format off + "\n" + "typedef struct $classname$__storage_ {\n" + " arc_ui32 _has_storage_[$sizeof_has_storage$];\n", + // clang-format on + "classname", class_name_, "sizeof_has_storage", + y_absl::StrCat(sizeof_has_storage_)); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(size_order_fields[i]) + .GenerateFieldStorageDeclaration(printer); + } + printer->Outdent(); + + printer->Print("} $classname$__storage_;\n\n", "classname", class_name_); + + // clang-format off + printer->Print( + "// This method is threadsafe because it is initially called\n" + "// in +initialize for each subclass.\n" + "+ (GPBDescriptor *)descriptor {\n" + " static GPBDescriptor *descriptor = nil;\n" + " if (!descriptor) {\n"); + // clang-format on + + // If the message scopes extensions, trigger the root class + // +initialize/+extensionRegistry as that is where the runtime support for + // extensions lives. + if (descriptor_->extension_count() > 0) { + // clang-format off + printer->Print( + " // Start up the root class to support the scoped extensions.\n" + " __unused Class rootStartup = [$root_class_name$ class];\n", + "root_class_name", FileClassName(descriptor_->file())); + // clang-format on + } else { + // The Root class has a debug runtime check, so if not starting that + // up, add the check. + printer->Print(" GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"); + } + + TextFormatDecodeData text_format_decode_data; + bool has_fields = descriptor_->field_count() > 0; + bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault(); + TProtoStringType field_description_type; + if (need_defaults) { + field_description_type = "GPBMessageFieldDescriptionWithDefault"; + } else { + field_description_type = "GPBMessageFieldDescription"; + } + if (has_fields) { + printer->Indent(); + printer->Indent(); + printer->Print("static $field_description_type$ fields[] = {\n", + "field_description_type", field_description_type); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); ++i) { + const FieldGenerator& field_generator = + field_generators_.get(sorted_fields[i]); + field_generator.GenerateFieldDescription(printer, need_defaults); + if (field_generator.needs_textformat_name_support()) { + text_format_decode_data.AddString(sorted_fields[i]->number(), + field_generator.generated_objc_name(), + field_generator.raw_field_name()); + } + } + printer->Outdent(); + printer->Print("};\n"); + printer->Outdent(); + printer->Outdent(); + } + + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> vars; + vars["classname"] = class_name_; + vars["message_name"] = descriptor_->name(); + vars["class_reference"] = ObjCClass(class_name_); + vars["file_description_name"] = file_description_name_; + vars["fields"] = has_fields ? "fields" : "NULL"; + if (has_fields) { + vars["fields_count"] = y_absl::StrCat("(arc_ui32)(sizeof(fields) / sizeof(", + field_description_type, "))"); + } else { + vars["fields_count"] = "0"; + } + + std::vector<TProtoStringType> init_flags; + init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs"); + init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown"); + init_flags.push_back( + "GPBDescriptorInitializationFlag_ClosedEnumSupportKnown"); + if (need_defaults) { + init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault"); + } + if (descriptor_->options().message_set_wire_format()) { + init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat"); + } + vars["init_flags"] = + BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION, init_flags); + + // clang-format off + printer->Print( + vars, + " GPBDescriptor *localDescriptor =\n" + " [GPBDescriptor allocDescriptorForClass:$class_reference$\n" + " messageName:@\"$message_name$\"\n" + " fileDescription:&$file_description_name$\n" + " fields:$fields$\n" + " fieldCount:$fields_count$\n" + " storageSize:sizeof($classname$__storage_)\n" + " flags:$init_flags$];\n"); + // clang-format on + if (!oneof_generators_.empty()) { + printer->Print(" static const char *oneofs[] = {\n"); + for (const auto& generator : oneof_generators_) { + printer->Print(" \"$name$\",\n", "name", + generator->DescriptorName()); + } + printer->Print( + // clang-format off + " };\n" + " [localDescriptor setupOneofs:oneofs\n" + " count:(arc_ui32)(sizeof(oneofs) / sizeof(char*))\n" + " firstHasIndex:$first_has_index$];\n", + // clang-format on + "first_has_index", oneof_generators_[0]->HasIndexAsString()); + } + if (text_format_decode_data.num_entries() != 0) { + const TProtoStringType text_format_data_str(text_format_decode_data.Data()); + // clang-format off + printer->Print( + "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" + " static const char *extraTextFormatInfo ="); + // clang-format on + static const int kBytesPerLine = 40; // allow for escaping + for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) { + printer->Print("\n \"$data$\"", "data", + EscapeTrigraphs(y_absl::CEscape( + text_format_data_str.substr(i, kBytesPerLine)))); + } + // clang-format off + printer->Print( + ";\n" + " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n" + "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"); + // clang-format on + } + if (!sorted_extensions.empty()) { + printer->Print(" static const GPBExtensionRange ranges[] = {\n"); + for (const auto& extension_range : sorted_extensions) { + printer->Print(" { .start = $start$, .end = $end$ },\n", "start", + y_absl::StrCat(extension_range.start), "end", + y_absl::StrCat(extension_range.end)); + } + // clang-format off + printer->Print( + " };\n" + " [localDescriptor setupExtensionRanges:ranges\n" + " count:(arc_ui32)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); + // clang-format on + } + if (descriptor_->containing_type() != nullptr) { + TProtoStringType containing_class = ClassName(descriptor_->containing_type()); + TProtoStringType parent_class_ref = ObjCClass(containing_class); + printer->Print( + // clang-format off + " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n", + // clang-format on + "parent_class_ref", parent_class_ref); + } + // clang-format off + printer->Print( + " #if defined(DEBUG) && DEBUG\n" + " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" + " #endif // DEBUG\n" + " descriptor = localDescriptor;\n" + " }\n" + " return descriptor;\n" + "}\n\n" + "@end\n\n"); + // clang-format on + + if (!deprecated_attribute_.empty()) { + // clang-format off + printer->Print( + "#pragma clang diagnostic pop\n" + "\n"); + // clang-format on + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateCFunctionImplementations(printer); + } + + for (const auto& generator : oneof_generators_) { + generator->GenerateClearFunctionImplementation(printer); + } +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/message.h index 71eec0d0c71..c4698371b7f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/message.h @@ -31,13 +31,16 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__ +#include <cstddef> +#include <memory> #include <string> -#include <set> #include <vector> -#include <google/protobuf/compiler/objectivec/objectivec_field.h> -#include <google/protobuf/compiler/objectivec/objectivec_oneof.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/io/printer.h> + +#include "y_absl/container/btree_set.h" +#include "google/protobuf/compiler/objectivec/field.h" +#include "google/protobuf/compiler/objectivec/oneof.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -45,50 +48,39 @@ namespace compiler { namespace objectivec { class ExtensionGenerator; -class EnumGenerator; class MessageGenerator { public: - MessageGenerator(const TProtoStringType& root_classname, + MessageGenerator(const TProtoStringType& file_description_name, const Descriptor* descriptor); - ~MessageGenerator(); + ~MessageGenerator() = default; MessageGenerator(const MessageGenerator&) = delete; MessageGenerator& operator=(const MessageGenerator&) = delete; - void GenerateStaticVariablesInitialization(io::Printer* printer); - void GenerateEnumHeader(io::Printer* printer); - void GenerateMessageHeader(io::Printer* printer); - void GenerateSource(io::Printer* printer); - void GenerateExtensionRegistrationSource(io::Printer* printer); - void DetermineObjectiveCClassDefinitions(std::set<TProtoStringType>* fwd_decls); - void DetermineForwardDeclarations(std::set<TProtoStringType>* fwd_decls, - bool include_external_types); + void AddExtensionGenerators( + std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators); + + void GenerateMessageHeader(io::Printer* printer) const; + void GenerateSource(io::Printer* printer) const; + void DetermineObjectiveCClassDefinitions( + y_absl::btree_set<TProtoStringType>* fwd_decls) const; + void DetermineForwardDeclarations(y_absl::btree_set<TProtoStringType>* fwd_decls, + bool include_external_types) const; // Checks if the message or a nested message includes a oneof definition. - bool IncludesOneOfDefinition() const; + bool IncludesOneOfDefinition() const { return !oneof_generators_.empty(); } private: - void GenerateParseFromMethodsHeader(io::Printer* printer); - - void GenerateSerializeOneFieldSource(io::Printer* printer, - const FieldDescriptor* field); - void GenerateSerializeOneExtensionRangeSource( - io::Printer* printer, const Descriptor::ExtensionRange* range); - - void GenerateMessageDescriptionSource(io::Printer* printer); - void GenerateDescriptionOneFieldSource(io::Printer* printer, - const FieldDescriptor* field); - const TProtoStringType root_classname_; + const TProtoStringType file_description_name_; const Descriptor* descriptor_; FieldGeneratorMap field_generators_; const TProtoStringType class_name_; const TProtoStringType deprecated_attribute_; - std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_; - std::vector<std::unique_ptr<EnumGenerator>> enum_generators_; - std::vector<std::unique_ptr<MessageGenerator>> nested_message_generators_; + std::vector<const ExtensionGenerator*> extension_generators_; std::vector<std::unique_ptr<OneofGenerator>> oneof_generators_; + size_t sizeof_has_storage_; }; } // namespace objectivec diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/message_field.cc index 8ae073a12ad..5156b4f21ff 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/message_field.cc @@ -28,12 +28,14 @@ // (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 <map> +#include "google/protobuf/compiler/objectivec/message_field.h" + #include <string> -#include <google/protobuf/compiler/objectivec/objectivec_message_field.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/io/printer.h> +#include "y_absl/container/btree_set.h" +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/compiler/objectivec/helpers.h" +#include "google/protobuf/compiler/objectivec/names.h" namespace google { namespace protobuf { @@ -42,8 +44,9 @@ namespace objectivec { namespace { -void SetMessageVariables(const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetMessageVariables( + const FieldDescriptor* descriptor, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { const TProtoStringType& message_type = ClassName(descriptor->message_type()); const TProtoStringType& containing_class = ClassName(descriptor->containing_type()); @@ -62,26 +65,24 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor) SetMessageVariables(descriptor, &variables_); } -MessageFieldGenerator::~MessageFieldGenerator() {} - void MessageFieldGenerator::DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, + y_absl::btree_set<TProtoStringType>* fwd_decls, bool include_external_types) const { - ObjCObjFieldGenerator::DetermineForwardDeclarations( - fwd_decls, include_external_types); + ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls, + include_external_types); // Within a file there is no requirement on the order of the messages, so // local references need a forward declaration. External files (not WKTs), // need one when requested. - if ((include_external_types && - !IsProtobufLibraryBundledProtoFile(descriptor_->message_type()->file())) || + if ((include_external_types && !IsProtobufLibraryBundledProtoFile( + descriptor_->message_type()->file())) || descriptor_->file() == descriptor_->message_type()->file()) { // Class name is already in "storage_type". - fwd_decls->insert("@class " + variable("storage_type")); + fwd_decls->insert(y_absl::StrCat("@class ", variable("storage_type"), ";")); } } void MessageFieldGenerator::DetermineObjectiveCClassDefinitions( - std::set<TProtoStringType>* fwd_decls) const { + y_absl::btree_set<TProtoStringType>* fwd_decls) const { fwd_decls->insert(ObjCClassDeclaration(variable("storage_type"))); } @@ -89,31 +90,30 @@ RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( const FieldDescriptor* descriptor) : RepeatedFieldGenerator(descriptor) { SetMessageVariables(descriptor, &variables_); + TProtoStringType storage_type = variables_["storage_type"]; variables_["array_storage_type"] = "NSMutableArray"; variables_["array_property_type"] = - "NSMutableArray<" + variables_["storage_type"] + "*>"; + y_absl::StrCat("NSMutableArray<", storage_type, "*>"); } -RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} - void RepeatedMessageFieldGenerator::DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, + y_absl::btree_set<TProtoStringType>* fwd_decls, bool include_external_types) const { - RepeatedFieldGenerator::DetermineForwardDeclarations( - fwd_decls, include_external_types); + RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls, + include_external_types); // Within a file there is no requirement on the order of the messages, so // local references need a forward declaration. External files (not WKTs), // need one when requested. - if ((include_external_types && - !IsProtobufLibraryBundledProtoFile(descriptor_->message_type()->file())) || + if ((include_external_types && !IsProtobufLibraryBundledProtoFile( + descriptor_->message_type()->file())) || descriptor_->file() == descriptor_->message_type()->file()) { // Class name is already in "storage_type". - fwd_decls->insert("@class " + variable("storage_type")); + fwd_decls->insert(y_absl::StrCat("@class ", variable("storage_type"), ";")); } } void RepeatedMessageFieldGenerator::DetermineObjectiveCClassDefinitions( - std::set<TProtoStringType>* fwd_decls) const { + y_absl::btree_set<TProtoStringType>* fwd_decls) const { fwd_decls->insert(ObjCClassDeclaration(variable("storage_type"))); } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/message_field.h index 50ddb633cc9..303b69a7c6c 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/message_field.h @@ -31,9 +31,10 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__ -#include <map> #include <string> -#include <google/protobuf/compiler/objectivec/objectivec_field.h> + +#include "y_absl/container/btree_set.h" +#include "google/protobuf/compiler/objectivec/field.h" namespace google { namespace protobuf { @@ -45,18 +46,16 @@ class MessageFieldGenerator : public ObjCObjFieldGenerator { protected: explicit MessageFieldGenerator(const FieldDescriptor* descriptor); + ~MessageFieldGenerator() override = default; MessageFieldGenerator(const MessageFieldGenerator&) = delete; MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete; - virtual ~MessageFieldGenerator(); - public: - virtual void DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, - bool include_external_types) const override; - virtual void DetermineObjectiveCClassDefinitions( - std::set<TProtoStringType>* fwd_decls) const override; + void DetermineForwardDeclarations(y_absl::btree_set<TProtoStringType>* fwd_decls, + bool include_external_types) const override; + void DetermineObjectiveCClassDefinitions( + y_absl::btree_set<TProtoStringType>* fwd_decls) const override; }; class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator { @@ -64,17 +63,17 @@ class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator { protected: explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor); - virtual ~RepeatedMessageFieldGenerator(); + ~RepeatedMessageFieldGenerator() override = default; RepeatedMessageFieldGenerator(const RepeatedMessageFieldGenerator&) = delete; - RepeatedMessageFieldGenerator operator=(const RepeatedMessageFieldGenerator&) = delete; + RepeatedMessageFieldGenerator operator=( + const RepeatedMessageFieldGenerator&) = delete; public: - virtual void DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, - bool include_external_types) const override; - virtual void DetermineObjectiveCClassDefinitions( - std::set<TProtoStringType>* fwd_decls) const override; + void DetermineForwardDeclarations(y_absl::btree_set<TProtoStringType>* fwd_decls, + bool include_external_types) const override; + void DetermineObjectiveCClassDefinitions( + y_absl::btree_set<TProtoStringType>* fwd_decls) const override; }; } // namespace objectivec diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/names.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/names.cc new file mode 100644 index 00000000000..3a3ee8ffd05 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/names.cc @@ -0,0 +1,1247 @@ +// 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/objectivec/names.h" + +#include <algorithm> +#include <climits> +#include <fstream> +#include <iostream> +#include <ostream> +#include <sstream> +#include <string> +#include <vector> + +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_split.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/objectivec/line_consumer.h" +#include "google/protobuf/compiler/objectivec/nsobject_methods.h" +#include "google/protobuf/descriptor.pb.h" + +// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some +// error cases, so it seems to be ok to use as a back door for errors. + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +bool BoolFromEnvVar(const char* env_var, bool default_value) { + const char* value = getenv(env_var); + if (value) { + return TProtoStringType("YES") == y_absl::AsciiStrToUpper(value); + } + return default_value; +} + +class SimpleLineCollector : public LineConsumer { + public: + explicit SimpleLineCollector(y_absl::flat_hash_set<TProtoStringType>* inout_set) + : set_(inout_set) {} + + bool ConsumeLine(y_absl::string_view line, TProtoStringType* out_error) override { + set_->insert(TProtoStringType(line)); + return true; + } + + private: + y_absl::flat_hash_set<TProtoStringType>* set_; +}; + +class PackageToPrefixesCollector : public LineConsumer { + public: + PackageToPrefixesCollector(y_absl::string_view usage, + y_absl::flat_hash_map<TProtoStringType, TProtoStringType>* + inout_package_to_prefix_map) + : usage_(usage), prefix_map_(inout_package_to_prefix_map) {} + + bool ConsumeLine(y_absl::string_view line, TProtoStringType* out_error) override; + + private: + const TProtoStringType usage_; + y_absl::flat_hash_map<TProtoStringType, TProtoStringType>* prefix_map_; +}; + +class PrefixModeStorage { + public: + PrefixModeStorage(); + + y_absl::string_view package_to_prefix_mappings_path() const { + return package_to_prefix_mappings_path_; + } + void set_package_to_prefix_mappings_path(y_absl::string_view path) { + package_to_prefix_mappings_path_ = TProtoStringType(path); + package_to_prefix_map_.clear(); + } + + y_absl::string_view prefix_from_proto_package_mappings( + const FileDescriptor* file); + + bool use_package_name() const { return use_package_name_; } + void set_use_package_name(bool on_or_off) { use_package_name_ = on_or_off; } + + y_absl::string_view exception_path() const { return exception_path_; } + void set_exception_path(y_absl::string_view path) { + exception_path_ = TProtoStringType(path); + exceptions_.clear(); + } + + bool is_package_exempted(y_absl::string_view package); + + // When using a proto package as the prefix, this should be added as the + // prefix in front of it. + y_absl::string_view forced_package_prefix() const { return forced_prefix_; } + void set_forced_package_prefix(y_absl::string_view prefix) { + forced_prefix_ = TProtoStringType(prefix); + } + + private: + bool use_package_name_; + y_absl::flat_hash_map<TProtoStringType, TProtoStringType> package_to_prefix_map_; + TProtoStringType package_to_prefix_mappings_path_; + TProtoStringType exception_path_; + TProtoStringType forced_prefix_; + y_absl::flat_hash_set<TProtoStringType> exceptions_; +}; + +PrefixModeStorage::PrefixModeStorage() { + // Even thought there are generation options, have an env back door since some + // of these helpers could be used in other plugins. + + use_package_name_ = BoolFromEnvVar("GPB_OBJC_USE_PACKAGE_AS_PREFIX", false); + + const char* exception_path = + getenv("GPB_OBJC_PACKAGE_PREFIX_EXCEPTIONS_PATH"); + if (exception_path) { + exception_path_ = exception_path; + } + + const char* prefix = getenv("GPB_OBJC_USE_PACKAGE_AS_PREFIX_PREFIX"); + if (prefix) { + forced_prefix_ = prefix; + } +} + +constexpr y_absl::string_view kNoPackagePrefix = "no_package:"; + +y_absl::string_view PrefixModeStorage::prefix_from_proto_package_mappings( + const FileDescriptor* file) { + if (!file) { + return ""; + } + + if (package_to_prefix_map_.empty() && + !package_to_prefix_mappings_path_.empty()) { + TProtoStringType error_str; + // Re use the same collector as we use for expected_prefixes_path since the + // file format is the same. + PackageToPrefixesCollector collector("Package to prefixes", + &package_to_prefix_map_); + if (!ParseSimpleFile(package_to_prefix_mappings_path_, &collector, + &error_str)) { + if (error_str.empty()) { + error_str = y_absl::StrCat("protoc:0: warning: Failed to parse ", + "prefix to proto package mappings file: ", + package_to_prefix_mappings_path_); + } + std::cerr << error_str << std::endl; + std::cerr.flush(); + package_to_prefix_map_.clear(); + } + } + + const TProtoStringType package = file->package(); + // For files without packages, the can be registered as "no_package:PATH", + // allowing the expected prefixes file. + const TProtoStringType lookup_key = + package.empty() ? y_absl::StrCat(kNoPackagePrefix, file->name()) : package; + + auto prefix_lookup = package_to_prefix_map_.find(lookup_key); + + if (prefix_lookup != package_to_prefix_map_.end()) { + return prefix_lookup->second; + } + + return ""; +} + +bool PrefixModeStorage::is_package_exempted(y_absl::string_view package) { + if (exceptions_.empty() && !exception_path_.empty()) { + TProtoStringType error_str; + SimpleLineCollector collector(&exceptions_); + if (!ParseSimpleFile(exception_path_, &collector, &error_str)) { + if (error_str.empty()) { + error_str = TProtoStringType("protoc:0: warning: Failed to parse") + + TProtoStringType(" package prefix exceptions file: ") + + exception_path_; + } + std::cerr << error_str << std::endl; + std::cerr.flush(); + exceptions_.clear(); + } + + // If the file was empty put something in it so it doesn't get reloaded over + // and over. + if (exceptions_.empty()) { + exceptions_.insert("<not a real package>"); + } + } + + return exceptions_.contains(package); +} + +PrefixModeStorage& g_prefix_mode = *new PrefixModeStorage(); + +} // namespace + +y_absl::string_view GetPackageToPrefixMappingsPath() { + return g_prefix_mode.package_to_prefix_mappings_path(); +} + +void SetPackageToPrefixMappingsPath(y_absl::string_view file_path) { + g_prefix_mode.set_package_to_prefix_mappings_path(file_path); +} + +bool UseProtoPackageAsDefaultPrefix() { + return g_prefix_mode.use_package_name(); +} + +void SetUseProtoPackageAsDefaultPrefix(bool on_or_off) { + g_prefix_mode.set_use_package_name(on_or_off); +} + +y_absl::string_view GetProtoPackagePrefixExceptionList() { + return g_prefix_mode.exception_path(); +} + +void SetProtoPackagePrefixExceptionList(y_absl::string_view file_path) { + g_prefix_mode.set_exception_path(file_path); +} + +y_absl::string_view GetForcedPackagePrefix() { + return g_prefix_mode.forced_package_prefix(); +} + +void SetForcedPackagePrefix(y_absl::string_view prefix) { + g_prefix_mode.set_forced_package_prefix(prefix); +} + +namespace { + +const char* const kUpperSegmentsList[] = {"url", "http", "https"}; + +const y_absl::flat_hash_set<y_absl::string_view>& UpperSegments() { + static const auto* words = [] { + auto* words = new y_absl::flat_hash_set<y_absl::string_view>(); + + for (const auto word : kUpperSegmentsList) { + words->emplace(word); + } + return words; + }(); + return *words; +} + +// Internal helper for name handing. +// Do not expose this outside of helpers, stick to having functions for specific +// cases (ClassName(), FieldName()), so there is always consistent suffix rules. +TProtoStringType UnderscoresToCamelCase(y_absl::string_view input, + bool first_capitalized) { + std::vector<TProtoStringType> values; + TProtoStringType current; + + bool last_char_was_number = false; + bool last_char_was_lower = false; + bool last_char_was_upper = false; + for (int i = 0; i < input.size(); i++) { + char c = input[i]; + if (y_absl::ascii_isdigit(c)) { + if (!last_char_was_number) { + values.push_back(current); + current = ""; + } + current += c; + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + last_char_was_number = true; + } else if (y_absl::ascii_islower(c)) { + // lowercase letter can follow a lowercase or uppercase letter + if (!last_char_was_lower && !last_char_was_upper) { + values.push_back(current); + current = ""; + } + current += c; // already lower + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + last_char_was_lower = true; + } else if (y_absl::ascii_isupper(c)) { + if (!last_char_was_upper) { + values.push_back(current); + current = ""; + } + current += y_absl::ascii_tolower(c); + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + last_char_was_upper = true; + } else { + last_char_was_number = last_char_was_lower = last_char_was_upper = false; + } + } + values.push_back(current); + + TProtoStringType result; + bool first_segment_forces_upper = false; + for (auto& value : values) { + bool all_upper = UpperSegments().contains(value); + if (all_upper && (result.length() == 0)) { + first_segment_forces_upper = true; + } + if (all_upper) { + y_absl::AsciiStrToUpper(&value); + } else { + value[0] = y_absl::ascii_toupper(value[0]); + } + result += value; + } + if ((result.length() != 0) && !first_capitalized && + !first_segment_forces_upper) { + result[0] = y_absl::ascii_tolower(result[0]); + } + return result; +} + +const char* const kReservedWordList[] = { + // Note NSObject Methods: + // These are brought in from nsobject_methods.h that is generated + // using method_dump.sh. See kNSObjectMethods below. + + // Objective-C "keywords" that aren't in C + // From + // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c + // with some others added on. + "id", + "_cmd", + "super", + "in", + "out", + "inout", + "bycopy", + "byref", + "oneway", + "self", + "instancetype", + "nullable", + "nonnull", + "nil", + "Nil", + "YES", + "NO", + "weak", + + // C/C++ keywords (Incl C++ 0x11) + // From http://en.cppreference.com/w/cpp/keywords + "and", + "and_eq", + "alignas", + "alignof", + "asm", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "char16_t", + "char32_t", + "class", + "compl", + "const", + "constexpr", + "const_cast", + "continue", + "decltype", + "default", + "delete", + "double", + "dynamic_cast", + "else", + "enum", + "explicit", + "export", + "extern ", + "false", + "float", + "for", + "friend", + "goto", + "if", + "inline", + "int", + "long", + "mutable", + "namespace", + "new", + "noexcept", + "not", + "not_eq", + "nullptr", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "register", + "reinterpret_cast", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "static_cast", + "struct", + "switch", + "template", + "this", + "thread_local", + "throw", + "true", + "try", + "typedef", + "typeid", + "typename", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "xor", + "xor_eq", + + // C99 keywords + // From + // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm + "restrict", + + // GCC/Clang extension + "typeof", + + // Not a keyword, but will break you + "NULL", + + // C88+ specs call for these to be macros, so depending on what they are + // defined to be it can lead to odd errors for some Xcode/SDK versions. + "stdin", + "stdout", + "stderr", + + // Objective-C Runtime typedefs + // From <obc/runtime.h> + "Category", + "Ivar", + "Method", + "Protocol", + + // GPBMessage Methods + // Only need to add instance methods that may conflict with + // method declared in protos. The main cases are methods + // that take no arguments, or setFoo:/hasFoo: type methods. + "clear", + "data", + "delimitedData", + "descriptor", + "extensionRegistry", + "extensionsCurrentlySet", + "initialized", + "isInitialized", + "serializedSize", + "sortedExtensionsInUse", + "unknownFields", + + // MacTypes.h names + "Fixed", + "Fract", + "Size", + "LogicalAddress", + "PhysicalAddress", + "ByteCount", + "ByteOffset", + "Duration", + "AbsoluteTime", + "OptionBits", + "ItemCount", + "PBVersion", + "ScriptCode", + "LangCode", + "RegionCode", + "OSType", + "ProcessSerialNumber", + "Point", + "Rect", + "FixedPoint", + "FixedRect", + "Style", + "StyleParameter", + "StyleField", + "TimeScale", + "TimeBase", + "TimeRecord", +}; + +const y_absl::flat_hash_set<y_absl::string_view>& ReservedWords() { + static const auto* words = [] { + auto* words = new y_absl::flat_hash_set<y_absl::string_view>(); + + for (const auto word : kReservedWordList) { + words->emplace(word); + } + return words; + }(); + return *words; +} + +const y_absl::flat_hash_set<y_absl::string_view>& NSObjectMethods() { + static const auto* words = [] { + auto* words = new y_absl::flat_hash_set<y_absl::string_view>(); + + for (const auto word : kNSObjectMethodsList) { + words->emplace(word); + } + return words; + }(); + return *words; +} + +// returns true is input starts with __ or _[A-Z] which are reserved identifiers +// in C/ C++. All calls should go through UnderscoresToCamelCase before getting +// here but this verifies and allows for future expansion if we decide to +// redefine what a reserved C identifier is (for example the GNU list +// https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html ) +bool IsReservedCIdentifier(y_absl::string_view input) { + if (input.length() > 2) { + if (input.at(0) == '_') { + if (isupper(input.at(1)) || input.at(1) == '_') { + return true; + } + } + } + return false; +} + +TProtoStringType SanitizeNameForObjC(y_absl::string_view prefix, + y_absl::string_view input, + y_absl::string_view extension, + TProtoStringType* out_suffix_added) { + TProtoStringType sanitized; + // We add the prefix in the cases where the string is missing a prefix. + // We define "missing a prefix" as where 'input': + // a) Doesn't start with the prefix or + // b) Isn't equivalent to the prefix or + // c) Has the prefix, but the letter after the prefix is lowercase + if (y_absl::StartsWith(input, prefix)) { + if (input.length() == prefix.length() || + !y_absl::ascii_isupper(input[prefix.length()])) { + sanitized = y_absl::StrCat(prefix, input); + } else { + sanitized = TProtoStringType(input); + } + } else { + sanitized = y_absl::StrCat(prefix, input); + } + if (IsReservedCIdentifier(sanitized) || ReservedWords().contains(sanitized) || + NSObjectMethods().contains(sanitized)) { + if (out_suffix_added) *out_suffix_added = TProtoStringType(extension); + return y_absl::StrCat(sanitized, extension); + } + if (out_suffix_added) out_suffix_added->clear(); + return sanitized; +} + +TProtoStringType NameFromFieldDescriptor(const FieldDescriptor* field) { + if (field->type() == FieldDescriptor::TYPE_GROUP) { + return field->message_type()->name(); + } else { + return field->name(); + } +} + +void PathSplit(y_absl::string_view path, TProtoStringType* directory, + TProtoStringType* basename) { + y_absl::string_view::size_type last_slash = path.rfind('/'); + if (last_slash == y_absl::string_view::npos) { + if (directory) { + *directory = ""; + } + if (basename) { + *basename = TProtoStringType(path); + } + } else { + if (directory) { + *directory = TProtoStringType(path.substr(0, last_slash)); + } + if (basename) { + *basename = TProtoStringType(path.substr(last_slash + 1)); + } + } +} + +bool IsSpecialNamePrefix(y_absl::string_view name, + const std::vector<TProtoStringType>& special_names) { + for (const auto& special_name : special_names) { + const size_t length = special_name.length(); + if (name.compare(0, length, special_name) == 0) { + if (name.length() > length) { + // If name is longer than the special_name that it matches the next + // character must be not lower case (newton vs newTon vs new_ton). + return !y_absl::ascii_islower(name[length]); + } else { + return true; + } + } + } + return false; +} + +void MaybeUnQuote(y_absl::string_view* input) { + if ((input->length() >= 2) && + ((*input->data() == '\'' || *input->data() == '"')) && + ((*input)[input->length() - 1] == *input->data())) { + input->remove_prefix(1); + input->remove_suffix(1); + } +} + +} // namespace + +bool IsRetainedName(y_absl::string_view name) { + // List of prefixes from + // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html + static const std::vector<TProtoStringType>* retained_names = + new std::vector<TProtoStringType>({"new", "alloc", "copy", "mutableCopy"}); + return IsSpecialNamePrefix(name, *retained_names); +} + +bool IsInitName(y_absl::string_view name) { + static const std::vector<TProtoStringType>* init_names = + new std::vector<TProtoStringType>({"init"}); + return IsSpecialNamePrefix(name, *init_names); +} + +bool IsCreateName(y_absl::string_view name) { + // List of segments from + // https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html#//apple_ref/doc/uid/20001148-103029 + static const std::vector<TProtoStringType>* create_names = + new std::vector<TProtoStringType>({"Create", "Copy"}); + + for (const auto& create_name : *create_names) { + const size_t length = create_name.length(); + size_t pos = name.find(create_name); + if (pos != TProtoStringType::npos) { + // The above docs don't actually call out anything about the characters + // before the special words. So it's not clear if something like + // "FOOCreate" would or would not match the "The Create Rule", but by not + // checking, and claiming it does match, then callers will annotate with + // `cf_returns_not_retained` which will ensure things work as desired. + // + // The footnote here is the docs do have a passing reference to "NoCopy", + // but again, not looking for that and just returning `true` will cause + // callers to annotate the api as not being a Create Rule function. + + // If name is longer than the create_names[i] that it matches the next + // character must be not lower case (Copyright vs CopyFoo vs Copy_Foo). + if (name.length() > pos + length) { + return !y_absl::ascii_islower(name[pos + length]); + } else { + return true; + } + } + } + return false; +} + +TProtoStringType BaseFileName(const FileDescriptor* file) { + TProtoStringType basename; + PathSplit(file->name(), nullptr, &basename); + return basename; +} + +TProtoStringType FileClassPrefix(const FileDescriptor* file) { + // Always honor the file option. + if (file->options().has_objc_class_prefix()) { + return file->options().objc_class_prefix(); + } + + // If package prefix is specified in an prefix to proto mappings file then use + // that. + y_absl::string_view objc_class_prefix = + g_prefix_mode.prefix_from_proto_package_mappings(file); + if (!objc_class_prefix.empty()) { + return TProtoStringType(objc_class_prefix); + } + + // If package prefix isn't enabled, done. + if (!g_prefix_mode.use_package_name()) { + return ""; + } + + // If the package is in the exceptions list, done. + if (g_prefix_mode.is_package_exempted(file->package())) { + return ""; + } + + // Transform the package into a prefix: use the dot segments as part, + // camelcase each one and then join them with underscores, and add an + // underscore at the end. + TProtoStringType result; + const std::vector<TProtoStringType> segments = + y_absl::StrSplit(file->package(), '.', y_absl::SkipEmpty()); + for (const auto& segment : segments) { + const TProtoStringType part = UnderscoresToCamelCase(segment, true); + if (part.empty()) { + continue; + } + if (!result.empty()) { + result.append("_"); + } + result.append(part); + } + if (!result.empty()) { + result.append("_"); + } + return y_absl::StrCat(g_prefix_mode.forced_package_prefix(), result); +} + +TProtoStringType FilePath(const FileDescriptor* file) { + TProtoStringType output; + TProtoStringType basename; + TProtoStringType directory; + PathSplit(file->name(), &directory, &basename); + if (directory.length() > 0) { + output = y_absl::StrCat(directory, "/"); + } + basename = StripProto(basename); + + // CamelCase to be more ObjC friendly. + basename = UnderscoresToCamelCase(basename, true); + + return y_absl::StrCat(output, basename); +} + +TProtoStringType FilePathBasename(const FileDescriptor* file) { + TProtoStringType output; + TProtoStringType basename; + TProtoStringType directory; + PathSplit(file->name(), &directory, &basename); + basename = StripProto(basename); + + // CamelCase to be more ObjC friendly. + output = UnderscoresToCamelCase(basename, true); + + return output; +} + +TProtoStringType FileClassName(const FileDescriptor* file) { + const TProtoStringType prefix = FileClassPrefix(file); + const TProtoStringType name = y_absl::StrCat( + UnderscoresToCamelCase(StripProto(BaseFileName(file)), true), "Root"); + // There aren't really any reserved words that end in "Root", but playing + // it safe and checking. + return SanitizeNameForObjC(prefix, name, "_RootClass", nullptr); +} + +TProtoStringType ClassNameWorker(const Descriptor* descriptor) { + TProtoStringType name; + if (descriptor->containing_type() != nullptr) { + return y_absl::StrCat(ClassNameWorker(descriptor->containing_type()), "_", + descriptor->name()); + } + return y_absl::StrCat(name, descriptor->name()); +} + +TProtoStringType ClassNameWorker(const EnumDescriptor* descriptor) { + TProtoStringType name; + if (descriptor->containing_type() != nullptr) { + return y_absl::StrCat(ClassNameWorker(descriptor->containing_type()), "_", + descriptor->name()); + } + return y_absl::StrCat(name, descriptor->name()); +} + +TProtoStringType ClassName(const Descriptor* descriptor) { + return ClassName(descriptor, nullptr); +} + +TProtoStringType ClassName(const Descriptor* descriptor, + TProtoStringType* out_suffix_added) { + // 1. Message names are used as is (style calls for CamelCase, trust it). + // 2. Check for reserved word at the very end and then suffix things. + const TProtoStringType prefix = FileClassPrefix(descriptor->file()); + const TProtoStringType name = ClassNameWorker(descriptor); + return SanitizeNameForObjC(prefix, name, "_Class", out_suffix_added); +} + +TProtoStringType EnumName(const EnumDescriptor* descriptor) { + // 1. Enum names are used as is (style calls for CamelCase, trust it). + // 2. Check for reserved word at the every end and then suffix things. + // message Fixed { + // message Size {...} + // enum Mumble {...} + // ... + // } + // yields Fixed_Class, Fixed_Size. + const TProtoStringType prefix = FileClassPrefix(descriptor->file()); + const TProtoStringType name = ClassNameWorker(descriptor); + return SanitizeNameForObjC(prefix, name, "_Enum", nullptr); +} + +TProtoStringType EnumValueName(const EnumValueDescriptor* descriptor) { + // Because of the Switch enum compatibility, the name on the enum has to have + // the suffix handing, so it slightly diverges from how nested classes work. + // enum Fixed { + // FOO = 1 + // } + // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo). + const TProtoStringType class_name = EnumName(descriptor->type()); + const TProtoStringType value_str = + UnderscoresToCamelCase(descriptor->name(), true); + const TProtoStringType name = y_absl::StrCat(class_name, "_", value_str); + // There aren't really any reserved words with an underscore and a leading + // capital letter, but playing it safe and checking. + return SanitizeNameForObjC("", name, "_Value", nullptr); +} + +TProtoStringType EnumValueShortName(const EnumValueDescriptor* descriptor) { + // Enum value names (EnumValueName above) are the enum name turned into + // a class name and then the value name is CamelCased and concatenated; the + // whole thing then gets sanitized for reserved words. + // The "short name" is intended to be the final leaf, the value name; but + // you can't simply send that off to sanitize as that could result in it + // getting modified when the full name didn't. For example enum + // "StorageModes" has a value "retain". So the full name is + // "StorageModes_Retain", but if we sanitize "retain" it would become + // "RetainValue". + // So the right way to get the short name is to take the full enum name + // and then strip off the enum name (leaving the value name and anything + // done by sanitize). + const TProtoStringType class_name = EnumName(descriptor->type()); + const TProtoStringType long_name_prefix = y_absl::StrCat(class_name, "_"); + const TProtoStringType long_name = EnumValueName(descriptor); + return TProtoStringType(y_absl::StripPrefix(long_name, long_name_prefix)); +} + +TProtoStringType UnCamelCaseEnumShortName(y_absl::string_view name) { + TProtoStringType result; + for (int i = 0; i < name.size(); i++) { + char c = name[i]; + if (i > 0 && y_absl::ascii_isupper(c)) { + result += '_'; + } + result += y_absl::ascii_toupper(c); + } + return result; +} + +TProtoStringType ExtensionMethodName(const FieldDescriptor* descriptor) { + const TProtoStringType name = NameFromFieldDescriptor(descriptor); + const TProtoStringType result = UnderscoresToCamelCase(name, false); + return SanitizeNameForObjC("", result, "_Extension", nullptr); +} + +TProtoStringType FieldName(const FieldDescriptor* field) { + const TProtoStringType name = NameFromFieldDescriptor(field); + TProtoStringType result = UnderscoresToCamelCase(name, false); + if (field->is_repeated() && !field->is_map()) { + // Add "Array" before do check for reserved worlds. + y_absl::StrAppend(&result, "Array"); + } else { + // If it wasn't repeated, but ends in "Array", force on the _p suffix. + if (y_absl::EndsWith(result, "Array")) { + y_absl::StrAppend(&result, "_p"); + } + } + return SanitizeNameForObjC("", result, "_p", nullptr); +} + +TProtoStringType FieldNameCapitalized(const FieldDescriptor* field) { + // Want the same suffix handling, so upcase the first letter of the other + // name. + TProtoStringType result = FieldName(field); + if (result.length() > 0) { + result[0] = y_absl::ascii_toupper(result[0]); + } + return result; +} + +TProtoStringType OneofEnumName(const OneofDescriptor* descriptor) { + const Descriptor* fieldDescriptor = descriptor->containing_type(); + TProtoStringType name = y_absl::StrCat( + ClassName(fieldDescriptor), "_", + UnderscoresToCamelCase(descriptor->name(), true), "_OneOfCase"); + // No sanitize needed because the OS never has names that end in _OneOfCase. + return name; +} + +TProtoStringType OneofName(const OneofDescriptor* descriptor) { + TProtoStringType name = UnderscoresToCamelCase(descriptor->name(), false); + // No sanitize needed because it gets OneOfCase added and that shouldn't + // ever conflict. + return name; +} + +TProtoStringType OneofNameCapitalized(const OneofDescriptor* descriptor) { + // Use the common handling and then up-case the first letter. + TProtoStringType result = OneofName(descriptor); + if (result.length() > 0) { + result[0] = y_absl::ascii_toupper(result[0]); + } + return result; +} + +TProtoStringType UnCamelCaseFieldName(y_absl::string_view name, + const FieldDescriptor* field) { + y_absl::string_view worker(name); + if (y_absl::EndsWith(worker, "_p")) { + worker = y_absl::StripSuffix(worker, "_p"); + } + if (field->is_repeated() && y_absl::EndsWith(worker, "Array")) { + worker = y_absl::StripSuffix(worker, "Array"); + } + if (field->type() == FieldDescriptor::TYPE_GROUP) { + if (worker.length() > 0) { + if (y_absl::ascii_islower(worker[0])) { + TProtoStringType copy(worker); + copy[0] = y_absl::ascii_toupper(worker[0]); + return copy; + } + } + return TProtoStringType(worker); + } else { + TProtoStringType result; + for (int i = 0; i < worker.size(); i++) { + char c = worker[i]; + if (y_absl::ascii_isupper(c)) { + if (i > 0) { + result += '_'; + } + result += y_absl::ascii_tolower(c); + } else { + result += c; + } + } + return result; + } +} + +// Making these a generator option for folks that don't use CocoaPods, but do +// want to put the library in a framework is an interesting question. The +// problem is it means changing sources shipped with the library to actually +// use a different value; so it isn't as simple as a option. +const char* const ProtobufLibraryFrameworkName = "Protobuf"; + +TProtoStringType ProtobufFrameworkImportSymbol(y_absl::string_view framework_name) { + // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS + return y_absl::StrCat("GPB_USE_", y_absl::AsciiStrToUpper(framework_name), + "_FRAMEWORK_IMPORTS"); +} + +bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) { + // We don't check the name prefix or proto package because some files + // (descriptor.proto), aren't shipped generated by the library, so this + // seems to be the safest way to only catch the ones shipped. + const TProtoStringType name = file->name(); + if (name == "google/protobuf/any.proto" || + name == "google/protobuf/api.proto" || + name == "google/protobuf/duration.proto" || + name == "google/protobuf/empty.proto" || + name == "google/protobuf/field_mask.proto" || + name == "google/protobuf/source_context.proto" || + name == "google/protobuf/struct.proto" || + name == "google/protobuf/timestamp.proto" || + name == "google/protobuf/type.proto" || + name == "google/protobuf/wrappers.proto") { + return true; + } + return false; +} + +namespace { + +bool PackageToPrefixesCollector::ConsumeLine(y_absl::string_view line, + TProtoStringType* out_error) { + int offset = line.find('='); + if (offset == y_absl::string_view::npos) { + *out_error = + y_absl::StrCat(usage_, " file line without equal sign: '", line, "'."); + return false; + } + y_absl::string_view package = + y_absl::StripAsciiWhitespace(line.substr(0, offset)); + y_absl::string_view prefix = + y_absl::StripAsciiWhitespace(line.substr(offset + 1)); + MaybeUnQuote(&prefix); + // Don't really worry about error checking the package/prefix for + // being valid. Assume the file is validated when it is created/edited. + (*prefix_map_)[package] = TProtoStringType(prefix); + return true; +} + +bool LoadExpectedPackagePrefixes( + y_absl::string_view expected_prefixes_path, + y_absl::flat_hash_map<TProtoStringType, TProtoStringType>* prefix_map, + TProtoStringType* out_error) { + if (expected_prefixes_path.empty()) { + return true; + } + + PackageToPrefixesCollector collector("Expected prefixes", prefix_map); + return ParseSimpleFile(expected_prefixes_path, &collector, out_error); +} + +bool ValidateObjCClassPrefix( + const FileDescriptor* file, y_absl::string_view expected_prefixes_path, + const y_absl::flat_hash_map<TProtoStringType, TProtoStringType>& + expected_package_prefixes, + bool prefixes_must_be_registered, bool require_prefixes, + TProtoStringType* out_error) { + // Reminder: An explicit prefix option of "" is valid in case the default + // prefixing is set to use the proto package and a file needs to be generated + // without any prefix at all (for legacy reasons). + + bool has_prefix = file->options().has_objc_class_prefix(); + bool have_expected_prefix_file = !expected_prefixes_path.empty(); + + const TProtoStringType prefix = file->options().objc_class_prefix(); + const TProtoStringType package = file->package(); + // For files without packages, the can be registered as "no_package:PATH", + // allowing the expected prefixes file. + const TProtoStringType lookup_key = + package.empty() ? y_absl::StrCat(kNoPackagePrefix, file->name()) : package; + + // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some + // error cases, so it seems to be ok to use as a back door for warnings. + + // Check: Error - See if there was an expected prefix for the package and + // report if it doesn't match (wrong or missing). + auto package_match = expected_package_prefixes.find(lookup_key); + if (package_match != expected_package_prefixes.end()) { + // There was an entry, and... + if (has_prefix && package_match->second == prefix) { + // ...it matches. All good, out of here! + return true; + } else { + // ...it didn't match! + *out_error = + y_absl::StrCat("error: Expected 'option objc_class_prefix = \"", + package_match->second, "\";'"); + if (!package.empty()) { + y_absl::StrAppend(out_error, " for package '", package, "'"); + } + y_absl::StrAppend(out_error, " in '", file->name(), "'"); + if (has_prefix) { + y_absl::StrAppend(out_error, "; but found '", prefix, "' instead"); + } + y_absl::StrAppend(out_error, "."); + return false; + } + } + + // If there was no prefix option, we're done at this point. + if (!has_prefix) { + if (require_prefixes) { + *out_error = y_absl::StrCat("error: '", file->name(), + "' does not have a required 'option" + " objc_class_prefix'."); + return false; + } + return true; + } + + // When the prefix is non empty, check it against the expected entries. + if (!prefix.empty() && have_expected_prefix_file) { + // For a non empty prefix, look for any other package that uses the prefix. + TProtoStringType other_package_for_prefix; + for (auto i = expected_package_prefixes.begin(); + i != expected_package_prefixes.end(); ++i) { + if (i->second == prefix) { + other_package_for_prefix = i->first; + // Stop on the first real package listing, if it was a no_package file + // specific entry, keep looking to try and find a package one. + if (!y_absl::StartsWith(other_package_for_prefix, kNoPackagePrefix)) { + break; + } + } + } + + // Check: Error - Make sure the prefix wasn't expected for a different + // package (overlap is allowed, but it has to be listed as an expected + // overlap). + if (!other_package_for_prefix.empty()) { + *out_error = y_absl::StrCat("error: Found 'option objc_class_prefix = \"", + prefix, "\";' in '", file->name(), + "'; that prefix is already used for "); + if (y_absl::StartsWith(other_package_for_prefix, kNoPackagePrefix)) { + y_absl::StrAppend( + out_error, "file '", + y_absl::StripPrefix(other_package_for_prefix, kNoPackagePrefix), + "'."); + } else { + y_absl::StrAppend(out_error, "'package ", other_package_for_prefix, + ";'."); + } + y_absl::StrAppend(out_error, " It can only be reused by adding '", + lookup_key, " = ", prefix, + "' to the expected prefixes file (", + expected_prefixes_path, ")."); + return false; // Only report first usage of the prefix. + } + } // !prefix.empty() && have_expected_prefix_file + + // Check: Warning - Make sure the prefix is is a reasonable value according + // to Apple's rules (the checks above implicitly whitelist anything that + // doesn't meet these rules). + if (!prefix.empty() && !y_absl::ascii_isupper(prefix[0])) { + std::cerr << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" + << prefix << "\";' in '" << file->name() << "';" + << " it should start with a capital letter." << std::endl; + std::cerr.flush(); + } + if (!prefix.empty() && prefix.length() < 3) { + // Apple reserves 2 character prefixes for themselves. They do use some + // 3 character prefixes, but they haven't updated the rules/docs. + std::cerr << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" + << prefix << "\";' in '" << file->name() << "';" + << " Apple recommends they should be at least 3 characters long." + << std::endl; + std::cerr.flush(); + } + + // Check: Error/Warning - If the given package/prefix pair wasn't expected, + // issue a error/warning to added to the file. + if (have_expected_prefix_file) { + if (prefixes_must_be_registered) { + *out_error = y_absl::StrCat( + "error: '", file->name(), "' has 'option objc_class_prefix = \"", + prefix, "\";', but it is not registered. Add '", lookup_key, " = ", + (prefix.empty() ? "\"\"" : prefix), + "' to the expected prefixes file (", expected_prefixes_path, ")."); + return false; + } + + std::cerr + << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \"" + << prefix << "\";' in '" << file->name() << "'; consider adding '" + << lookup_key << " = " << (prefix.empty() ? "\"\"" : prefix) + << "' to the expected prefixes file (" << expected_prefixes_path << ")." + << std::endl; + std::cerr.flush(); + } + + return true; +} + +} // namespace + +Options::Options() { + // While there are generator options, also support env variables to help with + // build systems where it isn't as easy to hook in for add the generation + // options when invoking protoc. + const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES"); + if (file_path) { + expected_prefixes_path = file_path; + } + const char* suppressions = + getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS"); + if (suppressions) { + expected_prefixes_suppressions = + y_absl::StrSplit(suppressions, ';', y_absl::SkipEmpty()); + } + prefixes_must_be_registered = + BoolFromEnvVar("GPB_OBJC_PREFIXES_MUST_BE_REGISTERED", false); + require_prefixes = BoolFromEnvVar("GPB_OBJC_REQUIRE_PREFIXES", false); +} + +bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files, + TProtoStringType* out_error) { + // Options's ctor load from the environment. + Options options; + return ValidateObjCClassPrefixes(files, options, out_error); +} + +bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files, + const Options& validation_options, + TProtoStringType* out_error) { + // Allow a '-' as the path for the expected prefixes to completely disable + // even the most basic of checks. + if (validation_options.expected_prefixes_path == "-") { + return true; + } + + // Load the expected package prefixes, if available, to validate against. + y_absl::flat_hash_map<TProtoStringType, TProtoStringType> expected_package_prefixes; + if (!LoadExpectedPackagePrefixes(validation_options.expected_prefixes_path, + &expected_package_prefixes, out_error)) { + return false; + } + + for (auto file : files) { + bool should_skip = + (std::find(validation_options.expected_prefixes_suppressions.begin(), + validation_options.expected_prefixes_suppressions.end(), + file->name()) != + validation_options.expected_prefixes_suppressions.end()); + if (should_skip) { + continue; + } + + bool is_valid = + ValidateObjCClassPrefix(file, validation_options.expected_prefixes_path, + expected_package_prefixes, + validation_options.prefixes_must_be_registered, + validation_options.require_prefixes, out_error); + if (!is_valid) { + return false; + } + } + return true; +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/names.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/names.h new file mode 100644 index 00000000000..3ee2cd8e905 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/names.h @@ -0,0 +1,179 @@ +// 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. + +// Helper functions for generating ObjectiveC code. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_NAMES_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_NAMES_H__ + +#include <string> +#include <vector> + +#include "google/protobuf/descriptor.h" + +// Must be included last +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// Get/Set the path to a file to load for objc class prefix lookups. +PROTOC_EXPORT y_absl::string_view GetPackageToPrefixMappingsPath(); +PROTOC_EXPORT void SetPackageToPrefixMappingsPath(y_absl::string_view file_path); +// Get/Set if the proto package should be used to make the default prefix for +// symbols. This will then impact most of the type naming apis below. It is done +// as a global to not break any other generator reusing the methods since they +// are exported. +PROTOC_EXPORT bool UseProtoPackageAsDefaultPrefix(); +PROTOC_EXPORT void SetUseProtoPackageAsDefaultPrefix(bool on_or_off); +// Get/Set the path to a file to load as exceptions when +// `UseProtoPackageAsDefaultPrefix()` is `true`. An empty string means there +// should be no exceptions. +PROTOC_EXPORT y_absl::string_view GetProtoPackagePrefixExceptionList(); +PROTOC_EXPORT void SetProtoPackagePrefixExceptionList( + y_absl::string_view file_path); +// Get/Set a prefix to add before the prefix generated from the package name. +// This is only used when UseProtoPackageAsDefaultPrefix() is True. +PROTOC_EXPORT y_absl::string_view GetForcedPackagePrefix(); +PROTOC_EXPORT void SetForcedPackagePrefix(y_absl::string_view prefix); + +// Returns true if the name requires a ns_returns_not_retained attribute applied +// to it. +PROTOC_EXPORT bool IsRetainedName(y_absl::string_view name); + +// Returns true if the name starts with "init" and will need to have special +// handling under ARC. +PROTOC_EXPORT bool IsInitName(y_absl::string_view name); + +// Returns true if the name requires a cf_returns_not_retained attribute applied +// to it. +PROTOC_EXPORT bool IsCreateName(y_absl::string_view name); + +// Gets the objc_class_prefix or the prefix made from the proto package. +PROTOC_EXPORT TProtoStringType 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. +PROTOC_EXPORT TProtoStringType FilePath(const FileDescriptor* file); + +// Just like FilePath(), but without the directory part. +PROTOC_EXPORT TProtoStringType 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 +PROTOC_EXPORT TProtoStringType FileClassName(const FileDescriptor* file); + +// These return the fully-qualified class name corresponding to the given +// descriptor. +PROTOC_EXPORT TProtoStringType ClassName(const Descriptor* descriptor); +PROTOC_EXPORT TProtoStringType ClassName(const Descriptor* descriptor, + TProtoStringType* out_suffix_added); +PROTOC_EXPORT TProtoStringType EnumName(const EnumDescriptor* descriptor); + +// Returns the fully-qualified name of the enum value corresponding to the +// the descriptor. +PROTOC_EXPORT TProtoStringType EnumValueName(const EnumValueDescriptor* descriptor); + +// Returns the name of the enum value corresponding to the descriptor. +PROTOC_EXPORT TProtoStringType EnumValueShortName( + const EnumValueDescriptor* descriptor); + +// Reverse what an enum does. +PROTOC_EXPORT TProtoStringType UnCamelCaseEnumShortName(y_absl::string_view name); + +// Returns the name to use for the extension (used as the method off the file's +// Root class). +PROTOC_EXPORT TProtoStringType ExtensionMethodName( + const FieldDescriptor* descriptor); + +// Returns the transformed field name. +PROTOC_EXPORT TProtoStringType FieldName(const FieldDescriptor* field); +PROTOC_EXPORT TProtoStringType FieldNameCapitalized(const FieldDescriptor* field); + +// Returns the transformed oneof name. +PROTOC_EXPORT TProtoStringType OneofEnumName(const OneofDescriptor* descriptor); +PROTOC_EXPORT TProtoStringType OneofName(const OneofDescriptor* descriptor); +PROTOC_EXPORT TProtoStringType OneofNameCapitalized( + const OneofDescriptor* descriptor); + +// Reverse of the above. +PROTOC_EXPORT TProtoStringType UnCamelCaseFieldName(y_absl::string_view name, + const FieldDescriptor* field); + +// The name the commonly used by the library when built as a framework. +// This lines up to the name used in the CocoaPod. +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. +PROTOC_EXPORT TProtoStringType ProtobufFrameworkImportSymbol( + y_absl::string_view framework_name); + +// --------------------------------------------------------------------------- + +// These aren't really "naming" related, but can be useful for something +// building on top of ObjC Protos to be able to share the knowledge/enforcement. + +// Checks if the file is one of the proto's bundled with the library. +PROTOC_EXPORT bool IsProtobufLibraryBundledProtoFile( + const FileDescriptor* file); + +// Generator Prefix Validation Options (see generator.cc for a +// description of each): +struct Options { + Options(); + TProtoStringType expected_prefixes_path; + std::vector<TProtoStringType> expected_prefixes_suppressions; + bool prefixes_must_be_registered; + bool require_prefixes; +}; + +// 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. +PROTOC_EXPORT bool ValidateObjCClassPrefixes( + const std::vector<const FileDescriptor*>& files, + const Options& validation_options, TProtoStringType* out_error); +// Same was the other ValidateObjCClassPrefixes() calls, but the options all +// come from the environment variables. +PROTOC_EXPORT bool ValidateObjCClassPrefixes( + const std::vector<const FileDescriptor*>& files, TProtoStringType* out_error); + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_NAMES_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/nsobject_methods.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/nsobject_methods.h new file mode 100644 index 00000000000..7a1b9ef2cdd --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/nsobject_methods.h @@ -0,0 +1,227 @@ +// 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. + +// NSObject methods +// Autogenerated by method_dump.sh. Do not edit by hand. +// Date: Thu Nov 1 14:12:16 PDT 2018 +// macOS: MacOSX10.14.sdk +// iOS: iPhoneSimulator12.1.sdk + +const char* const kNSObjectMethodsList[] = { + "CAMLType", + "CA_copyRenderValue", + "CA_prepareRenderValue", + "NS_copyCGImage", + "NS_tiledLayerVisibleRect", + "___tryRetain_OA", + "__autorelease_OA", + "__dealloc_zombie", + "__release_OA", + "__retain_OA", + "_accessibilityFinalize", + "_accessibilityIsTableViewDescendant", + "_accessibilityUIElementSpecifier", + "_accessibilityUseConvenienceAPI", + "_allowsDirectEncoding", + "_asScriptTerminologyNameArray", + "_asScriptTerminologyNameString", + "_bindingAdaptor", + "_cfTypeID", + "_copyDescription", + "_destroyObserverList", + "_didEndKeyValueObserving", + "_implicitObservationInfo", + "_internalAccessibilityAttributedHint", + "_internalAccessibilityAttributedLabel", + "_internalAccessibilityAttributedValue", + "_isAXConnector", + "_isAccessibilityContainerSectionCandidate", + "_isAccessibilityContentNavigatorSectionCandidate", + "_isAccessibilityContentSectionCandidate", + "_isAccessibilityTopLevelNavigatorSectionCandidate", + "_isDeallocating", + "_isKVOA", + "_isToManyChangeInformation", + "_ivarDescription", + "_localClassNameForClass", + "_methodDescription", + "_observerStorage", + "_overrideUseFastBlockObservers", + "_propertyDescription", + "_releaseBindingAdaptor", + "_scriptingCount", + "_scriptingCountNonrecursively", + "_scriptingDebugDescription", + "_scriptingExists", + "_scriptingShouldCheckObjectIndexes", + "_shortMethodDescription", + "_shouldSearchChildrenForSection", + "_traitStorageList", + "_tryRetain", + "_ui_descriptionBuilder", + "_uikit_variesByTraitCollections", + "_web_description", + "_webkit_invokeOnMainThread", + "_willBeginKeyValueObserving", + "accessibilityActivate", + "accessibilityActivationPoint", + "accessibilityAllowsOverriddenAttributesWhenIgnored", + "accessibilityAssistiveTechnologyFocusedIdentifiers", + "accessibilityAttributedHint", + "accessibilityAttributedLabel", + "accessibilityAttributedValue", + "accessibilityContainer", + "accessibilityContainerType", + "accessibilityCustomActions", + "accessibilityCustomRotors", + "accessibilityDecrement", + "accessibilityDragSourceDescriptors", + "accessibilityDropPointDescriptors", + "accessibilityElementCount", + "accessibilityElementDidBecomeFocused", + "accessibilityElementDidLoseFocus", + "accessibilityElementIsFocused", + "accessibilityElements", + "accessibilityElementsHidden", + "accessibilityFrame", + "accessibilityHeaderElements", + "accessibilityHint", + "accessibilityIdentification", + "accessibilityIdentifier", + "accessibilityIncrement", + "accessibilityLabel", + "accessibilityLanguage", + "accessibilityLocalizedStringKey", + "accessibilityNavigationStyle", + "accessibilityOverriddenAttributes", + "accessibilityParameterizedAttributeNames", + "accessibilityPath", + "accessibilityPerformEscape", + "accessibilityPerformMagicTap", + "accessibilityPresenterProcessIdentifier", + "accessibilityShouldUseUniqueId", + "accessibilitySupportsNotifications", + "accessibilitySupportsOverriddenAttributes", + "accessibilityTemporaryChildren", + "accessibilityTraits", + "accessibilityValue", + "accessibilityViewIsModal", + "accessibilityVisibleArea", + "allPropertyKeys", + "allowsWeakReference", + "attributeKeys", + "autoContentAccessingProxy", + "autorelease", + "awakeFromNib", + "boolValueSafe", + "bs_encoded", + "bs_isPlistableType", + "bs_secureEncoded", + "cl_json_serializeKey", + "class", + "classCode", + "classDescription", + "classForArchiver", + "classForCoder", + "classForKeyedArchiver", + "classForPortCoder", + "className", + "clearProperties", + "copy", + "dealloc", + "debugDescription", + "defaultAccessibilityTraits", + "description", + "doubleValueSafe", + "entityName", + "exposedBindings", + "finalize", + "finishObserving", + "flushKeyBindings", + "hash", + "init", + "int64ValueSafe", + "isAccessibilityElement", + "isAccessibilityElementByDefault", + "isElementAccessibilityExposedToInterfaceBuilder", + "isFault", + "isNSArray__", + "isNSCFConstantString__", + "isNSData__", + "isNSDate__", + "isNSDictionary__", + "isNSNumber__", + "isNSObject__", + "isNSOrderedSet__", + "isNSSet__", + "isNSString__", + "isNSTimeZone__", + "isNSValue__", + "isProxy", + "mutableCopy", + "nilValueForKey", + "objectSpecifier", + "observationInfo", + "pep_onDetachedThread", + "pep_onMainThread", + "pep_onMainThreadIfNecessary", + "prepareForInterfaceBuilder", + "release", + "releaseOnMainThread", + "retain", + "retainCount", + "retainWeakReference", + "scriptingProperties", + "self", + "shouldGroupAccessibilityChildren", + "storedAccessibilityActivationPoint", + "storedAccessibilityContainerType", + "storedAccessibilityElementsHidden", + "storedAccessibilityFrame", + "storedAccessibilityNavigationStyle", + "storedAccessibilityTraits", + "storedAccessibilityViewIsModal", + "storedIsAccessibilityElement", + "storedShouldGroupAccessibilityChildren", + "stringValueSafe", + "superclass", + "toManyRelationshipKeys", + "toOneRelationshipKeys", + "traitStorageList", + "un_safeBoolValue", + "userInterfaceItemIdentifier", + "utf8ValueSafe", + "valuesForKeysWithDictionary", + "zone", + // Protocol: CAAnimatableValue + // Protocol: CARenderValue + // Protocol: NSObject + // Protocol: ROCKRemoteInvocationInterface +}; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_file.cc deleted file mode 100644 index e1bb09f9961..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ /dev/null @@ -1,681 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <google/protobuf/compiler/objectivec/objectivec_file.h> -#include <google/protobuf/compiler/objectivec/objectivec_enum.h> -#include <google/protobuf/compiler/objectivec/objectivec_extension.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/compiler/objectivec/objectivec_message.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/stubs/stl_util.h> -#include <google/protobuf/stubs/strutil.h> -#include <algorithm> // std::find() -#include <iostream> -#include <sstream> - -// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some -// error cases, so it seems to be ok to use as a back door for errors. - -namespace google { -namespace protobuf { -namespace compiler { -namespace objectivec { - -namespace { - -// This is also found in GPBBootstrap.h, and needs to be kept in sync. -const arc_i32 GOOGLE_PROTOBUF_OBJC_VERSION = 30004; - -const char* kHeaderExtension = ".pbobjc.h"; - -TProtoStringType BundledFileName(const FileDescriptor* file) { - return "GPB" + FilePathBasename(file) + kHeaderExtension; -} - -// Checks if a message contains any enums definitions (on the message or -// a nested message under it). -bool MessageContainsEnums(const Descriptor* message) { - if (message->enum_type_count() > 0) { - return true; - } - for (int i = 0; i < message->nested_type_count(); i++) { - if (MessageContainsEnums(message->nested_type(i))) { - return true; - } - } - return false; -} - -// Checks if a message contains any extension definitions (on the message or -// a nested message under it). -bool MessageContainsExtensions(const Descriptor* message) { - if (message->extension_count() > 0) { - return true; - } - for (int i = 0; i < message->nested_type_count(); i++) { - if (MessageContainsExtensions(message->nested_type(i))) { - return true; - } - } - return false; -} - -// Checks if the file contains any enum definitions (at the root or -// nested under a message). -bool FileContainsEnums(const FileDescriptor* file) { - if (file->enum_type_count() > 0) { - return true; - } - for (int i = 0; i < file->message_type_count(); i++) { - if (MessageContainsEnums(file->message_type(i))) { - return true; - } - } - return false; -} - -// Checks if the file contains any extensions definitions (at the root or -// nested under a message). -bool FileContainsExtensions(const FileDescriptor* file) { - if (file->extension_count() > 0) { - return true; - } - for (int i = 0; i < file->message_type_count(); i++) { - if (MessageContainsExtensions(file->message_type(i))) { - return true; - } - } - return false; -} - -bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) { - for (int i = 0; i < file->dependency_count(); i++) { - if (dep == file->dependency(i)) { - return true; - } - } - return false; -} - -struct FileDescriptorsOrderedByName { - inline bool operator()(const FileDescriptor* a, - const FileDescriptor* b) const { - return a->name() < b->name(); - } -}; - -} // namespace - -FileGenerator::CommonState::CommonState() { } - -const FileGenerator::CommonState::MinDepsEntry& -FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensionsInternal( - const FileDescriptor* file) { - auto it = deps_info_cache_.find(file); - if (it != deps_info_cache_.end()) { - return it->second; - } - - std::set<const FileDescriptor*> min_deps_collector; - std::set<const FileDescriptor*> covered_deps_collector; - std::set<const FileDescriptor*> to_prune; - for (int i = 0; i < file->dependency_count(); i++) { - const FileDescriptor* dep = file->dependency(i); - MinDepsEntry dep_info = - CollectMinimalFileDepsContainingExtensionsInternal(dep); - - // Everything the dep covered, this file will also cover. - covered_deps_collector.insert(dep_info.covered_deps.begin(), dep_info.covered_deps.end()); - // Prune everything from the dep's covered list in case another dep lists it - // as a min dep. - to_prune.insert(dep_info.covered_deps.begin(), dep_info.covered_deps.end()); - - // Does the dep have any extensions... - if (dep_info.has_extensions) { - // Yes -> Add this file, prune its min_deps and add them to the covered deps. - min_deps_collector.insert(dep); - to_prune.insert(dep_info.min_deps.begin(), dep_info.min_deps.end()); - covered_deps_collector.insert(dep_info.min_deps.begin(), dep_info.min_deps.end()); - } else { - // No -> Just use its min_deps. - min_deps_collector.insert(dep_info.min_deps.begin(), dep_info.min_deps.end()); - } - } - - const bool file_has_exts = FileContainsExtensions(file); - - // Fast path: if nothing to prune or there was only one dep, the prune work is - // a waste, skip it. - if (to_prune.empty() || file->dependency_count() == 1) { - return deps_info_cache_.insert( - {file, {file_has_exts, min_deps_collector, covered_deps_collector}}).first->second; - } - - std::set<const FileDescriptor*> min_deps; - std::copy_if(min_deps_collector.begin(), min_deps_collector.end(), - std::inserter(min_deps, min_deps.end()), - [&](const FileDescriptor* value){ - return to_prune.find(value) == to_prune.end(); - }); - return deps_info_cache_.insert( - {file, {file_has_exts, min_deps, covered_deps_collector}}).first->second; -} - -// Collect the deps of the given file that contain extensions. This can be used to -// create the chain of roots that need to be wired together. -// -// NOTE: If any changes are made to this and the supporting functions, you will -// need to manually validate what the generated code is for the test files: -// objectivec/Tests/unittest_extension_chain_*.proto -// There are comments about what the expected code should be line and limited -// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports -// specifically). -const std::vector<const FileDescriptor*> -FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensions( - const FileDescriptor* file) { - std::set<const FileDescriptor*> min_deps = - CollectMinimalFileDepsContainingExtensionsInternal(file).min_deps; - // Sort the list since pointer order isn't stable across runs. - std::vector<const FileDescriptor*> result(min_deps.begin(), min_deps.end()); - std::sort(result.begin(), result.end(), FileDescriptorsOrderedByName()); - return result; -} - -FileGenerator::FileGenerator(const FileDescriptor* file, - const GenerationOptions& generation_options, - CommonState& common_state) - : file_(file), - generation_options_(generation_options), - common_state_(common_state), - root_class_name_(FileClassName(file)), - is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)) { - for (int i = 0; i < file_->enum_type_count(); i++) { - EnumGenerator* generator = new EnumGenerator(file_->enum_type(i)); - enum_generators_.emplace_back(generator); - } - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator* generator = - new MessageGenerator(root_class_name_, file_->message_type(i)); - message_generators_.emplace_back(generator); - } - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator* generator = - new ExtensionGenerator(root_class_name_, file_->extension(i)); - extension_generators_.emplace_back(generator); - } -} - -FileGenerator::~FileGenerator() {} - -void FileGenerator::GenerateHeader(io::Printer* printer) { - std::vector<TProtoStringType> headers; - // Generated files bundled with the library get minimal imports, everything - // else gets the wrapper so everything is usable. - if (is_bundled_proto_) { - headers.push_back("GPBDescriptor.h"); - headers.push_back("GPBMessage.h"); - headers.push_back("GPBRootObject.h"); - for (int i = 0; i < file_->dependency_count(); i++) { - const TProtoStringType header_name = BundledFileName(file_->dependency(i)); - headers.push_back(header_name); - } - } else { - headers.push_back("GPBProtocolBuffers.h"); - } - PrintFileRuntimePreamble(printer, headers); - - // Add some verification that the generated code matches the source the - // code is being compiled with. - // NOTE: This captures the raw numeric values at the time the generator was - // compiled, since that will be the versions for the ObjC runtime at that - // time. The constants in the generated code will then get their values at - // at compile time (so checking against the headers being used to compile). - printer->Print( - "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n" - "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n" - "#endif\n" - "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n" - "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n" - "#endif\n" - "\n", - "google_protobuf_objc_version", StrCat(GOOGLE_PROTOBUF_OBJC_VERSION)); - - // The bundled protos (WKTs) don't use of forward declarations. - bool headers_use_forward_declarations = - generation_options_.headers_use_forward_declarations && !is_bundled_proto_; - - { - ImportWriter import_writer( - generation_options_.generate_for_named_framework, - generation_options_.named_framework_to_proto_path_mappings_path, - generation_options_.runtime_import_prefix, - /* include_wkt_imports = */ false); - const TProtoStringType header_extension(kHeaderExtension); - if (headers_use_forward_declarations) { - // #import any headers for "public imports" in the proto file. - for (int i = 0; i < file_->public_dependency_count(); i++) { - import_writer.AddFile(file_->public_dependency(i), header_extension); - } - } else { - for (int i = 0; i < file_->dependency_count(); i++) { - import_writer.AddFile(file_->dependency(i), header_extension); - } - } - import_writer.Print(printer); - } - - // Note: - // deprecated-declarations suppression is only needed if some place in this - // proto file is something deprecated or if it references something from - // another file that is deprecated. - printer->Print( - "// @@protoc_insertion_point(imports)\n" - "\n" - "#pragma clang diagnostic push\n" - "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n" - "\n" - "CF_EXTERN_C_BEGIN\n" - "\n"); - - std::set<TProtoStringType> fwd_decls; - for (const auto& generator : message_generators_) { - generator->DetermineForwardDeclarations( - &fwd_decls, - /* include_external_types = */ headers_use_forward_declarations); - } - for (std::set<TProtoStringType>::const_iterator i(fwd_decls.begin()); - i != fwd_decls.end(); ++i) { - printer->Print("$value$;\n", "value", *i); - } - if (fwd_decls.begin() != fwd_decls.end()) { - printer->Print("\n"); - } - - printer->Print( - "NS_ASSUME_NONNULL_BEGIN\n" - "\n"); - - // need to write out all enums first - for (const auto& generator : enum_generators_) { - generator->GenerateHeader(printer); - } - - for (const auto& generator : message_generators_) { - generator->GenerateEnumHeader(printer); - } - - // For extensions to chain together, the Root gets created even if there - // are no extensions. - printer->Print( - "#pragma mark - $root_class_name$\n" - "\n" - "/**\n" - " * Exposes the extension registry for this file.\n" - " *\n" - " * The base class provides:\n" - " * @code\n" - " * + (GPBExtensionRegistry *)extensionRegistry;\n" - " * @endcode\n" - " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n" - " * this file and all files that it depends on.\n" - " **/\n" - "GPB_FINAL @interface $root_class_name$ : GPBRootObject\n" - "@end\n" - "\n", - "root_class_name", root_class_name_); - - if (!extension_generators_.empty()) { - // The dynamic methods block is only needed if there are extensions. - printer->Print( - "@interface $root_class_name$ (DynamicMethods)\n", - "root_class_name", root_class_name_); - - for (const auto& generator : extension_generators_) { - generator->GenerateMembersHeader(printer); - } - - printer->Print("@end\n\n"); - } // !extension_generators_.empty() - - for (const auto& generator : message_generators_) { - generator->GenerateMessageHeader(printer); - } - - printer->Print( - "NS_ASSUME_NONNULL_END\n" - "\n" - "CF_EXTERN_C_END\n" - "\n" - "#pragma clang diagnostic pop\n" - "\n" - "// @@protoc_insertion_point(global_scope)\n"); -} - -void FileGenerator::GenerateSource(io::Printer* printer) { - // #import the runtime support. - std::vector<TProtoStringType> headers; - headers.push_back("GPBProtocolBuffers_RuntimeSupport.h"); - if (is_bundled_proto_) { - headers.push_back(BundledFileName(file_)); - } - PrintFileRuntimePreamble(printer, headers); - - // Enums use atomic in the generated code, so add the system import as needed. - if (FileContainsEnums(file_)) { - printer->Print( - "#import <stdatomic.h>\n" - "\n"); - } - - std::vector<const FileDescriptor*> deps_with_extensions = - common_state_.CollectMinimalFileDepsContainingExtensions(file_); - - // The bundled protos (WKTs) don't use of forward declarations. - bool headers_use_forward_declarations = - generation_options_.headers_use_forward_declarations && !is_bundled_proto_; - - { - ImportWriter import_writer( - generation_options_.generate_for_named_framework, - generation_options_.named_framework_to_proto_path_mappings_path, - generation_options_.runtime_import_prefix, - /* include_wkt_imports = */ false); - const TProtoStringType header_extension(kHeaderExtension); - - // #import the header for this proto file. - import_writer.AddFile(file_, header_extension); - - if (headers_use_forward_declarations) { - // #import the headers for anything that a plain dependency of this proto - // file (that means they were just an include, not a "public" include). - std::set<TProtoStringType> public_import_names; - for (int i = 0; i < file_->public_dependency_count(); i++) { - public_import_names.insert(file_->public_dependency(i)->name()); - } - for (int i = 0; i < file_->dependency_count(); i++) { - const FileDescriptor *dep = file_->dependency(i); - bool public_import = (public_import_names.count(dep->name()) != 0); - if (!public_import) { - import_writer.AddFile(dep, header_extension); - } - } - } - - // If any indirect dependency provided extensions, it needs to be directly - // imported so it can get merged into the root's extensions registry. - // See the Note by CollectMinimalFileDepsContainingExtensions before - // changing this. - for (std::vector<const FileDescriptor*>::iterator iter = - deps_with_extensions.begin(); - iter != deps_with_extensions.end(); ++iter) { - if (!IsDirectDependency(*iter, file_)) { - import_writer.AddFile(*iter, header_extension); - } - } - - import_writer.Print(printer); - } - - bool includes_oneof = false; - for (const auto& generator : message_generators_) { - if (generator->IncludesOneOfDefinition()) { - includes_oneof = true; - break; - } - } - - std::set<TProtoStringType> fwd_decls; - for (const auto& generator : message_generators_) { - generator->DetermineObjectiveCClassDefinitions(&fwd_decls); - } - for (const auto& generator : extension_generators_) { - generator->DetermineObjectiveCClassDefinitions(&fwd_decls); - } - - // Note: - // deprecated-declarations suppression is only needed if some place in this - // proto file is something deprecated or if it references something from - // another file that is deprecated. - // dollar-in-identifier-extension is needed because we use references to - // objc class names that have $ in identifiers. - printer->Print( - "// @@protoc_insertion_point(imports)\n" - "\n" - "#pragma clang diagnostic push\n" - "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"); - if (includes_oneof) { - // The generated code for oneof's uses direct ivar access, suppress the - // warning in case developer turn that on in the context they compile the - // generated code. - printer->Print( - "#pragma clang diagnostic ignored \"-Wdirect-ivar-access\"\n"); - } - if (!fwd_decls.empty()) { - printer->Print( - "#pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n"); - } - printer->Print( - "\n"); - if (!fwd_decls.empty()) { - printer->Print( - "#pragma mark - Objective C Class declarations\n" - "// Forward declarations of Objective C classes that we can use as\n" - "// static values in struct initializers.\n" - "// We don't use [Foo class] because it is not a static value.\n"); - } - for (const auto& i : fwd_decls) { - printer->Print("$value$\n", "value", i); - } - if (!fwd_decls.empty()) { - printer->Print("\n"); - } - printer->Print( - "#pragma mark - $root_class_name$\n" - "\n" - "@implementation $root_class_name$\n\n", - "root_class_name", root_class_name_); - - const bool file_contains_extensions = FileContainsExtensions(file_); - - // If there were any extensions or this file has any dependencies, output - // a registry to override to create the file specific registry. - if (file_contains_extensions || !deps_with_extensions.empty()) { - printer->Print( - "+ (GPBExtensionRegistry*)extensionRegistry {\n" - " // This is called by +initialize so there is no need to worry\n" - " // about thread safety and initialization of registry.\n" - " static GPBExtensionRegistry* registry = nil;\n" - " if (!registry) {\n" - " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n" - " registry = [[GPBExtensionRegistry alloc] init];\n"); - - printer->Indent(); - printer->Indent(); - - if (file_contains_extensions) { - printer->Print( - "static GPBExtensionDescription descriptions[] = {\n"); - printer->Indent(); - for (const auto& generator : extension_generators_) { - generator->GenerateStaticVariablesInitialization(printer); - } - for (const auto& generator : message_generators_) { - generator->GenerateStaticVariablesInitialization(printer); - } - printer->Outdent(); - printer->Print( - "};\n" - "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n" - " GPBExtensionDescriptor *extension =\n" - " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]\n" - " usesClassRefs:YES];\n" - " [registry addExtension:extension];\n" - " [self globallyRegisterExtension:extension];\n" - " [extension release];\n" - "}\n"); - } - - if (deps_with_extensions.empty()) { - printer->Print( - "// None of the imports (direct or indirect) defined extensions, so no need to add\n" - "// them to this registry.\n"); - } else { - printer->Print( - "// Merge in the imports (direct or indirect) that defined extensions.\n"); - for (std::vector<const FileDescriptor*>::iterator iter = - deps_with_extensions.begin(); - iter != deps_with_extensions.end(); ++iter) { - const TProtoStringType root_class_name(FileClassName((*iter))); - printer->Print( - "[registry addExtensions:[$dependency$ extensionRegistry]];\n", - "dependency", root_class_name); - } - } - - printer->Outdent(); - printer->Outdent(); - - printer->Print( - " }\n" - " return registry;\n" - "}\n"); - } else { - if (file_->dependency_count() > 0) { - printer->Print( - "// No extensions in the file and none of the imports (direct or indirect)\n" - "// defined extensions, so no need to generate +extensionRegistry.\n"); - } else { - printer->Print( - "// No extensions in the file and no imports, so no need to generate\n" - "// +extensionRegistry.\n"); - } - } - - printer->Print("\n@end\n\n"); - - // File descriptor only needed if there are messages to use it. - if (!message_generators_.empty()) { - std::map<TProtoStringType, TProtoStringType> vars; - vars["root_class_name"] = root_class_name_; - vars["package"] = file_->package(); - vars["objc_prefix"] = FileClassPrefix(file_); - switch (file_->syntax()) { - case FileDescriptor::SYNTAX_UNKNOWN: - vars["syntax"] = "GPBFileSyntaxUnknown"; - break; - case FileDescriptor::SYNTAX_PROTO2: - vars["syntax"] = "GPBFileSyntaxProto2"; - break; - case FileDescriptor::SYNTAX_PROTO3: - vars["syntax"] = "GPBFileSyntaxProto3"; - break; - } - printer->Print(vars, - "#pragma mark - $root_class_name$_FileDescriptor\n" - "\n" - "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" - " // This is called by +initialize so there is no need to worry\n" - " // about thread safety of the singleton.\n" - " static GPBFileDescriptor *descriptor = NULL;\n" - " if (!descriptor) {\n" - " GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"); - if (!vars["objc_prefix"].empty()) { - printer->Print( - vars, - " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" - " objcPrefix:@\"$objc_prefix$\"\n" - " syntax:$syntax$];\n"); - } else { - printer->Print( - vars, - " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" - " syntax:$syntax$];\n"); - } - printer->Print( - " }\n" - " return descriptor;\n" - "}\n" - "\n"); - } - - for (const auto& generator : enum_generators_) { - generator->GenerateSource(printer); - } - for (const auto& generator : message_generators_) { - generator->GenerateSource(printer); - } - - printer->Print( - "\n" - "#pragma clang diagnostic pop\n" - "\n" - "// @@protoc_insertion_point(global_scope)\n"); -} - -// Helper to print the import of the runtime support at the top of generated -// files. This currently only supports the runtime coming from a framework -// as defined by the official CocoaPod. -void FileGenerator::PrintFileRuntimePreamble( - io::Printer* printer, - const std::vector<TProtoStringType>& headers_to_import) const { - printer->Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $filename$\n" - "\n", - "filename", file_->name()); - - if (is_bundled_proto_) { - // This is basically a clone of ImportWriter::PrintRuntimeImports() but - // without the CPP symbol gate, since within the bundled files, that isn't - // needed. - TProtoStringType import_prefix = generation_options_.runtime_import_prefix; - if (!import_prefix.empty()) { - import_prefix += "/"; - } - for (const auto& header : headers_to_import) { - printer->Print( - "#import \"$import_prefix$$header$\"\n", - "import_prefix", import_prefix, - "header", header); - } - } else { - ImportWriter::PrintRuntimeImports( - printer, headers_to_import, generation_options_.runtime_import_prefix, true); - } - - printer->Print("\n"); -} - -} // namespace objectivec -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc deleted file mode 100644 index 5122fa46c09..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ /dev/null @@ -1,2044 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef _MSC_VER -#include <unistd.h> -#endif -#include <climits> -#include <errno.h> -#include <fcntl.h> -#include <fstream> -#include <iostream> -#include <sstream> -#include <stdlib.h> -#include <unordered_set> -#include <vector> - -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/io/io_win32.h> -#include <google/protobuf/port.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/port.h> -#include <google/protobuf/stubs/strutil.h> - -// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some -// error cases, so it seems to be ok to use as a back door for errors. - -namespace google { -namespace protobuf { -namespace compiler { -namespace objectivec { - -// <io.h> is transitively included in this file. Import the functions explicitly -// in this port namespace to avoid ambiguous definition. -namespace posix { -#ifdef _WIN32 -using ::google::protobuf::io::win32::open; -#else -using ::open; -#endif -} // namespace port - -namespace { - -bool BoolFromEnvVar(const char* env_var, bool default_value) { - const char* value = getenv(env_var); - if (value) { - return TProtoStringType("YES") == ToUpper(value); - } - return default_value; -} - -class SimpleLineCollector : public LineConsumer { - public: - SimpleLineCollector(std::unordered_set<TProtoStringType>* inout_set) - : set_(inout_set) {} - - virtual bool ConsumeLine(const StringPiece& line, TProtoStringType* out_error) override { - set_->insert(TProtoStringType(line)); - return true; - } - - private: - std::unordered_set<TProtoStringType>* set_; -}; - -class PackageToPrefixesCollector : public LineConsumer { - public: - PackageToPrefixesCollector(const TProtoStringType &usage, - std::map<TProtoStringType, TProtoStringType>* inout_package_to_prefix_map) - : usage_(usage), prefix_map_(inout_package_to_prefix_map) {} - - virtual bool ConsumeLine(const StringPiece& line, TProtoStringType* out_error) override; - - private: - const TProtoStringType usage_; - std::map<TProtoStringType, TProtoStringType>* prefix_map_; -}; - -class PrefixModeStorage { - public: - PrefixModeStorage(); - - const TProtoStringType package_to_prefix_mappings_path() const { return package_to_prefix_mappings_path_; } - void set_package_to_prefix_mappings_path(const TProtoStringType& path) { - package_to_prefix_mappings_path_ = path; - package_to_prefix_map_.clear(); - } - - TProtoStringType prefix_from_proto_package_mappings(const FileDescriptor* file); - - bool use_package_name() const { return use_package_name_; } - void set_use_package_name(bool on_or_off) { use_package_name_ = on_or_off; } - - const TProtoStringType exception_path() const { return exception_path_; } - void set_exception_path(const TProtoStringType& path) { - exception_path_ = path; - exceptions_.clear(); - } - - bool is_package_exempted(const TProtoStringType& package); - - // When using a proto package as the prefix, this should be added as the - // prefix in front of it. - const TProtoStringType& forced_package_prefix() const { return forced_prefix_; } - - private: - bool use_package_name_; - std::map<TProtoStringType, TProtoStringType> package_to_prefix_map_; - TProtoStringType package_to_prefix_mappings_path_; - TProtoStringType exception_path_; - TProtoStringType forced_prefix_; - std::unordered_set<TProtoStringType> exceptions_; -}; - -PrefixModeStorage::PrefixModeStorage() { - // Even thought there are generation options, have an env back door since some - // of these helpers could be used in other plugins. - - use_package_name_ = BoolFromEnvVar("GPB_OBJC_USE_PACKAGE_AS_PREFIX", false); - - const char* exception_path = getenv("GPB_OBJC_PACKAGE_PREFIX_EXCEPTIONS_PATH"); - if (exception_path) { - exception_path_ = exception_path; - } - - // This one is a not expected to be common, so it doesn't get a generation - // option, just the env var. - const char* prefix = getenv("GPB_OBJC_USE_PACKAGE_AS_PREFIX_PREFIX"); - if (prefix) { - forced_prefix_ = prefix; - } -} - -TProtoStringType PrefixModeStorage::prefix_from_proto_package_mappings(const FileDescriptor* file) { - if (!file) { - return ""; - } - - if (package_to_prefix_map_.empty() && !package_to_prefix_mappings_path_.empty()) { - TProtoStringType error_str; - // Re use the same collector as we use for expected_prefixes_path since the file - // format is the same. - PackageToPrefixesCollector collector("Package to prefixes", &package_to_prefix_map_); - if (!ParseSimpleFile(package_to_prefix_mappings_path_, &collector, &error_str)) { - if (error_str.empty()) { - error_str = TProtoStringType("protoc:0: warning: Failed to parse") - + TProtoStringType(" prefix to proto package mappings file: ") - + package_to_prefix_mappings_path_; - } - std::cerr << error_str << std::endl; - std::cerr.flush(); - package_to_prefix_map_.clear(); - } - } - - const TProtoStringType package = file->package(); - // For files without packages, the can be registered as "no_package:PATH", - // allowing the expected prefixes file. - static const TProtoStringType no_package_prefix("no_package:"); - const TProtoStringType lookup_key = package.empty() ? no_package_prefix + file->name() : package; - - std::map<TProtoStringType, TProtoStringType>::const_iterator prefix_lookup = - package_to_prefix_map_.find(lookup_key); - - if (prefix_lookup != package_to_prefix_map_.end()) { - return prefix_lookup->second; - } - - return ""; -} - -bool PrefixModeStorage::is_package_exempted(const TProtoStringType& package) { - if (exceptions_.empty() && !exception_path_.empty()) { - TProtoStringType error_str; - SimpleLineCollector collector(&exceptions_); - if (!ParseSimpleFile(exception_path_, &collector, &error_str)) { - if (error_str.empty()) { - error_str = TProtoStringType("protoc:0: warning: Failed to parse") - + TProtoStringType(" package prefix exceptions file: ") - + exception_path_; - } - std::cerr << error_str << std::endl; - std::cerr.flush(); - exceptions_.clear(); - } - - // If the file was empty put something in it so it doesn't get reloaded over - // and over. - if (exceptions_.empty()) { - exceptions_.insert("<not a real package>"); - } - } - - return exceptions_.count(package) != 0; -} - -PrefixModeStorage g_prefix_mode; - -} // namespace - -TProtoStringType GetPackageToPrefixMappingsPath() { - return g_prefix_mode.package_to_prefix_mappings_path(); -} - -void SetPackageToPrefixMappingsPath(const TProtoStringType& file_path) { - g_prefix_mode.set_package_to_prefix_mappings_path(file_path); -} - -bool UseProtoPackageAsDefaultPrefix() { - return g_prefix_mode.use_package_name(); -} - -void SetUseProtoPackageAsDefaultPrefix(bool on_or_off) { - g_prefix_mode.set_use_package_name(on_or_off); -} - -TProtoStringType GetProtoPackagePrefixExceptionList() { - return g_prefix_mode.exception_path(); -} - -void SetProtoPackagePrefixExceptionList(const TProtoStringType& file_path) { - g_prefix_mode.set_exception_path(file_path); -} - -Options::Options() { - // While there are generator options, also support env variables to help with - // build systems where it isn't as easy to hook in for add the generation - // options when invoking protoc. - const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES"); - if (file_path) { - expected_prefixes_path = file_path; - } - const char* suppressions = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS"); - if (suppressions) { - expected_prefixes_suppressions = - Split(suppressions, ";", true); - } - prefixes_must_be_registered = - BoolFromEnvVar("GPB_OBJC_PREFIXES_MUST_BE_REGISTERED", false); - require_prefixes = BoolFromEnvVar("GPB_OBJC_REQUIRE_PREFIXES", false); -} - -namespace { - -std::unordered_set<TProtoStringType> MakeWordsMap(const char* const words[], - size_t num_words) { - std::unordered_set<TProtoStringType> result; - for (int i = 0; i < num_words; i++) { - result.insert(words[i]); - } - return result; -} - -const char* const kUpperSegmentsList[] = {"url", "http", "https"}; - -std::unordered_set<TProtoStringType> kUpperSegments = - MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList)); - -bool ascii_isnewline(char c) { - return c == '\n' || c == '\r'; -} - -// Internal helper for name handing. -// Do not expose this outside of helpers, stick to having functions for specific -// cases (ClassName(), FieldName()), so there is always consistent suffix rules. -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& input, - bool first_capitalized) { - std::vector<TProtoStringType> values; - TProtoStringType current; - - bool last_char_was_number = false; - bool last_char_was_lower = false; - bool last_char_was_upper = false; - for (int i = 0; i < input.size(); i++) { - char c = input[i]; - if (ascii_isdigit(c)) { - if (!last_char_was_number) { - values.push_back(current); - current = ""; - } - current += c; - last_char_was_number = last_char_was_lower = last_char_was_upper = false; - last_char_was_number = true; - } else if (ascii_islower(c)) { - // lowercase letter can follow a lowercase or uppercase letter - if (!last_char_was_lower && !last_char_was_upper) { - values.push_back(current); - current = ""; - } - current += c; // already lower - last_char_was_number = last_char_was_lower = last_char_was_upper = false; - last_char_was_lower = true; - } else if (ascii_isupper(c)) { - if (!last_char_was_upper) { - values.push_back(current); - current = ""; - } - current += ascii_tolower(c); - last_char_was_number = last_char_was_lower = last_char_was_upper = false; - last_char_was_upper = true; - } else { - last_char_was_number = last_char_was_lower = last_char_was_upper = false; - } - } - values.push_back(current); - - TProtoStringType result; - bool first_segment_forces_upper = false; - for (std::vector<TProtoStringType>::iterator i = values.begin(); i != values.end(); - ++i) { - TProtoStringType value = *i; - bool all_upper = (kUpperSegments.count(value) > 0); - if (all_upper && (result.length() == 0)) { - first_segment_forces_upper = true; - } - for (int j = 0; j < value.length(); j++) { - if (j == 0 || all_upper) { - value[j] = ascii_toupper(value[j]); - } else { - // Nothing, already in lower. - } - } - result += value; - } - if ((result.length() != 0) && - !first_capitalized && - !first_segment_forces_upper) { - result[0] = ascii_tolower(result[0]); - } - return result; -} - -const char* const kReservedWordList[] = { - // Note NSObject Methods: - // These are brought in from objectivec_nsobject_methods.h that is generated - // using method_dump.sh. See kNSObjectMethods below. - - // Objective C "keywords" that aren't in C - // From - // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c - // with some others added on. - "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway", - "self", "instancetype", "nullable", "nonnull", "nil", "Nil", - "YES", "NO", "weak", - - // C/C++ keywords (Incl C++ 0x11) - // From http://en.cppreference.com/w/cpp/keywords - "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor", - "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class", - "compl", "const", "constexpr", "const_cast", "continue", "decltype", - "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit", - "export", "extern ", "false", "float", "for", "friend", "goto", "if", - "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not", - "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected", - "public", "register", "reinterpret_cast", "return", "short", "signed", - "sizeof", "static", "static_assert", "static_cast", "struct", "switch", - "template", "this", "thread_local", "throw", "true", "try", "typedef", - "typeid", "typename", "union", "unsigned", "using", "virtual", "void", - "volatile", "wchar_t", "while", "xor", "xor_eq", - - // C99 keywords - // From - // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm - "restrict", - - // GCC/Clang extension - "typeof", - - // Not a keyword, but will break you - "NULL", - - // C88+ specs call for these to be macros, so depending on what they are - // defined to be it can lead to odd errors for some Xcode/SDK versions. - "stdin", "stdout", "stderr", - - // Objective-C Runtime typedefs - // From <obc/runtime.h> - "Category", "Ivar", "Method", "Protocol", - - // GPBMessage Methods - // Only need to add instance methods that may conflict with - // method declared in protos. The main cases are methods - // that take no arguments, or setFoo:/hasFoo: type methods. - "clear", "data", "delimitedData", "descriptor", "extensionRegistry", - "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize", - "sortedExtensionsInUse", "unknownFields", - - // MacTypes.h names - "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount", - "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount", - "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType", - "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style", - "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord", -}; - -// returns true is input starts with __ or _[A-Z] which are reserved identifiers -// in C/ C++. All calls should go through UnderscoresToCamelCase before getting here -// but this verifies and allows for future expansion if we decide to redefine what a -// reserved C identifier is (for example the GNU list -// https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html ) -bool IsReservedCIdentifier(const TProtoStringType& input) { - if (input.length() > 2) { - if (input.at(0) == '_') { - if (isupper(input.at(1)) || input.at(1) == '_') { - return true; - } - } - } - return false; -} - -TProtoStringType SanitizeNameForObjC(const TProtoStringType& prefix, - const TProtoStringType& input, - const TProtoStringType& extension, - TProtoStringType* out_suffix_added) { - static const std::unordered_set<TProtoStringType> kReservedWords = - MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList)); - static const std::unordered_set<TProtoStringType> kNSObjectMethods = - MakeWordsMap(kNSObjectMethodsList, GOOGLE_ARRAYSIZE(kNSObjectMethodsList)); - TProtoStringType sanitized; - // We add the prefix in the cases where the string is missing a prefix. - // We define "missing a prefix" as where 'input': - // a) Doesn't start with the prefix or - // b) Isn't equivalent to the prefix or - // c) Has the prefix, but the letter after the prefix is lowercase - if (HasPrefixString(input, prefix)) { - if (input.length() == prefix.length() || !ascii_isupper(input[prefix.length()])) { - sanitized = prefix + input; - } else { - sanitized = input; - } - } else { - sanitized = prefix + input; - } - if (IsReservedCIdentifier(sanitized) || - (kReservedWords.count(sanitized) > 0) || - (kNSObjectMethods.count(sanitized) > 0)) { - if (out_suffix_added) *out_suffix_added = extension; - return sanitized + extension; - } - if (out_suffix_added) out_suffix_added->clear(); - return sanitized; -} - -TProtoStringType NameFromFieldDescriptor(const FieldDescriptor* field) { - if (field->type() == FieldDescriptor::TYPE_GROUP) { - return field->message_type()->name(); - } else { - return field->name(); - } -} - -void PathSplit(const TProtoStringType& path, TProtoStringType* directory, - TProtoStringType* basename) { - TProtoStringType::size_type last_slash = path.rfind('/'); - if (last_slash == TProtoStringType::npos) { - if (directory) { - *directory = ""; - } - if (basename) { - *basename = path; - } - } else { - if (directory) { - *directory = path.substr(0, last_slash); - } - if (basename) { - *basename = path.substr(last_slash + 1); - } - } -} - -bool IsSpecialName(const TProtoStringType& name, const TProtoStringType* special_names, - size_t count) { - for (size_t i = 0; i < count; ++i) { - size_t length = special_names[i].length(); - if (name.compare(0, length, special_names[i]) == 0) { - if (name.length() > length) { - // If name is longer than the retained_name[i] that it matches - // the next character must be not lower case (newton vs newTon vs - // new_ton). - return !ascii_islower(name[length]); - } else { - return true; - } - } - } - return false; -} - -TProtoStringType GetZeroEnumNameForFlagType(const FlagType flag_type) { - switch(flag_type) { - case FLAGTYPE_DESCRIPTOR_INITIALIZATION: - return "GPBDescriptorInitializationFlag_None"; - case FLAGTYPE_EXTENSION: - return "GPBExtensionNone"; - case FLAGTYPE_FIELD: - return "GPBFieldNone"; - default: - GOOGLE_LOG(FATAL) << "Can't get here."; - return "0"; - } -} - -TProtoStringType GetEnumNameForFlagType(const FlagType flag_type) { - switch(flag_type) { - case FLAGTYPE_DESCRIPTOR_INITIALIZATION: - return "GPBDescriptorInitializationFlags"; - case FLAGTYPE_EXTENSION: - return "GPBExtensionOptions"; - case FLAGTYPE_FIELD: - return "GPBFieldFlags"; - default: - GOOGLE_LOG(FATAL) << "Can't get here."; - return TProtoStringType(); - } -} - -void MaybeUnQuote(StringPiece* input) { - if ((input->length() >= 2) && - ((*input->data() == '\'' || *input->data() == '"')) && - ((*input)[input->length() - 1] == *input->data())) { - input->remove_prefix(1); - input->remove_suffix(1); - } -} - -} // namespace - -// Escape C++ trigraphs by escaping question marks to \? -TProtoStringType EscapeTrigraphs(const TProtoStringType& to_escape) { - return StringReplace(to_escape, "?", "\\?", true); -} - -void TrimWhitespace(StringPiece* input) { - while (!input->empty() && ascii_isspace(*input->data())) { - input->remove_prefix(1); - } - while (!input->empty() && ascii_isspace((*input)[input->length() - 1])) { - input->remove_suffix(1); - } -} - -bool IsRetainedName(const TProtoStringType& name) { - // List of prefixes from - // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html - static const TProtoStringType retained_names[] = {"new", "alloc", "copy", - "mutableCopy"}; - return IsSpecialName(name, retained_names, - sizeof(retained_names) / sizeof(retained_names[0])); -} - -bool IsInitName(const TProtoStringType& name) { - static const TProtoStringType init_names[] = {"init"}; - return IsSpecialName(name, init_names, - sizeof(init_names) / sizeof(init_names[0])); -} - -TProtoStringType BaseFileName(const FileDescriptor* file) { - TProtoStringType basename; - PathSplit(file->name(), NULL, &basename); - return basename; -} - -TProtoStringType FileClassPrefix(const FileDescriptor* file) { - // Always honor the file option. - if (file->options().has_objc_class_prefix()) { - return file->options().objc_class_prefix(); - } - - // If package prefix is specified in an prefix to proto mappings file then use that. - TProtoStringType objc_class_prefix = g_prefix_mode.prefix_from_proto_package_mappings(file); - if (!objc_class_prefix.empty()) { - return objc_class_prefix; - } - - // If package prefix isn't enabled, done. - if (!g_prefix_mode.use_package_name()) { - return ""; - } - - // If the package is in the exceptions list, done. - if (g_prefix_mode.is_package_exempted(file->package())) { - return ""; - } - - // Transform the package into a prefix: use the dot segments as part, - // camelcase each one and then join them with underscores, and add an - // underscore at the end. - TProtoStringType result; - const std::vector<TProtoStringType> segments = Split(file->package(), ".", true); - for (const auto& segment : segments) { - const TProtoStringType part = UnderscoresToCamelCase(segment, true); - if (part.empty()) { - continue; - } - if (!result.empty()) { - result.append("_"); - } - result.append(part); - } - if (!result.empty()) { - result.append("_"); - } - return g_prefix_mode.forced_package_prefix() + result; -} - -TProtoStringType FilePath(const FileDescriptor* file) { - TProtoStringType output; - TProtoStringType basename; - TProtoStringType directory; - PathSplit(file->name(), &directory, &basename); - if (directory.length() > 0) { - output = directory + "/"; - } - basename = StripProto(basename); - - // CamelCase to be more ObjC friendly. - basename = UnderscoresToCamelCase(basename, true); - - output += basename; - return output; -} - -TProtoStringType FilePathBasename(const FileDescriptor* file) { - TProtoStringType output; - TProtoStringType basename; - TProtoStringType directory; - PathSplit(file->name(), &directory, &basename); - basename = StripProto(basename); - - // CamelCase to be more ObjC friendly. - output = UnderscoresToCamelCase(basename, true); - - return output; -} - -TProtoStringType FileClassName(const FileDescriptor* file) { - const TProtoStringType prefix = FileClassPrefix(file); - const TProtoStringType name = - UnderscoresToCamelCase(StripProto(BaseFileName(file)), true) + "Root"; - // There aren't really any reserved words that end in "Root", but playing - // it safe and checking. - return SanitizeNameForObjC(prefix, name, "_RootClass", NULL); -} - -TProtoStringType ClassNameWorker(const Descriptor* descriptor) { - TProtoStringType name; - if (descriptor->containing_type() != NULL) { - name = ClassNameWorker(descriptor->containing_type()); - name += "_"; - } - return name + descriptor->name(); -} - -TProtoStringType ClassNameWorker(const EnumDescriptor* descriptor) { - TProtoStringType name; - if (descriptor->containing_type() != NULL) { - name = ClassNameWorker(descriptor->containing_type()); - name += "_"; - } - return name + descriptor->name(); -} - -TProtoStringType ClassName(const Descriptor* descriptor) { - return ClassName(descriptor, NULL); -} - -TProtoStringType ClassName(const Descriptor* descriptor, - TProtoStringType* out_suffix_added) { - // 1. Message names are used as is (style calls for CamelCase, trust it). - // 2. Check for reserved word at the very end and then suffix things. - const TProtoStringType prefix = FileClassPrefix(descriptor->file()); - const TProtoStringType name = ClassNameWorker(descriptor); - return SanitizeNameForObjC(prefix, name, "_Class", out_suffix_added); -} - -TProtoStringType EnumName(const EnumDescriptor* descriptor) { - // 1. Enum names are used as is (style calls for CamelCase, trust it). - // 2. Check for reserved word at the every end and then suffix things. - // message Fixed { - // message Size {...} - // enum Mumble {...} - // ... - // } - // yields Fixed_Class, Fixed_Size. - const TProtoStringType prefix = FileClassPrefix(descriptor->file()); - const TProtoStringType name = ClassNameWorker(descriptor); - return SanitizeNameForObjC(prefix, name, "_Enum", NULL); -} - -TProtoStringType EnumValueName(const EnumValueDescriptor* descriptor) { - // Because of the Switch enum compatibility, the name on the enum has to have - // the suffix handing, so it slightly diverges from how nested classes work. - // enum Fixed { - // FOO = 1 - // } - // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo). - const TProtoStringType class_name = EnumName(descriptor->type()); - const TProtoStringType value_str = - UnderscoresToCamelCase(descriptor->name(), true); - const TProtoStringType name = class_name + "_" + value_str; - // There aren't really any reserved words with an underscore and a leading - // capital letter, but playing it safe and checking. - return SanitizeNameForObjC("", name, "_Value", NULL); -} - -TProtoStringType EnumValueShortName(const EnumValueDescriptor* descriptor) { - // Enum value names (EnumValueName above) are the enum name turned into - // a class name and then the value name is CamelCased and concatenated; the - // whole thing then gets sanitized for reserved words. - // The "short name" is intended to be the final leaf, the value name; but - // you can't simply send that off to sanitize as that could result in it - // getting modified when the full name didn't. For example enum - // "StorageModes" has a value "retain". So the full name is - // "StorageModes_Retain", but if we sanitize "retain" it would become - // "RetainValue". - // So the right way to get the short name is to take the full enum name - // and then strip off the enum name (leaving the value name and anything - // done by sanitize). - const TProtoStringType class_name = EnumName(descriptor->type()); - const TProtoStringType long_name_prefix = class_name + "_"; - const TProtoStringType long_name = EnumValueName(descriptor); - return StripPrefixString(long_name, long_name_prefix); -} - -TProtoStringType UnCamelCaseEnumShortName(const TProtoStringType& name) { - TProtoStringType result; - for (int i = 0; i < name.size(); i++) { - char c = name[i]; - if (i > 0 && ascii_isupper(c)) { - result += '_'; - } - result += ascii_toupper(c); - } - return result; -} - -TProtoStringType ExtensionMethodName(const FieldDescriptor* descriptor) { - const TProtoStringType name = NameFromFieldDescriptor(descriptor); - const TProtoStringType result = UnderscoresToCamelCase(name, false); - return SanitizeNameForObjC("", result, "_Extension", NULL); -} - -TProtoStringType FieldName(const FieldDescriptor* field) { - const TProtoStringType name = NameFromFieldDescriptor(field); - TProtoStringType result = UnderscoresToCamelCase(name, false); - if (field->is_repeated() && !field->is_map()) { - // Add "Array" before do check for reserved worlds. - result += "Array"; - } else { - // If it wasn't repeated, but ends in "Array", force on the _p suffix. - if (HasSuffixString(result, "Array")) { - result += "_p"; - } - } - return SanitizeNameForObjC("", result, "_p", NULL); -} - -TProtoStringType FieldNameCapitalized(const FieldDescriptor* field) { - // Want the same suffix handling, so upcase the first letter of the other - // name. - TProtoStringType result = FieldName(field); - if (result.length() > 0) { - result[0] = ascii_toupper(result[0]); - } - return result; -} - -TProtoStringType OneofEnumName(const OneofDescriptor* descriptor) { - const Descriptor* fieldDescriptor = descriptor->containing_type(); - TProtoStringType name = ClassName(fieldDescriptor); - name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase"; - // No sanitize needed because the OS never has names that end in _OneOfCase. - return name; -} - -TProtoStringType OneofName(const OneofDescriptor* descriptor) { - TProtoStringType name = UnderscoresToCamelCase(descriptor->name(), false); - // No sanitize needed because it gets OneOfCase added and that shouldn't - // ever conflict. - return name; -} - -TProtoStringType OneofNameCapitalized(const OneofDescriptor* descriptor) { - // Use the common handling and then up-case the first letter. - TProtoStringType result = OneofName(descriptor); - if (result.length() > 0) { - result[0] = ascii_toupper(result[0]); - } - return result; -} - -TProtoStringType ObjCClass(const TProtoStringType& class_name) { - return TProtoStringType("GPBObjCClass(") + class_name + ")"; -} - -TProtoStringType ObjCClassDeclaration(const TProtoStringType& class_name) { - return TProtoStringType("GPBObjCClassDeclaration(") + class_name + ");"; -} - -TProtoStringType UnCamelCaseFieldName(const TProtoStringType& name, const FieldDescriptor* field) { - TProtoStringType worker(name); - if (HasSuffixString(worker, "_p")) { - worker = StripSuffixString(worker, "_p"); - } - if (field->is_repeated() && HasSuffixString(worker, "Array")) { - worker = StripSuffixString(worker, "Array"); - } - if (field->type() == FieldDescriptor::TYPE_GROUP) { - if (worker.length() > 0) { - if (ascii_islower(worker[0])) { - worker[0] = ascii_toupper(worker[0]); - } - } - return worker; - } else { - TProtoStringType result; - for (int i = 0; i < worker.size(); i++) { - char c = worker[i]; - if (ascii_isupper(c)) { - if (i > 0) { - result += '_'; - } - result += ascii_tolower(c); - } else { - result += c; - } - } - return result; - } -} - -TProtoStringType GetCapitalizedType(const FieldDescriptor* field) { - switch (field->type()) { - case FieldDescriptor::TYPE_INT32: - return "Int32"; - case FieldDescriptor::TYPE_UINT32: - return "UInt32"; - case FieldDescriptor::TYPE_SINT32: - return "SInt32"; - case FieldDescriptor::TYPE_FIXED32: - return "Fixed32"; - case FieldDescriptor::TYPE_SFIXED32: - return "SFixed32"; - case FieldDescriptor::TYPE_INT64: - return "Int64"; - case FieldDescriptor::TYPE_UINT64: - return "UInt64"; - case FieldDescriptor::TYPE_SINT64: - return "SInt64"; - case FieldDescriptor::TYPE_FIXED64: - return "Fixed64"; - case FieldDescriptor::TYPE_SFIXED64: - return "SFixed64"; - case FieldDescriptor::TYPE_FLOAT: - return "Float"; - case FieldDescriptor::TYPE_DOUBLE: - return "Double"; - case FieldDescriptor::TYPE_BOOL: - return "Bool"; - case FieldDescriptor::TYPE_STRING: - return "String"; - case FieldDescriptor::TYPE_BYTES: - return "Bytes"; - case FieldDescriptor::TYPE_ENUM: - return "Enum"; - case FieldDescriptor::TYPE_GROUP: - return "Group"; - case FieldDescriptor::TYPE_MESSAGE: - return "Message"; - } - - // Some compilers report reaching end of function even though all cases of - // the enum are handed in the switch. - GOOGLE_LOG(FATAL) << "Can't get here."; - return TProtoStringType(); -} - -ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) { - switch (field_type) { - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_SINT32: - case FieldDescriptor::TYPE_SFIXED32: - return OBJECTIVECTYPE_INT32; - - case FieldDescriptor::TYPE_UINT32: - case FieldDescriptor::TYPE_FIXED32: - return OBJECTIVECTYPE_UINT32; - - case FieldDescriptor::TYPE_INT64: - case FieldDescriptor::TYPE_SINT64: - case FieldDescriptor::TYPE_SFIXED64: - return OBJECTIVECTYPE_INT64; - - case FieldDescriptor::TYPE_UINT64: - case FieldDescriptor::TYPE_FIXED64: - return OBJECTIVECTYPE_UINT64; - - case FieldDescriptor::TYPE_FLOAT: - return OBJECTIVECTYPE_FLOAT; - - case FieldDescriptor::TYPE_DOUBLE: - return OBJECTIVECTYPE_DOUBLE; - - case FieldDescriptor::TYPE_BOOL: - return OBJECTIVECTYPE_BOOLEAN; - - case FieldDescriptor::TYPE_STRING: - return OBJECTIVECTYPE_STRING; - - case FieldDescriptor::TYPE_BYTES: - return OBJECTIVECTYPE_DATA; - - case FieldDescriptor::TYPE_ENUM: - return OBJECTIVECTYPE_ENUM; - - case FieldDescriptor::TYPE_GROUP: - case FieldDescriptor::TYPE_MESSAGE: - return OBJECTIVECTYPE_MESSAGE; - } - - // Some compilers report reaching end of function even though all cases of - // the enum are handed in the switch. - GOOGLE_LOG(FATAL) << "Can't get here."; - return OBJECTIVECTYPE_INT32; -} - -bool IsPrimitiveType(const FieldDescriptor* field) { - ObjectiveCType type = GetObjectiveCType(field); - switch (type) { - case OBJECTIVECTYPE_INT32: - case OBJECTIVECTYPE_UINT32: - case OBJECTIVECTYPE_INT64: - case OBJECTIVECTYPE_UINT64: - case OBJECTIVECTYPE_FLOAT: - case OBJECTIVECTYPE_DOUBLE: - case OBJECTIVECTYPE_BOOLEAN: - case OBJECTIVECTYPE_ENUM: - return true; - break; - default: - return false; - } -} - -bool IsReferenceType(const FieldDescriptor* field) { - return !IsPrimitiveType(field); -} - -static TProtoStringType HandleExtremeFloatingPoint(TProtoStringType val, - bool add_float_suffix) { - if (val == "nan") { - return "NAN"; - } else if (val == "inf") { - return "INFINITY"; - } else if (val == "-inf") { - return "-INFINITY"; - } else { - // float strings with ., e or E need to have f appended - if (add_float_suffix && (val.find(".") != TProtoStringType::npos || - val.find("e") != TProtoStringType::npos || - val.find("E") != TProtoStringType::npos)) { - val += "f"; - } - return val; - } -} - -TProtoStringType GPBGenericValueFieldName(const FieldDescriptor* field) { - // Returns the field within the GPBGenericValue union to use for the given - // field. - if (field->is_repeated()) { - return "valueMessage"; - } - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - return "valueInt32"; - case FieldDescriptor::CPPTYPE_UINT32: - return "valueUInt32"; - case FieldDescriptor::CPPTYPE_INT64: - return "valueInt64"; - case FieldDescriptor::CPPTYPE_UINT64: - return "valueUInt64"; - case FieldDescriptor::CPPTYPE_FLOAT: - return "valueFloat"; - case FieldDescriptor::CPPTYPE_DOUBLE: - return "valueDouble"; - case FieldDescriptor::CPPTYPE_BOOL: - return "valueBool"; - case FieldDescriptor::CPPTYPE_STRING: - if (field->type() == FieldDescriptor::TYPE_BYTES) { - return "valueData"; - } else { - return "valueString"; - } - case FieldDescriptor::CPPTYPE_ENUM: - return "valueEnum"; - case FieldDescriptor::CPPTYPE_MESSAGE: - return "valueMessage"; - } - - // Some compilers report reaching end of function even though all cases of - // the enum are handed in the switch. - GOOGLE_LOG(FATAL) << "Can't get here."; - return TProtoStringType(); -} - - -TProtoStringType DefaultValue(const FieldDescriptor* field) { - // Repeated fields don't have defaults. - if (field->is_repeated()) { - return "nil"; - } - - // Switch on cpp_type since we need to know which default_value_* method - // of FieldDescriptor to call. - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - // gcc and llvm reject the decimal form of kint32min and kint64min. - if (field->default_value_int32() == INT_MIN) { - return "-0x80000000"; - } - return StrCat(field->default_value_int32()); - case FieldDescriptor::CPPTYPE_UINT32: - return StrCat(field->default_value_uint32()) + "U"; - case FieldDescriptor::CPPTYPE_INT64: - // gcc and llvm reject the decimal form of kint32min and kint64min. - if (field->default_value_int64() == LLONG_MIN) { - return "-0x8000000000000000LL"; - } - return StrCat(field->default_value_int64()) + "LL"; - case FieldDescriptor::CPPTYPE_UINT64: - return StrCat(field->default_value_uint64()) + "ULL"; - case FieldDescriptor::CPPTYPE_DOUBLE: - return HandleExtremeFloatingPoint( - SimpleDtoa(field->default_value_double()), false); - case FieldDescriptor::CPPTYPE_FLOAT: - return HandleExtremeFloatingPoint( - SimpleFtoa(field->default_value_float()), true); - case FieldDescriptor::CPPTYPE_BOOL: - return field->default_value_bool() ? "YES" : "NO"; - case FieldDescriptor::CPPTYPE_STRING: { - const bool has_default_value = field->has_default_value(); - const TProtoStringType& default_string = field->default_value_string(); - if (!has_default_value || default_string.length() == 0) { - // If the field is defined as being the empty string, - // then we will just assign to nil, as the empty string is the - // default for both strings and data. - return "nil"; - } - if (field->type() == FieldDescriptor::TYPE_BYTES) { - // We want constant fields in our data structures so we can - // declare them as static. To achieve this we cheat and stuff - // a escaped c string (prefixed with a length) into the data - // field, and cast it to an (NSData*) so it will compile. - // The runtime library knows how to handle it. - - // Must convert to a standard byte order for packing length into - // a cstring. - arc_ui32 length = ghtonl(default_string.length()); - TProtoStringType bytes((const char*)&length, sizeof(length)); - bytes.append(default_string); - return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\""; - } else { - return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\""; - } - } - case FieldDescriptor::CPPTYPE_ENUM: - return EnumValueName(field->default_value_enum()); - case FieldDescriptor::CPPTYPE_MESSAGE: - return "nil"; - } - - // Some compilers report reaching end of function even though all cases of - // the enum are handed in the switch. - GOOGLE_LOG(FATAL) << "Can't get here."; - return TProtoStringType(); -} - -bool HasNonZeroDefaultValue(const FieldDescriptor* field) { - // Repeated fields don't have defaults. - if (field->is_repeated()) { - return false; - } - - // As much as checking field->has_default_value() seems useful, it isn't - // because of enums. proto2 syntax allows the first item in an enum (the - // default) to be non zero. So checking field->has_default_value() would - // result in missing this non zero default. See MessageWithOneBasedEnum in - // objectivec/Tests/unittest_objc.proto for a test Message to confirm this. - - // Some proto file set the default to the zero value, so make sure the value - // isn't the zero case. - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - return field->default_value_int32() != 0; - case FieldDescriptor::CPPTYPE_UINT32: - return field->default_value_uint32() != 0U; - case FieldDescriptor::CPPTYPE_INT64: - return field->default_value_int64() != 0LL; - case FieldDescriptor::CPPTYPE_UINT64: - return field->default_value_uint64() != 0ULL; - case FieldDescriptor::CPPTYPE_DOUBLE: - return field->default_value_double() != 0.0; - case FieldDescriptor::CPPTYPE_FLOAT: - return field->default_value_float() != 0.0f; - case FieldDescriptor::CPPTYPE_BOOL: - return field->default_value_bool(); - case FieldDescriptor::CPPTYPE_STRING: { - const TProtoStringType& default_string = field->default_value_string(); - return default_string.length() != 0; - } - case FieldDescriptor::CPPTYPE_ENUM: - return field->default_value_enum()->number() != 0; - case FieldDescriptor::CPPTYPE_MESSAGE: - return false; - } - - // Some compilers report reaching end of function even though all cases of - // the enum are handed in the switch. - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; -} - -TProtoStringType BuildFlagsString(const FlagType flag_type, - const std::vector<TProtoStringType>& strings) { - if (strings.empty()) { - return GetZeroEnumNameForFlagType(flag_type); - } else if (strings.size() == 1) { - return strings[0]; - } - TProtoStringType string("(" + GetEnumNameForFlagType(flag_type) + ")("); - for (size_t i = 0; i != strings.size(); ++i) { - if (i > 0) { - string.append(" | "); - } - string.append(strings[i]); - } - string.append(")"); - return string; -} - -TProtoStringType BuildCommentsString(const SourceLocation& location, - bool prefer_single_line) { - const TProtoStringType& comments = location.leading_comments.empty() - ? location.trailing_comments - : location.leading_comments; - std::vector<TProtoStringType> lines; - lines = Split(comments, "\n", false); - while (!lines.empty() && lines.back().empty()) { - lines.pop_back(); - } - // If there are no comments, just return an empty string. - if (lines.empty()) { - return ""; - } - - TProtoStringType prefix; - TProtoStringType suffix; - TProtoStringType final_comments; - TProtoStringType epilogue; - - bool add_leading_space = false; - - if (prefer_single_line && lines.size() == 1) { - prefix = "/** "; - suffix = " */\n"; - } else { - prefix = "* "; - suffix = "\n"; - final_comments += "/**\n"; - epilogue = " **/\n"; - add_leading_space = true; - } - - for (int i = 0; i < lines.size(); i++) { - TProtoStringType line = StripPrefixString(lines[i], " "); - // HeaderDoc and appledoc use '\' and '@' for markers; escape them. - line = StringReplace(line, "\\", "\\\\", true); - line = StringReplace(line, "@", "\\@", true); - // Decouple / from * to not have inline comments inside comments. - line = StringReplace(line, "/*", "/\\*", true); - line = StringReplace(line, "*/", "*\\/", true); - line = prefix + line; - StripWhitespace(&line); - // If not a one line, need to add the first space before *, as - // StripWhitespace would have removed it. - line = (add_leading_space ? " " : "") + line; - final_comments += line + suffix; - } - final_comments += epilogue; - return final_comments; -} - -// Making these a generator option for folks that don't use CocoaPods, but do -// want to put the library in a framework is an interesting question. The -// problem is it means changing sources shipped with the library to actually -// use a different value; so it isn't as simple as a option. -const char* const ProtobufLibraryFrameworkName = "Protobuf"; - -TProtoStringType ProtobufFrameworkImportSymbol(const TProtoStringType& framework_name) { - // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS - TProtoStringType result = TProtoStringType("GPB_USE_"); - result += ToUpper(framework_name); - result += "_FRAMEWORK_IMPORTS"; - return result; -} - -bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) { - // We don't check the name prefix or proto package because some files - // (descriptor.proto), aren't shipped generated by the library, so this - // seems to be the safest way to only catch the ones shipped. - const TProtoStringType name = file->name(); - if (name == "google/protobuf/any.proto" || - name == "google/protobuf/api.proto" || - name == "google/protobuf/duration.proto" || - name == "google/protobuf/empty.proto" || - name == "google/protobuf/field_mask.proto" || - name == "google/protobuf/source_context.proto" || - name == "google/protobuf/struct.proto" || - name == "google/protobuf/timestamp.proto" || - name == "google/protobuf/type.proto" || - name == "google/protobuf/wrappers.proto") { - return true; - } - return false; -} - -bool ReadLine(StringPiece* input, StringPiece* line) { - for (int len = 0; len < input->size(); ++len) { - if (ascii_isnewline((*input)[len])) { - *line = StringPiece(input->data(), len); - ++len; // advance over the newline - *input = StringPiece(input->data() + len, input->size() - len); - return true; - } - } - return false; // Ran out of input with no newline. -} - -void RemoveComment(StringPiece* input) { - int offset = input->find('#'); - if (offset != StringPiece::npos) { - input->remove_suffix(input->length() - offset); - } -} - -namespace { - -bool PackageToPrefixesCollector::ConsumeLine( - const StringPiece& line, TProtoStringType* out_error) { - int offset = line.find('='); - if (offset == StringPiece::npos) { - *out_error = usage_ + " file line without equal sign: '" + StrCat(line) + "'."; - return false; - } - StringPiece package = line.substr(0, offset); - StringPiece prefix = line.substr(offset + 1); - TrimWhitespace(&package); - TrimWhitespace(&prefix); - MaybeUnQuote(&prefix); - // Don't really worry about error checking the package/prefix for - // being valid. Assume the file is validated when it is created/edited. - (*prefix_map_)[TProtoStringType(package)] = TProtoStringType(prefix); - return true; -} - -bool LoadExpectedPackagePrefixes(const TProtoStringType& expected_prefixes_path, - std::map<TProtoStringType, TProtoStringType>* prefix_map, - TProtoStringType* out_error) { - if (expected_prefixes_path.empty()) { - return true; - } - - PackageToPrefixesCollector collector("Expected prefixes", prefix_map); - return ParseSimpleFile( - expected_prefixes_path, &collector, out_error); -} - -bool ValidateObjCClassPrefix( - const FileDescriptor* file, const TProtoStringType& expected_prefixes_path, - const std::map<TProtoStringType, TProtoStringType>& expected_package_prefixes, - bool prefixes_must_be_registered, bool require_prefixes, - TProtoStringType* out_error) { - // Reminder: An explicit prefix option of "" is valid in case the default - // prefixing is set to use the proto package and a file needs to be generated - // without any prefix at all (for legacy reasons). - - bool has_prefix = file->options().has_objc_class_prefix(); - bool have_expected_prefix_file = !expected_prefixes_path.empty(); - - const TProtoStringType prefix = file->options().objc_class_prefix(); - const TProtoStringType package = file->package(); - // For files without packages, the can be registered as "no_package:PATH", - // allowing the expected prefixes file. - static const TProtoStringType no_package_prefix("no_package:"); - const TProtoStringType lookup_key = - package.empty() ? no_package_prefix + file->name() : package; - - // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some - // error cases, so it seems to be ok to use as a back door for warnings. - - // Check: Error - See if there was an expected prefix for the package and - // report if it doesn't match (wrong or missing). - std::map<TProtoStringType, TProtoStringType>::const_iterator package_match = - expected_package_prefixes.find(lookup_key); - if (package_match != expected_package_prefixes.end()) { - // There was an entry, and... - if (has_prefix && package_match->second == prefix) { - // ...it matches. All good, out of here! - return true; - } else { - // ...it didn't match! - *out_error = "error: Expected 'option objc_class_prefix = \"" + - package_match->second + "\";'"; - if (!package.empty()) { - *out_error += " for package '" + package + "'"; - } - *out_error += " in '" + file->name() + "'"; - if (has_prefix) { - *out_error += "; but found '" + prefix + "' instead"; - } - *out_error += "."; - return false; - } - } - - // If there was no prefix option, we're done at this point. - if (!has_prefix) { - if (require_prefixes) { - *out_error = - "error: '" + file->name() + "' does not have a required 'option" + - " objc_class_prefix'."; - return false; - } - return true; - } - - // When the prefix is non empty, check it against the expected entries. - if (!prefix.empty() && have_expected_prefix_file) { - // For a non empty prefix, look for any other package that uses the prefix. - TProtoStringType other_package_for_prefix; - for (std::map<TProtoStringType, TProtoStringType>::const_iterator i = - expected_package_prefixes.begin(); - i != expected_package_prefixes.end(); ++i) { - if (i->second == prefix) { - other_package_for_prefix = i->first; - // Stop on the first real package listing, if it was a no_package file - // specific entry, keep looking to try and find a package one. - if (!HasPrefixString(other_package_for_prefix, no_package_prefix)) { - break; - } - } - } - - // Check: Error - Make sure the prefix wasn't expected for a different - // package (overlap is allowed, but it has to be listed as an expected - // overlap). - if (!other_package_for_prefix.empty()) { - *out_error = - "error: Found 'option objc_class_prefix = \"" + prefix + - "\";' in '" + file->name() + "'; that prefix is already used for "; - if (HasPrefixString(other_package_for_prefix, no_package_prefix)) { - *out_error += "file '" + - StripPrefixString(other_package_for_prefix, no_package_prefix) + - "'."; - } else { - *out_error += "'package " + other_package_for_prefix + ";'."; - } - *out_error += - " It can only be reused by adding '" + lookup_key + " = " + prefix + - "' to the expected prefixes file (" + expected_prefixes_path + ")."; - return false; // Only report first usage of the prefix. - } - } // !prefix.empty() && have_expected_prefix_file - - // Check: Warning - Make sure the prefix is is a reasonable value according - // to Apple's rules (the checks above implicitly whitelist anything that - // doesn't meet these rules). - if (!prefix.empty() && !ascii_isupper(prefix[0])) { - std::cerr - << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" - << prefix << "\";' in '" << file->name() << "';" - << " it should start with a capital letter." << std::endl; - std::cerr.flush(); - } - if (!prefix.empty() && prefix.length() < 3) { - // Apple reserves 2 character prefixes for themselves. They do use some - // 3 character prefixes, but they haven't updated the rules/docs. - std::cerr - << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" - << prefix << "\";' in '" << file->name() << "';" - << " Apple recommends they should be at least 3 characters long." - << std::endl; - std::cerr.flush(); - } - - // Check: Error/Warning - If the given package/prefix pair wasn't expected, - // issue a error/warning to added to the file. - if (have_expected_prefix_file) { - if (prefixes_must_be_registered) { - *out_error = - "error: '" + file->name() + "' has 'option objc_class_prefix = \"" + - prefix + "\";', but it is not registered. Add '" + lookup_key + " = " + - (prefix.empty() ? "\"\"" : prefix) + - "' to the expected prefixes file (" + expected_prefixes_path + ")."; - return false; - } - - std::cerr - << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \"" - << prefix << "\";' in '" << file->name() << "'; consider adding '" - << lookup_key << " = " << (prefix.empty() ? "\"\"" : prefix) - << "' to the expected prefixes file (" << expected_prefixes_path - << ")." << std::endl; - std::cerr.flush(); - } - - return true; -} - -} // namespace - -bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files, - TProtoStringType* out_error) { - // Options's ctor load from the environment. - Options options; - return ValidateObjCClassPrefixes(files, options, out_error); -} - -bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files, - const Options& generation_options, - TProtoStringType* out_error) { - // Allow a '-' as the path for the expected prefixes to completely disable - // even the most basic of checks. - if (generation_options.expected_prefixes_path == "-") { - return true; - } - - // Load the expected package prefixes, if available, to validate against. - std::map<TProtoStringType, TProtoStringType> expected_package_prefixes; - if (!LoadExpectedPackagePrefixes(generation_options.expected_prefixes_path, - &expected_package_prefixes, - out_error)) { - return false; - } - - for (int i = 0; i < files.size(); i++) { - bool should_skip = - (std::find(generation_options.expected_prefixes_suppressions.begin(), - generation_options.expected_prefixes_suppressions.end(), - files[i]->name()) - != generation_options.expected_prefixes_suppressions.end()); - if (should_skip) { - continue; - } - - bool is_valid = - ValidateObjCClassPrefix(files[i], - generation_options.expected_prefixes_path, - expected_package_prefixes, - generation_options.prefixes_must_be_registered, - generation_options.require_prefixes, - out_error); - if (!is_valid) { - return false; - } - } - return true; -} - -TextFormatDecodeData::TextFormatDecodeData() { } - -TextFormatDecodeData::~TextFormatDecodeData() { } - -void TextFormatDecodeData::AddString(arc_i32 key, - const TProtoStringType& input_for_decode, - const TProtoStringType& desired_output) { - for (std::vector<DataEntry>::const_iterator i = entries_.begin(); - i != entries_.end(); ++i) { - if (i->first == key) { - std::cerr << "error: duplicate key (" << key - << ") making TextFormat data, input: \"" << input_for_decode - << "\", desired: \"" << desired_output << "\"." << std::endl; - std::cerr.flush(); - abort(); - } - } - - const TProtoStringType& data = TextFormatDecodeData::DecodeDataForString( - input_for_decode, desired_output); - entries_.push_back(DataEntry(key, data)); -} - -TProtoStringType TextFormatDecodeData::Data() const { - std::ostringstream data_stringstream; - - if (num_entries() > 0) { - io::OstreamOutputStream data_outputstream(&data_stringstream); - io::CodedOutputStream output_stream(&data_outputstream); - - output_stream.WriteVarint32(num_entries()); - for (std::vector<DataEntry>::const_iterator i = entries_.begin(); - i != entries_.end(); ++i) { - output_stream.WriteVarint32(i->first); - output_stream.WriteString(i->second); - } - } - - data_stringstream.flush(); - return TProtoStringType{data_stringstream.str()}; -} - -namespace { - -// Helper to build up the decode data for a string. -class DecodeDataBuilder { - public: - DecodeDataBuilder() { Reset(); } - - bool AddCharacter(const char desired, const char input); - void AddUnderscore() { - Push(); - need_underscore_ = true; - } - TProtoStringType Finish() { - Push(); - return decode_data_; - } - - private: - static constexpr uint8_t kAddUnderscore = 0x80; - - static constexpr uint8_t kOpAsIs = 0x00; - static constexpr uint8_t kOpFirstUpper = 0x40; - static constexpr uint8_t kOpFirstLower = 0x20; - static constexpr uint8_t kOpAllUpper = 0x60; - - static constexpr int kMaxSegmentLen = 0x1f; - - void AddChar(const char desired) { - ++segment_len_; - is_all_upper_ &= ascii_isupper(desired); - } - - void Push() { - uint8_t op = (op_ | segment_len_); - if (need_underscore_) op |= kAddUnderscore; - if (op != 0) { - decode_data_ += (char)op; - } - Reset(); - } - - bool AddFirst(const char desired, const char input) { - if (desired == input) { - op_ = kOpAsIs; - } else if (desired == ascii_toupper(input)) { - op_ = kOpFirstUpper; - } else if (desired == ascii_tolower(input)) { - op_ = kOpFirstLower; - } else { - // Can't be transformed to match. - return false; - } - AddChar(desired); - return true; - } - - void Reset() { - need_underscore_ = false; - op_ = 0; - segment_len_ = 0; - is_all_upper_ = true; - } - - bool need_underscore_; - bool is_all_upper_; - uint8_t op_; - int segment_len_; - - TProtoStringType decode_data_; -}; - -bool DecodeDataBuilder::AddCharacter(const char desired, const char input) { - // If we've hit the max size, push to start a new segment. - if (segment_len_ == kMaxSegmentLen) { - Push(); - } - if (segment_len_ == 0) { - return AddFirst(desired, input); - } - - // Desired and input match... - if (desired == input) { - // If we aren't transforming it, or we're upper casing it and it is - // supposed to be uppercase; just add it to the segment. - if ((op_ != kOpAllUpper) || ascii_isupper(desired)) { - AddChar(desired); - return true; - } - - // Add the current segment, and start the next one. - Push(); - return AddFirst(desired, input); - } - - // If we need to uppercase, and everything so far has been uppercase, - // promote op to AllUpper. - if ((desired == ascii_toupper(input)) && is_all_upper_) { - op_ = kOpAllUpper; - AddChar(desired); - return true; - } - - // Give up, push and start a new segment. - Push(); - return AddFirst(desired, input); -} - -// If decode data can't be generated, a directive for the raw string -// is used instead. -TProtoStringType DirectDecodeString(const TProtoStringType& str) { - TProtoStringType result; - result += (char)'\0'; // Marker for full string. - result += str; - result += (char)'\0'; // End of string. - return result; -} - -} // namespace - -// static -TProtoStringType TextFormatDecodeData::DecodeDataForString( - const TProtoStringType& input_for_decode, const TProtoStringType& desired_output) { - if (input_for_decode.empty() || desired_output.empty()) { - std::cerr << "error: got empty string for making TextFormat data, input: \"" - << input_for_decode << "\", desired: \"" << desired_output << "\"." - << std::endl; - std::cerr.flush(); - abort(); - } - if ((input_for_decode.find('\0') != TProtoStringType::npos) || - (desired_output.find('\0') != TProtoStringType::npos)) { - std::cerr << "error: got a null char in a string for making TextFormat data," - << " input: \"" << CEscape(input_for_decode) << "\", desired: \"" - << CEscape(desired_output) << "\"." << std::endl; - std::cerr.flush(); - abort(); - } - - DecodeDataBuilder builder; - - // Walk the output building it from the input. - int x = 0; - for (int y = 0; y < desired_output.size(); y++) { - const char d = desired_output[y]; - if (d == '_') { - builder.AddUnderscore(); - continue; - } - - if (x >= input_for_decode.size()) { - // Out of input, no way to encode it, just return a full decode. - return DirectDecodeString(desired_output); - } - if (builder.AddCharacter(d, input_for_decode[x])) { - ++x; // Consumed one input - } else { - // Couldn't transform for the next character, just return a full decode. - return DirectDecodeString(desired_output); - } - } - - if (x != input_for_decode.size()) { - // Extra input (suffix from name sanitizing?), just return a full decode. - return DirectDecodeString(desired_output); - } - - // Add the end marker. - return builder.Finish() + (char)'\0'; -} - -namespace { - -class Parser { - public: - Parser(LineConsumer* line_consumer) - : line_consumer_(line_consumer), line_(0) {} - - // Feeds in some input, parse what it can, returning success/failure. Calling - // again after an error is undefined. - bool ParseChunk(StringPiece chunk, TProtoStringType* out_error); - - // Should be called to finish parsing (after all input has been provided via - // successful calls to ParseChunk(), calling after a ParseChunk() failure is - // undefined). Returns success/failure. - bool Finish(TProtoStringType* out_error); - - int last_line() const { return line_; } - - private: - LineConsumer* line_consumer_; - int line_; - TProtoStringType leftover_; -}; - -bool Parser::ParseChunk(StringPiece chunk, TProtoStringType* out_error) { - StringPiece full_chunk; - if (!leftover_.empty()) { - leftover_ += TProtoStringType(chunk); - full_chunk = StringPiece(leftover_); - } else { - full_chunk = chunk; - } - - StringPiece line; - while (ReadLine(&full_chunk, &line)) { - ++line_; - RemoveComment(&line); - TrimWhitespace(&line); - if (!line.empty() && !line_consumer_->ConsumeLine(line, out_error)) { - if (out_error->empty()) { - *out_error = "ConsumeLine failed without setting an error."; - } - leftover_.clear(); - return false; - } - } - - if (full_chunk.empty()) { - leftover_.clear(); - } else { - leftover_ = TProtoStringType(full_chunk); - } - return true; -} - -bool Parser::Finish(TProtoStringType* out_error) { - // If there is still something to go, flush it with a newline. - if (!leftover_.empty() && !ParseChunk("\n", out_error)) { - return false; - } - // This really should never fail if ParseChunk succeeded, but check to be sure. - if (!leftover_.empty()) { - *out_error = "ParseSimple Internal error: finished with pending data."; - return false; - } - return true; -} - -TProtoStringType FullErrorString(const TProtoStringType& name, int line_num, const TProtoStringType& msg) { - return TProtoStringType("error: ") + name + " Line " + StrCat(line_num) + ", " + msg; -} - -} // namespace - -LineConsumer::LineConsumer() {} - -LineConsumer::~LineConsumer() {} - -bool ParseSimpleFile(const TProtoStringType& path, LineConsumer* line_consumer, - TProtoStringType* out_error) { - int fd; - do { - fd = posix::open(path.c_str(), O_RDONLY); - } while (fd < 0 && errno == EINTR); - if (fd < 0) { - *out_error = TProtoStringType("error: Unable to open \"") + path + "\", " + - strerror(errno); - return false; - } - io::FileInputStream file_stream(fd); - file_stream.SetCloseOnDelete(true); - - return ParseSimpleStream(file_stream, path, line_consumer, out_error); -} - -bool ParseSimpleStream(io::ZeroCopyInputStream& input_stream, - const TProtoStringType& stream_name, - LineConsumer* line_consumer, - TProtoStringType* out_error) { - TProtoStringType local_error; - Parser parser(line_consumer); - const void* buf; - int buf_len; - while (input_stream.Next(&buf, &buf_len)) { - if (buf_len == 0) { - continue; - } - - if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len), - &local_error)) { - *out_error = FullErrorString(stream_name, parser.last_line(), local_error); - return false; - } - } - if (!parser.Finish(&local_error)) { - *out_error = FullErrorString(stream_name, parser.last_line(), local_error); - return false; - } - return true; -} - -ImportWriter::ImportWriter( - const TProtoStringType& generate_for_named_framework, - const TProtoStringType& named_framework_to_proto_path_mappings_path, - const TProtoStringType& runtime_import_prefix, bool include_wkt_imports) - : generate_for_named_framework_(generate_for_named_framework), - named_framework_to_proto_path_mappings_path_( - named_framework_to_proto_path_mappings_path), - runtime_import_prefix_(runtime_import_prefix), - include_wkt_imports_(include_wkt_imports), - need_to_parse_mapping_file_(true) {} - -ImportWriter::~ImportWriter() {} - -void ImportWriter::AddFile(const FileDescriptor* file, - const TProtoStringType& header_extension) { - if (IsProtobufLibraryBundledProtoFile(file)) { - // The imports of the WKTs are only needed within the library itself, - // in other cases, they get skipped because the generated code already - // import GPBProtocolBuffers.h and hence proves them. - if (include_wkt_imports_) { - const TProtoStringType header_name = - "GPB" + FilePathBasename(file) + header_extension; - protobuf_imports_.push_back(header_name); - } - return; - } - - // Lazy parse any mappings. - if (need_to_parse_mapping_file_) { - ParseFrameworkMappings(); - } - - std::map<TProtoStringType, TProtoStringType>::iterator proto_lookup = - proto_file_to_framework_name_.find(file->name()); - if (proto_lookup != proto_file_to_framework_name_.end()) { - other_framework_imports_.push_back( - proto_lookup->second + "/" + - FilePathBasename(file) + header_extension); - return; - } - - if (!generate_for_named_framework_.empty()) { - other_framework_imports_.push_back( - generate_for_named_framework_ + "/" + - FilePathBasename(file) + header_extension); - return; - } - - other_imports_.push_back(FilePath(file) + header_extension); -} - -void ImportWriter::Print(io::Printer* printer) const { - bool add_blank_line = false; - - if (!protobuf_imports_.empty()) { - PrintRuntimeImports(printer, protobuf_imports_, runtime_import_prefix_); - add_blank_line = true; - } - - if (!other_framework_imports_.empty()) { - if (add_blank_line) { - printer->Print("\n"); - } - - for (std::vector<TProtoStringType>::const_iterator iter = - other_framework_imports_.begin(); - iter != other_framework_imports_.end(); ++iter) { - printer->Print( - "#import <$header$>\n", - "header", *iter); - } - - add_blank_line = true; - } - - if (!other_imports_.empty()) { - if (add_blank_line) { - printer->Print("\n"); - } - - for (std::vector<TProtoStringType>::const_iterator iter = other_imports_.begin(); - iter != other_imports_.end(); ++iter) { - printer->Print( - "#import \"$header$\"\n", - "header", *iter); - } - } -} - -void ImportWriter::PrintRuntimeImports( - io::Printer* printer, const std::vector<TProtoStringType>& header_to_import, - const TProtoStringType& runtime_import_prefix, bool default_cpp_symbol) { - // Given an override, use that. - if (!runtime_import_prefix.empty()) { - for (const auto& header : header_to_import) { - printer->Print( - " #import \"$import_prefix$/$header$\"\n", - "import_prefix", runtime_import_prefix, - "header", header); - } - return; - } - - const TProtoStringType framework_name(ProtobufLibraryFrameworkName); - const TProtoStringType cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); - - if (default_cpp_symbol) { - printer->Print( - "// This CPP symbol can be defined to use imports that match up to the framework\n" - "// imports needed when using CocoaPods.\n" - "#if !defined($cpp_symbol$)\n" - " #define $cpp_symbol$ 0\n" - "#endif\n" - "\n", - "cpp_symbol", cpp_symbol); - } - - printer->Print( - "#if $cpp_symbol$\n", - "cpp_symbol", cpp_symbol); - for (const auto& header : header_to_import) { - printer->Print( - " #import <$framework_name$/$header$>\n", - "framework_name", framework_name, - "header", header); - } - printer->Print( - "#else\n"); - for (const auto& header : header_to_import) { - printer->Print( - " #import \"$header$\"\n", - "header", header); - } - printer->Print( - "#endif\n"); -} - -void ImportWriter::ParseFrameworkMappings() { - need_to_parse_mapping_file_ = false; - if (named_framework_to_proto_path_mappings_path_.empty()) { - return; // Nothing to do. - } - - ProtoFrameworkCollector collector(&proto_file_to_framework_name_); - TProtoStringType parse_error; - if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_, - &collector, &parse_error)) { - std::cerr << "error parsing " << named_framework_to_proto_path_mappings_path_ - << " : " << parse_error << std::endl; - std::cerr.flush(); - } -} - -bool ImportWriter::ProtoFrameworkCollector::ConsumeLine( - const StringPiece& line, TProtoStringType* out_error) { - int offset = line.find(':'); - if (offset == StringPiece::npos) { - *out_error = - TProtoStringType("Framework/proto file mapping line without colon sign: '") + - TProtoStringType(line) + "'."; - return false; - } - StringPiece framework_name = line.substr(0, offset); - StringPiece proto_file_list = line.substr(offset + 1); - TrimWhitespace(&framework_name); - - int start = 0; - while (start < proto_file_list.length()) { - offset = proto_file_list.find(',', start); - if (offset == StringPiece::npos) { - offset = proto_file_list.length(); - } - - StringPiece proto_file = proto_file_list.substr(start, offset - start); - TrimWhitespace(&proto_file); - if (!proto_file.empty()) { - std::map<TProtoStringType, TProtoStringType>::iterator existing_entry = - map_->find(TProtoStringType(proto_file)); - if (existing_entry != map_->end()) { - std::cerr << "warning: duplicate proto file reference, replacing " - "framework entry for '" - << TProtoStringType(proto_file) << "' with '" << TProtoStringType(framework_name) - << "' (was '" << existing_entry->second << "')." << std::endl; - std::cerr.flush(); - } - - if (proto_file.find(' ') != StringPiece::npos) { - std::cerr << "note: framework mapping file had a proto file with a " - "space in, hopefully that isn't a missing comma: '" - << TProtoStringType(proto_file) << "'" << std::endl; - std::cerr.flush(); - } - - (*map_)[TProtoStringType(proto_file)] = TProtoStringType(framework_name); - } - - start = offset + 1; - } - - return true; -} - -} // namespace objectivec -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index afbf34b7adf..038fde59269 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -1,353 +1,2 @@ -// 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. - -// Helper functions for generating ObjectiveC code. - -#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ -#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ - -#include <string> -#include <vector> - -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/zero_copy_stream.h> - -#include <google/protobuf/port_def.inc> - -namespace google { -namespace protobuf { -namespace compiler { -namespace objectivec { - -// Get/Set the path to a file to load for objc class prefix lookups. -TProtoStringType PROTOC_EXPORT GetPackageToPrefixMappingsPath(); -void PROTOC_EXPORT SetPackageToPrefixMappingsPath( - const TProtoStringType& file_path); -// Get/Set if the proto package should be used to make the default prefix for -// symbols. This will then impact most of the type naming apis below. It is done -// as a global to not break any other generator reusing the methods since they -// are exported. -bool PROTOC_EXPORT UseProtoPackageAsDefaultPrefix(); -void PROTOC_EXPORT SetUseProtoPackageAsDefaultPrefix(bool on_or_off); -// Get/Set the path to a file to load as exceptions when -// `UseProtoPackageAsDefaultPrefix()` is `true`. An empty string means there -// should be no exceptions. -TProtoStringType PROTOC_EXPORT GetProtoPackagePrefixExceptionList(); -void PROTOC_EXPORT SetProtoPackagePrefixExceptionList( - const TProtoStringType& file_path); - -// Generator Prefix Validation Options (see objectivec_generator.cc for a -// description of each): -struct Options { - Options(); - TProtoStringType expected_prefixes_path; - std::vector<TProtoStringType> expected_prefixes_suppressions; - bool prefixes_must_be_registered; - bool require_prefixes; -}; - -// Escape C++ trigraphs by escaping question marks to "\?". -TProtoStringType PROTOC_EXPORT EscapeTrigraphs(const TProtoStringType& to_escape); - -// Remove white space from either end of a StringPiece. -void PROTOC_EXPORT TrimWhitespace(StringPiece* input); - -// Returns true if the name requires a ns_returns_not_retained attribute applied -// to it. -bool PROTOC_EXPORT IsRetainedName(const TProtoStringType& name); - -// Returns true if the name starts with "init" and will need to have special -// handling under ARC. -bool PROTOC_EXPORT IsInitName(const TProtoStringType& name); - -// Gets the objc_class_prefix or the prefix made from the proto package. -TProtoStringType 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. -TProtoStringType PROTOC_EXPORT FilePath(const FileDescriptor* file); - -// Just like FilePath(), but without the directory part. -TProtoStringType 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 -TProtoStringType PROTOC_EXPORT FileClassName(const FileDescriptor* file); - -// These return the fully-qualified class name corresponding to the given -// descriptor. -TProtoStringType PROTOC_EXPORT ClassName(const Descriptor* descriptor); -TProtoStringType PROTOC_EXPORT ClassName(const Descriptor* descriptor, - TProtoStringType* out_suffix_added); -TProtoStringType PROTOC_EXPORT EnumName(const EnumDescriptor* descriptor); - -// Returns the fully-qualified name of the enum value corresponding to the -// the descriptor. -TProtoStringType PROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor); - -// Returns the name of the enum value corresponding to the descriptor. -TProtoStringType PROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor); - -// Reverse what an enum does. -TProtoStringType PROTOC_EXPORT UnCamelCaseEnumShortName(const TProtoStringType& name); - -// Returns the name to use for the extension (used as the method off the file's -// Root class). -TProtoStringType PROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor); - -// Returns the transformed field name. -TProtoStringType PROTOC_EXPORT FieldName(const FieldDescriptor* field); -TProtoStringType PROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field); - -// Returns the transformed oneof name. -TProtoStringType PROTOC_EXPORT OneofEnumName(const OneofDescriptor* descriptor); -TProtoStringType PROTOC_EXPORT OneofName(const OneofDescriptor* descriptor); -TProtoStringType PROTOC_EXPORT OneofNameCapitalized(const OneofDescriptor* descriptor); - -// Returns a symbol that can be used in C code to refer to an Objective C -// class without initializing the class. -TProtoStringType PROTOC_EXPORT ObjCClass(const TProtoStringType& class_name); - -// Declares an Objective C class without initializing the class so that it can -// be refrerred to by ObjCClass. -TProtoStringType PROTOC_EXPORT ObjCClassDeclaration(const TProtoStringType& class_name); - -inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) { - return file->syntax() == FileDescriptor::SYNTAX_PROTO3; -} - -inline bool IsMapEntryMessage(const Descriptor* descriptor) { - return descriptor->options().map_entry(); -} - -// Reverse of the above. -TProtoStringType PROTOC_EXPORT UnCamelCaseFieldName(const TProtoStringType& name, - const FieldDescriptor* field); - -enum ObjectiveCType { - OBJECTIVECTYPE_INT32, - OBJECTIVECTYPE_UINT32, - OBJECTIVECTYPE_INT64, - OBJECTIVECTYPE_UINT64, - OBJECTIVECTYPE_FLOAT, - OBJECTIVECTYPE_DOUBLE, - OBJECTIVECTYPE_BOOLEAN, - OBJECTIVECTYPE_STRING, - OBJECTIVECTYPE_DATA, - OBJECTIVECTYPE_ENUM, - OBJECTIVECTYPE_MESSAGE -}; - -enum FlagType { - FLAGTYPE_DESCRIPTOR_INITIALIZATION, - FLAGTYPE_EXTENSION, - FLAGTYPE_FIELD -}; - -template <class TDescriptor> -TProtoStringType GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, - const FileDescriptor* file = NULL, - bool preSpace = true, - bool postNewline = false) { - bool isDeprecated = descriptor->options().deprecated(); - // The file is only passed when checking Messages & Enums, so those types - // get tagged. At the moment, it doesn't seem to make sense to tag every - // field or enum value with when the file is deprecated. - bool isFileLevelDeprecation = false; - if (!isDeprecated && file) { - isFileLevelDeprecation = file->options().deprecated(); - isDeprecated = isFileLevelDeprecation; - } - if (isDeprecated) { - TProtoStringType message; - const FileDescriptor* sourceFile = descriptor->file(); - if (isFileLevelDeprecation) { - message = sourceFile->name() + " is deprecated."; - } else { - message = descriptor->full_name() + " is deprecated (see " + - sourceFile->name() + ")."; - } - - TProtoStringType result = TProtoStringType("GPB_DEPRECATED_MSG(\"") + message + "\")"; - if (preSpace) { - result.insert(0, " "); - } - if (postNewline) { - result.append("\n"); - } - return result; - } else { - return ""; - } -} - -TProtoStringType PROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field); - -ObjectiveCType PROTOC_EXPORT -GetObjectiveCType(FieldDescriptor::Type field_type); - -inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) { - return GetObjectiveCType(field->type()); -} - -bool PROTOC_EXPORT IsPrimitiveType(const FieldDescriptor* field); -bool PROTOC_EXPORT IsReferenceType(const FieldDescriptor* field); - -TProtoStringType PROTOC_EXPORT -GPBGenericValueFieldName(const FieldDescriptor* field); -TProtoStringType PROTOC_EXPORT DefaultValue(const FieldDescriptor* field); -bool PROTOC_EXPORT HasNonZeroDefaultValue(const FieldDescriptor* field); - -TProtoStringType PROTOC_EXPORT -BuildFlagsString(const FlagType type, const std::vector<TProtoStringType>& strings); - -// Builds HeaderDoc/appledoc style comments out of the comments in the .proto -// file. -TProtoStringType 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 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. -TProtoStringType PROTOC_EXPORT -ProtobufFrameworkImportSymbol(const TProtoStringType& framework_name); - -// Checks if the file is one of the proto's bundled with the library. -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 PROTOC_EXPORT ValidateObjCClassPrefixes( - const std::vector<const FileDescriptor*>& files, - const Options& validation_options, TProtoStringType* out_error); -// Same was the other ValidateObjCClassPrefixes() calls, but the options all -// come from the environment variables. -bool PROTOC_EXPORT ValidateObjCClassPrefixes( - const std::vector<const FileDescriptor*>& files, TProtoStringType* out_error); - -// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform -// the input into the expected output. -class PROTOC_EXPORT TextFormatDecodeData { - public: - TextFormatDecodeData(); - ~TextFormatDecodeData(); - - TextFormatDecodeData(const TextFormatDecodeData&) = delete; - TextFormatDecodeData& operator=(const TextFormatDecodeData&) = delete; - - void AddString(arc_i32 key, const TProtoStringType& input_for_decode, - const TProtoStringType& desired_output); - size_t num_entries() const { return entries_.size(); } - TProtoStringType Data() const; - - static TProtoStringType DecodeDataForString(const TProtoStringType& input_for_decode, - const TProtoStringType& desired_output); - - private: - typedef std::pair<arc_i32, TProtoStringType> DataEntry; - std::vector<DataEntry> entries_; -}; - -// Helper for parsing simple files. -class PROTOC_EXPORT LineConsumer { - public: - LineConsumer(); - virtual ~LineConsumer(); - virtual bool ConsumeLine(const StringPiece& line, TProtoStringType* out_error) = 0; -}; - -bool PROTOC_EXPORT ParseSimpleFile(const TProtoStringType& path, - LineConsumer* line_consumer, - TProtoStringType* out_error); - -bool PROTOC_EXPORT ParseSimpleStream(io::ZeroCopyInputStream& input_stream, - const TProtoStringType& stream_name, - LineConsumer* line_consumer, - TProtoStringType* out_error); - -// Helper class for parsing framework import mappings and generating -// import statements. -class PROTOC_EXPORT ImportWriter { - public: - ImportWriter(const TProtoStringType& generate_for_named_framework, - const TProtoStringType& named_framework_to_proto_path_mappings_path, - const TProtoStringType& runtime_import_prefix, - bool include_wkt_imports); - ~ImportWriter(); - - void AddFile(const FileDescriptor* file, const TProtoStringType& header_extension); - void Print(io::Printer* printer) const; - - static void PrintRuntimeImports(io::Printer* printer, - const std::vector<TProtoStringType>& header_to_import, - const TProtoStringType& runtime_import_prefix, - bool default_cpp_symbol = false); - - private: - class ProtoFrameworkCollector : public LineConsumer { - public: - ProtoFrameworkCollector(std::map<TProtoStringType, TProtoStringType>* inout_proto_file_to_framework_name) - : map_(inout_proto_file_to_framework_name) {} - - virtual bool ConsumeLine(const StringPiece& line, TProtoStringType* out_error) override; - - private: - std::map<TProtoStringType, TProtoStringType>* map_; - }; - - void ParseFrameworkMappings(); - - const TProtoStringType generate_for_named_framework_; - const TProtoStringType named_framework_to_proto_path_mappings_path_; - const TProtoStringType runtime_import_prefix_; - const bool include_wkt_imports_; - std::map<TProtoStringType, TProtoStringType> proto_file_to_framework_name_; - bool need_to_parse_mapping_file_; - - std::vector<TProtoStringType> protobuf_imports_; - std::vector<TProtoStringType> other_framework_imports_; - std::vector<TProtoStringType> other_imports_; -}; - -} // namespace objectivec -} // namespace compiler -} // namespace protobuf -} // namespace google - -#include <google/protobuf/port_undef.inc> - -#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__ +#include "helpers.h" +#include "names.h"
\ No newline at end of file diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc deleted file mode 100644 index bf73592e566..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ /dev/null @@ -1,633 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include <algorithm> -#include <iostream> -#include <sstream> - -#include <google/protobuf/compiler/objectivec/objectivec_message.h> -#include <google/protobuf/compiler/objectivec/objectivec_enum.h> -#include <google/protobuf/compiler/objectivec/objectivec_extension.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/stubs/stl_util.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/descriptor.pb.h> - -namespace google { -namespace protobuf { -namespace compiler { -namespace objectivec { - -namespace { -struct FieldOrderingByNumber { - inline bool operator()(const FieldDescriptor* a, - const FieldDescriptor* b) const { - return a->number() < b->number(); - } -}; - -int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) { - // The first item in the object structure is our uint32[] for has bits. - // We then want to order things to make the instances as small as - // possible. So we follow the has bits with: - // 1. Anything always 4 bytes - float, *32, enums - // 2. Anything that is always a pointer (they will be 8 bytes on 64 bit - // builds and 4 bytes on 32bit builds. - // 3. Anything always 8 bytes - double, *64 - // - // NOTE: Bools aren't listed, they were stored in the has bits. - // - // Why? Using 64bit builds as an example, this means worse case, we have - // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes - // are wasted before the 4 byte values. Then if we have an odd number of - // those 4 byte values, the 8 byte values will be pushed down by 32bits to - // keep them aligned. But the structure will end 8 byte aligned, so no - // waste on the end. If you did the reverse order, you could waste 4 bytes - // before the first 8 byte value (after the has array), then a single - // bool on the end would need 7 bytes of padding to make the overall - // structure 8 byte aligned; so 11 bytes, wasted total. - - // Anything repeated is a GPB*Array/NSArray, so pointer. - if (descriptor->is_repeated()) { - return 3; - } - - switch (descriptor->type()) { - // All always 8 bytes. - case FieldDescriptor::TYPE_DOUBLE: - case FieldDescriptor::TYPE_INT64: - case FieldDescriptor::TYPE_SINT64: - case FieldDescriptor::TYPE_UINT64: - case FieldDescriptor::TYPE_SFIXED64: - case FieldDescriptor::TYPE_FIXED64: - return 4; - - // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes - // depending on the build architecture. - case FieldDescriptor::TYPE_GROUP: - case FieldDescriptor::TYPE_MESSAGE: - case FieldDescriptor::TYPE_STRING: - case FieldDescriptor::TYPE_BYTES: - return 3; - - // All always 4 bytes (enums are int32s). - case FieldDescriptor::TYPE_FLOAT: - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_SINT32: - case FieldDescriptor::TYPE_UINT32: - case FieldDescriptor::TYPE_SFIXED32: - case FieldDescriptor::TYPE_FIXED32: - case FieldDescriptor::TYPE_ENUM: - return 2; - - // 0 bytes. Stored in the has bits. - case FieldDescriptor::TYPE_BOOL: - return 99; // End of the list (doesn't really matter). - } - - // Some compilers report reaching end of function even though all cases of - // the enum are handed in the switch. - GOOGLE_LOG(FATAL) << "Can't get here."; - return 0; -} - -struct FieldOrderingByStorageSize { - inline bool operator()(const FieldDescriptor* a, - const FieldDescriptor* b) const { - // Order by grouping. - const int order_group_a = OrderGroupForFieldDescriptor(a); - const int order_group_b = OrderGroupForFieldDescriptor(b); - if (order_group_a != order_group_b) { - return order_group_a < order_group_b; - } - // Within the group, order by field number (provides stable ordering). - return a->number() < b->number(); - } -}; - -struct ExtensionRangeOrdering { - bool operator()(const Descriptor::ExtensionRange* a, - const Descriptor::ExtensionRange* b) const { - return a->start < b->start; - } -}; - -// Sort the fields of the given Descriptor by number into a new[]'d array -// and return it. -const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { - const FieldDescriptor** fields = - new const FieldDescriptor* [descriptor->field_count()]; - for (int i = 0; i < descriptor->field_count(); i++) { - fields[i] = descriptor->field(i); - } - std::sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber()); - return fields; -} - -// Sort the fields of the given Descriptor by storage size into a new[]'d -// array and return it. -const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) { - const FieldDescriptor** fields = - new const FieldDescriptor* [descriptor->field_count()]; - for (int i = 0; i < descriptor->field_count(); i++) { - fields[i] = descriptor->field(i); - } - std::sort(fields, fields + descriptor->field_count(), - FieldOrderingByStorageSize()); - return fields; -} -} // namespace - -MessageGenerator::MessageGenerator(const TProtoStringType& root_classname, - const Descriptor* descriptor) - : root_classname_(root_classname), - descriptor_(descriptor), - field_generators_(descriptor), - class_name_(ClassName(descriptor_)), - deprecated_attribute_(GetOptionalDeprecatedAttribute( - descriptor, descriptor->file(), false, true)) { - for (int i = 0; i < descriptor_->extension_count(); i++) { - extension_generators_.emplace_back( - new ExtensionGenerator(class_name_, descriptor_->extension(i))); - } - - for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) { - OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); - oneof_generators_.emplace_back(generator); - } - - for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i)); - enum_generators_.emplace_back(generator); - } - - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator* generator = - new MessageGenerator(root_classname_, - descriptor_->nested_type(i)); - nested_message_generators_.emplace_back(generator); - } -} - -MessageGenerator::~MessageGenerator() {} - -void MessageGenerator::GenerateStaticVariablesInitialization( - io::Printer* printer) { - for (const auto& generator : extension_generators_) { - generator->GenerateStaticVariablesInitialization(printer); - } - - for (const auto& generator : nested_message_generators_) { - generator->GenerateStaticVariablesInitialization(printer); - } -} - -void MessageGenerator::DetermineForwardDeclarations( - std::set<TProtoStringType>* fwd_decls, - bool include_external_types) { - if (!IsMapEntryMessage(descriptor_)) { - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* fieldDescriptor = descriptor_->field(i); - field_generators_.get(fieldDescriptor) - .DetermineForwardDeclarations(fwd_decls, include_external_types); - } - } - - for (const auto& generator : nested_message_generators_) { - generator->DetermineForwardDeclarations(fwd_decls, include_external_types); - } -} - -void MessageGenerator::DetermineObjectiveCClassDefinitions( - std::set<TProtoStringType>* fwd_decls) { - if (!IsMapEntryMessage(descriptor_)) { - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* fieldDescriptor = descriptor_->field(i); - field_generators_.get(fieldDescriptor) - .DetermineObjectiveCClassDefinitions(fwd_decls); - } - } - - for (const auto& generator : extension_generators_) { - generator->DetermineObjectiveCClassDefinitions(fwd_decls); - } - - for (const auto& generator : nested_message_generators_) { - generator->DetermineObjectiveCClassDefinitions(fwd_decls); - } - - const Descriptor* containing_descriptor = descriptor_->containing_type(); - if (containing_descriptor != NULL) { - TProtoStringType containing_class = ClassName(containing_descriptor); - fwd_decls->insert(ObjCClassDeclaration(containing_class)); - } -} - -bool MessageGenerator::IncludesOneOfDefinition() const { - if (!oneof_generators_.empty()) { - return true; - } - - for (const auto& generator : nested_message_generators_) { - if (generator->IncludesOneOfDefinition()) { - return true; - } - } - - return false; -} - -void MessageGenerator::GenerateEnumHeader(io::Printer* printer) { - for (const auto& generator : enum_generators_) { - generator->GenerateHeader(printer); - } - - for (const auto& generator : nested_message_generators_) { - generator->GenerateEnumHeader(printer); - } -} - -void MessageGenerator::GenerateExtensionRegistrationSource( - io::Printer* printer) { - for (const auto& generator : extension_generators_) { - generator->GenerateRegistrationSource(printer); - } - - for (const auto& generator : nested_message_generators_) { - generator->GenerateExtensionRegistrationSource(printer); - } -} - -void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { - // This a a map entry message, just recurse and do nothing directly. - if (IsMapEntryMessage(descriptor_)) { - for (const auto& generator : nested_message_generators_) { - generator->GenerateMessageHeader(printer); - } - return; - } - - printer->Print( - "#pragma mark - $classname$\n" - "\n", - "classname", class_name_); - - if (descriptor_->field_count()) { - std::unique_ptr<const FieldDescriptor*[]> sorted_fields( - SortFieldsByNumber(descriptor_)); - - printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", - "classname", class_name_); - printer->Indent(); - - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(sorted_fields[i]) - .GenerateFieldNumberConstant(printer); - } - - printer->Outdent(); - printer->Print("};\n\n"); - } - - for (const auto& generator : oneof_generators_) { - generator->GenerateCaseEnum(printer); - } - - TProtoStringType message_comments; - SourceLocation location; - if (descriptor_->GetSourceLocation(&location)) { - message_comments = BuildCommentsString(location, false); - } else { - message_comments = ""; - } - - printer->Print( - "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n", - "classname", class_name_, - "deprecated_attribute", deprecated_attribute_, - "comments", message_comments); - - std::vector<char> seen_oneofs(oneof_generators_.size(), 0); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - const OneofDescriptor* oneof = field->real_containing_oneof(); - if (oneof) { - const int oneof_index = oneof->index(); - if (!seen_oneofs[oneof_index]) { - seen_oneofs[oneof_index] = 1; - oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( - printer); - } - } - field_generators_.get(field).GeneratePropertyDeclaration(printer); - } - - printer->Print("@end\n\n"); - - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateCFunctionDeclarations(printer); - } - - if (!oneof_generators_.empty()) { - for (const auto& generator : oneof_generators_) { - generator->GenerateClearFunctionDeclaration(printer); - } - printer->Print("\n"); - } - - if (descriptor_->extension_count() > 0) { - printer->Print("@interface $classname$ (DynamicMethods)\n\n", - "classname", class_name_); - for (const auto& generator : extension_generators_) { - generator->GenerateMembersHeader(printer); - } - printer->Print("@end\n\n"); - } - - for (const auto& generator : nested_message_generators_) { - generator->GenerateMessageHeader(printer); - } -} - -void MessageGenerator::GenerateSource(io::Printer* printer) { - if (!IsMapEntryMessage(descriptor_)) { - printer->Print( - "#pragma mark - $classname$\n" - "\n", - "classname", class_name_); - - if (!deprecated_attribute_.empty()) { - // No warnings when compiling the impl of this deprecated class. - printer->Print( - "#pragma clang diagnostic push\n" - "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n" - "\n"); - } - - printer->Print("@implementation $classname$\n\n", - "classname", class_name_); - - for (const auto& generator : oneof_generators_) { - generator->GeneratePropertyImplementation(printer); - } - - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GeneratePropertyImplementation(printer); - } - - std::unique_ptr<const FieldDescriptor*[]> sorted_fields( - SortFieldsByNumber(descriptor_)); - std::unique_ptr<const FieldDescriptor*[]> size_order_fields( - SortFieldsByStorageSize(descriptor_)); - - std::vector<const Descriptor::ExtensionRange*> sorted_extensions; - sorted_extensions.reserve(descriptor_->extension_range_count()); - for (int i = 0; i < descriptor_->extension_range_count(); ++i) { - sorted_extensions.push_back(descriptor_->extension_range(i)); - } - - std::sort(sorted_extensions.begin(), sorted_extensions.end(), - ExtensionRangeOrdering()); - - // Assign has bits: - // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing - // who needs has bits and assigning them. - // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative - // index that groups all the elements in the oneof. - size_t num_has_bits = field_generators_.CalculateHasBits(); - size_t sizeof_has_storage = (num_has_bits + 31) / 32; - if (sizeof_has_storage == 0) { - // In the case where no field needs has bits, don't let the _has_storage_ - // end up as zero length (zero length arrays are sort of a grey area - // since it has to be at the start of the struct). This also ensures a - // field with only oneofs keeps the required negative indices they need. - sizeof_has_storage = 1; - } - // Tell all the fields the oneof base. - for (const auto& generator : oneof_generators_) { - generator->SetOneofIndexBase(sizeof_has_storage); - } - field_generators_.SetOneofIndexBase(sizeof_has_storage); - // sizeof_has_storage needs enough bits for the single fields that aren't in - // any oneof, and then one int32 for each oneof (to store the field number). - sizeof_has_storage += oneof_generators_.size(); - - printer->Print( - "\n" - "typedef struct $classname$__storage_ {\n" - " arc_ui32 _has_storage_[$sizeof_has_storage$];\n", - "classname", class_name_, - "sizeof_has_storage", StrCat(sizeof_has_storage)); - printer->Indent(); - - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(size_order_fields[i]) - .GenerateFieldStorageDeclaration(printer); - } - printer->Outdent(); - - printer->Print("} $classname$__storage_;\n\n", "classname", class_name_); - - - printer->Print( - "// This method is threadsafe because it is initially called\n" - "// in +initialize for each subclass.\n" - "+ (GPBDescriptor *)descriptor {\n" - " static GPBDescriptor *descriptor = nil;\n" - " if (!descriptor) {\n"); - - TextFormatDecodeData text_format_decode_data; - bool has_fields = descriptor_->field_count() > 0; - bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault(); - TProtoStringType field_description_type; - if (need_defaults) { - field_description_type = "GPBMessageFieldDescriptionWithDefault"; - } else { - field_description_type = "GPBMessageFieldDescription"; - } - if (has_fields) { - printer->Indent(); - printer->Indent(); - printer->Print( - "static $field_description_type$ fields[] = {\n", - "field_description_type", field_description_type); - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); ++i) { - const FieldGenerator& field_generator = - field_generators_.get(sorted_fields[i]); - field_generator.GenerateFieldDescription(printer, need_defaults); - if (field_generator.needs_textformat_name_support()) { - text_format_decode_data.AddString(sorted_fields[i]->number(), - field_generator.generated_objc_name(), - field_generator.raw_field_name()); - } - } - printer->Outdent(); - printer->Print( - "};\n"); - printer->Outdent(); - printer->Outdent(); - } - - std::map<TProtoStringType, TProtoStringType> vars; - vars["classname"] = class_name_; - vars["rootclassname"] = root_classname_; - vars["fields"] = has_fields ? "fields" : "NULL"; - if (has_fields) { - vars["fields_count"] = - "(arc_ui32)(sizeof(fields) / sizeof(" + field_description_type + "))"; - } else { - vars["fields_count"] = "0"; - } - - std::vector<TProtoStringType> init_flags; - init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs"); - init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown"); - if (need_defaults) { - init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault"); - } - if (descriptor_->options().message_set_wire_format()) { - init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat"); - } - vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION, - init_flags); - - printer->Print( - vars, - " GPBDescriptor *localDescriptor =\n" - " [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" - " rootClass:[$rootclassname$ class]\n" - " file:$rootclassname$_FileDescriptor()\n" - " fields:$fields$\n" - " fieldCount:$fields_count$\n" - " storageSize:sizeof($classname$__storage_)\n" - " flags:$init_flags$];\n"); - if (!oneof_generators_.empty()) { - printer->Print( - " static const char *oneofs[] = {\n"); - for (const auto& generator : oneof_generators_) { - printer->Print(" \"$name$\",\n", "name", - generator->DescriptorName()); - } - printer->Print( - " };\n" - " [localDescriptor setupOneofs:oneofs\n" - " count:(arc_ui32)(sizeof(oneofs) / sizeof(char*))\n" - " firstHasIndex:$first_has_index$];\n", - "first_has_index", oneof_generators_[0]->HasIndexAsString()); - } - if (text_format_decode_data.num_entries() != 0) { - const TProtoStringType text_format_data_str(text_format_decode_data.Data()); - printer->Print( - "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" - " static const char *extraTextFormatInfo ="); - static const int kBytesPerLine = 40; // allow for escaping - for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) { - printer->Print( - "\n \"$data$\"", - "data", EscapeTrigraphs( - CEscape(text_format_data_str.substr(i, kBytesPerLine)))); - } - printer->Print( - ";\n" - " [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n" - "#endif // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"); - } - if (!sorted_extensions.empty()) { - printer->Print( - " static const GPBExtensionRange ranges[] = {\n"); - for (int i = 0; i < sorted_extensions.size(); i++) { - printer->Print(" { .start = $start$, .end = $end$ },\n", - "start", StrCat(sorted_extensions[i]->start), - "end", StrCat(sorted_extensions[i]->end)); - } - printer->Print( - " };\n" - " [localDescriptor setupExtensionRanges:ranges\n" - " count:(arc_ui32)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); - } - if (descriptor_->containing_type() != NULL) { - TProtoStringType containing_class = ClassName(descriptor_->containing_type()); - TProtoStringType parent_class_ref = ObjCClass(containing_class); - printer->Print( - " [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n", - "parent_class_ref", parent_class_ref); - } - TProtoStringType suffix_added; - ClassName(descriptor_, &suffix_added); - if (!suffix_added.empty()) { - printer->Print( - " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n", - "suffix", suffix_added); - } - printer->Print( - " #if defined(DEBUG) && DEBUG\n" - " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" - " #endif // DEBUG\n" - " descriptor = localDescriptor;\n" - " }\n" - " return descriptor;\n" - "}\n\n" - "@end\n\n"); - - if (!deprecated_attribute_.empty()) { - printer->Print( - "#pragma clang diagnostic pop\n" - "\n"); - } - - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateCFunctionImplementations(printer); - } - - for (const auto& generator : oneof_generators_) { - generator->GenerateClearFunctionImplementation(printer); - } - } - - for (const auto& generator : enum_generators_) { - generator->GenerateSource(printer); - } - - for (const auto& generator : nested_message_generators_) { - generator->GenerateSource(printer); - } -} - -} // namespace objectivec -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h deleted file mode 100644 index 163304665cb..00000000000 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h +++ /dev/null @@ -1,197 +0,0 @@ -// NSObject methods -// Autogenerated by method_dump.sh. Do not edit by hand. -// Date: Thu Nov 1 14:12:16 PDT 2018 -// macOS: MacOSX10.14.sdk -// iOS: iPhoneSimulator12.1.sdk - -const char* const kNSObjectMethodsList[] = { - "CAMLType", - "CA_copyRenderValue", - "CA_prepareRenderValue", - "NS_copyCGImage", - "NS_tiledLayerVisibleRect", - "___tryRetain_OA", - "__autorelease_OA", - "__dealloc_zombie", - "__release_OA", - "__retain_OA", - "_accessibilityFinalize", - "_accessibilityIsTableViewDescendant", - "_accessibilityUIElementSpecifier", - "_accessibilityUseConvenienceAPI", - "_allowsDirectEncoding", - "_asScriptTerminologyNameArray", - "_asScriptTerminologyNameString", - "_bindingAdaptor", - "_cfTypeID", - "_copyDescription", - "_destroyObserverList", - "_didEndKeyValueObserving", - "_implicitObservationInfo", - "_internalAccessibilityAttributedHint", - "_internalAccessibilityAttributedLabel", - "_internalAccessibilityAttributedValue", - "_isAXConnector", - "_isAccessibilityContainerSectionCandidate", - "_isAccessibilityContentNavigatorSectionCandidate", - "_isAccessibilityContentSectionCandidate", - "_isAccessibilityTopLevelNavigatorSectionCandidate", - "_isDeallocating", - "_isKVOA", - "_isToManyChangeInformation", - "_ivarDescription", - "_localClassNameForClass", - "_methodDescription", - "_observerStorage", - "_overrideUseFastBlockObservers", - "_propertyDescription", - "_releaseBindingAdaptor", - "_scriptingCount", - "_scriptingCountNonrecursively", - "_scriptingDebugDescription", - "_scriptingExists", - "_scriptingShouldCheckObjectIndexes", - "_shortMethodDescription", - "_shouldSearchChildrenForSection", - "_traitStorageList", - "_tryRetain", - "_ui_descriptionBuilder", - "_uikit_variesByTraitCollections", - "_web_description", - "_webkit_invokeOnMainThread", - "_willBeginKeyValueObserving", - "accessibilityActivate", - "accessibilityActivationPoint", - "accessibilityAllowsOverriddenAttributesWhenIgnored", - "accessibilityAssistiveTechnologyFocusedIdentifiers", - "accessibilityAttributedHint", - "accessibilityAttributedLabel", - "accessibilityAttributedValue", - "accessibilityContainer", - "accessibilityContainerType", - "accessibilityCustomActions", - "accessibilityCustomRotors", - "accessibilityDecrement", - "accessibilityDragSourceDescriptors", - "accessibilityDropPointDescriptors", - "accessibilityElementCount", - "accessibilityElementDidBecomeFocused", - "accessibilityElementDidLoseFocus", - "accessibilityElementIsFocused", - "accessibilityElements", - "accessibilityElementsHidden", - "accessibilityFrame", - "accessibilityHeaderElements", - "accessibilityHint", - "accessibilityIdentification", - "accessibilityIdentifier", - "accessibilityIncrement", - "accessibilityLabel", - "accessibilityLanguage", - "accessibilityLocalizedStringKey", - "accessibilityNavigationStyle", - "accessibilityOverriddenAttributes", - "accessibilityParameterizedAttributeNames", - "accessibilityPath", - "accessibilityPerformEscape", - "accessibilityPerformMagicTap", - "accessibilityPresenterProcessIdentifier", - "accessibilityShouldUseUniqueId", - "accessibilitySupportsNotifications", - "accessibilitySupportsOverriddenAttributes", - "accessibilityTemporaryChildren", - "accessibilityTraits", - "accessibilityValue", - "accessibilityViewIsModal", - "accessibilityVisibleArea", - "allPropertyKeys", - "allowsWeakReference", - "attributeKeys", - "autoContentAccessingProxy", - "autorelease", - "awakeFromNib", - "boolValueSafe", - "bs_encoded", - "bs_isPlistableType", - "bs_secureEncoded", - "cl_json_serializeKey", - "class", - "classCode", - "classDescription", - "classForArchiver", - "classForCoder", - "classForKeyedArchiver", - "classForPortCoder", - "className", - "clearProperties", - "copy", - "dealloc", - "debugDescription", - "defaultAccessibilityTraits", - "description", - "doubleValueSafe", - "entityName", - "exposedBindings", - "finalize", - "finishObserving", - "flushKeyBindings", - "hash", - "init", - "int64ValueSafe", - "isAccessibilityElement", - "isAccessibilityElementByDefault", - "isElementAccessibilityExposedToInterfaceBuilder", - "isFault", - "isNSArray__", - "isNSCFConstantString__", - "isNSData__", - "isNSDate__", - "isNSDictionary__", - "isNSNumber__", - "isNSObject__", - "isNSOrderedSet__", - "isNSSet__", - "isNSString__", - "isNSTimeZone__", - "isNSValue__", - "isProxy", - "mutableCopy", - "nilValueForKey", - "objectSpecifier", - "observationInfo", - "pep_onDetachedThread", - "pep_onMainThread", - "pep_onMainThreadIfNecessary", - "prepareForInterfaceBuilder", - "release", - "releaseOnMainThread", - "retain", - "retainCount", - "retainWeakReference", - "scriptingProperties", - "self", - "shouldGroupAccessibilityChildren", - "storedAccessibilityActivationPoint", - "storedAccessibilityContainerType", - "storedAccessibilityElementsHidden", - "storedAccessibilityFrame", - "storedAccessibilityNavigationStyle", - "storedAccessibilityTraits", - "storedAccessibilityViewIsModal", - "storedIsAccessibilityElement", - "storedShouldGroupAccessibilityChildren", - "stringValueSafe", - "superclass", - "toManyRelationshipKeys", - "toOneRelationshipKeys", - "traitStorageList", - "un_safeBoolValue", - "userInterfaceItemIdentifier", - "utf8ValueSafe", - "valuesForKeysWithDictionary", - "zone", -// Protocol: CAAnimatableValue -// Protocol: CARenderValue -// Protocol: NSObject -// Protocol: ROCKRemoteInvocationInterface -}; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/oneof.cc index 5197ff63a37..aa534d32f7b 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/oneof.cc @@ -28,13 +28,14 @@ // (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 <map> +#include "google/protobuf/compiler/objectivec/oneof.h" + #include <string> -#include <google/protobuf/compiler/objectivec/objectivec_oneof.h> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/objectivec/helpers.h" +#include "google/protobuf/compiler/objectivec/names.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -46,7 +47,7 @@ OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor) variables_["enum_name"] = OneofEnumName(descriptor_); variables_["name"] = OneofName(descriptor_); variables_["capitalized_name"] = OneofNameCapitalized(descriptor_); - variables_["raw_index"] = StrCat(descriptor_->index()); + variables_["raw_index"] = y_absl::StrCat(descriptor_->index()); const Descriptor* msg_descriptor = descriptor_->containing_type(); variables_["owning_message_class"] = ClassName(msg_descriptor); @@ -60,63 +61,63 @@ OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor) variables_["comments"] = comments; } -OneofGenerator::~OneofGenerator() {} - void OneofGenerator::SetOneofIndexBase(int index_base) { int index = descriptor_->index() + index_base; // Flip the sign to mark it as a oneof. - variables_["index"] = StrCat(-index); + variables_["index"] = y_absl::StrCat(-index); } -void OneofGenerator::GenerateCaseEnum(io::Printer* printer) { - printer->Print( - variables_, - "typedef GPB_ENUM($enum_name$) {\n"); +void OneofGenerator::GenerateCaseEnum(io::Printer* printer) const { + printer->Print(variables_, "typedef GPB_ENUM($enum_name$) {\n"); printer->Indent(); - printer->Print( - variables_, - "$enum_name$_GPBUnsetOneOfCase = 0,\n"); - TProtoStringType enum_name = variables_["enum_name"]; + printer->Print(variables_, "$enum_name$_GPBUnsetOneOfCase = 0,\n"); + TProtoStringType enum_name = variables_.find("enum_name")->second; for (int j = 0; j < descriptor_->field_count(); j++) { const FieldDescriptor* field = descriptor_->field(j); TProtoStringType field_name = FieldNameCapitalized(field); - printer->Print( - "$enum_name$_$field_name$ = $field_number$,\n", - "enum_name", enum_name, - "field_name", field_name, - "field_number", StrCat(field->number())); + printer->Print("$enum_name$_$field_name$ = $field_number$,\n", "enum_name", + enum_name, "field_name", field_name, "field_number", + y_absl::StrCat(field->number())); } printer->Outdent(); + // clang-format off printer->Print( "};\n" "\n"); + // clang-format on } void OneofGenerator::GeneratePublicCasePropertyDeclaration( - io::Printer* printer) { + io::Printer* printer) const { + // clang-format off printer->Print( variables_, "$comments$" "@property(nonatomic, readonly) $enum_name$ $name$OneOfCase;\n" "\n"); + // clang-format on } -void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) { +void OneofGenerator::GenerateClearFunctionDeclaration( + io::Printer* printer) const { + // clang-format off printer->Print( variables_, "/**\n" " * Clears whatever value was set for the oneof '$name$'.\n" " **/\n" "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n"); + // clang-format on } -void OneofGenerator::GeneratePropertyImplementation(io::Printer* printer) { - printer->Print( - variables_, - "@dynamic $name$OneOfCase;\n"); +void OneofGenerator::GeneratePropertyImplementation( + io::Printer* printer) const { + printer->Print(variables_, "@dynamic $name$OneOfCase;\n"); } -void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) { +void OneofGenerator::GenerateClearFunctionImplementation( + io::Printer* printer) const { + // clang-format off printer->Print( variables_, "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n" @@ -124,13 +125,14 @@ void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) { " GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n" " GPBClearOneof(message, oneof);\n" "}\n"); + // clang-format on } -TProtoStringType OneofGenerator::DescriptorName(void) const { +TProtoStringType OneofGenerator::DescriptorName() const { return variables_.find("name")->second; } -TProtoStringType OneofGenerator::HasIndexAsString(void) const { +TProtoStringType OneofGenerator::HasIndexAsString() const { return variables_.find("index")->second; } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/oneof.h index 4173a0325cc..411f832f21e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_oneof.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/oneof.h @@ -32,10 +32,11 @@ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__ #include <string> -#include <set> #include <vector> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/io/printer.h> + +#include "y_absl/container/flat_hash_map.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { @@ -45,27 +46,27 @@ namespace objectivec { class OneofGenerator { public: explicit OneofGenerator(const OneofDescriptor* descriptor); - ~OneofGenerator(); + ~OneofGenerator() = default; OneofGenerator(const OneofGenerator&) = delete; OneofGenerator& operator=(const OneofGenerator&) = delete; void SetOneofIndexBase(int index_base); - void GenerateCaseEnum(io::Printer* printer); + void GenerateCaseEnum(io::Printer* printer) const; - void GeneratePublicCasePropertyDeclaration(io::Printer* printer); - void GenerateClearFunctionDeclaration(io::Printer* printer); + void GeneratePublicCasePropertyDeclaration(io::Printer* printer) const; + void GenerateClearFunctionDeclaration(io::Printer* printer) const; - void GeneratePropertyImplementation(io::Printer* printer); - void GenerateClearFunctionImplementation(io::Printer* printer); + void GeneratePropertyImplementation(io::Printer* printer) const; + void GenerateClearFunctionImplementation(io::Printer* printer) const; - TProtoStringType DescriptorName(void) const; - TProtoStringType HasIndexAsString(void) const; + TProtoStringType DescriptorName() const; + TProtoStringType HasIndexAsString() const; private: const OneofDescriptor* descriptor_; - std::map<TProtoStringType, TProtoStringType> variables_; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> variables_; }; } // namespace objectivec diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/options.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/options.h new file mode 100644 index 00000000000..d0f7ee0c763 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/options.h @@ -0,0 +1,57 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_OPTIONS_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_OPTIONS_H__ + +#include <string> + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// Generation options, documented within generator.cc. +struct GenerationOptions { + TProtoStringType generate_for_named_framework; + TProtoStringType named_framework_to_proto_path_mappings_path; + TProtoStringType runtime_import_prefix; + // TODO(thomasvl): Eventually flip this default to false for better interop + // with Swift if proto usages span modules made from ObjC sources. + bool headers_use_forward_declarations = true; + bool experimental_multi_source_generation = false; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_OPTIONS_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/primitive_field.cc index f83e2691aee..aa839ecf2b4 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/primitive_field.cc @@ -28,22 +28,21 @@ // (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 <map> +#include "google/protobuf/compiler/objectivec/primitive_field.h" + #include <string> -#include <google/protobuf/compiler/objectivec/objectivec_helpers.h> -#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/stubs/strutil.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/str_cat.h" +#include "google/protobuf/compiler/objectivec/helpers.h" +#include "google/protobuf/io/printer.h" namespace google { namespace protobuf { namespace compiler { namespace objectivec { -using internal::WireFormat; -using internal::WireFormatLite; - namespace { const char* PrimitiveTypeName(const FieldDescriptor* descriptor) { @@ -70,13 +69,13 @@ const char* PrimitiveTypeName(const FieldDescriptor* descriptor) { case OBJECTIVECTYPE_ENUM: return "arc_i32"; case OBJECTIVECTYPE_MESSAGE: - return NULL; // Messages go through objectivec_message_field.cc|h. + return nullptr; // Messages go through message_field.cc|h. } // Some compilers report reaching end of function even though all cases of // the enum are handed in the switch. - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + Y_ABSL_LOG(FATAL) << "Can't get here."; + return nullptr; } const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) { @@ -103,18 +102,19 @@ const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) { case OBJECTIVECTYPE_ENUM: return "Enum"; case OBJECTIVECTYPE_MESSAGE: - // Want NSArray (but goes through objectivec_message_field.cc|h). + // Want NSArray (but goes through message_field.cc|h). return ""; } // Some compilers report reaching end of function even though all cases of // the enum are handed in the switch. - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; + Y_ABSL_LOG(FATAL) << "Can't get here."; + return nullptr; } -void SetPrimitiveVariables(const FieldDescriptor* descriptor, - std::map<TProtoStringType, TProtoStringType>* variables) { +void SetPrimitiveVariables( + const FieldDescriptor* descriptor, + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType>* variables) { TProtoStringType primitive_name = PrimitiveTypeName(descriptor); (*variables)["type"] = primitive_name; (*variables)["storage_type"] = primitive_name; @@ -128,8 +128,6 @@ PrimitiveFieldGenerator::PrimitiveFieldGenerator( SetPrimitiveVariables(descriptor, &variables_); } -PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} - void PrimitiveFieldGenerator::GenerateFieldStorageDeclaration( io::Printer* printer) const { if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) { @@ -139,7 +137,7 @@ void PrimitiveFieldGenerator::GenerateFieldStorageDeclaration( } } -int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded(void) const { +int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded() const { if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) { // Reserve a bit for the storage of the boolean. return 1; @@ -147,10 +145,10 @@ int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded(void) const { return 0; } -void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int has_base) { +void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) { if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) { // Set into the offset the has bit to use for the actual value. - variables_["storage_offset_value"] = StrCat(has_base); + variables_["storage_offset_value"] = y_absl::StrCat(index_base); variables_["storage_offset_comment"] = " // Stored in _has_storage_ to save space."; } @@ -163,8 +161,6 @@ PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator( variables_["property_storage_attribute"] = "copy"; } -PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {} - RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( const FieldDescriptor* descriptor) : RepeatedFieldGenerator(descriptor) { @@ -172,16 +168,15 @@ RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( TProtoStringType base_name = PrimitiveArrayTypeName(descriptor); if (base_name.length()) { - variables_["array_storage_type"] = "GPB" + base_name + "Array"; + variables_["array_storage_type"] = y_absl::StrCat("GPB", base_name, "Array"); } else { + TProtoStringType storage_type = variables_["storage_type"]; variables_["array_storage_type"] = "NSMutableArray"; variables_["array_property_type"] = - "NSMutableArray<" + variables_["storage_type"] + "*>"; + y_absl::StrCat("NSMutableArray<", storage_type, "*>"); } } -RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} - } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/primitive_field.h index 06a1528a82a..e6916055cd5 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/primitive_field.h @@ -31,7 +31,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__ -#include <google/protobuf/compiler/objectivec/objectivec_field.h> +#include "google/protobuf/compiler/objectivec/field.h" namespace google { namespace protobuf { @@ -43,15 +43,15 @@ class PrimitiveFieldGenerator : public SingleFieldGenerator { protected: explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor); - virtual ~PrimitiveFieldGenerator(); + ~PrimitiveFieldGenerator() override = default; PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete; PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete; - virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override; + void GenerateFieldStorageDeclaration(io::Printer* printer) const override; - virtual int ExtraRuntimeHasBitsNeeded(void) const override; - virtual void SetExtraRuntimeHasBitsBase(int index_base) override; + int ExtraRuntimeHasBitsNeeded() const override; + void SetExtraRuntimeHasBitsBase(int index_base) override; }; class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator { @@ -59,7 +59,7 @@ class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator { protected: explicit PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor); - virtual ~PrimitiveObjFieldGenerator(); + ~PrimitiveObjFieldGenerator() override = default; PrimitiveObjFieldGenerator(const PrimitiveObjFieldGenerator&) = delete; PrimitiveObjFieldGenerator& operator=(const PrimitiveObjFieldGenerator&) = @@ -71,7 +71,7 @@ class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator { protected: explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor); - virtual ~RepeatedPrimitiveFieldGenerator(); + ~RepeatedPrimitiveFieldGenerator() override = default; RepeatedPrimitiveFieldGenerator(const RepeatedPrimitiveFieldGenerator&) = delete; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/text_format_decode_data.cc b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/text_format_decode_data.cc new file mode 100644 index 00000000000..f254c6093f4 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/text_format_decode_data.cc @@ -0,0 +1,254 @@ +// 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/objectivec/text_format_decode_data.h" + +#include <iostream> +#include <ostream> +#include <sstream> +#include <string> +#include <vector> + +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/match.h" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/io/zero_copy_stream_impl.h" + +// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some +// error cases, so it seems to be ok to use as a back door for errors. + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +namespace { + +// Helper to build up the decode data for a string. +class DecodeDataBuilder { + public: + DecodeDataBuilder() { Reset(); } + + bool AddCharacter(char desired, char input); + void AddUnderscore() { + Push(); + need_underscore_ = true; + } + TProtoStringType Finish() { + Push(); + return decode_data_; + } + + private: + static constexpr uint8_t kAddUnderscore = 0x80; + + static constexpr uint8_t kOpAsIs = 0x00; + static constexpr uint8_t kOpFirstUpper = 0x40; + static constexpr uint8_t kOpFirstLower = 0x20; + static constexpr uint8_t kOpAllUpper = 0x60; + + static constexpr int kMaxSegmentLen = 0x1f; + + void AddChar(const char desired) { + ++segment_len_; + is_all_upper_ &= y_absl::ascii_isupper(desired); + } + + void Push() { + uint8_t op = (op_ | segment_len_); + if (need_underscore_) op |= kAddUnderscore; + if (op != 0) { + decode_data_ += (char)op; + } + Reset(); + } + + bool AddFirst(const char desired, const char input) { + if (desired == input) { + op_ = kOpAsIs; + } else if (desired == y_absl::ascii_toupper(input)) { + op_ = kOpFirstUpper; + } else if (desired == y_absl::ascii_tolower(input)) { + op_ = kOpFirstLower; + } else { + // Can't be transformed to match. + return false; + } + AddChar(desired); + return true; + } + + void Reset() { + need_underscore_ = false; + op_ = 0; + segment_len_ = 0; + is_all_upper_ = true; + } + + bool need_underscore_; + bool is_all_upper_; + uint8_t op_; + int segment_len_; + + TProtoStringType decode_data_; +}; + +bool DecodeDataBuilder::AddCharacter(char desired, char input) { + // If we've hit the max size, push to start a new segment. + if (segment_len_ == kMaxSegmentLen) { + Push(); + } + if (segment_len_ == 0) { + return AddFirst(desired, input); + } + + // Desired and input match... + if (desired == input) { + // If we aren't transforming it, or we're upper casing it and it is + // supposed to be uppercase; just add it to the segment. + if ((op_ != kOpAllUpper) || y_absl::ascii_isupper(desired)) { + AddChar(desired); + return true; + } + + // Add the current segment, and start the next one. + Push(); + return AddFirst(desired, input); + } + + // If we need to uppercase, and everything so far has been uppercase, + // promote op to AllUpper. + if ((desired == y_absl::ascii_toupper(input)) && is_all_upper_) { + op_ = kOpAllUpper; + AddChar(desired); + return true; + } + + // Give up, push and start a new segment. + Push(); + return AddFirst(desired, input); +} + +// If decode data can't be generated, a directive for the raw string +// is used instead. +TProtoStringType DirectDecodeString(const TProtoStringType& str) { + TProtoStringType result; + result += (char)'\0'; // Marker for full string. + result += str; + result += (char)'\0'; // End of string. + return result; +} + +} // namespace + +void TextFormatDecodeData::AddString(arc_i32 key, + const TProtoStringType& input_for_decode, + const TProtoStringType& desired_output) { + for (std::vector<DataEntry>::const_iterator i = entries_.begin(); + i != entries_.end(); ++i) { + Y_ABSL_CHECK(i->first != key) + << "error: duplicate key (" << key + << ") making TextFormat data, input: \"" << input_for_decode + << "\", desired: \"" << desired_output << "\"."; + } + + const TProtoStringType& data = TextFormatDecodeData::DecodeDataForString( + input_for_decode, desired_output); + entries_.push_back(DataEntry(key, data)); +} + +TProtoStringType TextFormatDecodeData::Data() const { + std::ostringstream data_stringstream; + + if (num_entries() > 0) { + io::OstreamOutputStream data_outputstream(&data_stringstream); + io::CodedOutputStream output_stream(&data_outputstream); + + output_stream.WriteVarint32(num_entries()); + for (std::vector<DataEntry>::const_iterator i = entries_.begin(); + i != entries_.end(); ++i) { + output_stream.WriteVarint32(i->first); + output_stream.WriteString(i->second); + } + } + + data_stringstream.flush(); + return data_stringstream.str(); +} + +// static +TProtoStringType TextFormatDecodeData::DecodeDataForString( + const TProtoStringType& input_for_decode, const TProtoStringType& desired_output) { + Y_ABSL_CHECK(!input_for_decode.empty() && !desired_output.empty()) + << "error: got empty string for making TextFormat data, input: \"" + << input_for_decode << "\", desired: \"" << desired_output << "\"."; + Y_ABSL_CHECK(!y_absl::StrContains(input_for_decode, '\0') && + !y_absl::StrContains(desired_output, '\0')) + << "error: got a null char in a string for making TextFormat data," + << " input: \"" << y_absl::CEscape(input_for_decode) << "\", desired: \"" + << y_absl::CEscape(desired_output) << "\"."; + + DecodeDataBuilder builder; + + // Walk the output building it from the input. + int x = 0; + for (int y = 0; y < desired_output.size(); y++) { + const char d = desired_output[y]; + if (d == '_') { + builder.AddUnderscore(); + continue; + } + + if (x >= input_for_decode.size()) { + // Out of input, no way to encode it, just return a full decode. + return DirectDecodeString(desired_output); + } + if (builder.AddCharacter(d, input_for_decode[x])) { + ++x; // Consumed one input + } else { + // Couldn't transform for the next character, just return a full decode. + return DirectDecodeString(desired_output); + } + } + + if (x != input_for_decode.size()) { + // Extra input (suffix from name sanitizing?), just return a full decode. + return DirectDecodeString(desired_output); + } + + // Add the end marker. + return builder.Finish() + (char)'\0'; +} + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/text_format_decode_data.h b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/text_format_decode_data.h new file mode 100644 index 00000000000..135e4045b42 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/objectivec/text_format_decode_data.h @@ -0,0 +1,83 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__ +#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__ + +#include <string> +#include <utility> +#include <vector> + +#include "util/generic/string.h" + +// Must be included last +#include "google/protobuf/port_def.inc" + +using TProtoStringType = TString; + +namespace google { +namespace protobuf { +namespace compiler { +namespace objectivec { + +// TODO(b/250947994): PROTOC_EXPORT is only used to allow the CMake build to +// find/link these in the unittest, this is not public api. + +// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform +// the input into the expected output. +class PROTOC_EXPORT TextFormatDecodeData { + public: + TextFormatDecodeData() = default; + ~TextFormatDecodeData() = default; + + TextFormatDecodeData(const TextFormatDecodeData&) = delete; + TextFormatDecodeData& operator=(const TextFormatDecodeData&) = delete; + + void AddString(arc_i32 key, const TProtoStringType& input_for_decode, + const TProtoStringType& desired_output); + size_t num_entries() const { return entries_.size(); } + TProtoStringType Data() const; + + static TProtoStringType DecodeDataForString(const TProtoStringType& input_for_decode, + const TProtoStringType& desired_output); + + private: + typedef std::pair<arc_i32, TProtoStringType> DataEntry; + std::vector<DataEntry> entries_; +}; + +} // namespace objectivec +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/parser.cc b/contrib/libs/protoc/src/google/protobuf/compiler/parser.cc index 2900d324d21..e244db96cc8 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/parser.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/parser.cc @@ -34,35 +34,43 @@ // // Recursive descent FTW. -#include <google/protobuf/compiler/parser.h> +#include "google/protobuf/compiler/parser.h" #include <float.h> #include <cstdint> #include <limits> -#include <unordered_map> -#include <unordered_set> - -#include <google/protobuf/stubs/casts.h> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/tokenizer.h> -#include <google/protobuf/wire_format.h> -#include <google/protobuf/stubs/map_util.h> -#include <google/protobuf/stubs/hash.h> +#include <string> +#include <tuple> +#include <utility> +#include <vector> + +#include "y_absl/base/casts.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/strtod.h" +#include "google/protobuf/io/tokenizer.h" +#include "google/protobuf/port.h" +#include "google/protobuf/wire_format.h" namespace google { namespace protobuf { namespace compiler { - -using internal::WireFormat; - namespace { -typedef std::unordered_map<TProtoStringType, FieldDescriptorProto::Type> TypeNameMap; +using ::google::protobuf::internal::DownCast; + +using TypeNameMap = + y_absl::flat_hash_map<y_absl::string_view, FieldDescriptorProto::Type>; const TypeNameMap& GetTypeNameTable() { static auto* table = new auto([]() { @@ -93,7 +101,7 @@ const TypeNameMap& GetTypeNameTable() { // Camel-case the field name and append "Entry" for generated map entry name. // e.g. map<KeyType, ValueType> foo_map => FooMapEntry -TProtoStringType MapEntryName(const TProtoStringType& field_name) { +TProtoStringType MapEntryName(y_absl::string_view field_name) { TProtoStringType result; static const char kSuffix[] = "Entry"; result.reserve(field_name.size() + sizeof(kSuffix)); @@ -123,7 +131,7 @@ bool IsLowercase(char c) { return c >= 'a' && c <= 'z'; } bool IsNumber(char c) { return c >= '0' && c <= '9'; } -bool IsUpperCamelCase(const TProtoStringType& name) { +bool IsUpperCamelCase(y_absl::string_view name) { if (name.empty()) { return true; } @@ -140,7 +148,7 @@ bool IsUpperCamelCase(const TProtoStringType& name) { return true; } -bool IsUpperUnderscore(const TProtoStringType& name) { +bool IsUpperUnderscore(y_absl::string_view name) { for (const char c : name) { if (!IsUppercase(c) && c != '_' && !IsNumber(c)) { return false; @@ -149,7 +157,7 @@ bool IsUpperUnderscore(const TProtoStringType& name) { return true; } -bool IsLowerUnderscore(const TProtoStringType& name) { +bool IsLowerUnderscore(y_absl::string_view name) { for (const char c : name) { if (!IsLowercase(c) && c != '_' && !IsNumber(c)) { return false; @@ -158,7 +166,7 @@ bool IsLowerUnderscore(const TProtoStringType& name) { return true; } -bool IsNumberFollowUnderscore(const TProtoStringType& name) { +bool IsNumberFollowUnderscore(y_absl::string_view name) { for (int i = 1; i < name.length(); i++) { const char c = name[i]; if (IsNumber(c) && name[i - 1] == '_') { @@ -193,7 +201,7 @@ Parser::~Parser() {} // =================================================================== -inline bool Parser::LookingAt(const char* text) { +inline bool Parser::LookingAt(y_absl::string_view text) { return input_->current().text == text; } @@ -203,7 +211,7 @@ inline bool Parser::LookingAtType(io::Tokenizer::TokenType token_type) { inline bool Parser::AtEnd() { return LookingAtType(io::Tokenizer::TYPE_END); } -bool Parser::TryConsume(const char* text) { +bool Parser::TryConsume(y_absl::string_view text) { if (LookingAt(text)) { input_->Next(); return true; @@ -212,50 +220,49 @@ bool Parser::TryConsume(const char* text) { } } -bool Parser::Consume(const char* text, const char* error) { +bool Parser::Consume(y_absl::string_view text, y_absl::string_view error) { if (TryConsume(text)) { return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::Consume(const char* text) { - TProtoStringType error = "Expected \"" + TProtoStringType(text) + "\"."; - return Consume(text, error.c_str()); +bool Parser::Consume(y_absl::string_view text) { + return Consume(text, y_absl::StrCat("Expected \"", text, "\".")); } -bool Parser::ConsumeIdentifier(TProtoStringType* output, const char* error) { +bool Parser::ConsumeIdentifier(TProtoStringType* output, y_absl::string_view error) { if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { *output = input_->current().text; input_->Next(); return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::ConsumeInteger(int* output, const char* error) { +bool Parser::ConsumeInteger(int* output, y_absl::string_view error) { if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { arc_ui64 value = 0; if (!io::Tokenizer::ParseInteger(input_->current().text, std::numeric_limits<arc_i32>::max(), &value)) { - AddError("Integer out of range."); + RecordError("Integer out of range."); // We still return true because we did, in fact, parse an integer. } *output = value; input_->Next(); return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::ConsumeSignedInteger(int* output, const char* error) { +bool Parser::ConsumeSignedInteger(int* output, y_absl::string_view error) { bool is_negative = false; arc_ui64 max_value = std::numeric_limits<arc_i32>::max(); if (TryConsume("-")) { @@ -270,23 +277,32 @@ bool Parser::ConsumeSignedInteger(int* output, const char* error) { } bool Parser::ConsumeInteger64(arc_ui64 max_value, arc_ui64* output, - const char* error) { + y_absl::string_view error) { if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { if (!io::Tokenizer::ParseInteger(input_->current().text, max_value, output)) { - AddError("Integer out of range."); + RecordError("Integer out of range."); // We still return true because we did, in fact, parse an integer. *output = 0; } input_->Next(); return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::ConsumeNumber(double* output, const char* error) { +bool Parser::TryConsumeInteger64(arc_ui64 max_value, arc_ui64* output) { + if (LookingAtType(io::Tokenizer::TYPE_INTEGER) && + io::Tokenizer::ParseInteger(input_->current().text, max_value, output)) { + input_->Next(); + return true; + } + return false; +} + +bool Parser::ConsumeNumber(double* output, y_absl::string_view error) { if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) { *output = io::Tokenizer::ParseFloat(input_->current().text); input_->Next(); @@ -294,13 +310,19 @@ bool Parser::ConsumeNumber(double* output, const char* error) { } else if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { // Also accept integers. arc_ui64 value = 0; - if (!io::Tokenizer::ParseInteger(input_->current().text, - std::numeric_limits<arc_ui64>::max(), - &value)) { - AddError("Integer out of range."); + if (io::Tokenizer::ParseInteger(input_->current().text, + std::numeric_limits<arc_ui64>::max(), + &value)) { + *output = value; + } else if (input_->current().text[0] == '0') { + // octal or hexadecimal; don't bother parsing as float + RecordError("Integer out of range."); + // We still return true because we did, in fact, parse a number. + } else if (!io::Tokenizer::TryParseFloat(input_->current().text, output)) { + // out of int range, and not valid float? 🤷 + RecordError("Integer out of range."); // We still return true because we did, in fact, parse a number. } - *output = value; input_->Next(); return true; } else if (LookingAt("inf")) { @@ -312,12 +334,12 @@ bool Parser::ConsumeNumber(double* output, const char* error) { input_->Next(); return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::ConsumeString(TProtoStringType* output, const char* error) { +bool Parser::ConsumeString(TProtoStringType* output, y_absl::string_view error) { if (LookingAtType(io::Tokenizer::TYPE_STRING)) { io::Tokenizer::ParseString(input_->current().text, output); input_->Next(); @@ -328,12 +350,12 @@ bool Parser::ConsumeString(TProtoStringType* output, const char* error) { } return true; } else { - AddError(error); + RecordError(error); return false; } } -bool Parser::TryConsumeEndOfDeclaration(const char* text, +bool Parser::TryConsumeEndOfDeclaration(y_absl::string_view text, const LocationRecorder* location) { if (LookingAt(text)) { TProtoStringType leading, trailing; @@ -347,7 +369,7 @@ bool Parser::TryConsumeEndOfDeclaration(const char* text, if (location != nullptr) { upcoming_detached_comments_.swap(detached); location->AttachComments(&leading, &trailing, &detached); - } else if (strcmp(text, "}") == 0) { + } else if (text == "}") { // If the current location is null and we are finishing the current scope, // drop pending upcoming detached comments. upcoming_detached_comments_.swap(detached); @@ -364,36 +386,39 @@ bool Parser::TryConsumeEndOfDeclaration(const char* text, } } -bool Parser::ConsumeEndOfDeclaration(const char* text, +bool Parser::ConsumeEndOfDeclaration(y_absl::string_view text, const LocationRecorder* location) { if (TryConsumeEndOfDeclaration(text, location)) { return true; } else { - AddError("Expected \"" + TProtoStringType(text) + "\"."); + RecordError(y_absl::StrCat("Expected \"", text, "\".")); return false; } } // ------------------------------------------------------------------- -void Parser::AddError(int line, int column, const TProtoStringType& error) { +void Parser::RecordError(int line, int column, y_absl::string_view error) { if (error_collector_ != nullptr) { - error_collector_->AddError(line, column, error); + error_collector_->RecordError(line, column, error); } had_errors_ = true; } -void Parser::AddError(const TProtoStringType& error) { - AddError(input_->current().line, input_->current().column, error); +void Parser::RecordError(y_absl::string_view error) { + RecordError(input_->current().line, input_->current().column, error); } -void Parser::AddWarning(const TProtoStringType& warning) { +void Parser::RecordWarning(int line, int column, y_absl::string_view warning) { if (error_collector_ != nullptr) { - error_collector_->AddWarning(input_->current().line, - input_->current().column, warning); + error_collector_->RecordWarning(line, column, warning); } } +void Parser::RecordWarning(y_absl::string_view warning) { + RecordWarning(input_->current().line, input_->current().column, warning); +} + // ------------------------------------------------------------------- Parser::LocationRecorder::LocationRecorder(Parser* parser) @@ -491,8 +516,8 @@ int Parser::LocationRecorder::CurrentPathSize() const { void Parser::LocationRecorder::AttachComments( TProtoStringType* leading, TProtoStringType* trailing, std::vector<TProtoStringType>* detached_comments) const { - GOOGLE_CHECK(!location_->has_leading_comments()); - GOOGLE_CHECK(!location_->has_trailing_comments()); + Y_ABSL_CHECK(!location_->has_leading_comments()); + Y_ABSL_CHECK(!location_->has_trailing_comments()); if (!leading->empty()) { location_->mutable_leading_comments()->swap(*leading); @@ -563,16 +588,16 @@ bool Parser::ValidateEnum(const EnumDescriptorProto* proto) { } if (has_allow_alias && !allow_alias) { - TProtoStringType error = - "\"" + proto->name() + + TProtoStringType error = y_absl::StrCat( + "\"", proto->name(), "\" declares 'option allow_alias = false;' which has no effect. " - "Please remove the declaration."; + "Please remove the declaration."); // This needlessly clutters declarations with nops. - AddError(error); + RecordError(error); return false; } - std::set<int> used_values; + y_absl::flat_hash_set<int> used_values; bool has_duplicates = false; for (int i = 0; i < proto->value_size(); ++i) { const EnumValueDescriptorProto& enum_value = proto->value(i); @@ -584,14 +609,14 @@ bool Parser::ValidateEnum(const EnumDescriptorProto* proto) { } } if (allow_alias && !has_duplicates) { - TProtoStringType error = - "\"" + proto->name() + + TProtoStringType error = y_absl::StrCat( + "\"", proto->name(), "\" declares support for enum aliases but no enum values share field " "numbers. Please remove the unnecessary 'option allow_alias = true;' " - "declaration."; + "declaration."); // Generate an error if an enum declares support for duplicate enum values // and does not use it protect future authors. - AddError(error); + RecordError(error); return false; } @@ -600,10 +625,9 @@ bool Parser::ValidateEnum(const EnumDescriptorProto* proto) { if (!allow_alias) { for (const auto& enum_value : proto->value()) { if (!IsUpperUnderscore(enum_value.name())) { - AddWarning( - "Enum constant should be in UPPER_CASE. Found: " + - enum_value.name() + - ". See https://developers.google.com/protocol-buffers/docs/style"); + RecordWarning(y_absl::StrCat( + "Enum constant should be in UPPER_CASE. Found: ", enum_value.name(), + ". See https://developers.google.com/protocol-buffers/docs/style")); } } } @@ -634,14 +658,17 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { root_location.RecordLegacyLocation(file, DescriptorPool::ErrorCollector::OTHER); - if (require_syntax_identifier_ || LookingAt("syntax")) { + if (require_syntax_identifier_ || LookingAt("syntax") + ) { if (!ParseSyntaxIdentifier(root_location)) { // Don't attempt to parse the file if we didn't recognize the syntax // identifier. return false; } // Store the syntax into the file. - if (file != nullptr) file->set_syntax(syntax_identifier_); + if (file != nullptr) { + file->set_syntax(syntax_identifier_); + } } else if (!stop_after_syntax_identifier_) { syntax_identifier_ = "proto2"; } @@ -656,7 +683,7 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { SkipStatement(); if (LookingAt("}")) { - AddError("Unmatched \"}\"."); + RecordError("Unmatched \"}\"."); input_->NextWithComments(nullptr, &upcoming_detached_comments_, &upcoming_doc_comments_); } @@ -674,9 +701,10 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { LocationRecorder syntax_location(parent, FileDescriptorProto::kSyntaxFieldNumber); - DO(Consume( - "syntax", - "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'.")); + DO(Consume("syntax", + "File must begin with a syntax statement, e.g. 'syntax = " + "\"proto2\";'.")); + DO(Consume("=")); io::Tokenizer::Token syntax_token = input_->current(); TProtoStringType syntax; @@ -684,13 +712,12 @@ bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { DO(ConsumeEndOfDeclaration(";", &syntax_location)); syntax_identifier_ = syntax; - if (syntax != "proto2" && syntax != "proto3" && !stop_after_syntax_identifier_) { - AddError(syntax_token.line, syntax_token.column, - "Unrecognized syntax identifier \"" + syntax + - "\". This parser " - "only recognizes \"proto2\" and \"proto3\"."); + RecordError(syntax_token.line, syntax_token.column, + y_absl::StrCat("Unrecognized syntax identifier \"", syntax, + "\". This parser " + "only recognizes \"proto2\" and \"proto3\".")); return false; } @@ -735,7 +762,7 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, return ParseOption(file->mutable_options(), location, file, OPTION_STATEMENT); } else { - AddError("Expected top-level statement (e.g. \"message\")."); + RecordError("Expected top-level statement (e.g. \"message\")."); return false; } } @@ -754,10 +781,9 @@ bool Parser::ParseMessageDefinition( DescriptorPool::ErrorCollector::NAME); DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); if (!IsUpperCamelCase(message->name())) { - AddWarning( - "Message name should be in UpperCamelCase. Found: " + - message->name() + - ". See https://developers.google.com/protocol-buffers/docs/style"); + RecordWarning(y_absl::StrCat( + "Message name should be in UpperCamelCase. Found: ", message->name(), + ". See https://developers.google.com/protocol-buffers/docs/style")); } } DO(ParseMessageBlock(message, message_location, containing_file)); @@ -768,7 +794,7 @@ bool Parser::ParseMessageDefinition( // // We have to make sure the oneof names don't conflict with any other // field or oneof. - std::unordered_set<TProtoStringType> names; + y_absl::flat_hash_set<TProtoStringType> names; for (const auto& field : message->field()) { names.insert(field.name()); } @@ -793,7 +819,7 @@ bool Parser::ParseMessageDefinition( names.insert(oneof_name); field.set_oneof_index(message->oneof_decl_size()); OneofDescriptorProto* oneof = message->add_oneof_decl(); - oneof->set_name(oneof_name); + oneof->set_name(std::move(oneof_name)); } } } @@ -857,7 +883,7 @@ bool Parser::ParseMessageBlock(DescriptorProto* message, while (!TryConsumeEndOfDeclaration("}", nullptr)) { if (AtEnd()) { - AddError("Reached end of input in message definition (missing '}')."); + RecordError("Reached end of input in message definition (missing '}')."); return false; } @@ -986,7 +1012,7 @@ bool Parser::ParseMessageFieldNoLabel( field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); } if (!field->has_label()) { - AddError("Expected \"required\", \"optional\", or \"repeated\"."); + RecordError("Expected \"required\", \"optional\", or \"repeated\"."); // We can actually reasonably recover here by just assuming the user // forgot the label altogether. field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); @@ -1016,15 +1042,15 @@ bool Parser::ParseMessageFieldNoLabel( DO(ConsumeIdentifier(field->mutable_name(), "Expected field name.")); if (!IsLowerUnderscore(field->name())) { - AddWarning( - "Field name should be lowercase. Found: " + field->name() + - ". See: https://developers.google.com/protocol-buffers/docs/style"); + RecordWarning(y_absl::StrCat( + "Field name should be lowercase. Found: ", field->name(), + ". See: https://developers.google.com/protocol-buffers/docs/style")); } if (IsNumberFollowUnderscore(field->name())) { - AddWarning( - "Number should not come right after an underscore. Found: " + - field->name() + - ". See: https://developers.google.com/protocol-buffers/docs/style"); + RecordWarning(y_absl::StrCat( + "Number should not come right after an underscore. Found: ", + field->name(), + ". See: https://developers.google.com/protocol-buffers/docs/style")); } } DO(Consume("=", "Missing field number.")); @@ -1077,16 +1103,16 @@ bool Parser::ParseMessageFieldNoLabel( // with a capital letter and lower-case the field name. New code should // not use groups; it should use nested messages. if (group->name()[0] < 'A' || 'Z' < group->name()[0]) { - AddError(name_token.line, name_token.column, - "Group names must start with a capital letter."); + RecordError(name_token.line, name_token.column, + "Group names must start with a capital letter."); } - LowerString(field->mutable_name()); + y_absl::AsciiStrToLower(field->mutable_name()); field->set_type_name(group->name()); if (LookingAt("{")) { DO(ParseMessageBlock(group, group_location, containing_file)); } else { - AddError("Missing group body."); + RecordError("Missing group body."); return false; } } else { @@ -1104,17 +1130,17 @@ bool Parser::ParseMessageFieldNoLabel( bool Parser::ParseMapType(MapField* map_field, FieldDescriptorProto* field, LocationRecorder& type_name_location) { if (field->has_oneof_index()) { - AddError("Map fields are not allowed in oneofs."); + RecordError("Map fields are not allowed in oneofs."); return false; } if (field->has_label()) { - AddError( + RecordError( "Field labels (required/optional/repeated) are not allowed on " "map fields."); return false; } if (field->has_extendee()) { - AddError("Map fields are not allowed to be extensions."); + RecordError("Map fields are not allowed to be extensions."); return false; } field->set_label(FieldDescriptorProto::LABEL_REPEATED); @@ -1226,7 +1252,7 @@ bool Parser::ParseDefaultAssignment( FieldDescriptorProto* field, const LocationRecorder& field_location, const FileDescriptorProto* containing_file) { if (field->has_default_value()) { - AddError("Already set option \"default\"."); + RecordError("Already set option \"default\"."); field->clear_default_value(); } @@ -1279,7 +1305,7 @@ bool Parser::ParseDefaultAssignment( DO(ConsumeInteger64(max_value, &value, "Expected integer for field default value.")); // And stringify it again. - default_value->append(StrCat(value)); + default_value->append(y_absl::StrCat(value)); break; } @@ -1295,38 +1321,38 @@ bool Parser::ParseDefaultAssignment( // Numeric, not negative. if (TryConsume("-")) { - AddError("Unsigned field can't have negative default value."); + RecordError("Unsigned field can't have negative default value."); } // Parse the integer to verify that it is not out-of-range. arc_ui64 value; DO(ConsumeInteger64(max_value, &value, "Expected integer for field default value.")); // And stringify it again. - default_value->append(StrCat(value)); + default_value->append(y_absl::StrCat(value)); break; } case FieldDescriptorProto::TYPE_FLOAT: - case FieldDescriptorProto::TYPE_DOUBLE: + case FieldDescriptorProto::TYPE_DOUBLE: { // These types can be negative. if (TryConsume("-")) { default_value->append("-"); } // Parse the integer because we have to convert hex integers to decimal // floats. - double value; + double value = 0.0; DO(ConsumeNumber(&value, "Expected number.")); // And stringify it again. - default_value->append(SimpleDtoa(value)); + default_value->append(io::SimpleDtoa(value)); break; - + } case FieldDescriptorProto::TYPE_BOOL: if (TryConsume("true")) { default_value->assign("true"); } else if (TryConsume("false")) { default_value->assign("false"); } else { - AddError("Expected \"true\" or \"false\"."); + RecordError("Expected \"true\" or \"false\"."); return false; } break; @@ -1342,7 +1368,7 @@ bool Parser::ParseDefaultAssignment( case FieldDescriptorProto::TYPE_BYTES: DO(ConsumeString(default_value, "Expected string.")); - *default_value = CEscape(*default_value); + *default_value = y_absl::CEscape(*default_value); break; case FieldDescriptorProto::TYPE_ENUM: @@ -1353,7 +1379,7 @@ bool Parser::ParseDefaultAssignment( case FieldDescriptorProto::TYPE_MESSAGE: case FieldDescriptorProto::TYPE_GROUP: - AddError("Messages can't have default values."); + RecordError("Messages can't have default values."); return false; } @@ -1364,7 +1390,7 @@ bool Parser::ParseJsonName(FieldDescriptorProto* field, const LocationRecorder& field_location, const FileDescriptorProto* containing_file) { if (field->has_json_name()) { - AddError("Already set option \"json_name\"."); + RecordError("Already set option \"json_name\"."); field->clear_json_name(); } @@ -1443,7 +1469,7 @@ bool Parser::ParseUninterpretedBlock(TProtoStringType* value) { value->append(input_->current().text); input_->Next(); } - AddError("Unexpected end of stream while parsing aggregate value."); + RecordError("Unexpected end of stream while parsing aggregate value."); return false; } @@ -1456,7 +1482,7 @@ bool Parser::ParseOption(Message* options, // Create an entry in the uninterpreted_option field. const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()->FindFieldByName("uninterpreted_option"); - GOOGLE_CHECK(uninterpreted_option_field != nullptr) + Y_ABSL_CHECK(uninterpreted_option_field != nullptr) << "No field named \"uninterpreted_option\" in the Options proto."; const Reflection* reflection = options->GetReflection(); @@ -1470,7 +1496,7 @@ bool Parser::ParseOption(Message* options, } UninterpretedOption* uninterpreted_option = - down_cast<UninterpretedOption*>(options->GetReflection()->AddMessage( + DownCast<UninterpretedOption*>(options->GetReflection()->AddMessage( options, uninterpreted_option_field)); // Parse dot-separated name. @@ -1509,25 +1535,26 @@ bool Parser::ParseOption(Message* options, switch (input_->current().type) { case io::Tokenizer::TYPE_START: - GOOGLE_LOG(FATAL) << "Trying to read value before any tokens have been read."; + Y_ABSL_LOG(FATAL) + << "Trying to read value before any tokens have been read."; return false; case io::Tokenizer::TYPE_END: - AddError("Unexpected end of stream while parsing option value."); + RecordError("Unexpected end of stream while parsing option value."); return false; case io::Tokenizer::TYPE_WHITESPACE: case io::Tokenizer::TYPE_NEWLINE: - GOOGLE_CHECK(!input_->report_whitespace() && !input_->report_newlines()) + Y_ABSL_CHECK(!input_->report_whitespace() && !input_->report_newlines()) << "Whitespace tokens were not requested."; - GOOGLE_LOG(FATAL) << "Tokenizer reported whitespace."; + Y_ABSL_LOG(FATAL) << "Tokenizer reported whitespace."; return false; case io::Tokenizer::TYPE_IDENTIFIER: { value_location.AddPath( UninterpretedOption::kIdentifierValueFieldNumber); if (is_negative) { - AddError("Invalid '-' symbol before identifier."); + RecordError("Invalid '-' symbol before identifier."); return false; } TProtoStringType value; @@ -1542,23 +1569,27 @@ bool Parser::ParseOption(Message* options, is_negative ? static_cast<arc_ui64>(std::numeric_limits<arc_i64>::max()) + 1 : std::numeric_limits<arc_ui64>::max(); - DO(ConsumeInteger64(max_value, &value, "Expected integer.")); - if (is_negative) { - value_location.AddPath( - UninterpretedOption::kNegativeIntValueFieldNumber); - uninterpreted_option->set_negative_int_value( - static_cast<arc_i64>(0 - value)); - } else { - value_location.AddPath( - UninterpretedOption::kPositiveIntValueFieldNumber); - uninterpreted_option->set_positive_int_value(value); + if (TryConsumeInteger64(max_value, &value)) { + if (is_negative) { + value_location.AddPath( + UninterpretedOption::kNegativeIntValueFieldNumber); + uninterpreted_option->set_negative_int_value( + static_cast<arc_i64>(0 - value)); + } else { + value_location.AddPath( + UninterpretedOption::kPositiveIntValueFieldNumber); + uninterpreted_option->set_positive_int_value(value); + } + break; } - break; + // value too large for an integer; fall through below to treat as + // floating point + Y_ABSL_FALLTHROUGH_INTENDED; } case io::Tokenizer::TYPE_FLOAT: { value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber); - double value; + double value = 0.0; DO(ConsumeNumber(&value, "Expected number.")); uninterpreted_option->set_double_value(is_negative ? -value : value); break; @@ -1567,7 +1598,7 @@ bool Parser::ParseOption(Message* options, case io::Tokenizer::TYPE_STRING: { value_location.AddPath(UninterpretedOption::kStringValueFieldNumber); if (is_negative) { - AddError("Invalid '-' symbol before string."); + RecordError("Invalid '-' symbol before string."); return false; } TProtoStringType value; @@ -1583,7 +1614,7 @@ bool Parser::ParseOption(Message* options, DO(ParseUninterpretedBlock( uninterpreted_option->mutable_aggregate_value())); } else { - AddError("Expected option value."); + RecordError("Expected option value."); return false; } break; @@ -1719,11 +1750,27 @@ bool Parser::ParseReserved(DescriptorProto* message, } } +bool Parser::ParseReservedName(TProtoStringType* name, + y_absl::string_view error_message) { + // Capture the position of the token, in case we have to report an + // error after it is consumed. + int line = input_->current().line; + int col = input_->current().column; + DO(ConsumeString(name, error_message)); + if (!io::Tokenizer::IsIdentifier(*name)) { + RecordWarning( + line, col, + y_absl::StrFormat("Reserved name \"%s\" is not a valid identifier.", + *name)); + } + return true; +} + bool Parser::ParseReservedNames(DescriptorProto* message, const LocationRecorder& parent_location) { do { LocationRecorder location(parent_location, message->reserved_name_size()); - DO(ConsumeString(message->add_reserved_name(), "Expected field name.")); + DO(ParseReservedName(message->add_reserved_name(), "Expected field name.")); } while (TryConsume(",")); DO(ConsumeEndOfDeclaration(";", &parent_location)); return true; @@ -1778,42 +1825,41 @@ bool Parser::ParseReservedNumbers(DescriptorProto* message, return true; } -bool Parser::ParseReserved(EnumDescriptorProto* message, - const LocationRecorder& message_location) { +bool Parser::ParseReserved(EnumDescriptorProto* proto, + const LocationRecorder& enum_location) { io::Tokenizer::Token start_token = input_->current(); // Parse the declaration. DO(Consume("reserved")); if (LookingAtType(io::Tokenizer::TYPE_STRING)) { - LocationRecorder location(message_location, + LocationRecorder location(enum_location, EnumDescriptorProto::kReservedNameFieldNumber); location.StartAt(start_token); - return ParseReservedNames(message, location); + return ParseReservedNames(proto, location); } else { - LocationRecorder location(message_location, + LocationRecorder location(enum_location, EnumDescriptorProto::kReservedRangeFieldNumber); location.StartAt(start_token); - return ParseReservedNumbers(message, location); + return ParseReservedNumbers(proto, location); } } -bool Parser::ParseReservedNames(EnumDescriptorProto* message, +bool Parser::ParseReservedNames(EnumDescriptorProto* proto, const LocationRecorder& parent_location) { do { - LocationRecorder location(parent_location, message->reserved_name_size()); - DO(ConsumeString(message->add_reserved_name(), "Expected enum value.")); + LocationRecorder location(parent_location, proto->reserved_name_size()); + DO(ParseReservedName(proto->add_reserved_name(), "Expected enum value.")); } while (TryConsume(",")); DO(ConsumeEndOfDeclaration(";", &parent_location)); return true; } -bool Parser::ParseReservedNumbers(EnumDescriptorProto* message, +bool Parser::ParseReservedNumbers(EnumDescriptorProto* proto, const LocationRecorder& parent_location) { bool first = true; do { - LocationRecorder location(parent_location, message->reserved_range_size()); + LocationRecorder location(parent_location, proto->reserved_range_size()); - EnumDescriptorProto::EnumReservedRange* range = - message->add_reserved_range(); + EnumDescriptorProto::EnumReservedRange* range = proto->add_reserved_range(); int start, end; io::Tokenizer::Token start_token; { @@ -1873,7 +1919,7 @@ bool Parser::ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions, do { if (AtEnd()) { - AddError("Reached end of input in extend definition (missing '}')."); + RecordError("Reached end of input in extend definition (missing '}')."); return false; } @@ -1926,7 +1972,7 @@ bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, do { if (AtEnd()) { - AddError("Reached end of input in oneof definition (missing '}')."); + RecordError("Reached end of input in oneof definition (missing '}')."); return false; } @@ -1944,7 +1990,7 @@ bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, // on an individual member of a oneof. if (LookingAt("required") || LookingAt("optional") || LookingAt("repeated")) { - AddError( + RecordError( "Fields in oneofs must not have labels (required / optional " "/ repeated)."); // We can continue parsing here because we understand what the user @@ -2003,7 +2049,7 @@ bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, while (!TryConsumeEndOfDeclaration("}", nullptr)) { if (AtEnd()) { - AddError("Reached end of input in enum definition (missing '}')."); + RecordError("Reached end of input in enum definition (missing '}')."); return false; } @@ -2120,7 +2166,7 @@ bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, while (!TryConsumeEndOfDeclaration("}", nullptr)) { if (AtEnd()) { - AddError("Reached end of input in service definition (missing '}')."); + RecordError("Reached end of input in service definition (missing '}')."); return false; } @@ -2224,7 +2270,7 @@ bool Parser::ParseMethodOptions(const LocationRecorder& parent_location, ConsumeEndOfDeclaration("{", &parent_location); while (!TryConsumeEndOfDeclaration("}", nullptr)) { if (AtEnd()) { - AddError("Reached end of input in method options (missing '}')."); + RecordError("Reached end of input in method options (missing '}')."); return false; } @@ -2288,7 +2334,7 @@ bool Parser::ParseUserDefinedType(TProtoStringType* type_name) { // if we are parsing a field type then we would not get here because // primitives are allowed there as well. So this error message doesn't // need to account for enums. - AddError("Expected message type."); + RecordError("Expected message type."); // Pretend to accept this type so that we can go on parsing. *type_name = input_->current().text; @@ -2320,7 +2366,7 @@ bool Parser::ParsePackage(FileDescriptorProto* file, const LocationRecorder& root_location, const FileDescriptorProto* containing_file) { if (file->has_package()) { - AddError("Multiple package definitions."); + RecordError("Multiple package definitions."); // Don't append the new package to the old one. Just replace it. Not // that it really matters since this is an error anyway. file->clear_package(); @@ -2391,33 +2437,27 @@ bool SourceLocationTable::Find( const Message* descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, int* line, int* column) const { - const std::pair<int, int>* result = - FindOrNull(location_map_, std::make_pair(descriptor, location)); - if (result == nullptr) { + auto it = location_map_.find({descriptor, location}); + if (it == location_map_.end()) { *line = -1; *column = 0; return false; - } else { - *line = result->first; - *column = result->second; - return true; } + std::tie(*line, *column) = it->second; + return true; } bool SourceLocationTable::FindImport(const Message* descriptor, - const TProtoStringType& name, int* line, + y_absl::string_view name, int* line, int* column) const { - const std::pair<int, int>* result = - FindOrNull(import_location_map_, std::make_pair(descriptor, name)); - if (result == nullptr) { + auto it = import_location_map_.find({descriptor, TProtoStringType(name)}); + if (it == import_location_map_.end()) { *line = -1; *column = 0; return false; - } else { - *line = result->first; - *column = result->second; - return true; } + std::tie(*line, *column) = it->second; + return true; } void SourceLocationTable::Add( diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/parser.h b/contrib/libs/protoc/src/google/protobuf/compiler/parser.h index c92b5f28f4c..72db054327d 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/parser.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/parser.h @@ -38,17 +38,18 @@ #define GOOGLE_PROTOBUF_COMPILER_PARSER_H__ #include <cstdint> -#include <map> #include <string> #include <utility> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/tokenizer.h> -#include <google/protobuf/repeated_field.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/tokenizer.h" +#include "google/protobuf/repeated_field.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -71,6 +72,8 @@ class SourceLocationTable; class PROTOBUF_EXPORT Parser { public: Parser(); + Parser(const Parser&) = delete; + Parser& operator=(const Parser&) = delete; ~Parser(); // Parse the entire input and construct a FileDescriptorProto representing @@ -98,7 +101,7 @@ class PROTOBUF_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 TProtoStringType& GetSyntaxIdentifier() { return syntax_identifier_; } + y_absl::string_view 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 @@ -151,38 +154,41 @@ class PROTOBUF_EXPORT Parser { inline bool AtEnd(); // True if the next token matches the given text. - inline bool LookingAt(const char* text); + inline bool LookingAt(y_absl::string_view text); // True if the next token is of the given type. inline bool LookingAtType(io::Tokenizer::TokenType token_type); // If the next token exactly matches the text given, consume it and return // true. Otherwise, return false without logging an error. - bool TryConsume(const char* text); + bool TryConsume(y_absl::string_view text); // These attempt to read some kind of token from the input. If successful, // they return true. Otherwise they return false and add the given error // to the error list. // Consume a token with the exact text given. - bool Consume(const char* text, const char* error); + bool Consume(y_absl::string_view text, y_absl::string_view error); // Same as above, but automatically generates the error "Expected \"text\".", // where "text" is the expected token text. - bool Consume(const char* text); + bool Consume(y_absl::string_view text); // Consume a token of type IDENTIFIER and store its text in "output". - bool ConsumeIdentifier(TProtoStringType* output, const char* error); + bool ConsumeIdentifier(TProtoStringType* output, y_absl::string_view error); // Consume an integer and store its value in "output". - bool ConsumeInteger(int* output, const char* error); + bool ConsumeInteger(int* output, y_absl::string_view error); // Consume a signed integer and store its value in "output". - bool ConsumeSignedInteger(int* output, const char* error); + bool ConsumeSignedInteger(int* output, y_absl::string_view error); // Consume a 64-bit integer and store its value in "output". If the value // is greater than max_value, an error will be reported. bool ConsumeInteger64(arc_ui64 max_value, arc_ui64* output, - const char* error); + y_absl::string_view error); + // Try to consume a 64-bit integer and store its value in "output". No + // error is reported on failure, allowing caller to consume token another way. + bool TryConsumeInteger64(arc_ui64 max_value, arc_ui64* output); // Consume a number and store its value in "output". This will accept // tokens of either INTEGER or FLOAT type. - bool ConsumeNumber(double* output, const char* error); + bool ConsumeNumber(double* output, y_absl::string_view error); // Consume a string literal and store its (unescaped) value in "output". - bool ConsumeString(TProtoStringType* output, const char* error); + bool ConsumeString(TProtoStringType* output, y_absl::string_view error); // Consume a token representing the end of the statement. Comments between // this token and the next will be harvested for documentation. The given @@ -193,27 +199,30 @@ class PROTOBUF_EXPORT Parser { // have been passed around by const reference, for no particularly good // reason. We should probably go through and change them all to mutable // pointer to make this more intuitive. - bool TryConsumeEndOfDeclaration(const char* text, + bool TryConsumeEndOfDeclaration(y_absl::string_view text, const LocationRecorder* location); - bool TryConsumeEndOfDeclarationFinishScope(const char* text, + bool TryConsumeEndOfDeclarationFinishScope(y_absl::string_view text, const LocationRecorder* location); - bool ConsumeEndOfDeclaration(const char* text, + bool ConsumeEndOfDeclaration(y_absl::string_view text, const LocationRecorder* location); // ----------------------------------------------------------------- // Error logging helpers - // Invokes error_collector_->AddError(), if error_collector_ is not NULL. - void AddError(int line, int column, const TProtoStringType& error); + // Invokes error_collector_->RecordError(), if error_collector_ is not NULL. + void RecordError(int line, int column, y_absl::string_view error); - // Invokes error_collector_->AddError() with the line and column number + // Invokes error_collector_->RecordError() with the line and column number // of the current token. - void AddError(const TProtoStringType& error); + void RecordError(y_absl::string_view error); - // Invokes error_collector_->AddWarning() with the line and column number + // Invokes error_collector_->RecordWarning(), if error_collector_ is not NULL. + void RecordWarning(int line, int column, y_absl::string_view warning); + + // Invokes error_collector_->RecordWarning() with the line and column number // of the current token. - void AddWarning(const TProtoStringType& warning); + void RecordWarning(y_absl::string_view warning); // Records a location in the SourceCodeInfo.location table (see // descriptor.proto). We use RAII to ensure that the start and end locations @@ -304,7 +313,7 @@ class PROTOBUF_EXPORT Parser { // were no errors; only that there were no *syntax* errors. For instance, // if a service method is defined using proper syntax but uses a primitive // type as its input or output, ParseMethodField() still returns true - // and only reports the error by calling AddError(). In practice, this + // and only reports the error by calling RecordError(). In practice, this // makes logic much simpler for the caller. // Parse a top-level message, enum, service, etc. @@ -392,6 +401,7 @@ class PROTOBUF_EXPORT Parser { const LocationRecorder& message_location); bool ParseReservedNames(DescriptorProto* message, const LocationRecorder& parent_location); + bool ParseReservedName(TProtoStringType* name, y_absl::string_view error_message); bool ParseReservedNumbers(DescriptorProto* message, const LocationRecorder& parent_location); bool ParseReserved(EnumDescriptorProto* message, @@ -545,8 +555,6 @@ class PROTOBUF_EXPORT Parser { // the next element (See SourceCodeInfo.Location in descriptor.proto), when // ConsumeEndOfDeclaration() is called. std::vector<TProtoStringType> upcoming_detached_comments_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser); }; // A table mapping (descriptor, ErrorLocation) pairs -- as reported by @@ -570,7 +578,7 @@ class PROTOBUF_EXPORT SourceLocationTable { bool Find(const Message* descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, int* line, int* column) const; - bool FindImport(const Message* descriptor, const TProtoStringType& name, int* line, + bool FindImport(const Message* descriptor, y_absl::string_view name, int* line, int* column) const; // Adds a location to the table. @@ -584,12 +592,12 @@ class PROTOBUF_EXPORT SourceLocationTable { void Clear(); private: - typedef std::map< + using LocationMap = y_absl::flat_hash_map< std::pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>, - std::pair<int, int> > - LocationMap; + std::pair<int, int>>; LocationMap location_map_; - std::map<std::pair<const Message*, TProtoStringType>, std::pair<int, int> > + y_absl::flat_hash_map<std::pair<const Message*, TProtoStringType>, + std::pair<int, int>> import_location_map_; }; @@ -597,6 +605,6 @@ class PROTOBUF_EXPORT SourceLocationTable { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_PARSER_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/php/names.cc b/contrib/libs/protoc/src/google/protobuf/compiler/php/names.cc new file mode 100644 index 00000000000..e6fc0145f03 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/php/names.cc @@ -0,0 +1,144 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "google/protobuf/compiler/php/names.h" + +#include <string> + +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/plugin.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" + +const char* const kReservedNames[] = { + "abstract", "and", "array", "as", "break", + "callable", "case", "catch", "class", "clone", + "const", "continue", "declare", "default", "die", + "do", "echo", "else", "elseif", "empty", + "enddeclare", "endfor", "endforeach", "endif", "endswitch", + "endwhile", "eval", "exit", "extends", "final", + "finally", "fn", "for", "foreach", "function", + "global", "goto", "if", "implements", "include", + "include_once", "instanceof", "insteadof", "interface", "isset", + "list", "match", "namespace", "new", "or", + "parent", "print", "private", "protected", "public", + "readonly", "require", "require_once", "return", "self", + "static", "switch", "throw", "trait", "try", + "unset", "use", "var", "while", "xor", + "yield", "int", "float", "bool", "string", + "true", "false", "null", "void", "iterable"}; +const int kReservedNamesSize = 80; + +namespace google { +namespace protobuf { +namespace compiler { +namespace php { + +bool IsReservedName(y_absl::string_view name) { + TProtoStringType lower(name); + lower.to_lower(); + for (int i = 0; i < kReservedNamesSize; i++) { + if (lower == kReservedNames[i]) { + return true; + } + } + return false; +} + +TProtoStringType ReservedNamePrefix(const TProtoStringType& classname, + const FileDescriptor* file) { + if (IsReservedName(classname)) { + if (file->package() == "google.protobuf") { + return "GPB"; + } else { + return "PB"; + } + } + + return ""; +} + +namespace { + +template <typename DescriptorType> +TProtoStringType ClassNamePrefixImpl(const TProtoStringType& classname, + const DescriptorType* desc) { + const TProtoStringType& prefix = (desc->file()->options()).php_class_prefix(); + if (!prefix.empty()) { + return prefix; + } + + return ReservedNamePrefix(classname, desc->file()); +} + +template <typename DescriptorType> +TProtoStringType GeneratedClassNameImpl(const DescriptorType* desc) { + TProtoStringType classname = ClassNamePrefixImpl(desc->name(), desc) + desc->name(); + const Descriptor* containing = desc->containing_type(); + while (containing != NULL) { + classname = ClassNamePrefixImpl(containing->name(), desc) + containing->name() + + '\\' + classname; + containing = containing->containing_type(); + } + return classname; +} + +TProtoStringType GeneratedClassNameImpl(const ServiceDescriptor* desc) { + TProtoStringType classname = desc->name(); + return ClassNamePrefixImpl(classname, desc) + classname; +} + +} // namespace + +TProtoStringType ClassNamePrefix(const TProtoStringType& classname, + const Descriptor* desc) { + return ClassNamePrefixImpl(classname, desc); +} +TProtoStringType ClassNamePrefix(const TProtoStringType& classname, + const EnumDescriptor* desc) { + return ClassNamePrefixImpl(classname, desc); +} + +TProtoStringType GeneratedClassName(const Descriptor* desc) { + return GeneratedClassNameImpl(desc); +} + +TProtoStringType GeneratedClassName(const EnumDescriptor* desc) { + return GeneratedClassNameImpl(desc); +} + +TProtoStringType GeneratedClassName(const ServiceDescriptor* desc) { + return GeneratedClassNameImpl(desc); +} + +} // namespace php +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/php/names.h b/contrib/libs/protoc/src/google/protobuf/compiler/php/names.h new file mode 100644 index 00000000000..62d7bc5e6c3 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/php/names.h @@ -0,0 +1,73 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_PHP_NAMES_H__ +#define GOOGLE_PROTOBUF_COMPILER_PHP_NAMES_H__ + +#include "google/protobuf/descriptor.h" + +#include <string> + +#include "y_absl/strings/string_view.h" +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { +namespace php { + +// Whether or not a name is reserved. +PROTOC_EXPORT bool IsReservedName(y_absl::string_view name); + +// A prefix to stick in front of reserved names to avoid clashes. +PROTOC_EXPORT TProtoStringType ReservedNamePrefix(const TProtoStringType& classname, + const FileDescriptor* file); + +// A prefix to stick in front of all class names. +PROTOC_EXPORT TProtoStringType ClassNamePrefix(const TProtoStringType& classname, + const Descriptor* desc); +PROTOC_EXPORT TProtoStringType ClassNamePrefix(const TProtoStringType& classname, + const EnumDescriptor* desc); + +// To skip reserved keywords in php, some generated classname are prefixed. +// Other code generators may need following API to figure out the actual +// classname. +PROTOC_EXPORT TProtoStringType GeneratedClassName(const Descriptor* desc); +PROTOC_EXPORT TProtoStringType GeneratedClassName(const EnumDescriptor* desc); +PROTOC_EXPORT TProtoStringType GeneratedClassName(const ServiceDescriptor* desc); + +} // namespace php +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_COMPILER_PHP_NAMES_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/php/php_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/php/php_generator.cc index ecaccec3391..a39a9c5c0ee 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/php/php_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/php/php_generator.cc @@ -28,50 +28,43 @@ // (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/php/php_generator.h> - -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/plugin.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> -#include <google/protobuf/stubs/port.h> -#include <google/protobuf/stubs/strutil.h> +#include "google/protobuf/compiler/php/php_generator.h" +#include <algorithm> #include <sstream> +#include <string> +#include <vector> + +#include "google/protobuf/compiler/code_generator.h" +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" +#include <google/protobuf/stubs/port.h> + #include <util/string/cast.h> -const TProtoStringType kDescriptorFile = "google/protobuf/descriptor.proto"; -const TProtoStringType kEmptyFile = "google/protobuf/empty.proto"; -const TProtoStringType kEmptyMetadataFile = "GPBMetadata/Google/Protobuf/GPBEmpty.php"; -const TProtoStringType kDescriptorMetadataFile = +constexpr y_absl::string_view kDescriptorFile = + "google/protobuf/descriptor.proto"; +constexpr y_absl::string_view kEmptyFile = "google/protobuf/empty.proto"; +constexpr y_absl::string_view kEmptyMetadataFile = + "GPBMetadata/Google/Protobuf/GPBEmpty.php"; +constexpr y_absl::string_view kDescriptorMetadataFile = "GPBMetadata/Google/Protobuf/Internal/Descriptor.php"; -const TProtoStringType kDescriptorDirName = "Google/Protobuf/Internal"; -const TProtoStringType kDescriptorPackageName = "Google\\Protobuf\\Internal"; -const char* const kReservedNames[] = { - "abstract", "and", "array", "as", "break", - "callable", "case", "catch", "class", "clone", - "const", "continue", "declare", "default", "die", - "do", "echo", "else", "elseif", "empty", - "enddeclare", "endfor", "endforeach", "endif", "endswitch", - "endwhile", "eval", "exit", "extends", "final", - "finally", "fn", "for", "foreach", "function", - "global", "goto", "if", "implements", "include", - "include_once", "instanceof", "insteadof", "interface", "isset", - "list", "match", "namespace", "new", "or", - "parent", "print", "private", "protected", "public", - "readonly", "require", "require_once", "return", "self", - "static", "switch", "throw", "trait", "try", - "unset", "use", "var", "while", "xor", - "yield", "int", "float", "bool", "string", - "true", "false", "null", "void", "iterable"}; -const char* const kValidConstantNames[] = { - "int", "float", "bool", "string", "true", - "false", "null", "void", "iterable", "parent", - "self", "readonly" -}; -const int kReservedNamesSize = 80; +constexpr y_absl::string_view kDescriptorPackageName = + "Google\\Protobuf\\Internal"; +constexpr y_absl::string_view kValidConstantNames[] = { + "int", "float", "bool", "string", "true", "false", + "null", "void", "iterable", "parent", "self", "readonly"}; const int kValidConstantNamesSize = 12; const int kFieldSetter = 1; const int kFieldGetter = 2; @@ -86,18 +79,18 @@ struct Options { bool is_descriptor = false; bool aggregate_metadata = false; bool gen_c_wkt = false; - std::set<TProtoStringType> aggregate_metadata_prefixes; + y_absl::flat_hash_set<TProtoStringType> aggregate_metadata_prefixes; }; namespace { // Forward decls. -TProtoStringType PhpName(const TProtoStringType& full_name, const Options& options); +TProtoStringType PhpName(y_absl::string_view full_name, const Options& options); TProtoStringType IntToString(arc_i32 value); -TProtoStringType FilenameToClassname(const TProtoStringType& filename); +TProtoStringType FilenameToClassname(y_absl::string_view filename); TProtoStringType GeneratedMetadataFileName(const FileDescriptor* file, const Options& options); -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& name, +TProtoStringType UnderscoresToCamelCase(y_absl::string_view name, bool cap_first_letter); void Indent(io::Printer* printer); void Outdent(io::Printer* printer); @@ -123,68 +116,19 @@ void GenerateServiceDocComment(io::Printer* printer, void GenerateServiceMethodDocComment(io::Printer* printer, const MethodDescriptor* method); -TProtoStringType ReservedNamePrefix(const TProtoStringType& classname, - const FileDescriptor* file) { - bool is_reserved = false; - - TProtoStringType lower = classname; - lower.to_lower(); - - for (int i = 0; i < kReservedNamesSize; i++) { - if (lower == kReservedNames[i]) { - is_reserved = true; - break; - } - } - - if (is_reserved) { - if (file->package() == "google.protobuf") { - return "GPB"; - } else { - return "PB"; - } - } - - return ""; -} - template <typename DescriptorType> TProtoStringType DescriptorFullName(const DescriptorType* desc, bool is_internal) { + y_absl::string_view full_name = desc->full_name(); if (is_internal) { - return StringReplace(desc->full_name(), - "google.protobuf", - "google.protobuf.internal", false); - } else { - return desc->full_name(); - } -} - -template <typename DescriptorType> -TProtoStringType ClassNamePrefix(const TProtoStringType& classname, - const DescriptorType* desc) { - const TProtoStringType& prefix = (desc->file()->options()).php_class_prefix(); - if (!prefix.empty()) { - return prefix; - } - - return ReservedNamePrefix(classname, desc->file()); -} - -template <typename DescriptorType> -TProtoStringType GeneratedClassNameImpl(const DescriptorType* desc) { - TProtoStringType classname = ClassNamePrefix(desc->name(), desc) + desc->name(); - const Descriptor* containing = desc->containing_type(); - while (containing != NULL) { - classname = ClassNamePrefix(containing->name(), desc) + containing->name() - + '\\' + classname; - containing = containing->containing_type(); + constexpr y_absl::string_view replace = "google.protobuf"; + size_t index = full_name.find(replace); + if (index != TProtoStringType::npos) { + return y_absl::StrCat(full_name.substr(0, index), + "google.protobuf.internal", + full_name.substr(index + replace.size())); + } } - return classname; -} - -TProtoStringType GeneratedClassNameImpl(const ServiceDescriptor* desc) { - TProtoStringType classname = desc->name(); - return ClassNamePrefix(classname, desc) + classname; + return TProtoStringType(full_name); } template <typename DescriptorType> @@ -198,31 +142,13 @@ TProtoStringType LegacyGeneratedClassName(const DescriptorType* desc) { return ClassNamePrefix(classname, desc) + classname; } -TProtoStringType ClassNamePrefix(const TProtoStringType& classname) { - TProtoStringType lower = classname; - lower.to_lower(); - - for (int i = 0; i < kReservedNamesSize; i++) { - if (lower == kReservedNames[i]) { - return "PB"; - } - } - - return ""; -} - -TProtoStringType ConstantNamePrefix(const TProtoStringType& classname) { +TProtoStringType ConstantNamePrefix(y_absl::string_view classname) { bool is_reserved = false; - TProtoStringType lower = classname; + TProtoStringType lower(classname); lower.to_lower(); - for (int i = 0; i < kReservedNamesSize; i++) { - if (lower == kReservedNames[i]) { - is_reserved = true; - break; - } - } + is_reserved = IsReservedName(lower); for (int i = 0; i < kValidConstantNamesSize; i++) { if (lower == kValidConstantNames[i]) { @@ -242,9 +168,9 @@ template <typename DescriptorType> TProtoStringType RootPhpNamespace(const DescriptorType* desc, const Options& options) { if (desc->file()->options().has_php_namespace()) { - const TProtoStringType& php_namespace = desc->file()->options().php_namespace(); + y_absl::string_view php_namespace = desc->file()->options().php_namespace(); if (!php_namespace.empty()) { - return php_namespace; + return TProtoStringType(php_namespace); } return ""; } @@ -257,10 +183,10 @@ TProtoStringType RootPhpNamespace(const DescriptorType* desc, template <typename DescriptorType> TProtoStringType FullClassName(const DescriptorType* desc, const Options& options) { - TProtoStringType classname = GeneratedClassNameImpl(desc); + TProtoStringType classname = GeneratedClassName(desc); TProtoStringType php_namespace = RootPhpNamespace(desc, options); if (!php_namespace.empty()) { - return php_namespace + "\\" + classname; + return y_absl::StrCat(php_namespace, "\\", classname); } return classname; } @@ -278,14 +204,19 @@ TProtoStringType LegacyFullClassName(const DescriptorType* desc, TProtoStringType classname = LegacyGeneratedClassName(desc); TProtoStringType php_namespace = RootPhpNamespace(desc, options); if (!php_namespace.empty()) { - return php_namespace + "\\" + classname; + return y_absl::StrCat(php_namespace, "\\", classname); } return classname; } -TProtoStringType PhpName(const TProtoStringType& full_name, const Options& options) { +TProtoStringType PhpNamePrefix(y_absl::string_view classname) { + if (IsReservedName(classname)) return "PB"; + return ""; +} + +TProtoStringType PhpName(y_absl::string_view full_name, const Options& options) { if (options.is_descriptor) { - return kDescriptorPackageName; + return TProtoStringType(kDescriptorPackageName); } TProtoStringType segment; @@ -296,7 +227,7 @@ TProtoStringType PhpName(const TProtoStringType& full_name, const Options& optio segment += full_name[i] + ('A' - 'a'); cap_next_letter = false; } else if (full_name[i] == '.') { - result += ClassNamePrefix(segment) + segment + '\\'; + result += PhpNamePrefix(segment) + segment + '\\'; segment = ""; cap_next_letter = true; } else { @@ -304,7 +235,7 @@ TProtoStringType PhpName(const TProtoStringType& full_name, const Options& optio cap_next_letter = false; } } - result += ClassNamePrefix(segment) + segment; + result += PhpNamePrefix(segment) + segment; return result; } @@ -334,51 +265,51 @@ TProtoStringType DefaultForField(const FieldDescriptor* field) { TProtoStringType GeneratedMetadataFileName(const FileDescriptor* file, const Options& options) { - const TProtoStringType& proto_file = file->name(); + y_absl::string_view proto_file = file->name(); int start_index = 0; - int first_index = proto_file.find_first_of("/", start_index); + int first_index = proto_file.find_first_of('/', start_index); TProtoStringType result = ""; TProtoStringType segment = ""; if (proto_file == kEmptyFile) { - return kEmptyMetadataFile; + return TProtoStringType(kEmptyMetadataFile); } if (options.is_descriptor) { - return kDescriptorMetadataFile; + return TProtoStringType(kDescriptorMetadataFile); } // Append directory name. - TProtoStringType file_no_suffix; - int lastindex = proto_file.find_last_of("."); + y_absl::string_view file_no_suffix; + int lastindex = proto_file.find_last_of('.'); if (proto_file == kEmptyFile) { - return kEmptyMetadataFile; + return TProtoStringType(kEmptyMetadataFile); } else { file_no_suffix = proto_file.substr(0, lastindex); } if (file->options().has_php_metadata_namespace()) { - const TProtoStringType& php_metadata_namespace = + y_absl::string_view php_metadata_namespace = file->options().php_metadata_namespace(); if (!php_metadata_namespace.empty() && php_metadata_namespace != "\\") { - result += php_metadata_namespace; + y_absl::StrAppend(&result, php_metadata_namespace); std::replace(result.begin(), result.vend(), '\\', '/'); if (result.at(result.size() - 1) != '/') { - result += "/"; + y_absl::StrAppend(&result, "/"); } } } else { - result += "GPBMetadata/"; + y_absl::StrAppend(&result, "GPBMetadata/"); while (first_index != TProtoStringType::npos) { segment = UnderscoresToCamelCase( file_no_suffix.substr(start_index, first_index - start_index), true); - result += ReservedNamePrefix(segment, file) + segment + "/"; + y_absl::StrAppend(&result, ReservedNamePrefix(segment, file), segment, "/"); start_index = first_index + 1; - first_index = file_no_suffix.find_first_of("/", start_index); + first_index = file_no_suffix.find_first_of('/', start_index); } } // Append file name. - int file_name_start = file_no_suffix.find_last_of("/"); + int file_name_start = file_no_suffix.find_last_of('/'); if (file_name_start == TProtoStringType::npos) { file_name_start = 0; } else { @@ -387,7 +318,8 @@ TProtoStringType GeneratedMetadataFileName(const FileDescriptor* file, segment = UnderscoresToCamelCase( file_no_suffix.substr(file_name_start, first_index - file_name_start), true); - return result + ReservedNamePrefix(segment, file) + segment + ".php"; + return y_absl::StrCat(result, ReservedNamePrefix(segment, file), segment, + ".php"); } TProtoStringType GeneratedMetadataFileName(const FileDescriptor* file, @@ -406,7 +338,7 @@ TProtoStringType GeneratedClassFileName(const DescriptorType* desc, result[i] = '/'; } } - return result + ".php"; + return y_absl::StrCat(result, ".php"); } template <typename DescriptorType> @@ -419,28 +351,33 @@ TProtoStringType LegacyGeneratedClassFileName(const DescriptorType* desc, result[i] = '/'; } } - return result + ".php"; + return y_absl::StrCat(result, ".php"); } template <typename DescriptorType> -TProtoStringType LegacyReadOnlyGeneratedClassFileName(const DescriptorType* desc, - const Options& options) { - TProtoStringType php_namespace = RootPhpNamespace(desc, options); +TProtoStringType LegacyReadOnlyGeneratedClassFileName(TProtoStringType php_namespace, + const DescriptorType* desc) { if (!php_namespace.empty()) { - return php_namespace + "/" + desc->name() + ".php"; + for (int i = 0; i < php_namespace.size(); i++) { + if (php_namespace[i] == '\\') { + php_namespace[i] = '/'; + } + } + return y_absl::StrCat(php_namespace, "/", desc->name(), ".php"); } - return desc->name() + ".php"; + + return y_absl::StrCat(desc->name(), ".php"); } TProtoStringType GeneratedServiceFileName(const ServiceDescriptor* service, const Options& options) { - TProtoStringType result = FullClassName(service, options) + "Interface"; + TProtoStringType result = FullClassName(service, options); for (int i = 0; i < result.size(); i++) { if (result[i] == '\\') { result[i] = '/'; } } - return result + ".php"; + return y_absl::StrCat(result, "Interface", ".php"); } TProtoStringType IntToString(arc_i32 value) { @@ -492,7 +429,7 @@ TProtoStringType PhpSetterTypeName(const FieldDescriptor* field, type = "string"; break; case FieldDescriptor::TYPE_MESSAGE: - type = "\\" + FullClassName(field->message_type(), options); + type = y_absl::StrCat("\\", FullClassName(field->message_type(), options)); break; case FieldDescriptor::TYPE_GROUP: return "null"; @@ -500,11 +437,12 @@ TProtoStringType PhpSetterTypeName(const FieldDescriptor* field, } if (field->is_repeated()) { // accommodate for edge case with multiple types. - size_t start_pos = type.find("|"); + size_t start_pos = type.find('|'); if (start_pos != TProtoStringType::npos) { type.replace(start_pos, 1, ">|array<"); } - type = "array<" + type + ">|\\Google\\Protobuf\\Internal\\RepeatedField"; + type = y_absl::StrCat("array<", type, + ">|\\Google\\Protobuf\\Internal\\RepeatedField"); } return type; } @@ -542,7 +480,7 @@ TProtoStringType PhpGetterTypeName(const FieldDescriptor* field, case FieldDescriptor::TYPE_STRING: case FieldDescriptor::TYPE_BYTES: return "string"; case FieldDescriptor::TYPE_MESSAGE: - return "\\" + FullClassName(field->message_type(), options); + return y_absl::StrCat("\\", FullClassName(field->message_type(), options)); case FieldDescriptor::TYPE_GROUP: return "null"; default: assert(false); return ""; } @@ -558,13 +496,14 @@ TProtoStringType PhpGetterTypeName(const FieldDescriptor* field, TProtoStringType EnumOrMessageSuffix(const FieldDescriptor* field, const Options& options) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - return ", '" + - DescriptorFullName(field->message_type(), options.is_descriptor) + - "'"; + return y_absl::StrCat( + ", '", DescriptorFullName(field->message_type(), options.is_descriptor), + "'"); } if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { - return ", '" + - DescriptorFullName(field->enum_type(), options.is_descriptor) + "'"; + return y_absl::StrCat( + ", '", DescriptorFullName(field->enum_type(), options.is_descriptor), + "'"); } return ""; } @@ -578,7 +517,7 @@ TProtoStringType EnumOrMessageSuffix(const FieldDescriptor* field, // Converts a name to camel-case. If cap_first_letter is true, capitalize the // first letter. -TProtoStringType UnderscoresToCamelCase(const TProtoStringType& name, +TProtoStringType UnderscoresToCamelCase(y_absl::string_view name, bool cap_first_letter) { TProtoStringType result; for (int i = 0; i < name.size(); i++) { @@ -659,8 +598,11 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, GenerateFieldDocComment(printer, field, options, kFieldGetter); // deprecation - TProtoStringType deprecation_trigger = (field->options().deprecated()) ? "@trigger_error('" + - field->name() + " is deprecated.', E_USER_DEPRECATED);\n " : ""; + TProtoStringType deprecation_trigger = + (field->options().deprecated()) + ? y_absl::StrCat("@trigger_error('", field->name(), + " is deprecated.', E_USER_DEPRECATED);\n ") + : ""; // Emit getter. if (oneof != NULL) { @@ -760,18 +702,16 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, "$arr = GPBUtil::checkMapField($var, " "\\Google\\Protobuf\\Internal\\GPBType::^key_type^, " "\\Google\\Protobuf\\Internal\\GPBType::^value_type^", - "key_type", ToUpper(key->type_name()), - "value_type", ToUpper(value->type_name())); + "key_type", y_absl::AsciiStrToUpper(key->type_name()), + "value_type", y_absl::AsciiStrToUpper(value->type_name())); if (value->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print( - ", \\^class_name^);\n", - "class_name", - FullClassName(value->message_type(), options) + "::class"); + printer->Print(", \\^class_name^);\n", "class_name", + y_absl::StrCat(FullClassName(value->message_type(), options), + "::class")); } else if (value->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer->Print( - ", \\^class_name^);\n", - "class_name", - FullClassName(value->enum_type(), options) + "::class"); + ", \\^class_name^);\n", "class_name", + y_absl::StrCat(FullClassName(value->enum_type(), options), "::class")); } else { printer->Print(");\n"); } @@ -779,17 +719,15 @@ void GenerateFieldAccessor(const FieldDescriptor* field, const Options& options, printer->Print( "$arr = GPBUtil::checkRepeatedField($var, " "\\Google\\Protobuf\\Internal\\GPBType::^type^", - "type", ToUpper(field->type_name())); + "type", y_absl::AsciiStrToUpper(field->type_name())); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print( - ", \\^class_name^);\n", - "class_name", - FullClassName(field->message_type(), options) + "::class"); + printer->Print(", \\^class_name^);\n", "class_name", + y_absl::StrCat(FullClassName(field->message_type(), options), + "::class")); } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer->Print( - ", \\^class_name^);\n", - "class_name", - FullClassName(field->enum_type(), options) + "::class"); + ", \\^class_name^);\n", "class_name", + y_absl::StrCat(FullClassName(field->enum_type(), options), "::class")); } else { printer->Print(");\n"); } @@ -879,16 +817,16 @@ void GenerateServiceMethod(const MethodDescriptor* method, ); } -void GenerateMessageToPool(const TProtoStringType& name_prefix, +void GenerateMessageToPool(y_absl::string_view name_prefix, const Descriptor* message, io::Printer* printer) { // Don't generate MapEntry messages -- we use the PHP extension's native // support for map fields instead. if (message->options().map_entry()) { return; } - TProtoStringType class_name = - (name_prefix.empty() ? "" : name_prefix + "\\") + - ReservedNamePrefix(message->name(), message->file()) + message->name(); + TProtoStringType class_name = y_absl::StrCat( + name_prefix.empty() ? "" : y_absl::StrCat(name_prefix, "\\"), + ReservedNamePrefix(message->name(), message->file()), message->name()); printer->Print( "$pool->addMessage('^message^', " @@ -909,9 +847,9 @@ void GenerateMessageToPool(const TProtoStringType& name_prefix, "->map('^field^', \\Google\\Protobuf\\Internal\\GPBType::^key^, " "\\Google\\Protobuf\\Internal\\GPBType::^value^, ^number^^other^)\n", "field", field->name(), - "key", ToUpper(key->type_name()), - "value", ToUpper(val->type_name()), - "number", StrCat(field->number()), + "key", y_absl::AsciiStrToUpper(key->type_name()), + "value", y_absl::AsciiStrToUpper(val->type_name()), + "number", y_absl::StrCat(field->number()), "other", EnumOrMessageSuffix(val, true)); } else if (!field->real_containing_oneof()) { printer->Print( @@ -919,8 +857,8 @@ void GenerateMessageToPool(const TProtoStringType& name_prefix, "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n", "field", field->name(), "label", LabelForField(field), - "type", ToUpper(field->type_name()), - "number", StrCat(field->number()), + "type", y_absl::AsciiStrToUpper(field->type_name()), + "number", y_absl::StrCat(field->number()), "other", EnumOrMessageSuffix(field, true)); } } @@ -937,8 +875,8 @@ void GenerateMessageToPool(const TProtoStringType& name_prefix, "->value('^field^', " "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n", "field", field->name(), - "type", ToUpper(field->type_name()), - "number", StrCat(field->number()), + "type", y_absl::AsciiStrToUpper(field->type_name()), + "number", y_absl::StrCat(field->number()), "other", EnumOrMessageSuffix(field, true)); } printer->Print("->finish()\n"); @@ -990,7 +928,7 @@ void GenerateAddFileToPool(const FileDescriptor* file, const Options& options, "$pool->finish();\n"); } else { for (int i = 0; i < file->dependency_count(); i++) { - const TProtoStringType& name = file->dependency(i)->name(); + y_absl::string_view name = file->dependency(i)->name(); // Currently, descriptor.proto is not ready for external usage. Skip to // import it for now, so that its dependencies can still work as long as // they don't use protos defined in descriptor.proto. @@ -1065,9 +1003,10 @@ void GenerateAddFileToPool(const FileDescriptor* file, const Options& options, static void AnalyzeDependencyForFile( const FileDescriptor* file, - std::set<const FileDescriptor*>* nodes_without_dependency, - std::map<const FileDescriptor*, std::set<const FileDescriptor*>>* deps, - std::map<const FileDescriptor*, int>* dependency_count) { + y_absl::flat_hash_set<const FileDescriptor*>* nodes_without_dependency, + y_absl::flat_hash_map<const FileDescriptor*, + y_absl::flat_hash_set<const FileDescriptor*>>* deps, + y_absl::flat_hash_map<const FileDescriptor*, int>* dependency_count) { int count = file->dependency_count(); for (int i = 0; i < file->dependency_count(); i++) { const FileDescriptor* dependency = file->dependency(i); @@ -1087,7 +1026,7 @@ static void AnalyzeDependencyForFile( continue; } if (deps->find(dependency) == deps->end()) { - (*deps)[dependency] = std::set<const FileDescriptor*>(); + (*deps)[dependency] = {}; } (*deps)[dependency].insert(file); AnalyzeDependencyForFile( @@ -1103,7 +1042,7 @@ static bool NeedsUnwrapping(const FileDescriptor* file, has_aggregate_metadata_prefix = true; } else { for (const auto& prefix : options.aggregate_metadata_prefixes) { - if (HasPrefixString(file->package(), prefix)) { + if (y_absl::StartsWith(file->package(), prefix)) { has_aggregate_metadata_prefix = true; break; } @@ -1123,9 +1062,11 @@ void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options, "}\n"); // Sort files according to dependency - std::map<const FileDescriptor*, std::set<const FileDescriptor*>> deps; - std::map<const FileDescriptor*, int> dependency_count; - std::set<const FileDescriptor*> nodes_without_dependency; + y_absl::flat_hash_map<const FileDescriptor*, + y_absl::flat_hash_set<const FileDescriptor*>> + deps; + y_absl::flat_hash_map<const FileDescriptor*, int> dependency_count; + y_absl::flat_hash_set<const FileDescriptor*> nodes_without_dependency; FileDescriptorSet sorted_file_set; AnalyzeDependencyForFile( @@ -1231,10 +1172,10 @@ void GenerateHead(const FileDescriptor* file, io::Printer* printer) { "filename", file->name()); } -TProtoStringType FilenameToClassname(const TProtoStringType& filename) { - int lastindex = filename.find_last_of("."); - TProtoStringType result = filename.substr(0, lastindex); - for (int i = 0; i < result.size(); i++) { +TProtoStringType FilenameToClassname(y_absl::string_view filename) { + size_t lastindex = filename.find_last_of('.'); + TProtoStringType result(filename.substr(0, lastindex)); + for (size_t i = 0; i < result.size(); i++) { if (result[i] == '/') { result[i] = '\\'; } @@ -1252,7 +1193,7 @@ void GenerateMetadataFile(const FileDescriptor* file, const Options& options, GenerateHead(file, &printer); TProtoStringType fullname = FilenameToClassname(filename); - int lastindex = fullname.find_last_of("\\"); + int lastindex = fullname.find_last_of('\\'); if (lastindex != TProtoStringType::npos) { printer.Print( @@ -1307,7 +1248,7 @@ void LegacyGenerateClassFile(const FileDescriptor* file, Outdent(&printer); printer.Print("}\n"); printer.Print("class_exists(^new^::class);\n", - "new", GeneratedClassNameImpl(desc)); + "new", GeneratedClassName(desc)); printer.Print("@trigger_error('^old^ is deprecated and will be removed in " "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n", "old", LegacyFullClassName(desc, options), @@ -1318,27 +1259,39 @@ template <typename DescriptorType> void LegacyReadOnlyGenerateClassFile(const FileDescriptor* file, const DescriptorType* desc, const Options& options, GeneratorContext* generator_context) { - TProtoStringType filename = LegacyReadOnlyGeneratedClassFileName(desc, options); + TProtoStringType fullname = FullClassName(desc, options); + TProtoStringType php_namespace; + TProtoStringType classname; + int lastindex = fullname.find_last_of("\\"); + + if (lastindex != TProtoStringType::npos) { + php_namespace = fullname.substr(0, lastindex); + classname = fullname.substr(lastindex + 1); + } else { + php_namespace = ""; + classname = fullname; + } + + TProtoStringType filename = LegacyReadOnlyGeneratedClassFileName(php_namespace, desc); std::unique_ptr<io::ZeroCopyOutputStream> output( generator_context->Open(filename)); io::Printer printer(output.get(), '^'); GenerateHead(file, &printer); - TProtoStringType php_namespace = RootPhpNamespace(desc, options); if (!php_namespace.empty()) { printer.Print( "namespace ^name^;\n\n", "name", php_namespace); } - TProtoStringType newname = FullClassName(desc, options); + printer.Print("class_exists(^new^::class); // autoload the new class, which " "will also create an alias to the deprecated class\n", - "new", GeneratedClassNameImpl(desc)); + "new", classname); printer.Print("@trigger_error(__NAMESPACE__ . '\\^old^ is deprecated and will be removed in " "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n", "old", desc->name(), - "fullname", newname); + "fullname", classname); } void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, @@ -1352,7 +1305,7 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, GenerateHead(file, &printer); TProtoStringType fullname = FilenameToClassname(filename); - int lastindex = fullname.find_last_of("\\"); + int lastindex = fullname.find_last_of('\\'); if (lastindex != TProtoStringType::npos) { printer.Print( @@ -1452,7 +1405,7 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, Outdent(&printer); printer.Print("}\n\n"); - // write legacy file for backwards compatibility with nested messages and enums + // write legacy alias for backwards compatibility with nested messages and enums if (en->containing_type() != NULL) { printer.Print( "// Adding a class alias for backwards compatibility with the previous class name.\n"); @@ -1460,7 +1413,6 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en, "class_alias(^new^::class, \\^old^::class);\n\n", "new", fullname, "old", LegacyFullClassName(en, options)); - LegacyGenerateClassFile(file, en, options, generator_context); } // Write legacy file for backwards compatibility with "readonly" keywword @@ -1494,7 +1446,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, GenerateHead(file, &printer); TProtoStringType fullname = FilenameToClassname(filename); - int lastindex = fullname.find_last_of("\\"); + int lastindex = fullname.find_last_of('\\'); if (lastindex != TProtoStringType::npos) { printer.Print( @@ -1580,7 +1532,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, Outdent(&printer); printer.Print("}\n\n"); - // write legacy file for backwards compatibility with nested messages and enums + // write legacy alias for backwards compatibility with nested messages and enums if (message->containing_type() != NULL) { printer.Print( "// Adding a class alias for backwards compatibility with the previous class name.\n"); @@ -1588,7 +1540,6 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message, "class_alias(^new^::class, \\^old^::class);\n\n", "new", fullname, "old", LegacyFullClassName(message, options)); - LegacyGenerateClassFile(file, message, options, generator_context); } // Write legacy file for backwards compatibility with "readonly" keywword @@ -1625,7 +1576,7 @@ void GenerateServiceFile( GenerateHead(file, &printer); TProtoStringType fullname = FilenameToClassname(filename); - int lastindex = fullname.find_last_of("\\"); + int lastindex = fullname.find_last_of('\\'); if (!file->options().php_namespace().empty() || (!file->options().has_php_namespace() && !file->package().empty()) || @@ -1679,7 +1630,7 @@ void GenerateFile(const FileDescriptor* file, const Options& options, } } -static TProtoStringType EscapePhpdoc(const TProtoStringType& input) { +static TProtoStringType EscapePhpdoc(y_absl::string_view input) { TProtoStringType result; result.reserve(input.size() * 2); @@ -1736,7 +1687,8 @@ static void GenerateDocCommentBodyForLocation( // HTML-escape them so that they don't accidentally close the doc comment. comments = EscapePhpdoc(comments); - std::vector<TProtoStringType> lines = Split(comments, "\n", true); + std::vector<y_absl::string_view> lines = + y_absl::StrSplit(comments, '\n', y_absl::SkipEmpty()); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } @@ -1767,8 +1719,8 @@ static void GenerateDocCommentBody( } } -static TProtoStringType FirstLineOf(const TProtoStringType& value) { - TProtoStringType result = value; +static TProtoStringType FirstLineOf(y_absl::string_view value) { + TProtoStringType result(value); TProtoStringType::size_type pos = result.find_first_of('\n'); if (pos != TProtoStringType::npos) { @@ -1935,17 +1887,13 @@ void GenerateServiceMethodDocComment(io::Printer* printer, } TProtoStringType FilenameCName(const FileDescriptor* file) { - TProtoStringType c_name = file->name(); - c_name = StringReplace(c_name, ".", "_", true); - c_name = StringReplace(c_name, "/", "_", true); - return c_name; + return y_absl::StrReplaceAll(file->name(), {{".", "_"}, {"/", "_"}}); } void GenerateCEnum(const EnumDescriptor* desc, io::Printer* printer) { - TProtoStringType c_name = desc->full_name(); - c_name = StringReplace(c_name, ".", "_", true); - TProtoStringType php_name = FullClassName(desc, Options()); - php_name = StringReplace(php_name, "\\", "\\\\", true); + TProtoStringType c_name = y_absl::StrReplaceAll(desc->full_name(), {{".", "_"}}); + TProtoStringType php_name = + y_absl::StrReplaceAll(FullClassName(desc, Options()), {{"\\", "\\\\"}}); printer->Print( "/* $c_name$ */\n" "\n" @@ -2028,10 +1976,9 @@ void GenerateCEnum(const EnumDescriptor* desc, io::Printer* printer) { } void GenerateCMessage(const Descriptor* message, io::Printer* printer) { - TProtoStringType c_name = message->full_name(); - c_name = StringReplace(c_name, ".", "_", true); - TProtoStringType php_name = FullClassName(message, Options()); - php_name = StringReplace(php_name, "\\", "\\\\", true); + TProtoStringType c_name = y_absl::StrReplaceAll(message->full_name(), {{".", "_"}}); + TProtoStringType php_name = + y_absl::StrReplaceAll(FullClassName(message, Options()), {{"\\", "\\\\"}}); printer->Print( "/* $c_name$ */\n" "\n" @@ -2181,8 +2128,7 @@ void GenerateCMessage(const Descriptor* message, io::Printer* printer) { } void GenerateEnumCInit(const EnumDescriptor* desc, io::Printer* printer) { - TProtoStringType c_name = desc->full_name(); - c_name = StringReplace(c_name, ".", "_", true); + TProtoStringType c_name = y_absl::StrReplaceAll(desc->full_name(), {{".", "_"}}); printer->Print( " $c_name$_ModuleInit();\n", @@ -2190,8 +2136,7 @@ void GenerateEnumCInit(const EnumDescriptor* desc, io::Printer* printer) { } void GenerateCInit(const Descriptor* message, io::Printer* printer) { - TProtoStringType c_name = message->full_name(); - c_name = StringReplace(c_name, ".", "_", true); + TProtoStringType c_name = y_absl::StrReplaceAll(message->full_name(), {{".", "_"}}); printer->Print( " $c_name$_ModuleInit();\n", @@ -2233,8 +2178,9 @@ void GenerateCWellKnownTypes(const std::vector<const FileDescriptor*>& files, TProtoStringType metadata_filename = GeneratedMetadataFileName(file, Options()); TProtoStringType metadata_classname = FilenameToClassname(metadata_filename); TProtoStringType metadata_c_name = - StringReplace(metadata_classname, "\\", "_", true); - metadata_classname = StringReplace(metadata_classname, "\\", "\\\\", true); + y_absl::StrReplaceAll(metadata_classname, {{"\\", "_"}}); + metadata_classname = + y_absl::StrReplaceAll(metadata_classname, {{"\\", "\\\\"}}); FileDescriptorProto file_proto; file->CopyTo(&file_proto); TProtoStringType serialized; @@ -2252,7 +2198,7 @@ void GenerateCWellKnownTypes(const std::vector<const FileDescriptor*>& files, for (size_t i = 0; i < serialized.size();) { for (size_t j = 0; j < 25 && i < serialized.size(); ++i, ++j) { - printer.Print("'$ch$', ", "ch", CEscape(serialized.substr(i, 1))); + printer.Print("'$ch$', ", "ch", y_absl::CEscape(serialized.substr(i, 1))); } printer.Print("\n"); } @@ -2315,7 +2261,7 @@ void GenerateCWellKnownTypes(const std::vector<const FileDescriptor*>& files, TProtoStringType metadata_filename = GeneratedMetadataFileName(file, Options()); TProtoStringType metadata_classname = FilenameToClassname(metadata_filename); TProtoStringType metadata_c_name = - StringReplace(metadata_classname, "\\", "_", true); + y_absl::StrReplaceAll(metadata_classname, {{"\\", "_"}}); printer.Print( " $metadata_c_name$_ModuleInit();\n", "metadata_c_name", metadata_c_name); @@ -2333,18 +2279,6 @@ void GenerateCWellKnownTypes(const std::vector<const FileDescriptor*>& files, } // namespace -TProtoStringType GeneratedClassName(const Descriptor* desc) { - return GeneratedClassNameImpl(desc); -} - -TProtoStringType GeneratedClassName(const EnumDescriptor* desc) { - return GeneratedClassNameImpl(desc); -} - -TProtoStringType GeneratedClassName(const ServiceDescriptor* desc) { - return GeneratedClassNameImpl(desc); -} - bool Generator::Generate(const FileDescriptor* file, const TProtoStringType& parameter, GeneratorContext* generator_context, @@ -2379,20 +2313,20 @@ bool Generator::GenerateAll(const std::vector<const FileDescriptor*>& files, TProtoStringType* error) const { Options options; - for (const auto& option : Split(parameter, ",", true)) { - const std::vector<TProtoStringType> option_pair = Split(option, "=", true); - if (HasPrefixString(option_pair[0], "aggregate_metadata")) { + for (const auto& option : y_absl::StrSplit(parameter, ",", y_absl::SkipEmpty())) { + const std::vector<TProtoStringType> option_pair = y_absl::StrSplit(option, "=", y_absl::SkipEmpty()); + if (y_absl::StartsWith(option_pair[0], "aggregate_metadata")) { options.aggregate_metadata = true; - for (const auto& prefix : Split(option_pair[1], "#", false)) { + for (const auto& prefix : y_absl::StrSplit(option_pair[1], "#", y_absl::AllowEmpty())) { options.aggregate_metadata_prefixes.emplace(prefix); - GOOGLE_LOG(INFO) << prefix; + Y_ABSL_LOG(INFO) << prefix; } } else if (option_pair[0] == "internal") { options.is_descriptor = true; } else if (option_pair[0] == "internal_generate_c_wkt") { GenerateCWellKnownTypes(files, generator_context); } else { - GOOGLE_LOG(FATAL) << "Unknown codegen option: " << option_pair[0]; + Y_ABSL_LOG(FATAL) << "Unknown codegen option: " << option_pair[0]; } } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/php/php_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/php/php_generator.h index 0247afaa560..66fa0034f58 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/php/php_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/php/php_generator.h @@ -31,12 +31,13 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__ #define GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__ -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/compiler/php/names.h" +#include "google/protobuf/descriptor.h" #include <string> -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -70,13 +71,6 @@ class PROTOC_EXPORT Generator : public CodeGenerator { TProtoStringType* error) const; }; -// To skip reserved keywords in php, some generated classname are prefixed. -// Other code generators may need following API to figure out the actual -// classname. -PROTOC_EXPORT TProtoStringType GeneratedClassName(const Descriptor* desc); -PROTOC_EXPORT TProtoStringType GeneratedClassName(const EnumDescriptor* desc); -PROTOC_EXPORT TProtoStringType GeneratedClassName(const ServiceDescriptor* desc); - inline bool IsWrapperType(const FieldDescriptor* descriptor) { return descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto"; @@ -87,6 +81,6 @@ inline bool IsWrapperType(const FieldDescriptor* descriptor) { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/plugin.cc b/contrib/libs/protoc/src/google/protobuf/compiler/plugin.cc index 68e23498c1d..b1dfde1088f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/plugin.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/plugin.cc @@ -30,25 +30,21 @@ // Author: [email protected] (Kenton Varda) -#include <google/protobuf/compiler/plugin.h> +#include "google/protobuf/compiler/plugin.h" #include <iostream> -#include <set> - #ifdef _WIN32 #include <fcntl.h> #else #include <unistd.h> #endif -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/compiler/plugin.pb.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/io_win32.h> -#include <google/protobuf/io/zero_copy_stream_impl.h> +#include "google/protobuf/compiler/plugin.pb.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/io_win32.h" +#include "google/protobuf/io/zero_copy_stream_impl.h" namespace google { @@ -128,10 +124,10 @@ bool GenerateCode(const CodeGeneratorRequest& request, for (int i = 0; i < request.file_to_generate_size(); i++) { parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i))); if (parsed_files.back() == nullptr) { - *error_msg = + *error_msg = y_absl::StrCat( "protoc asked plugin to generate a file but " - "did not provide a descriptor for the file: " + - request.file_to_generate(i); + "did not provide a descriptor for the file: ", + request.file_to_generate(i)); return false; } } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/plugin.h b/contrib/libs/protoc/src/google/protobuf/compiler/plugin.h index 65af26e0f74..516fbedcece 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/plugin.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/plugin.h @@ -66,7 +66,7 @@ #include <google/protobuf/stubs/port.h> // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -92,6 +92,6 @@ bool GenerateCode(const CodeGeneratorRequest& request, } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/plugin.pb.cc b/contrib/libs/protoc/src/google/protobuf/compiler/plugin.pb.cc index 55fa2a69812..b43ab534898 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/plugin.pb.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/plugin.pb.cc @@ -1,210 +1,266 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/compiler/plugin.proto -#include <google/protobuf/compiler/plugin.pb.h> +#include "google/protobuf/compiler/plugin.pb.h" #include <algorithm> - -#include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/extension_set.h> -#include <google/protobuf/wire_format_lite.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> +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/extension_set.h" +#include "google/protobuf/wire_format_lite.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" // @@protoc_insertion_point(includes) -#include <google/protobuf/port_def.inc> +// Must be included last. +#include "google/protobuf/port_def.inc" PROTOBUF_PRAGMA_INIT_SEG - namespace _pb = ::PROTOBUF_NAMESPACE_ID; -namespace _pbi = _pb::internal; - +namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal; PROTOBUF_NAMESPACE_OPEN namespace compiler { PROTOBUF_CONSTEXPR Version::Version( ::_pbi::ConstantInitialized): _impl_{ /*decltype(_impl_._has_bits_)*/{} , /*decltype(_impl_._cached_size_)*/{} - , /*decltype(_impl_.suffix_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} - , /*decltype(_impl_.major_)*/0 - , /*decltype(_impl_.minor_)*/0 - , /*decltype(_impl_.patch_)*/0} {} + , /*decltype(_impl_.suffix_)*/ { + &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {} + } + + , /*decltype(_impl_.major_)*/ 0 + + , /*decltype(_impl_.minor_)*/ 0 + + , /*decltype(_impl_.patch_)*/ 0 +} {} struct VersionDefaultTypeInternal { - PROTOBUF_CONSTEXPR VersionDefaultTypeInternal() - : _instance(::_pbi::ConstantInitialized{}) {} + PROTOBUF_CONSTEXPR VersionDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~VersionDefaultTypeInternal() {} union { Version _instance; }; }; -PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 VersionDefaultTypeInternal _Version_default_instance_; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 VersionDefaultTypeInternal _Version_default_instance_; PROTOBUF_CONSTEXPR CodeGeneratorRequest::CodeGeneratorRequest( ::_pbi::ConstantInitialized): _impl_{ /*decltype(_impl_._has_bits_)*/{} , /*decltype(_impl_._cached_size_)*/{} , /*decltype(_impl_.file_to_generate_)*/{} , /*decltype(_impl_.proto_file_)*/{} - , /*decltype(_impl_.parameter_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.parameter_)*/ { + &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {} + } + , /*decltype(_impl_.compiler_version_)*/nullptr} {} struct CodeGeneratorRequestDefaultTypeInternal { - PROTOBUF_CONSTEXPR CodeGeneratorRequestDefaultTypeInternal() - : _instance(::_pbi::ConstantInitialized{}) {} + PROTOBUF_CONSTEXPR CodeGeneratorRequestDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~CodeGeneratorRequestDefaultTypeInternal() {} union { CodeGeneratorRequest _instance; }; }; -PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_; PROTOBUF_CONSTEXPR CodeGeneratorResponse_File::CodeGeneratorResponse_File( ::_pbi::ConstantInitialized): _impl_{ /*decltype(_impl_._has_bits_)*/{} , /*decltype(_impl_._cached_size_)*/{} - , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} - , /*decltype(_impl_.insertion_point_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} - , /*decltype(_impl_.content_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.name_)*/ { + &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {} + } + + , /*decltype(_impl_.insertion_point_)*/ { + &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {} + } + + , /*decltype(_impl_.content_)*/ { + &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {} + } + , /*decltype(_impl_.generated_code_info_)*/nullptr} {} struct CodeGeneratorResponse_FileDefaultTypeInternal { - PROTOBUF_CONSTEXPR CodeGeneratorResponse_FileDefaultTypeInternal() - : _instance(::_pbi::ConstantInitialized{}) {} + PROTOBUF_CONSTEXPR CodeGeneratorResponse_FileDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~CodeGeneratorResponse_FileDefaultTypeInternal() {} union { CodeGeneratorResponse_File _instance; }; }; -PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_; PROTOBUF_CONSTEXPR CodeGeneratorResponse::CodeGeneratorResponse( ::_pbi::ConstantInitialized): _impl_{ /*decltype(_impl_._has_bits_)*/{} , /*decltype(_impl_._cached_size_)*/{} , /*decltype(_impl_.file_)*/{} - , /*decltype(_impl_.error_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} - , /*decltype(_impl_.supported_features_)*/arc_ui64{0u}} {} + , /*decltype(_impl_.error_)*/ { + &::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized {} + } + + , /*decltype(_impl_.supported_features_)*/ ::arc_ui64{0u} +} {} struct CodeGeneratorResponseDefaultTypeInternal { - PROTOBUF_CONSTEXPR CodeGeneratorResponseDefaultTypeInternal() - : _instance(::_pbi::ConstantInitialized{}) {} + PROTOBUF_CONSTEXPR CodeGeneratorResponseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {} ~CodeGeneratorResponseDefaultTypeInternal() {} union { CodeGeneratorResponse _instance; }; }; -PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_; + +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT + PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_; } // namespace compiler PROTOBUF_NAMESPACE_CLOSE static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[4]; static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1]; -static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr; - -const arc_ui32 TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.major_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.minor_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.patch_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.suffix_), - 1, - 2, - 3, - 0, - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.file_to_generate_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.parameter_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.proto_file_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.compiler_version_), - ~0u, - 0, - ~0u, - 1, - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.name_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.insertion_point_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.content_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.generated_code_info_), - 0, - 1, - 2, - 3, - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.error_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.supported_features_), - PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.file_), - 0, - 1, - ~0u, +static constexpr const ::_pb::ServiceDescriptor** + file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr; +const ::arc_ui32 TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE( + protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.major_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.minor_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.patch_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.suffix_), + 1, + 2, + 3, + 0, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.file_to_generate_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.parameter_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.proto_file_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.compiler_version_), + ~0u, + 0, + ~0u, + 1, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.name_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.insertion_point_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.content_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.generated_code_info_), + 0, + 1, + 2, + 3, + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.error_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.supported_features_), + PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.file_), + 0, + 1, + ~0u, }; -static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { - { 0, 10, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::Version)}, - { 14, 24, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest)}, - { 28, 38, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File)}, - { 42, 51, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse)}, + +static const ::_pbi::MigrationSchema + schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, 12, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::Version)}, + { 16, 28, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest)}, + { 32, 44, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File)}, + { 48, 59, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse)}, }; static const ::_pb::Message* const file_default_instances[] = { - &::PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_._instance, - &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_._instance, - &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_File_default_instance_._instance, - &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_File_default_instance_._instance, + &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_default_instance_._instance, }; - -const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto[] PROTOBUF_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" - "\"\301\002\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001(" - "\t\022\032\n\022supported_features\030\002 \001(\004\022B\n\004file\030\017 " - "\003(\01324.google.protobuf.compiler.CodeGener" - "atorResponse.File\032\177\n\004File\022\014\n\004name\030\001 \001(\t\022" - "\027\n\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(" - "\t\022\?\n\023generated_code_info\030\020 \001(\0132\".google." - "protobuf.GeneratedCodeInfo\"8\n\007Feature\022\020\n" - "\014FEATURE_NONE\020\000\022\033\n\027FEATURE_PROTO3_OPTION" - "AL\020\001BW\n\034com.google.protobuf.compilerB\014Pl" - "uginProtosZ)google.golang.org/protobuf/t" - "ypes/pluginpb" - ; -static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = { - &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, +const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto[] PROTOBUF_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" + "\"\301\002\n\025CodeGeneratorResponse\022\r\n\005error\030\001 \001(" + "\t\022\032\n\022supported_features\030\002 \001(\004\022B\n\004file\030\017 " + "\003(\01324.google.protobuf.compiler.CodeGener" + "atorResponse.File\032\177\n\004File\022\014\n\004name\030\001 \001(\t\022" + "\027\n\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(" + "\t\022\?\n\023generated_code_info\030\020 \001(\0132\".google." + "protobuf.GeneratedCodeInfo\"8\n\007Feature\022\020\n" + "\014FEATURE_NONE\020\000\022\033\n\027FEATURE_PROTO3_OPTION" + "AL\020\001Br\n\034com.google.protobuf.compilerB\014Pl" + "uginProtosZ)google.golang.org/protobuf/t" + "ypes/pluginpb\252\002\030Google.Protobuf.Compiler" +}; +static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = + { + &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, }; -static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once; +static ::y_absl::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once; const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto = { - false, false, 773, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, + false, + false, + 800, + descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto, "google/protobuf/compiler/plugin.proto", - &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps, 1, 4, - schemas, file_default_instances, TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets, - file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, + &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, + descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps, + 1, + 4, + schemas, + file_default_instances, + TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets, + file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, + file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, }; + +// This function exists to be marked as weak. +// It can significantly speed up compilation by breaking up LLVM's SCC +// in the .pb.cc translation units. Large translation units see a +// reduction of more than 35% of walltime for optimized builds. Without +// the weak attribute all the messages in the file, including all the +// vtables and everything they use become part of the same SCC through +// a cycle like: +// GetMetadata -> descriptor table -> default instances -> +// vtables -> GetMetadata +// By adding a weak function here we break the connection from the +// individual vtables back into the descriptor table. PROTOBUF_ATTRIBUTE_WEAK const ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter() { return &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto; } - // Force running AddDescriptors() at dynamic initialization time. -PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fcompiler_2fplugin_2eproto(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto); +PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 +static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fcompiler_2fplugin_2eproto(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto); PROTOBUF_NAMESPACE_OPEN namespace compiler { const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* CodeGeneratorResponse_Feature_descriptor() { @@ -220,20 +276,24 @@ bool CodeGeneratorResponse_Feature_IsValid(int value) { return false; } } +#if (__cplusplus < 201703) && \ + (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) -#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_NONE; constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL; constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::Feature_MIN; constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::Feature_MAX; constexpr int CodeGeneratorResponse::Feature_ARRAYSIZE; -#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +#endif // (__cplusplus < 201703) && + // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) // =================================================================== class Version::_Internal { public: using HasBits = decltype(std::declval<Version>()._impl_._has_bits_); + static constexpr ::arc_i32 kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(Version, _impl_._has_bits_); static void set_has_major(HasBits* has_bits) { (*has_bits)[0] |= 2u; } @@ -248,10 +308,9 @@ class Version::_Internal { } }; -Version::Version(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned) - : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { - SharedCtor(arena, is_message_owned); +Version::Version(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.Version) } Version::Version(const Version& from) @@ -260,42 +319,47 @@ Version::Version(const Version& from) new (&_impl_) Impl_{ decltype(_impl_._has_bits_){from._impl_._has_bits_} , /*decltype(_impl_._cached_size_)*/{} - , decltype(_impl_.suffix_){} - , decltype(_impl_.major_){} - , decltype(_impl_.minor_){} - , decltype(_impl_.patch_){}}; + , decltype(_impl_.suffix_) {} + + , decltype(_impl_.major_) {} + + , decltype(_impl_.minor_) {} + + , decltype(_impl_.patch_) {} + }; _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _impl_.suffix_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.suffix_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (from._internal_has_suffix()) { - _this->_impl_.suffix_.Set(from._internal_suffix(), - _this->GetArenaForAllocation()); + _impl_.suffix_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) { + _this->_impl_.suffix_.Set(from._internal_suffix(), _this->GetArenaForAllocation()); } ::memcpy(&_impl_.major_, &from._impl_.major_, - static_cast<size_t>(reinterpret_cast<char*>(&_impl_.patch_) - + static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.patch_) - reinterpret_cast<char*>(&_impl_.major_)) + sizeof(_impl_.patch_)); // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.Version) } -inline void Version::SharedCtor( - ::_pb::Arena* arena, bool is_message_owned) { +inline void Version::SharedCtor(::_pb::Arena* arena) { (void)arena; - (void)is_message_owned; new (&_impl_) Impl_{ decltype(_impl_._has_bits_){} , /*decltype(_impl_._cached_size_)*/{} - , decltype(_impl_.suffix_){} - , decltype(_impl_.major_){0} - , decltype(_impl_.minor_){0} - , decltype(_impl_.patch_){0} + , decltype(_impl_.suffix_) {} + + , decltype(_impl_.major_) { 0 } + + , decltype(_impl_.minor_) { 0 } + + , decltype(_impl_.patch_) { 0 } + }; _impl_.suffix_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.suffix_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.suffix_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING } Version::~Version() { @@ -308,7 +372,7 @@ Version::~Version() { } inline void Version::SharedDtor() { - GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + Y_ABSL_DCHECK(GetArenaForAllocation() == nullptr); _impl_.suffix_.Destroy(); } @@ -318,7 +382,7 @@ void Version::SetCachedSize(int size) const { void Version::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version) - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -327,7 +391,7 @@ void Version::Clear() { _impl_.suffix_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x0000000eu) { - ::memset(&_impl_.major_, 0, static_cast<size_t>( + ::memset(&_impl_.major_, 0, static_cast<::size_t>( reinterpret_cast<char*>(&_impl_.patch_) - reinterpret_cast<char*>(&_impl_.major_)) + sizeof(_impl_.patch_)); } @@ -339,47 +403,51 @@ const char* Version::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure _Internal::HasBits has_bits{}; while (!ctx->Done(&ptr)) { - arc_ui32 tag; + ::arc_ui32 tag; ptr = ::_pbi::ReadTag(ptr, &tag); switch (tag >> 3) { // optional int32 major = 1; case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) { _Internal::set_has_major(&has_bits); _impl_.major_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); CHK_(ptr); - } else + } else { goto handle_unusual; + } continue; // optional int32 minor = 2; case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) { _Internal::set_has_minor(&has_bits); _impl_.minor_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); CHK_(ptr); - } else + } else { goto handle_unusual; + } continue; // optional int32 patch = 3; case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 24)) { _Internal::set_has_patch(&has_bits); _impl_.patch_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); CHK_(ptr); - } else + } else { goto handle_unusual; + } continue; // optional string suffix = 4; case 4: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) { auto str = _internal_mutable_suffix(); ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); CHK_(ptr); #ifndef NDEBUG ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.Version.suffix"); #endif // !NDEBUG - } else + } else { goto handle_unusual; + } continue; default: goto handle_unusual; @@ -405,39 +473,40 @@ failure: #undef CHK_ } -uint8_t* Version::_InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { +::uint8_t* Version::_InternalSerialize( + ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.Version) - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _impl_._has_bits_[0]; // optional int32 major = 1; if (cached_has_bits & 0x00000002u) { target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteInt32ToArray(1, this->_internal_major(), target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 1, this->_internal_major(), target); } // optional int32 minor = 2; if (cached_has_bits & 0x00000004u) { target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteInt32ToArray(2, this->_internal_minor(), target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 2, this->_internal_minor(), target); } // optional int32 patch = 3; if (cached_has_bits & 0x00000008u) { target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteInt32ToArray(3, this->_internal_patch(), target); + target = ::_pbi::WireFormatLite::WriteInt32ToArray( + 3, this->_internal_patch(), target); } // optional string suffix = 4; if (cached_has_bits & 0x00000001u) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( - this->_internal_suffix().data(), static_cast<int>(this->_internal_suffix().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.Version.suffix"); - target = stream->WriteStringMaybeAliased( - 4, this->_internal_suffix(), target); + const TProtoStringType& _s = this->_internal_suffix(); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast<int>(_s.length()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.Version.suffix"); + target = stream->WriteStringMaybeAliased(4, _s, target); } if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { @@ -448,11 +517,11 @@ uint8_t* Version::_InternalSerialize( return target; } -size_t Version::ByteSizeLong() const { +::size_t Version::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.Version) - size_t total_size = 0; + ::size_t total_size = 0; - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -460,24 +529,26 @@ size_t Version::ByteSizeLong() const { if (cached_has_bits & 0x0000000fu) { // optional string suffix = 4; if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_suffix()); + total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_suffix()); } // optional int32 major = 1; if (cached_has_bits & 0x00000002u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_major()); + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_major()); } // optional int32 minor = 2; if (cached_has_bits & 0x00000004u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_minor()); + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_minor()); } // optional int32 patch = 3; if (cached_has_bits & 0x00000008u) { - total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_patch()); + total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( + this->_internal_patch()); } } @@ -495,8 +566,8 @@ void Version::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOB auto* const _this = static_cast<Version*>(&to_msg); auto& from = static_cast<const Version&>(from_msg); // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.Version) - GOOGLE_DCHECK_NE(&from, _this); - arc_ui32 cached_has_bits = 0; + Y_ABSL_DCHECK_NE(&from, _this); + ::arc_ui32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._impl_._has_bits_[0]; @@ -535,10 +606,8 @@ void Version::InternalSwap(Version* other) { auto* rhs_arena = other->GetArenaForAllocation(); _internal_metadata_.InternalSwap(&other->_internal_metadata_); swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( - &_impl_.suffix_, lhs_arena, - &other->_impl_.suffix_, rhs_arena - ); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.suffix_, lhs_arena, + &other->_impl_.suffix_, rhs_arena); ::PROTOBUF_NAMESPACE_ID::internal::memswap< PROTOBUF_FIELD_OFFSET(Version, _impl_.patch_) + sizeof(Version::_impl_.patch_) @@ -552,12 +621,13 @@ void Version::InternalSwap(Version* other) { &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[0]); } - // =================================================================== class CodeGeneratorRequest::_Internal { public: using HasBits = decltype(std::declval<CodeGeneratorRequest>()._impl_._has_bits_); + static constexpr ::arc_i32 kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(CodeGeneratorRequest, _impl_._has_bits_); static void set_has_parameter(HasBits* has_bits) { (*has_bits)[0] |= 1u; } @@ -574,10 +644,9 @@ CodeGeneratorRequest::_Internal::compiler_version(const CodeGeneratorRequest* ms void CodeGeneratorRequest::clear_proto_file() { _impl_.proto_file_.Clear(); } -CodeGeneratorRequest::CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned) - : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { - SharedCtor(arena, is_message_owned); +CodeGeneratorRequest::CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorRequest) } CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from) @@ -588,40 +657,39 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from) , /*decltype(_impl_._cached_size_)*/{} , decltype(_impl_.file_to_generate_){from._impl_.file_to_generate_} , decltype(_impl_.proto_file_){from._impl_.proto_file_} - , decltype(_impl_.parameter_){} + , decltype(_impl_.parameter_) {} + , decltype(_impl_.compiler_version_){nullptr}}; _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _impl_.parameter_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.parameter_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (from._internal_has_parameter()) { - _this->_impl_.parameter_.Set(from._internal_parameter(), - _this->GetArenaForAllocation()); + _impl_.parameter_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) { + _this->_impl_.parameter_.Set(from._internal_parameter(), _this->GetArenaForAllocation()); } - if (from._internal_has_compiler_version()) { + if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) { _this->_impl_.compiler_version_ = new ::PROTOBUF_NAMESPACE_ID::compiler::Version(*from._impl_.compiler_version_); } // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest) } -inline void CodeGeneratorRequest::SharedCtor( - ::_pb::Arena* arena, bool is_message_owned) { +inline void CodeGeneratorRequest::SharedCtor(::_pb::Arena* arena) { (void)arena; - (void)is_message_owned; new (&_impl_) Impl_{ decltype(_impl_._has_bits_){} , /*decltype(_impl_._cached_size_)*/{} , decltype(_impl_.file_to_generate_){arena} , decltype(_impl_.proto_file_){arena} - , decltype(_impl_.parameter_){} + , decltype(_impl_.parameter_) {} + , decltype(_impl_.compiler_version_){nullptr} }; _impl_.parameter_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.parameter_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.parameter_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING } CodeGeneratorRequest::~CodeGeneratorRequest() { @@ -634,7 +702,7 @@ CodeGeneratorRequest::~CodeGeneratorRequest() { } inline void CodeGeneratorRequest::SharedDtor() { - GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + Y_ABSL_DCHECK(GetArenaForAllocation() == nullptr); _impl_.file_to_generate_.~RepeatedPtrField(); _impl_.proto_file_.~RepeatedPtrField(); _impl_.parameter_.Destroy(); @@ -647,7 +715,7 @@ void CodeGeneratorRequest::SetCachedSize(int size) const { void CodeGeneratorRequest::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest) - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -659,7 +727,7 @@ void CodeGeneratorRequest::Clear() { _impl_.parameter_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000002u) { - GOOGLE_DCHECK(_impl_.compiler_version_ != nullptr); + Y_ABSL_DCHECK(_impl_.compiler_version_ != nullptr); _impl_.compiler_version_->Clear(); } } @@ -671,12 +739,12 @@ const char* CodeGeneratorRequest::_InternalParse(const char* ptr, ::_pbi::ParseC #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure _Internal::HasBits has_bits{}; while (!ctx->Done(&ptr)) { - arc_ui32 tag; + ::arc_ui32 tag; ptr = ::_pbi::ReadTag(ptr, &tag); switch (tag >> 3) { // repeated string file_to_generate = 1; case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) { ptr -= 1; do { ptr += 1; @@ -688,32 +756,35 @@ const char* CodeGeneratorRequest::_InternalParse(const char* ptr, ::_pbi::ParseC #endif // !NDEBUG if (!ctx->DataAvailable(ptr)) break; } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); - } else + } else { goto handle_unusual; + } continue; // optional string parameter = 2; case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) { auto str = _internal_mutable_parameter(); ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); CHK_(ptr); #ifndef NDEBUG ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorRequest.parameter"); #endif // !NDEBUG - } else + } else { goto handle_unusual; + } continue; // optional .google.protobuf.compiler.Version compiler_version = 3; case 3: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) { ptr = ctx->ParseMessage(_internal_mutable_compiler_version(), ptr); CHK_(ptr); - } else + } else { goto handle_unusual; + } continue; // repeated .google.protobuf.FileDescriptorProto proto_file = 15; case 15: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 122)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 122)) { ptr -= 1; do { ptr += 1; @@ -721,8 +792,9 @@ const char* CodeGeneratorRequest::_InternalParse(const char* ptr, ::_pbi::ParseC CHK_(ptr); if (!ctx->DataAvailable(ptr)) break; } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<122>(ptr)); - } else + } else { goto handle_unusual; + } continue; default: goto handle_unusual; @@ -748,31 +820,27 @@ failure: #undef CHK_ } -uint8_t* CodeGeneratorRequest::_InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { +::uint8_t* CodeGeneratorRequest::_InternalSerialize( + ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest) - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; (void) cached_has_bits; // repeated string file_to_generate = 1; - for (int i = 0, n = this->_internal_file_to_generate_size(); i < n; i++) { + for (int i = 0, n = this->_internal_file_to_generate_size(); i < n; ++i) { const auto& s = this->_internal_file_to_generate(i); - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( - s.data(), static_cast<int>(s.length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate"); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(s.data(), static_cast<int>(s.length()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate"); target = stream->WriteString(1, s, target); } cached_has_bits = _impl_._has_bits_[0]; // optional string parameter = 2; if (cached_has_bits & 0x00000001u) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( - this->_internal_parameter().data(), static_cast<int>(this->_internal_parameter().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorRequest.parameter"); - target = stream->WriteStringMaybeAliased( - 2, this->_internal_parameter(), target); + const TProtoStringType& _s = this->_internal_parameter(); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast<int>(_s.length()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorRequest.parameter"); + target = stream->WriteStringMaybeAliased(2, _s, target); } // optional .google.protobuf.compiler.Version compiler_version = 3; @@ -798,20 +866,18 @@ uint8_t* CodeGeneratorRequest::_InternalSerialize( return target; } -size_t CodeGeneratorRequest::ByteSizeLong() const { +::size_t CodeGeneratorRequest::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest) - size_t total_size = 0; + ::size_t total_size = 0; - arc_ui32 cached_has_bits = 0; + ::arc_ui32 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 * - ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(_impl_.file_to_generate_.size()); - for (int i = 0, n = _impl_.file_to_generate_.size(); i < n; i++) { - total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - _impl_.file_to_generate_.Get(i)); + total_size += 1 * ::PROTOBUF_NAMESPACE_ID::internal::FromIntSize(_impl_.file_to_generate_.size()); + for (int i = 0, n = _impl_.file_to_generate_.size(); i < n; ++i) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(_impl_.file_to_generate_.Get(i)); } // repeated .google.protobuf.FileDescriptorProto proto_file = 15; @@ -825,9 +891,8 @@ size_t CodeGeneratorRequest::ByteSizeLong() const { if (cached_has_bits & 0x00000003u) { // optional string parameter = 2; if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_parameter()); + total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_parameter()); } // optional .google.protobuf.compiler.Version compiler_version = 3; @@ -852,8 +917,8 @@ void CodeGeneratorRequest::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, c auto* const _this = static_cast<CodeGeneratorRequest*>(&to_msg); auto& from = static_cast<const CodeGeneratorRequest&>(from_msg); // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest) - GOOGLE_DCHECK_NE(&from, _this); - arc_ui32 cached_has_bits = 0; + Y_ABSL_DCHECK_NE(&from, _this); + ::arc_ui32 cached_has_bits = 0; (void) cached_has_bits; _this->_impl_.file_to_generate_.MergeFrom(from._impl_.file_to_generate_); @@ -892,10 +957,8 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) { swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); _impl_.file_to_generate_.InternalSwap(&other->_impl_.file_to_generate_); _impl_.proto_file_.InternalSwap(&other->_impl_.proto_file_); - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( - &_impl_.parameter_, lhs_arena, - &other->_impl_.parameter_, rhs_arena - ); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.parameter_, lhs_arena, + &other->_impl_.parameter_, rhs_arena); swap(_impl_.compiler_version_, other->_impl_.compiler_version_); } @@ -904,12 +967,13 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) { &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1]); } - // =================================================================== class CodeGeneratorResponse_File::_Internal { public: using HasBits = decltype(std::declval<CodeGeneratorResponse_File>()._impl_._has_bits_); + static constexpr ::arc_i32 kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse_File, _impl_._has_bits_); static void set_has_name(HasBits* has_bits) { (*has_bits)[0] |= 1u; } @@ -933,10 +997,9 @@ void CodeGeneratorResponse_File::clear_generated_code_info() { if (_impl_.generated_code_info_ != nullptr) _impl_.generated_code_info_->Clear(); _impl_._has_bits_[0] &= ~0x00000008u; } -CodeGeneratorResponse_File::CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned) - : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { - SharedCtor(arena, is_message_owned); +CodeGeneratorResponse_File::CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from) @@ -945,66 +1008,67 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon new (&_impl_) Impl_{ decltype(_impl_._has_bits_){from._impl_._has_bits_} , /*decltype(_impl_._cached_size_)*/{} - , decltype(_impl_.name_){} - , decltype(_impl_.insertion_point_){} - , decltype(_impl_.content_){} + , decltype(_impl_.name_) {} + + , decltype(_impl_.insertion_point_) {} + + , decltype(_impl_.content_) {} + , decltype(_impl_.generated_code_info_){nullptr}}; _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _impl_.name_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (from._internal_has_name()) { - _this->_impl_.name_.Set(from._internal_name(), - _this->GetArenaForAllocation()); + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) { + _this->_impl_.name_.Set(from._internal_name(), _this->GetArenaForAllocation()); } _impl_.insertion_point_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.insertion_point_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (from._internal_has_insertion_point()) { - _this->_impl_.insertion_point_.Set(from._internal_insertion_point(), - _this->GetArenaForAllocation()); + _impl_.insertion_point_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) { + _this->_impl_.insertion_point_.Set(from._internal_insertion_point(), _this->GetArenaForAllocation()); } _impl_.content_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.content_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (from._internal_has_content()) { - _this->_impl_.content_.Set(from._internal_content(), - _this->GetArenaForAllocation()); + _impl_.content_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if ((from._impl_._has_bits_[0] & 0x00000004u) != 0) { + _this->_impl_.content_.Set(from._internal_content(), _this->GetArenaForAllocation()); } - if (from._internal_has_generated_code_info()) { + if ((from._impl_._has_bits_[0] & 0x00000008u) != 0) { _this->_impl_.generated_code_info_ = new ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo(*from._impl_.generated_code_info_); } // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } -inline void CodeGeneratorResponse_File::SharedCtor( - ::_pb::Arena* arena, bool is_message_owned) { +inline void CodeGeneratorResponse_File::SharedCtor(::_pb::Arena* arena) { (void)arena; - (void)is_message_owned; new (&_impl_) Impl_{ decltype(_impl_._has_bits_){} , /*decltype(_impl_._cached_size_)*/{} - , decltype(_impl_.name_){} - , decltype(_impl_.insertion_point_){} - , decltype(_impl_.content_){} + , decltype(_impl_.name_) {} + + , decltype(_impl_.insertion_point_) {} + + , decltype(_impl_.content_) {} + , decltype(_impl_.generated_code_info_){nullptr} }; _impl_.name_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.name_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING _impl_.insertion_point_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.insertion_point_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.insertion_point_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING _impl_.content_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.content_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.content_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING } CodeGeneratorResponse_File::~CodeGeneratorResponse_File() { @@ -1017,7 +1081,7 @@ CodeGeneratorResponse_File::~CodeGeneratorResponse_File() { } inline void CodeGeneratorResponse_File::SharedDtor() { - GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + Y_ABSL_DCHECK(GetArenaForAllocation() == nullptr); _impl_.name_.Destroy(); _impl_.insertion_point_.Destroy(); _impl_.content_.Destroy(); @@ -1030,7 +1094,7 @@ void CodeGeneratorResponse_File::SetCachedSize(int size) const { void CodeGeneratorResponse_File::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File) - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -1046,7 +1110,7 @@ void CodeGeneratorResponse_File::Clear() { _impl_.content_.ClearNonDefaultToEmpty(); } if (cached_has_bits & 0x00000008u) { - GOOGLE_DCHECK(_impl_.generated_code_info_ != nullptr); + Y_ABSL_DCHECK(_impl_.generated_code_info_ != nullptr); _impl_.generated_code_info_->Clear(); } } @@ -1058,52 +1122,56 @@ const char* CodeGeneratorResponse_File::_InternalParse(const char* ptr, ::_pbi:: #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure _Internal::HasBits has_bits{}; while (!ctx->Done(&ptr)) { - arc_ui32 tag; + ::arc_ui32 tag; ptr = ::_pbi::ReadTag(ptr, &tag); switch (tag >> 3) { // optional string name = 1; case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) { auto str = _internal_mutable_name(); ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); CHK_(ptr); #ifndef NDEBUG ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.name"); #endif // !NDEBUG - } else + } else { goto handle_unusual; + } continue; // optional string insertion_point = 2; case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) { auto str = _internal_mutable_insertion_point(); ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); CHK_(ptr); #ifndef NDEBUG ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point"); #endif // !NDEBUG - } else + } else { goto handle_unusual; + } continue; // optional string content = 15; case 15: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 122)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 122)) { auto str = _internal_mutable_content(); ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); CHK_(ptr); #ifndef NDEBUG ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.content"); #endif // !NDEBUG - } else + } else { goto handle_unusual; + } continue; // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; case 16: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 130)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 130)) { ptr = ctx->ParseMessage(_internal_mutable_generated_code_info(), ptr); CHK_(ptr); - } else + } else { goto handle_unusual; + } continue; default: goto handle_unusual; @@ -1129,41 +1197,35 @@ failure: #undef CHK_ } -uint8_t* CodeGeneratorResponse_File::_InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { +::uint8_t* CodeGeneratorResponse_File::_InternalSerialize( + ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File) - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _impl_._has_bits_[0]; // optional string name = 1; if (cached_has_bits & 0x00000001u) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( - this->_internal_name().data(), static_cast<int>(this->_internal_name().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.File.name"); - target = stream->WriteStringMaybeAliased( - 1, this->_internal_name(), target); + const TProtoStringType& _s = this->_internal_name(); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast<int>(_s.length()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorResponse.File.name"); + target = stream->WriteStringMaybeAliased(1, _s, target); } // optional string insertion_point = 2; if (cached_has_bits & 0x00000002u) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( - this->_internal_insertion_point().data(), static_cast<int>(this->_internal_insertion_point().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point"); - target = stream->WriteStringMaybeAliased( - 2, this->_internal_insertion_point(), target); + const TProtoStringType& _s = this->_internal_insertion_point(); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast<int>(_s.length()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point"); + target = stream->WriteStringMaybeAliased(2, _s, target); } // optional string content = 15; if (cached_has_bits & 0x00000004u) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( - this->_internal_content().data(), static_cast<int>(this->_internal_content().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.File.content"); - target = stream->WriteStringMaybeAliased( - 15, this->_internal_content(), target); + const TProtoStringType& _s = this->_internal_content(); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast<int>(_s.length()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorResponse.File.content"); + target = stream->WriteStringMaybeAliased(15, _s, target); } // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; @@ -1181,11 +1243,11 @@ uint8_t* CodeGeneratorResponse_File::_InternalSerialize( return target; } -size_t CodeGeneratorResponse_File::ByteSizeLong() const { +::size_t CodeGeneratorResponse_File::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File) - size_t total_size = 0; + ::size_t total_size = 0; - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -1193,23 +1255,20 @@ size_t CodeGeneratorResponse_File::ByteSizeLong() const { if (cached_has_bits & 0x0000000fu) { // optional string name = 1; if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_name()); + total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); } // optional string insertion_point = 2; if (cached_has_bits & 0x00000002u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_insertion_point()); + total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_insertion_point()); } // optional string content = 15; if (cached_has_bits & 0x00000004u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_content()); + total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_content()); } // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; @@ -1234,8 +1293,8 @@ void CodeGeneratorResponse_File::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_ auto* const _this = static_cast<CodeGeneratorResponse_File*>(&to_msg); auto& from = static_cast<const CodeGeneratorResponse_File&>(from_msg); // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) - GOOGLE_DCHECK_NE(&from, _this); - arc_ui32 cached_has_bits = 0; + Y_ABSL_DCHECK_NE(&from, _this); + ::arc_ui32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = from._impl_._has_bits_[0]; @@ -1274,18 +1333,12 @@ void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) auto* rhs_arena = other->GetArenaForAllocation(); _internal_metadata_.InternalSwap(&other->_internal_metadata_); swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( - &_impl_.name_, lhs_arena, - &other->_impl_.name_, rhs_arena - ); - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( - &_impl_.insertion_point_, lhs_arena, - &other->_impl_.insertion_point_, rhs_arena - ); - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( - &_impl_.content_, lhs_arena, - &other->_impl_.content_, rhs_arena - ); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.name_, lhs_arena, + &other->_impl_.name_, rhs_arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.insertion_point_, lhs_arena, + &other->_impl_.insertion_point_, rhs_arena); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.content_, lhs_arena, + &other->_impl_.content_, rhs_arena); swap(_impl_.generated_code_info_, other->_impl_.generated_code_info_); } @@ -1294,12 +1347,13 @@ void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[2]); } - // =================================================================== class CodeGeneratorResponse::_Internal { public: using HasBits = decltype(std::declval<CodeGeneratorResponse>()._impl_._has_bits_); + static constexpr ::arc_i32 kHasBitsOffset = + 8 * PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_._has_bits_); static void set_has_error(HasBits* has_bits) { (*has_bits)[0] |= 1u; } @@ -1308,10 +1362,9 @@ class CodeGeneratorResponse::_Internal { } }; -CodeGeneratorResponse::CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned) - : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { - SharedCtor(arena, is_message_owned); +CodeGeneratorResponse::CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena) + : ::PROTOBUF_NAMESPACE_ID::Message(arena) { + SharedCtor(arena); // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse) } CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from) @@ -1321,37 +1374,38 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from) decltype(_impl_._has_bits_){from._impl_._has_bits_} , /*decltype(_impl_._cached_size_)*/{} , decltype(_impl_.file_){from._impl_.file_} - , decltype(_impl_.error_){} - , decltype(_impl_.supported_features_){}}; + , decltype(_impl_.error_) {} + + , decltype(_impl_.supported_features_) {} + }; _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); _impl_.error_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.error_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (from._internal_has_error()) { - _this->_impl_.error_.Set(from._internal_error(), - _this->GetArenaForAllocation()); + _impl_.error_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) { + _this->_impl_.error_.Set(from._internal_error(), _this->GetArenaForAllocation()); } _this->_impl_.supported_features_ = from._impl_.supported_features_; // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse) } -inline void CodeGeneratorResponse::SharedCtor( - ::_pb::Arena* arena, bool is_message_owned) { +inline void CodeGeneratorResponse::SharedCtor(::_pb::Arena* arena) { (void)arena; - (void)is_message_owned; new (&_impl_) Impl_{ decltype(_impl_._has_bits_){} , /*decltype(_impl_._cached_size_)*/{} , decltype(_impl_.file_){arena} - , decltype(_impl_.error_){} - , decltype(_impl_.supported_features_){arc_ui64{0u}} + , decltype(_impl_.error_) {} + + , decltype(_impl_.supported_features_) { ::arc_ui64{0u} } + }; _impl_.error_.InitDefault(); #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - _impl_.error_.Set("", GetArenaForAllocation()); - #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.error_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING } CodeGeneratorResponse::~CodeGeneratorResponse() { @@ -1364,7 +1418,7 @@ CodeGeneratorResponse::~CodeGeneratorResponse() { } inline void CodeGeneratorResponse::SharedDtor() { - GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + Y_ABSL_DCHECK(GetArenaForAllocation() == nullptr); _impl_.file_.~RepeatedPtrField(); _impl_.error_.Destroy(); } @@ -1375,7 +1429,7 @@ void CodeGeneratorResponse::SetCachedSize(int size) const { void CodeGeneratorResponse::Clear() { // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse) - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -1384,7 +1438,7 @@ void CodeGeneratorResponse::Clear() { if (cached_has_bits & 0x00000001u) { _impl_.error_.ClearNonDefaultToEmpty(); } - _impl_.supported_features_ = arc_ui64{0u}; + _impl_.supported_features_ = ::arc_ui64{0u}; _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); } @@ -1393,33 +1447,35 @@ const char* CodeGeneratorResponse::_InternalParse(const char* ptr, ::_pbi::Parse #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure _Internal::HasBits has_bits{}; while (!ctx->Done(&ptr)) { - arc_ui32 tag; + ::arc_ui32 tag; ptr = ::_pbi::ReadTag(ptr, &tag); switch (tag >> 3) { // optional string error = 1; case 1: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) { auto str = _internal_mutable_error(); ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); CHK_(ptr); #ifndef NDEBUG ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.error"); #endif // !NDEBUG - } else + } else { goto handle_unusual; + } continue; // optional uint64 supported_features = 2; case 2: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) { _Internal::set_has_supported_features(&has_bits); _impl_.supported_features_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); CHK_(ptr); - } else + } else { goto handle_unusual; + } continue; // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; case 15: - if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 122)) { + if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 122)) { ptr -= 1; do { ptr += 1; @@ -1427,8 +1483,9 @@ const char* CodeGeneratorResponse::_InternalParse(const char* ptr, ::_pbi::Parse CHK_(ptr); if (!ctx->DataAvailable(ptr)) break; } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<122>(ptr)); - } else + } else { goto handle_unusual; + } continue; default: goto handle_unusual; @@ -1454,27 +1511,26 @@ failure: #undef CHK_ } -uint8_t* CodeGeneratorResponse::_InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { +::uint8_t* CodeGeneratorResponse::_InternalSerialize( + ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse) - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; (void) cached_has_bits; cached_has_bits = _impl_._has_bits_[0]; // optional string error = 1; if (cached_has_bits & 0x00000001u) { - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField( - this->_internal_error().data(), static_cast<int>(this->_internal_error().length()), - ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, - "google.protobuf.compiler.CodeGeneratorResponse.error"); - target = stream->WriteStringMaybeAliased( - 1, this->_internal_error(), target); + const TProtoStringType& _s = this->_internal_error(); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(_s.data(), static_cast<int>(_s.length()), ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE, + "google.protobuf.compiler.CodeGeneratorResponse.error"); + target = stream->WriteStringMaybeAliased(1, _s, target); } // optional uint64 supported_features = 2; if (cached_has_bits & 0x00000002u) { target = stream->EnsureSpace(target); - target = ::_pbi::WireFormatLite::WriteUInt64ToArray(2, this->_internal_supported_features(), target); + target = ::_pbi::WireFormatLite::WriteUInt64ToArray( + 2, this->_internal_supported_features(), target); } // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; @@ -1493,11 +1549,11 @@ uint8_t* CodeGeneratorResponse::_InternalSerialize( return target; } -size_t CodeGeneratorResponse::ByteSizeLong() const { +::size_t CodeGeneratorResponse::ByteSizeLong() const { // @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse) - size_t total_size = 0; + ::size_t total_size = 0; - arc_ui32 cached_has_bits = 0; + ::arc_ui32 cached_has_bits = 0; // Prevent compiler warnings about cached_has_bits being unused (void) cached_has_bits; @@ -1512,14 +1568,14 @@ size_t CodeGeneratorResponse::ByteSizeLong() const { if (cached_has_bits & 0x00000003u) { // optional string error = 1; if (cached_has_bits & 0x00000001u) { - total_size += 1 + - ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( - this->_internal_error()); + total_size += 1 + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_error()); } // optional uint64 supported_features = 2; if (cached_has_bits & 0x00000002u) { - total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne(this->_internal_supported_features()); + total_size += ::_pbi::WireFormatLite::UInt64SizePlusOne( + this->_internal_supported_features()); } } @@ -1537,8 +1593,8 @@ void CodeGeneratorResponse::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, auto* const _this = static_cast<CodeGeneratorResponse*>(&to_msg); auto& from = static_cast<const CodeGeneratorResponse&>(from_msg); // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse) - GOOGLE_DCHECK_NE(&from, _this); - arc_ui32 cached_has_bits = 0; + Y_ABSL_DCHECK_NE(&from, _this); + ::arc_ui32 cached_has_bits = 0; (void) cached_has_bits; _this->_impl_.file_.MergeFrom(from._impl_.file_); @@ -1573,10 +1629,9 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { _internal_metadata_.InternalSwap(&other->_internal_metadata_); swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); _impl_.file_.InternalSwap(&other->_impl_.file_); - ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( - &_impl_.error_, lhs_arena, - &other->_impl_.error_, rhs_arena - ); + ::_pbi::ArenaStringPtr::InternalSwap(&_impl_.error_, lhs_arena, + &other->_impl_.error_, rhs_arena); + swap(_impl_.supported_features_, other->_impl_.supported_features_); } @@ -1585,7 +1640,6 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once, file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[3]); } - // @@protoc_insertion_point(namespace_scope) } // namespace compiler PROTOBUF_NAMESPACE_CLOSE @@ -1607,6 +1661,5 @@ Arena::CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRespo return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse >(arena); } PROTOBUF_NAMESPACE_CLOSE - // @@protoc_insertion_point(global_scope) -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/plugin.pb.h b/contrib/libs/protoc/src/google/protobuf/compiler/plugin.pb.h index ac9253cc58b..fb83d68d30e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/plugin.pb.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/plugin.pb.h @@ -1,46 +1,51 @@ // Generated by the protocol buffer compiler. DO NOT EDIT! // source: google/protobuf/compiler/plugin.proto -#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto -#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto +#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh +#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh #include <limits> #include <string> - -#include <google/protobuf/port_def.inc> -#if PROTOBUF_VERSION < 3021000 -#error This file was generated by a newer version of protoc which is -#error incompatible with your Protocol Buffer headers. Please update -#error your headers. -#endif -#if 3021003 < 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 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> -#include <google/protobuf/generated_message_util.h> -#include <google/protobuf/metadata_lite.h> -#include <google/protobuf/generated_message_reflection.h> -#include <google/protobuf/message.h> -#include <google/protobuf/repeated_field.h> // IWYU pragma: export -#include <google/protobuf/extension_set.h> // IWYU pragma: export -#include <google/protobuf/generated_enum_reflection.h> -#include <google/protobuf/unknown_field_set.h> -#include <google/protobuf/descriptor.pb.h> +#include <type_traits> + +#include "google/protobuf/port_def.inc" +#if PROTOBUF_VERSION < 4022000 +#error "This file was generated by a newer version of protoc which is" +#error "incompatible with your Protocol Buffer headers. Please update" +#error "your headers." +#endif // PROTOBUF_VERSION + +#if 4022005 < 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 "regenerate this file with a newer version of protoc." +#endif // PROTOBUF_MIN_PROTOC_VERSION +#include "google/protobuf/port_undef.inc" +#include "google/protobuf/io/coded_stream.h" +#include "google/protobuf/arena.h" +#include "google/protobuf/arenastring.h" +#include "google/protobuf/generated_message_util.h" +#include "google/protobuf/metadata_lite.h" +#include "google/protobuf/generated_message_reflection.h" +#include "google/protobuf/message.h" +#include "google/protobuf/repeated_field.h" // IWYU pragma: export +#include "google/protobuf/extension_set.h" // IWYU pragma: export +#include "google/protobuf/generated_enum_reflection.h" +#include "google/protobuf/unknown_field_set.h" +#include "google/protobuf/descriptor.pb.h" // @@protoc_insertion_point(includes) -#include <google/protobuf/port_def.inc> + +// Must be included last. +#include "google/protobuf/port_def.inc" + #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto PROTOC_EXPORT #ifdef major #undef major -#endif +#endif // major #ifdef minor #undef minor -#endif +#endif // minor + PROTOBUF_NAMESPACE_OPEN namespace internal { class AnyMetadata; @@ -49,9 +54,10 @@ PROTOBUF_NAMESPACE_CLOSE // Internal implementation detail -- do not use these members. struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto { - static const arc_ui32 offsets[]; + static const ::arc_ui32 offsets[]; }; -PROTOC_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto; +PROTOC_EXPORT extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable + descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto; PROTOBUF_NAMESPACE_OPEN namespace compiler { class CodeGeneratorRequest; @@ -67,41 +73,52 @@ class Version; struct VersionDefaultTypeInternal; PROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_; } // namespace compiler +template <> +PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest>(Arena*); +template <> +PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse>(Arena*); +template <> +PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File>(Arena*); +template <> +PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::Version* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::Version>(Arena*); PROTOBUF_NAMESPACE_CLOSE -PROTOBUF_NAMESPACE_OPEN -template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest>(Arena*); -template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse>(Arena*); -template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File>(Arena*); -template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::Version* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::Version>(Arena*); -PROTOBUF_NAMESPACE_CLOSE + PROTOBUF_NAMESPACE_OPEN namespace compiler { - enum CodeGeneratorResponse_Feature : int { CodeGeneratorResponse_Feature_FEATURE_NONE = 0, - CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL = 1 + CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL = 1, }; + PROTOC_EXPORT bool CodeGeneratorResponse_Feature_IsValid(int value); -constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MIN = CodeGeneratorResponse_Feature_FEATURE_NONE; -constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MAX = CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL; -constexpr int CodeGeneratorResponse_Feature_Feature_ARRAYSIZE = CodeGeneratorResponse_Feature_Feature_MAX + 1; - -PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* CodeGeneratorResponse_Feature_descriptor(); -template<typename T> -inline const TProtoStringType& CodeGeneratorResponse_Feature_Name(T enum_t_value) { - static_assert(::std::is_same<T, CodeGeneratorResponse_Feature>::value || - ::std::is_integral<T>::value, - "Incorrect type passed to function CodeGeneratorResponse_Feature_Name."); - return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( - CodeGeneratorResponse_Feature_descriptor(), enum_t_value); -} -inline bool CodeGeneratorResponse_Feature_Parse( - ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, CodeGeneratorResponse_Feature* value) { +constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MIN = static_cast<CodeGeneratorResponse_Feature>(0); +constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MAX = static_cast<CodeGeneratorResponse_Feature>(1); +constexpr int CodeGeneratorResponse_Feature_Feature_ARRAYSIZE = 1 + 1; +PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* +CodeGeneratorResponse_Feature_descriptor(); +template <typename T> +const TProtoStringType& CodeGeneratorResponse_Feature_Name(T value) { + static_assert(std::is_same<T, CodeGeneratorResponse_Feature>::value || + std::is_integral<T>::value, + "Incorrect type passed to Feature_Name()."); + return CodeGeneratorResponse_Feature_Name(static_cast<CodeGeneratorResponse_Feature>(value)); +} +template <> +inline const TProtoStringType& CodeGeneratorResponse_Feature_Name(CodeGeneratorResponse_Feature value) { + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<CodeGeneratorResponse_Feature_descriptor, + 0, 1>( + static_cast<int>(value)); +} +inline bool CodeGeneratorResponse_Feature_Parse(y_absl::string_view name, CodeGeneratorResponse_Feature* value) { return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<CodeGeneratorResponse_Feature>( - CodeGeneratorResponse_Feature_descriptor(), name, value); + CodeGeneratorResponse_Feature_descriptor(), name, value); } + // =================================================================== + +// ------------------------------------------------------------------- + class PROTOC_EXPORT Version final : public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ { public: @@ -177,7 +194,7 @@ class PROTOC_EXPORT Version final : } void UnsafeArenaSwap(Version* other) { if (other == this) return; - GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + Y_ABSL_DCHECK(GetOwningArena() == other->GetOwningArena()); InternalSwap(other); } @@ -198,26 +215,25 @@ class PROTOC_EXPORT Version final : PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; - size_t ByteSizeLong() const final; + ::size_t ByteSizeLong() const final; const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - uint8_t* _InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; int GetCachedSize() const final { return _impl_._cached_size_.Get(); } private: - void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); void SharedDtor(); void SetCachedSize(int size) const final; void InternalSwap(Version* other); private: friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + static ::y_absl::string_view FullMessageName() { return "google.protobuf.compiler.Version"; } protected: - explicit Version(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned = false); + explicit Version(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: static const ClassData _class_data_; @@ -237,61 +253,58 @@ class PROTOC_EXPORT Version final : }; // optional string suffix = 4; bool has_suffix() const; - private: - bool _internal_has_suffix() const; - public: - void clear_suffix(); + void clear_suffix() ; const TProtoStringType& suffix() const; - template <typename ArgT0 = const TProtoStringType&, typename... ArgT> - void set_suffix(ArgT0&& arg0, ArgT... args); + + + + + template <typename Arg_ = const TProtoStringType&, typename... Args_> + void set_suffix(Arg_&& arg, Args_... args); TProtoStringType* mutable_suffix(); PROTOBUF_NODISCARD TProtoStringType* release_suffix(); - void set_allocated_suffix(TProtoStringType* suffix); + void set_allocated_suffix(TProtoStringType* ptr); + private: const TProtoStringType& _internal_suffix() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_suffix(const TProtoStringType& value); + inline PROTOBUF_ALWAYS_INLINE void _internal_set_suffix( + const TProtoStringType& value); TProtoStringType* _internal_mutable_suffix(); - public: + public: // optional int32 major = 1; bool has_major() const; + void clear_major() ; + ::arc_i32 major() const; + void set_major(::arc_i32 value); + private: - bool _internal_has_major() const; - public: - void clear_major(); - arc_i32 major() const; - void set_major(arc_i32 value); - private: - arc_i32 _internal_major() const; - void _internal_set_major(arc_i32 value); - public: + ::arc_i32 _internal_major() const; + void _internal_set_major(::arc_i32 value); + public: // optional int32 minor = 2; bool has_minor() const; + void clear_minor() ; + ::arc_i32 minor() const; + void set_minor(::arc_i32 value); + private: - bool _internal_has_minor() const; - public: - void clear_minor(); - arc_i32 minor() const; - void set_minor(arc_i32 value); - private: - arc_i32 _internal_minor() const; - void _internal_set_minor(arc_i32 value); - public: + ::arc_i32 _internal_minor() const; + void _internal_set_minor(::arc_i32 value); + public: // optional int32 patch = 3; bool has_patch() const; + void clear_patch() ; + ::arc_i32 patch() const; + void set_patch(::arc_i32 value); + private: - bool _internal_has_patch() const; - public: - void clear_patch(); - arc_i32 patch() const; - void set_patch(arc_i32 value); - private: - arc_i32 _internal_patch() const; - void _internal_set_patch(arc_i32 value); - public: + ::arc_i32 _internal_patch() const; + void _internal_set_patch(::arc_i32 value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.compiler.Version) private: class _Internal; @@ -303,14 +316,13 @@ class PROTOC_EXPORT Version final : ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_; mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr suffix_; - arc_i32 major_; - arc_i32 minor_; - arc_i32 patch_; + ::arc_i32 major_; + ::arc_i32 minor_; + ::arc_i32 patch_; }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; -}; -// ------------------------------------------------------------------- +};// ------------------------------------------------------------------- class PROTOC_EXPORT CodeGeneratorRequest final : public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ { @@ -387,7 +399,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final : } void UnsafeArenaSwap(CodeGeneratorRequest* other) { if (other == this) return; - GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + Y_ABSL_DCHECK(GetOwningArena() == other->GetOwningArena()); InternalSwap(other); } @@ -408,26 +420,25 @@ class PROTOC_EXPORT CodeGeneratorRequest final : PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; - size_t ByteSizeLong() const final; + ::size_t ByteSizeLong() const final; const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - uint8_t* _InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; int GetCachedSize() const final { return _impl_._cached_size_.Get(); } private: - void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); void SharedDtor(); void SetCachedSize(int size) const final; void InternalSwap(CodeGeneratorRequest* other); private: friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + static ::y_absl::string_view FullMessageName() { return "google.protobuf.compiler.CodeGeneratorRequest"; } protected: - explicit CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned = false); + explicit CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: static const ClassData _class_data_; @@ -449,32 +460,37 @@ class PROTOC_EXPORT CodeGeneratorRequest final : int file_to_generate_size() const; private: int _internal_file_to_generate_size() const; + public: - void clear_file_to_generate(); + void clear_file_to_generate() ; const TProtoStringType& file_to_generate(int index) const; TProtoStringType* mutable_file_to_generate(int index); void set_file_to_generate(int index, const TProtoStringType& value); void set_file_to_generate(int index, TProtoStringType&& value); void set_file_to_generate(int index, const char* value); - void set_file_to_generate(int index, const char* value, size_t size); + void set_file_to_generate(int index, const char* value, std::size_t size); + void set_file_to_generate(int index, y_absl::string_view value); TProtoStringType* add_file_to_generate(); void add_file_to_generate(const TProtoStringType& value); void add_file_to_generate(TProtoStringType&& value); void add_file_to_generate(const char* value); - void add_file_to_generate(const char* value, size_t size); + void add_file_to_generate(const char* value, std::size_t size); + void add_file_to_generate(y_absl::string_view value); const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<TProtoStringType>& file_to_generate() const; ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<TProtoStringType>* mutable_file_to_generate(); + private: const TProtoStringType& _internal_file_to_generate(int index) const; TProtoStringType* _internal_add_file_to_generate(); - public: + public: // repeated .google.protobuf.FileDescriptorProto proto_file = 15; int proto_file_size() const; private: int _internal_proto_file_size() const; + public: - void clear_proto_file(); + void clear_proto_file() ; ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* mutable_proto_file(int index); ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >* mutable_proto_file(); @@ -486,31 +502,30 @@ class PROTOC_EXPORT CodeGeneratorRequest final : ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* add_proto_file(); const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto >& proto_file() const; - // optional string parameter = 2; bool has_parameter() const; - private: - bool _internal_has_parameter() const; - public: - void clear_parameter(); + void clear_parameter() ; const TProtoStringType& parameter() const; - template <typename ArgT0 = const TProtoStringType&, typename... ArgT> - void set_parameter(ArgT0&& arg0, ArgT... args); + + + + + template <typename Arg_ = const TProtoStringType&, typename... Args_> + void set_parameter(Arg_&& arg, Args_... args); TProtoStringType* mutable_parameter(); PROTOBUF_NODISCARD TProtoStringType* release_parameter(); - void set_allocated_parameter(TProtoStringType* parameter); + void set_allocated_parameter(TProtoStringType* ptr); + private: const TProtoStringType& _internal_parameter() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_parameter(const TProtoStringType& value); + inline PROTOBUF_ALWAYS_INLINE void _internal_set_parameter( + const TProtoStringType& value); TProtoStringType* _internal_mutable_parameter(); - public: + public: // optional .google.protobuf.compiler.Version compiler_version = 3; bool has_compiler_version() const; - private: - bool _internal_has_compiler_version() const; - public: - void clear_compiler_version(); + void clear_compiler_version() ; const ::PROTOBUF_NAMESPACE_ID::compiler::Version& compiler_version() const; PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version(); ::PROTOBUF_NAMESPACE_ID::compiler::Version* mutable_compiler_version(); @@ -522,7 +537,6 @@ class PROTOC_EXPORT CodeGeneratorRequest final : void unsafe_arena_set_allocated_compiler_version( ::PROTOBUF_NAMESPACE_ID::compiler::Version* compiler_version); ::PROTOBUF_NAMESPACE_ID::compiler::Version* unsafe_arena_release_compiler_version(); - // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) private: class _Internal; @@ -540,8 +554,7 @@ class PROTOC_EXPORT CodeGeneratorRequest final : }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; -}; -// ------------------------------------------------------------------- +};// ------------------------------------------------------------------- class PROTOC_EXPORT CodeGeneratorResponse_File final : public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ { @@ -618,7 +631,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : } void UnsafeArenaSwap(CodeGeneratorResponse_File* other) { if (other == this) return; - GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + Y_ABSL_DCHECK(GetOwningArena() == other->GetOwningArena()); InternalSwap(other); } @@ -639,26 +652,25 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; - size_t ByteSizeLong() const final; + ::size_t ByteSizeLong() const final; const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - uint8_t* _InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; int GetCachedSize() const final { return _impl_._cached_size_.Get(); } private: - void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); void SharedDtor(); void SetCachedSize(int size) const final; void InternalSwap(CodeGeneratorResponse_File* other); private: friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + static ::y_absl::string_view FullMessageName() { return "google.protobuf.compiler.CodeGeneratorResponse.File"; } protected: - explicit CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned = false); + explicit CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: static const ClassData _class_data_; @@ -678,64 +690,70 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : }; // optional string name = 1; bool has_name() const; - private: - bool _internal_has_name() const; - public: - void clear_name(); + void clear_name() ; const TProtoStringType& name() const; - template <typename ArgT0 = const TProtoStringType&, typename... ArgT> - void set_name(ArgT0&& arg0, ArgT... args); + + + + + template <typename Arg_ = const TProtoStringType&, typename... Args_> + void set_name(Arg_&& arg, Args_... args); TProtoStringType* mutable_name(); PROTOBUF_NODISCARD TProtoStringType* release_name(); - void set_allocated_name(TProtoStringType* name); + void set_allocated_name(TProtoStringType* ptr); + private: const TProtoStringType& _internal_name() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const TProtoStringType& value); + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name( + const TProtoStringType& value); TProtoStringType* _internal_mutable_name(); - public: + public: // optional string insertion_point = 2; bool has_insertion_point() const; - private: - bool _internal_has_insertion_point() const; - public: - void clear_insertion_point(); + void clear_insertion_point() ; const TProtoStringType& insertion_point() const; - template <typename ArgT0 = const TProtoStringType&, typename... ArgT> - void set_insertion_point(ArgT0&& arg0, ArgT... args); + + + + + template <typename Arg_ = const TProtoStringType&, typename... Args_> + void set_insertion_point(Arg_&& arg, Args_... args); TProtoStringType* mutable_insertion_point(); PROTOBUF_NODISCARD TProtoStringType* release_insertion_point(); - void set_allocated_insertion_point(TProtoStringType* insertion_point); + void set_allocated_insertion_point(TProtoStringType* ptr); + private: const TProtoStringType& _internal_insertion_point() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_insertion_point(const TProtoStringType& value); + inline PROTOBUF_ALWAYS_INLINE void _internal_set_insertion_point( + const TProtoStringType& value); TProtoStringType* _internal_mutable_insertion_point(); - public: + public: // optional string content = 15; bool has_content() const; - private: - bool _internal_has_content() const; - public: - void clear_content(); + void clear_content() ; const TProtoStringType& content() const; - template <typename ArgT0 = const TProtoStringType&, typename... ArgT> - void set_content(ArgT0&& arg0, ArgT... args); + + + + + template <typename Arg_ = const TProtoStringType&, typename... Args_> + void set_content(Arg_&& arg, Args_... args); TProtoStringType* mutable_content(); PROTOBUF_NODISCARD TProtoStringType* release_content(); - void set_allocated_content(TProtoStringType* content); + void set_allocated_content(TProtoStringType* ptr); + private: const TProtoStringType& _internal_content() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_content(const TProtoStringType& value); + inline PROTOBUF_ALWAYS_INLINE void _internal_set_content( + const TProtoStringType& value); TProtoStringType* _internal_mutable_content(); - public: + public: // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; bool has_generated_code_info() const; - private: - bool _internal_has_generated_code_info() const; - public: - void clear_generated_code_info(); + void clear_generated_code_info() ; const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& generated_code_info() const; PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* release_generated_code_info(); ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* mutable_generated_code_info(); @@ -747,7 +765,6 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : void unsafe_arena_set_allocated_generated_code_info( ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* generated_code_info); ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* unsafe_arena_release_generated_code_info(); - // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) private: class _Internal; @@ -765,8 +782,7 @@ class PROTOC_EXPORT CodeGeneratorResponse_File final : }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; -}; -// ------------------------------------------------------------------- +};// ------------------------------------------------------------------- class PROTOC_EXPORT CodeGeneratorResponse final : public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ { @@ -843,7 +859,7 @@ class PROTOC_EXPORT CodeGeneratorResponse final : } void UnsafeArenaSwap(CodeGeneratorResponse* other) { if (other == this) return; - GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + Y_ABSL_DCHECK(GetOwningArena() == other->GetOwningArena()); InternalSwap(other); } @@ -864,26 +880,25 @@ class PROTOC_EXPORT CodeGeneratorResponse final : PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; bool IsInitialized() const final; - size_t ByteSizeLong() const final; + ::size_t ByteSizeLong() const final; const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; - uint8_t* _InternalSerialize( - uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + ::uint8_t* _InternalSerialize( + ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; int GetCachedSize() const final { return _impl_._cached_size_.Get(); } private: - void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); void SharedDtor(); void SetCachedSize(int size) const final; void InternalSwap(CodeGeneratorResponse* other); private: friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; - static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + static ::y_absl::string_view FullMessageName() { return "google.protobuf.compiler.CodeGeneratorResponse"; } protected: - explicit CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena, - bool is_message_owned = false); + explicit CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::Arena* arena); public: static const ClassData _class_data_; @@ -895,33 +910,23 @@ class PROTOC_EXPORT CodeGeneratorResponse final : typedef CodeGeneratorResponse_File File; - typedef CodeGeneratorResponse_Feature Feature; - static constexpr Feature FEATURE_NONE = - CodeGeneratorResponse_Feature_FEATURE_NONE; - static constexpr Feature FEATURE_PROTO3_OPTIONAL = - CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL; + using Feature = CodeGeneratorResponse_Feature; + static constexpr Feature FEATURE_NONE = CodeGeneratorResponse_Feature_FEATURE_NONE; + static constexpr Feature FEATURE_PROTO3_OPTIONAL = CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL; static inline bool Feature_IsValid(int value) { return CodeGeneratorResponse_Feature_IsValid(value); } - static constexpr Feature Feature_MIN = - CodeGeneratorResponse_Feature_Feature_MIN; - static constexpr Feature Feature_MAX = - CodeGeneratorResponse_Feature_Feature_MAX; - static constexpr int Feature_ARRAYSIZE = - CodeGeneratorResponse_Feature_Feature_ARRAYSIZE; - static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* - Feature_descriptor() { + static constexpr Feature Feature_MIN = CodeGeneratorResponse_Feature_Feature_MIN; + static constexpr Feature Feature_MAX = CodeGeneratorResponse_Feature_Feature_MAX; + static constexpr int Feature_ARRAYSIZE = CodeGeneratorResponse_Feature_Feature_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Feature_descriptor() { return CodeGeneratorResponse_Feature_descriptor(); } - template<typename T> - static inline const TProtoStringType& Feature_Name(T enum_t_value) { - static_assert(::std::is_same<T, Feature>::value || - ::std::is_integral<T>::value, - "Incorrect type passed to function Feature_Name."); - return CodeGeneratorResponse_Feature_Name(enum_t_value); + template <typename T> + static inline const TProtoStringType& Feature_Name(T value) { + return CodeGeneratorResponse_Feature_Name(value); } - static inline bool Feature_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, - Feature* value) { + static inline bool Feature_Parse(y_absl::string_view name, Feature* value) { return CodeGeneratorResponse_Feature_Parse(name, value); } @@ -936,8 +941,9 @@ class PROTOC_EXPORT CodeGeneratorResponse final : int file_size() const; private: int _internal_file_size() const; + public: - void clear_file(); + void clear_file() ; ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* mutable_file(int index); ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >* mutable_file(); @@ -949,38 +955,38 @@ class PROTOC_EXPORT CodeGeneratorResponse final : ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* add_file(); const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File >& file() const; - // optional string error = 1; bool has_error() const; - private: - bool _internal_has_error() const; - public: - void clear_error(); + void clear_error() ; const TProtoStringType& error() const; - template <typename ArgT0 = const TProtoStringType&, typename... ArgT> - void set_error(ArgT0&& arg0, ArgT... args); + + + + + template <typename Arg_ = const TProtoStringType&, typename... Args_> + void set_error(Arg_&& arg, Args_... args); TProtoStringType* mutable_error(); PROTOBUF_NODISCARD TProtoStringType* release_error(); - void set_allocated_error(TProtoStringType* error); + void set_allocated_error(TProtoStringType* ptr); + private: const TProtoStringType& _internal_error() const; - inline PROTOBUF_ALWAYS_INLINE void _internal_set_error(const TProtoStringType& value); + inline PROTOBUF_ALWAYS_INLINE void _internal_set_error( + const TProtoStringType& value); TProtoStringType* _internal_mutable_error(); - public: + public: // optional uint64 supported_features = 2; bool has_supported_features() const; + void clear_supported_features() ; + ::arc_ui64 supported_features() const; + void set_supported_features(::arc_ui64 value); + private: - bool _internal_has_supported_features() const; - public: - void clear_supported_features(); - arc_ui64 supported_features() const; - void set_supported_features(arc_ui64 value); - private: - arc_ui64 _internal_supported_features() const; - void _internal_set_supported_features(arc_ui64 value); - public: + ::arc_ui64 _internal_supported_features() const; + void _internal_set_supported_features(::arc_ui64 value); + public: // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) private: class _Internal; @@ -993,114 +999,108 @@ class PROTOC_EXPORT CodeGeneratorResponse final : mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File > file_; ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr error_; - arc_ui64 supported_features_; + ::arc_ui64 supported_features_; }; union { Impl_ _impl_; }; friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto; }; + // =================================================================== + + // =================================================================== + #ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" #endif // __GNUC__ +// ------------------------------------------------------------------- + // Version // optional int32 major = 1; -inline bool Version::_internal_has_major() const { +inline bool Version::has_major() const { bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; return value; } -inline bool Version::has_major() const { - return _internal_has_major(); -} inline void Version::clear_major() { _impl_.major_ = 0; _impl_._has_bits_[0] &= ~0x00000002u; } -inline arc_i32 Version::_internal_major() const { - return _impl_.major_; -} -inline arc_i32 Version::major() const { +inline ::arc_i32 Version::major() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.major) return _internal_major(); } -inline void Version::_internal_set_major(arc_i32 value) { - _impl_._has_bits_[0] |= 0x00000002u; - _impl_.major_ = value; -} -inline void Version::set_major(arc_i32 value) { +inline void Version::set_major(::arc_i32 value) { _internal_set_major(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.major) } +inline ::arc_i32 Version::_internal_major() const { + return _impl_.major_; +} +inline void Version::_internal_set_major(::arc_i32 value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.major_ = value; +} // optional int32 minor = 2; -inline bool Version::_internal_has_minor() const { +inline bool Version::has_minor() const { bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; return value; } -inline bool Version::has_minor() const { - return _internal_has_minor(); -} inline void Version::clear_minor() { _impl_.minor_ = 0; _impl_._has_bits_[0] &= ~0x00000004u; } -inline arc_i32 Version::_internal_minor() const { - return _impl_.minor_; -} -inline arc_i32 Version::minor() const { +inline ::arc_i32 Version::minor() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.minor) return _internal_minor(); } -inline void Version::_internal_set_minor(arc_i32 value) { - _impl_._has_bits_[0] |= 0x00000004u; - _impl_.minor_ = value; -} -inline void Version::set_minor(arc_i32 value) { +inline void Version::set_minor(::arc_i32 value) { _internal_set_minor(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.minor) } +inline ::arc_i32 Version::_internal_minor() const { + return _impl_.minor_; +} +inline void Version::_internal_set_minor(::arc_i32 value) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.minor_ = value; +} // optional int32 patch = 3; -inline bool Version::_internal_has_patch() const { +inline bool Version::has_patch() const { bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; return value; } -inline bool Version::has_patch() const { - return _internal_has_patch(); -} inline void Version::clear_patch() { _impl_.patch_ = 0; _impl_._has_bits_[0] &= ~0x00000008u; } -inline arc_i32 Version::_internal_patch() const { - return _impl_.patch_; -} -inline arc_i32 Version::patch() const { +inline ::arc_i32 Version::patch() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.patch) return _internal_patch(); } -inline void Version::_internal_set_patch(arc_i32 value) { - _impl_._has_bits_[0] |= 0x00000008u; - _impl_.patch_ = value; -} -inline void Version::set_patch(arc_i32 value) { +inline void Version::set_patch(::arc_i32 value) { _internal_set_patch(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.patch) } +inline ::arc_i32 Version::_internal_patch() const { + return _impl_.patch_; +} +inline void Version::_internal_set_patch(::arc_i32 value) { + _impl_._has_bits_[0] |= 0x00000008u; + _impl_.patch_ = value; +} // optional string suffix = 4; -inline bool Version::_internal_has_suffix() const { +inline bool Version::has_suffix() const { bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; return value; } -inline bool Version::has_suffix() const { - return _internal_has_suffix(); -} inline void Version::clear_suffix() { _impl_.suffix_.ClearToEmpty(); _impl_._has_bits_[0] &= ~0x00000001u; @@ -1109,11 +1109,11 @@ inline const TProtoStringType& Version::suffix() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.suffix) return _internal_suffix(); } -template <typename ArgT0, typename... ArgT> -inline PROTOBUF_ALWAYS_INLINE -void Version::set_suffix(ArgT0&& arg0, ArgT... args) { - _impl_._has_bits_[0] |= 0x00000001u; - _impl_.suffix_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); +template <typename Arg_, typename... Args_> +inline PROTOBUF_ALWAYS_INLINE void Version::set_suffix(Arg_&& arg, + Args_... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.suffix_.Set(static_cast<Arg_&&>(arg), args..., GetArenaForAllocation()); // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.suffix) } inline TProtoStringType* Version::mutable_suffix() { @@ -1126,38 +1126,38 @@ inline const TProtoStringType& Version::_internal_suffix() const { } inline void Version::_internal_set_suffix(const TProtoStringType& value) { _impl_._has_bits_[0] |= 0x00000001u; + + _impl_.suffix_.Set(value, GetArenaForAllocation()); } inline TProtoStringType* Version::_internal_mutable_suffix() { _impl_._has_bits_[0] |= 0x00000001u; - return _impl_.suffix_.Mutable(GetArenaForAllocation()); + return _impl_.suffix_.Mutable( GetArenaForAllocation()); } inline TProtoStringType* Version::release_suffix() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.Version.suffix) - if (!_internal_has_suffix()) { + if ((_impl_._has_bits_[0] & 0x00000001u) == 0) { return nullptr; } _impl_._has_bits_[0] &= ~0x00000001u; - auto* p = _impl_.suffix_.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.suffix_.IsDefault()) { - _impl_.suffix_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - return p; -} -inline void Version::set_allocated_suffix(TProtoStringType* suffix) { - if (suffix != nullptr) { + auto* released = _impl_.suffix_.Release(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.suffix_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return released; +} +inline void Version::set_allocated_suffix(TProtoStringType* value) { + if (value != nullptr) { _impl_._has_bits_[0] |= 0x00000001u; } else { _impl_._has_bits_[0] &= ~0x00000001u; } - _impl_.suffix_.SetAllocated(suffix, GetArenaForAllocation()); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.suffix_.IsDefault()) { - _impl_.suffix_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.suffix_.SetAllocated(value, GetArenaForAllocation()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.suffix_.IsDefault()) { + _impl_.suffix_.Set("", GetArenaForAllocation()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.Version.suffix) } @@ -1200,18 +1200,20 @@ inline void CodeGeneratorRequest::set_file_to_generate(int index, TProtoStringTy // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) { - GOOGLE_DCHECK(value != nullptr); + Y_ABSL_DCHECK(value != nullptr); _impl_.file_to_generate_.Mutable(index)->assign(value); // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } -inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) { - _impl_.file_to_generate_.Mutable(index)->assign( - reinterpret_cast<const char*>(value), size); +inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, + std::size_t size) { + _impl_.file_to_generate_.Mutable(index)->assign(reinterpret_cast<const char*>(value), size); // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } -inline TProtoStringType* CodeGeneratorRequest::_internal_add_file_to_generate() { - return _impl_.file_to_generate_.Add(); +inline void CodeGeneratorRequest::set_file_to_generate(int index, y_absl::string_view value) { + _impl_.file_to_generate_.Mutable(index)->assign(value.data(), value.size()); + // @@protoc_insertion_point(field_set_string_piece:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } +inline TProtoStringType* CodeGeneratorRequest::_internal_add_file_to_generate() { return _impl_.file_to_generate_.Add(); } inline void CodeGeneratorRequest::add_file_to_generate(const TProtoStringType& value) { _impl_.file_to_generate_.Add()->assign(value); // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) @@ -1221,33 +1223,33 @@ inline void CodeGeneratorRequest::add_file_to_generate(TProtoStringType&& value) // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::add_file_to_generate(const char* value) { - GOOGLE_DCHECK(value != nullptr); + Y_ABSL_DCHECK(value != nullptr); _impl_.file_to_generate_.Add()->assign(value); // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } -inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) { +inline void CodeGeneratorRequest::add_file_to_generate(const char* value, std::size_t size) { _impl_.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 void CodeGeneratorRequest::add_file_to_generate(y_absl::string_view value) { + _impl_.file_to_generate_.Add()->assign(value.data(), value.size()); + // @@protoc_insertion_point(field_add_string_piece:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<TProtoStringType>& CodeGeneratorRequest::file_to_generate() const { // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return _impl_.file_to_generate_; } -inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<TProtoStringType>* -CodeGeneratorRequest::mutable_file_to_generate() { +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<TProtoStringType>* CodeGeneratorRequest::mutable_file_to_generate() { // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return &_impl_.file_to_generate_; } // optional string parameter = 2; -inline bool CodeGeneratorRequest::_internal_has_parameter() const { +inline bool CodeGeneratorRequest::has_parameter() const { bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; return value; } -inline bool CodeGeneratorRequest::has_parameter() const { - return _internal_has_parameter(); -} inline void CodeGeneratorRequest::clear_parameter() { _impl_.parameter_.ClearToEmpty(); _impl_._has_bits_[0] &= ~0x00000001u; @@ -1256,11 +1258,11 @@ inline const TProtoStringType& CodeGeneratorRequest::parameter() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter) return _internal_parameter(); } -template <typename ArgT0, typename... ArgT> -inline PROTOBUF_ALWAYS_INLINE -void CodeGeneratorRequest::set_parameter(ArgT0&& arg0, ArgT... args) { - _impl_._has_bits_[0] |= 0x00000001u; - _impl_.parameter_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); +template <typename Arg_, typename... Args_> +inline PROTOBUF_ALWAYS_INLINE void CodeGeneratorRequest::set_parameter(Arg_&& arg, + Args_... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.parameter_.Set(static_cast<Arg_&&>(arg), args..., GetArenaForAllocation()); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline TProtoStringType* CodeGeneratorRequest::mutable_parameter() { @@ -1273,38 +1275,38 @@ inline const TProtoStringType& CodeGeneratorRequest::_internal_parameter() const } inline void CodeGeneratorRequest::_internal_set_parameter(const TProtoStringType& value) { _impl_._has_bits_[0] |= 0x00000001u; + + _impl_.parameter_.Set(value, GetArenaForAllocation()); } inline TProtoStringType* CodeGeneratorRequest::_internal_mutable_parameter() { _impl_._has_bits_[0] |= 0x00000001u; - return _impl_.parameter_.Mutable(GetArenaForAllocation()); + return _impl_.parameter_.Mutable( GetArenaForAllocation()); } inline TProtoStringType* CodeGeneratorRequest::release_parameter() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter) - if (!_internal_has_parameter()) { + if ((_impl_._has_bits_[0] & 0x00000001u) == 0) { return nullptr; } _impl_._has_bits_[0] &= ~0x00000001u; - auto* p = _impl_.parameter_.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.parameter_.IsDefault()) { - _impl_.parameter_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - return p; -} -inline void CodeGeneratorRequest::set_allocated_parameter(TProtoStringType* parameter) { - if (parameter != nullptr) { + auto* released = _impl_.parameter_.Release(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.parameter_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return released; +} +inline void CodeGeneratorRequest::set_allocated_parameter(TProtoStringType* value) { + if (value != nullptr) { _impl_._has_bits_[0] |= 0x00000001u; } else { _impl_._has_bits_[0] &= ~0x00000001u; } - _impl_.parameter_.SetAllocated(parameter, GetArenaForAllocation()); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.parameter_.IsDefault()) { - _impl_.parameter_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.parameter_.SetAllocated(value, GetArenaForAllocation()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.parameter_.IsDefault()) { + _impl_.parameter_.Set("", GetArenaForAllocation()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter) } @@ -1346,14 +1348,11 @@ CodeGeneratorRequest::proto_file() const { } // optional .google.protobuf.compiler.Version compiler_version = 3; -inline bool CodeGeneratorRequest::_internal_has_compiler_version() const { +inline bool CodeGeneratorRequest::has_compiler_version() const { bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; PROTOBUF_ASSUME(!value || _impl_.compiler_version_ != nullptr); return value; } -inline bool CodeGeneratorRequest::has_compiler_version() const { - return _internal_has_compiler_version(); -} inline void CodeGeneratorRequest::clear_compiler_version() { if (_impl_.compiler_version_ != nullptr) _impl_.compiler_version_->Clear(); _impl_._has_bits_[0] &= ~0x00000002u; @@ -1440,13 +1439,10 @@ inline void CodeGeneratorRequest::set_allocated_compiler_version(::PROTOBUF_NAME // CodeGeneratorResponse_File // optional string name = 1; -inline bool CodeGeneratorResponse_File::_internal_has_name() const { +inline bool CodeGeneratorResponse_File::has_name() const { bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; return value; } -inline bool CodeGeneratorResponse_File::has_name() const { - return _internal_has_name(); -} inline void CodeGeneratorResponse_File::clear_name() { _impl_.name_.ClearToEmpty(); _impl_._has_bits_[0] &= ~0x00000001u; @@ -1455,11 +1451,11 @@ inline const TProtoStringType& CodeGeneratorResponse_File::name() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name) return _internal_name(); } -template <typename ArgT0, typename... ArgT> -inline PROTOBUF_ALWAYS_INLINE -void CodeGeneratorResponse_File::set_name(ArgT0&& arg0, ArgT... args) { - _impl_._has_bits_[0] |= 0x00000001u; - _impl_.name_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); +template <typename Arg_, typename... Args_> +inline PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse_File::set_name(Arg_&& arg, + Args_... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.name_.Set(static_cast<Arg_&&>(arg), args..., GetArenaForAllocation()); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline TProtoStringType* CodeGeneratorResponse_File::mutable_name() { @@ -1472,49 +1468,46 @@ inline const TProtoStringType& CodeGeneratorResponse_File::_internal_name() cons } inline void CodeGeneratorResponse_File::_internal_set_name(const TProtoStringType& value) { _impl_._has_bits_[0] |= 0x00000001u; + + _impl_.name_.Set(value, GetArenaForAllocation()); } inline TProtoStringType* CodeGeneratorResponse_File::_internal_mutable_name() { _impl_._has_bits_[0] |= 0x00000001u; - return _impl_.name_.Mutable(GetArenaForAllocation()); + return _impl_.name_.Mutable( GetArenaForAllocation()); } inline TProtoStringType* CodeGeneratorResponse_File::release_name() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name) - if (!_internal_has_name()) { + if ((_impl_._has_bits_[0] & 0x00000001u) == 0) { return nullptr; } _impl_._has_bits_[0] &= ~0x00000001u; - auto* p = _impl_.name_.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - return p; -} -inline void CodeGeneratorResponse_File::set_allocated_name(TProtoStringType* name) { - if (name != nullptr) { + auto* released = _impl_.name_.Release(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return released; +} +inline void CodeGeneratorResponse_File::set_allocated_name(TProtoStringType* value) { + if (value != nullptr) { _impl_._has_bits_[0] |= 0x00000001u; } else { _impl_._has_bits_[0] &= ~0x00000001u; } - _impl_.name_.SetAllocated(name, GetArenaForAllocation()); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.name_.IsDefault()) { - _impl_.name_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.name_.SetAllocated(value, GetArenaForAllocation()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.name_.IsDefault()) { + _impl_.name_.Set("", GetArenaForAllocation()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name) } // optional string insertion_point = 2; -inline bool CodeGeneratorResponse_File::_internal_has_insertion_point() const { +inline bool CodeGeneratorResponse_File::has_insertion_point() const { bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; return value; } -inline bool CodeGeneratorResponse_File::has_insertion_point() const { - return _internal_has_insertion_point(); -} inline void CodeGeneratorResponse_File::clear_insertion_point() { _impl_.insertion_point_.ClearToEmpty(); _impl_._has_bits_[0] &= ~0x00000002u; @@ -1523,11 +1516,11 @@ inline const TProtoStringType& CodeGeneratorResponse_File::insertion_point() con // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) return _internal_insertion_point(); } -template <typename ArgT0, typename... ArgT> -inline PROTOBUF_ALWAYS_INLINE -void CodeGeneratorResponse_File::set_insertion_point(ArgT0&& arg0, ArgT... args) { - _impl_._has_bits_[0] |= 0x00000002u; - _impl_.insertion_point_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); +template <typename Arg_, typename... Args_> +inline PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse_File::set_insertion_point(Arg_&& arg, + Args_... args) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.insertion_point_.Set(static_cast<Arg_&&>(arg), args..., GetArenaForAllocation()); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline TProtoStringType* CodeGeneratorResponse_File::mutable_insertion_point() { @@ -1540,49 +1533,46 @@ inline const TProtoStringType& CodeGeneratorResponse_File::_internal_insertion_p } inline void CodeGeneratorResponse_File::_internal_set_insertion_point(const TProtoStringType& value) { _impl_._has_bits_[0] |= 0x00000002u; + + _impl_.insertion_point_.Set(value, GetArenaForAllocation()); } inline TProtoStringType* CodeGeneratorResponse_File::_internal_mutable_insertion_point() { _impl_._has_bits_[0] |= 0x00000002u; - return _impl_.insertion_point_.Mutable(GetArenaForAllocation()); + return _impl_.insertion_point_.Mutable( GetArenaForAllocation()); } inline TProtoStringType* CodeGeneratorResponse_File::release_insertion_point() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) - if (!_internal_has_insertion_point()) { + if ((_impl_._has_bits_[0] & 0x00000002u) == 0) { return nullptr; } _impl_._has_bits_[0] &= ~0x00000002u; - auto* p = _impl_.insertion_point_.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.insertion_point_.IsDefault()) { - _impl_.insertion_point_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - return p; -} -inline void CodeGeneratorResponse_File::set_allocated_insertion_point(TProtoStringType* insertion_point) { - if (insertion_point != nullptr) { + auto* released = _impl_.insertion_point_.Release(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.insertion_point_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return released; +} +inline void CodeGeneratorResponse_File::set_allocated_insertion_point(TProtoStringType* value) { + if (value != nullptr) { _impl_._has_bits_[0] |= 0x00000002u; } else { _impl_._has_bits_[0] &= ~0x00000002u; } - _impl_.insertion_point_.SetAllocated(insertion_point, GetArenaForAllocation()); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.insertion_point_.IsDefault()) { - _impl_.insertion_point_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.insertion_point_.SetAllocated(value, GetArenaForAllocation()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.insertion_point_.IsDefault()) { + _impl_.insertion_point_.Set("", GetArenaForAllocation()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } // optional string content = 15; -inline bool CodeGeneratorResponse_File::_internal_has_content() const { +inline bool CodeGeneratorResponse_File::has_content() const { bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0; return value; } -inline bool CodeGeneratorResponse_File::has_content() const { - return _internal_has_content(); -} inline void CodeGeneratorResponse_File::clear_content() { _impl_.content_.ClearToEmpty(); _impl_._has_bits_[0] &= ~0x00000004u; @@ -1591,11 +1581,11 @@ inline const TProtoStringType& CodeGeneratorResponse_File::content() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content) return _internal_content(); } -template <typename ArgT0, typename... ArgT> -inline PROTOBUF_ALWAYS_INLINE -void CodeGeneratorResponse_File::set_content(ArgT0&& arg0, ArgT... args) { - _impl_._has_bits_[0] |= 0x00000004u; - _impl_.content_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); +template <typename Arg_, typename... Args_> +inline PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse_File::set_content(Arg_&& arg, + Args_... args) { + _impl_._has_bits_[0] |= 0x00000004u; + _impl_.content_.Set(static_cast<Arg_&&>(arg), args..., GetArenaForAllocation()); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline TProtoStringType* CodeGeneratorResponse_File::mutable_content() { @@ -1608,50 +1598,47 @@ inline const TProtoStringType& CodeGeneratorResponse_File::_internal_content() c } inline void CodeGeneratorResponse_File::_internal_set_content(const TProtoStringType& value) { _impl_._has_bits_[0] |= 0x00000004u; + + _impl_.content_.Set(value, GetArenaForAllocation()); } inline TProtoStringType* CodeGeneratorResponse_File::_internal_mutable_content() { _impl_._has_bits_[0] |= 0x00000004u; - return _impl_.content_.Mutable(GetArenaForAllocation()); + return _impl_.content_.Mutable( GetArenaForAllocation()); } inline TProtoStringType* CodeGeneratorResponse_File::release_content() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content) - if (!_internal_has_content()) { + if ((_impl_._has_bits_[0] & 0x00000004u) == 0) { return nullptr; } _impl_._has_bits_[0] &= ~0x00000004u; - auto* p = _impl_.content_.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.content_.IsDefault()) { - _impl_.content_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - return p; -} -inline void CodeGeneratorResponse_File::set_allocated_content(TProtoStringType* content) { - if (content != nullptr) { + auto* released = _impl_.content_.Release(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.content_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return released; +} +inline void CodeGeneratorResponse_File::set_allocated_content(TProtoStringType* value) { + if (value != nullptr) { _impl_._has_bits_[0] |= 0x00000004u; } else { _impl_._has_bits_[0] &= ~0x00000004u; } - _impl_.content_.SetAllocated(content, GetArenaForAllocation()); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.content_.IsDefault()) { - _impl_.content_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.content_.SetAllocated(value, GetArenaForAllocation()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.content_.IsDefault()) { + _impl_.content_.Set("", GetArenaForAllocation()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) } // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16; -inline bool CodeGeneratorResponse_File::_internal_has_generated_code_info() const { +inline bool CodeGeneratorResponse_File::has_generated_code_info() const { bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; PROTOBUF_ASSUME(!value || _impl_.generated_code_info_ != nullptr); return value; } -inline bool CodeGeneratorResponse_File::has_generated_code_info() const { - return _internal_has_generated_code_info(); -} inline const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo& CodeGeneratorResponse_File::_internal_generated_code_info() const { const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* p = _impl_.generated_code_info_; return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo&>( @@ -1735,13 +1722,10 @@ inline void CodeGeneratorResponse_File::set_allocated_generated_code_info(::PROT // CodeGeneratorResponse // optional string error = 1; -inline bool CodeGeneratorResponse::_internal_has_error() const { +inline bool CodeGeneratorResponse::has_error() const { bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0; return value; } -inline bool CodeGeneratorResponse::has_error() const { - return _internal_has_error(); -} inline void CodeGeneratorResponse::clear_error() { _impl_.error_.ClearToEmpty(); _impl_._has_bits_[0] &= ~0x00000001u; @@ -1750,11 +1734,11 @@ inline const TProtoStringType& CodeGeneratorResponse::error() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error) return _internal_error(); } -template <typename ArgT0, typename... ArgT> -inline PROTOBUF_ALWAYS_INLINE -void CodeGeneratorResponse::set_error(ArgT0&& arg0, ArgT... args) { - _impl_._has_bits_[0] |= 0x00000001u; - _impl_.error_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation()); +template <typename Arg_, typename... Args_> +inline PROTOBUF_ALWAYS_INLINE void CodeGeneratorResponse::set_error(Arg_&& arg, + Args_... args) { + _impl_._has_bits_[0] |= 0x00000001u; + _impl_.error_.Set(static_cast<Arg_&&>(arg), args..., GetArenaForAllocation()); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error) } inline TProtoStringType* CodeGeneratorResponse::mutable_error() { @@ -1767,68 +1751,65 @@ inline const TProtoStringType& CodeGeneratorResponse::_internal_error() const { } inline void CodeGeneratorResponse::_internal_set_error(const TProtoStringType& value) { _impl_._has_bits_[0] |= 0x00000001u; + + _impl_.error_.Set(value, GetArenaForAllocation()); } inline TProtoStringType* CodeGeneratorResponse::_internal_mutable_error() { _impl_._has_bits_[0] |= 0x00000001u; - return _impl_.error_.Mutable(GetArenaForAllocation()); + return _impl_.error_.Mutable( GetArenaForAllocation()); } inline TProtoStringType* CodeGeneratorResponse::release_error() { // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error) - if (!_internal_has_error()) { + if ((_impl_._has_bits_[0] & 0x00000001u) == 0) { return nullptr; } _impl_._has_bits_[0] &= ~0x00000001u; - auto* p = _impl_.error_.Release(); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.error_.IsDefault()) { - _impl_.error_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING - return p; -} -inline void CodeGeneratorResponse::set_allocated_error(TProtoStringType* error) { - if (error != nullptr) { + auto* released = _impl_.error_.Release(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.error_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + return released; +} +inline void CodeGeneratorResponse::set_allocated_error(TProtoStringType* value) { + if (value != nullptr) { _impl_._has_bits_[0] |= 0x00000001u; } else { _impl_._has_bits_[0] &= ~0x00000001u; } - _impl_.error_.SetAllocated(error, GetArenaForAllocation()); -#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING - if (_impl_.error_.IsDefault()) { - _impl_.error_.Set("", GetArenaForAllocation()); - } -#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.error_.SetAllocated(value, GetArenaForAllocation()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.error_.IsDefault()) { + _impl_.error_.Set("", GetArenaForAllocation()); + } + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error) } // optional uint64 supported_features = 2; -inline bool CodeGeneratorResponse::_internal_has_supported_features() const { +inline bool CodeGeneratorResponse::has_supported_features() const { bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0; return value; } -inline bool CodeGeneratorResponse::has_supported_features() const { - return _internal_has_supported_features(); -} inline void CodeGeneratorResponse::clear_supported_features() { - _impl_.supported_features_ = arc_ui64{0u}; + _impl_.supported_features_ = ::arc_ui64{0u}; _impl_._has_bits_[0] &= ~0x00000002u; } -inline arc_ui64 CodeGeneratorResponse::_internal_supported_features() const { - return _impl_.supported_features_; -} -inline arc_ui64 CodeGeneratorResponse::supported_features() const { +inline ::arc_ui64 CodeGeneratorResponse::supported_features() const { // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.supported_features) return _internal_supported_features(); } -inline void CodeGeneratorResponse::_internal_set_supported_features(arc_ui64 value) { - _impl_._has_bits_[0] |= 0x00000002u; - _impl_.supported_features_ = value; -} -inline void CodeGeneratorResponse::set_supported_features(arc_ui64 value) { +inline void CodeGeneratorResponse::set_supported_features(::arc_ui64 value) { _internal_set_supported_features(value); // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.supported_features) } +inline ::arc_ui64 CodeGeneratorResponse::_internal_supported_features() const { + return _impl_.supported_features_; +} +inline void CodeGeneratorResponse::_internal_set_supported_features(::arc_ui64 value) { + _impl_._has_bits_[0] |= 0x00000002u; + _impl_.supported_features_ = value; +} // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; inline int CodeGeneratorResponse::_internal_file_size() const { @@ -1871,25 +1852,20 @@ CodeGeneratorResponse::file() const { } #ifdef __GNUC__ - #pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif // __GNUC__ -// ------------------------------------------------------------------- - -// ------------------------------------------------------------------- - -// ------------------------------------------------------------------- - // @@protoc_insertion_point(namespace_scope) - } // namespace compiler PROTOBUF_NAMESPACE_CLOSE + PROTOBUF_NAMESPACE_OPEN -template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature> : ::std::true_type {}; template <> -inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature>() { +struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature> : std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature>() { return ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature_descriptor(); } @@ -1897,5 +1873,6 @@ PROTOBUF_NAMESPACE_CLOSE // @@protoc_insertion_point(global_scope) -#include <google/protobuf/port_undef.inc> -#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/plugin.proto b/contrib/libs/protoc/src/google/protobuf/compiler/plugin.proto index 9242aacc5bd..7ab6dffd730 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/plugin.proto +++ b/contrib/libs/protoc/src/google/protobuf/compiler/plugin.proto @@ -30,9 +30,6 @@ // Author: [email protected] (Kenton Varda) // -// WARNING: The plugin interface is currently EXPERIMENTAL and is subject to -// change. -// // protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is // just a program that reads a CodeGeneratorRequest from stdin and writes a // CodeGeneratorResponse to stdout. @@ -50,6 +47,7 @@ package google.protobuf.compiler; option java_package = "com.google.protobuf.compiler"; option java_outer_classname = "PluginProtos"; +option csharp_namespace = "Google.Protobuf.Compiler"; option go_package = "google.golang.org/protobuf/types/pluginpb"; import "google/protobuf/descriptor.proto"; @@ -92,7 +90,6 @@ message CodeGeneratorRequest { // The version number of protocol compiler. optional Version compiler_version = 3; - } // The plugin writes an encoded CodeGeneratorResponse to stdout. diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.cc index d1e4de467b9..aaf5e3f8cb8 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.cc @@ -42,27 +42,33 @@ // performance-minded Python code leverage the fast C++ implementation // directly. -#include <google/protobuf/compiler/python/generator.h> +#include "google/protobuf/compiler/python/generator.h" #include <algorithm> #include <limits> -#include <map> #include <memory> #include <string> #include <utility> #include <vector> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/stringprintf.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/compiler/python/helpers.h> -#include <google/protobuf/compiler/python/pyi_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/strip.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/compiler/python/helpers.h" +#include "google/protobuf/compiler/python/pyi_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/strtod.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { @@ -72,15 +78,15 @@ namespace python { namespace { // Returns the alias we assign to the module of the given .proto filename // when importing. See testPackageInitializationImport in -// net/proto2/python/internal/reflection_test.py +// third_party/py/google/protobuf/internal/reflection_test.py // to see why we need the alias. -TProtoStringType ModuleAlias(const TProtoStringType& filename) { +TProtoStringType ModuleAlias(y_absl::string_view filename) { TProtoStringType module_name = ModuleName(filename); // We can't have dots in the module name, so we replace each with _dot_. // But that could lead to a collision between a.b and a_dot_b, so we also // duplicate each underscore. - GlobalReplaceSubstring("_", "__", &module_name); - GlobalReplaceSubstring(".", "_dot_", &module_name); + y_absl::StrReplaceAll({{"_", "__"}}, &module_name); + y_absl::StrReplaceAll({{".", "_dot_"}}, &module_name); return module_name; } @@ -90,29 +96,7 @@ TProtoStringType ModuleAlias(const TProtoStringType& filename) { // in proto2/public/reflection.py. const char kDescriptorKey[] = "DESCRIPTOR"; - -// file output by this generator. -void PrintTopBoilerplate(io::Printer* printer, const FileDescriptor* file, - bool descriptor_proto) { - // TODO(robinson): Allow parameterization of Python version? - printer->Print( - "# -*- coding: utf-8 -*-\n" - "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "# source: $filename$\n" - "\"\"\"Generated protocol buffer code.\"\"\"\n", - "filename", file->name()); - printer->Print( - "from google.protobuf.internal import builder as _builder\n" - "from google.protobuf import descriptor as _descriptor\n" - "from google.protobuf import descriptor_pool as " - "_descriptor_pool\n" - "from google.protobuf import symbol_database as " - "_symbol_database\n"); - - printer->Print("# @@protoc_insertion_point(imports)\n\n"); - printer->Print("_sym_db = _symbol_database.Default()\n"); - printer->Print("\n\n"); -} +const char kThirdPartyPrefix[] = "google3.third_party.py."; // Returns a Python literal giving the default value for a field. // If the field specifies no explicit default value, we'll return @@ -131,13 +115,13 @@ TProtoStringType StringifyDefaultValue(const FieldDescriptor& field) { switch (field.cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - return StrCat(field.default_value_int32()); + return y_absl::StrCat(field.default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: - return StrCat(field.default_value_uint32()); + return y_absl::StrCat(field.default_value_uint32()); case FieldDescriptor::CPPTYPE_INT64: - return StrCat(field.default_value_int64()); + return y_absl::StrCat(field.default_value_int64()); case FieldDescriptor::CPPTYPE_UINT64: - return StrCat(field.default_value_uint64()); + return y_absl::StrCat(field.default_value_uint64()); case FieldDescriptor::CPPTYPE_DOUBLE: { double value = field.default_value_double(); if (value == std::numeric_limits<double>::infinity()) { @@ -151,7 +135,7 @@ TProtoStringType StringifyDefaultValue(const FieldDescriptor& field) { // infinity * 0 = nan return "(1e10000 * 0)"; } else { - return "float(" + SimpleDtoa(value) + ")"; + return y_absl::StrCat("float(", io::SimpleDtoa(value), ")"); } } case FieldDescriptor::CPPTYPE_FLOAT: { @@ -167,24 +151,24 @@ TProtoStringType StringifyDefaultValue(const FieldDescriptor& field) { // infinity - infinity = nan return "(1e10000 * 0)"; } else { - return "float(" + SimpleFtoa(value) + ")"; + return y_absl::StrCat("float(", io::SimpleFtoa(value), ")"); } } case FieldDescriptor::CPPTYPE_BOOL: return field.default_value_bool() ? "True" : "False"; case FieldDescriptor::CPPTYPE_ENUM: - return StrCat(field.default_value_enum()->number()); + return y_absl::StrCat(field.default_value_enum()->number()); case FieldDescriptor::CPPTYPE_STRING: - return "b\"" + CEscape(field.default_value_string()) + - (field.type() != FieldDescriptor::TYPE_STRING - ? "\"" - : "\".decode('utf-8')"); + return y_absl::StrCat("b\"", y_absl::CEscape(field.default_value_string()), + (field.type() != FieldDescriptor::TYPE_STRING + ? "\"" + : "\".decode('utf-8')")); case FieldDescriptor::CPPTYPE_MESSAGE: return "None"; } // (We could add a default case above but then we wouldn't get the nice // compiler warning when a new type is added.) - GOOGLE_LOG(FATAL) << "Not reached."; + Y_ABSL_LOG(FATAL) << "Not reached."; return ""; } @@ -196,8 +180,9 @@ TProtoStringType StringifySyntax(FileDescriptor::Syntax syntax) { return "proto3"; case FileDescriptor::SYNTAX_UNKNOWN: default: - GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 " - "and proto3 syntax."; + Y_ABSL_LOG(FATAL) + << "Unsupported syntax; this generator only supports proto2 " + "and proto3 syntax."; return ""; } } @@ -212,26 +197,42 @@ uint64_t Generator::GetSupportedFeatures() const { return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL; } +GeneratorOptions Generator::ParseParameter(y_absl::string_view parameter, + TProtoStringType* error) const { + GeneratorOptions options; + + std::vector<std::pair<TProtoStringType, TProtoStringType> > option_pairs; + ParseGeneratorParameter(parameter, &option_pairs); + + for (const std::pair<TProtoStringType, TProtoStringType>& option : option_pairs) { + if (!opensource_runtime_ && + option.first == "no_enforce_api_compatibility") { + // TODO(b/241584880): remove this legacy option, it has no effect. + } else if (!opensource_runtime_ && option.first == "bootstrap") { + options.bootstrap = true; + } else if (option.first == "pyi_out") { + options.generate_pyi = true; + } else if (option.first == "annotate_code") { + options.annotate_pyi = true; + } else { + *error = y_absl::StrCat("Unknown generator option: ", option.first); + } + } + return options; +} + bool Generator::Generate(const FileDescriptor* file, const TProtoStringType& parameter, GeneratorContext* context, TProtoStringType* error) const { // ----------------------------------------------------------------- - // parse generator options - bool cpp_generated_lib_linked = false; - - std::vector<std::pair<TProtoStringType, TProtoStringType> > options; - ParseGeneratorParameter(parameter, &options); - - for (int i = 0; i < options.size(); i++) { - if (options[i].first == "cpp_generated_lib_linked") { - cpp_generated_lib_linked = true; - } else if (options[i].first == "pyi_out") { - python::PyiGenerator pyi_generator; - if (!pyi_generator.Generate(file, "", context, error)) { - return false; - } - } else { - *error = "Unknown generator option: " + options[i].first; + GeneratorOptions options = ParseParameter(parameter, error); + if (!error->empty()) return false; + + // Generate pyi typing information + if (options.generate_pyi) { + python::PyiGenerator pyi_generator; + TProtoStringType pyi_options = options.annotate_pyi ? "annotate_code" : ""; + if (!pyi_generator.Generate(file, pyi_options, context, error)) { return false; } } @@ -243,78 +244,110 @@ bool Generator::Generate(const FileDescriptor* file, // TODO(kenton): The proper thing to do would be to allocate any state on // the stack and use that, so that the Generator class itself does not need // to have any mutable members. Then it is implicitly thread-safe. - MutexLock lock(&mutex_); + y_absl::MutexLock lock(&mutex_); file_ = file; TProtoStringType filename = GetFileName(file, ".py"); - pure_python_workable_ = !cpp_generated_lib_linked; - if (HasPrefixString(file->name(), "google/protobuf/")) { - pure_python_workable_ = true; - } FileDescriptorProto fdp; file_->CopyTo(&fdp); fdp.SerializeToString(&file_descriptor_serialized_); + if (!opensource_runtime_ && GeneratingDescriptorProto()) { + TProtoStringType bootstrap_filename = + "net/proto2/python/internal/descriptor_pb2.py"; + if (options.bootstrap) { + filename = bootstrap_filename; + } else { + std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); + io::Printer printer(output.get(), '$'); + printer.Print( + "from $internal_package$ import descriptor_pb2\n" + "\n", + "internal_package", InternalPackage()); + + // For static checkers, we need to explicitly assign to the symbols we + // publicly export. + for (int i = 0; i < file_->message_type_count(); i++) { + const Descriptor* message = file_->message_type(i); + printer.Print("$name$ = descriptor_pb2.$name$\n", "name", + message->name()); + } + + // Sadly some clients access our internal variables (starting with "_"). + // To support them, we iterate over *all* symbols to expose even the + // private ones. Statically type-checked code should (especially) never + // use these, so we don't worry about making them available to pytype + // checks. + printer.Print( + "\n" + "globals().update(descriptor_pb2.__dict__)\n" + "\n"); + + printer.Print( + "# @@protoc_insertion_point(module_scope)\n" + "\n"); + return true; + } + } std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); - GOOGLE_CHECK(output.get()); + Y_ABSL_CHECK(output.get()); io::Printer printer(output.get(), '$'); printer_ = &printer; - PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto()); - if (pure_python_workable_) { - PrintImports(); - } + PrintTopBoilerplate(); + PrintImports(); PrintFileDescriptor(); - if (pure_python_workable_) { - if (GeneratingDescriptorProto()) { - printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); - printer_->Indent(); - // Create enums before message descriptors - PrintAllNestedEnumsInFile(); - PrintMessageDescriptors(); - FixForeignFieldsInDescriptors(); - printer_->Outdent(); - printer_->Print("else:\n"); - printer_->Indent(); - } - // Find the message descriptors first and then use the message - // descriptor to find enums. - printer_->Print( - "_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())\n"); - if (GeneratingDescriptorProto()) { - printer_->Outdent(); - } + printer_->Print("_globals = globals()\n"); + if (GeneratingDescriptorProto()) { + printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); + printer_->Indent(); + // Create enums before message descriptors + PrintAllNestedEnumsInFile(); + PrintMessageDescriptors(); + FixForeignFieldsInDescriptors(); + printer_->Outdent(); + printer_->Print("else:\n"); + printer_->Indent(); + } + // Find the message descriptors first and then use the message + // descriptor to find enums. + printer_->Print( + "_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)\n"); + if (GeneratingDescriptorProto()) { + printer_->Outdent(); } TProtoStringType module_name = ModuleName(file->name()); + if (!opensource_runtime_) { + module_name = + TProtoStringType(y_absl::StripPrefix(module_name, kThirdPartyPrefix)); + } printer_->Print( "_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, '$module_name$', " - "globals())\n", + "_globals)\n", "module_name", module_name); - if (pure_python_workable_) { - printer.Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); - printer_->Indent(); + printer.Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); + printer_->Indent(); - // We have to fix up the extensions after the message classes themselves, - // since they need to call static RegisterExtension() methods on these - // classes. - FixForeignFieldsInExtensions(); - // Descriptor options may have custom extensions. These custom options - // can only be successfully parsed after we register corresponding - // extensions. Therefore we parse all options again here to recognize - // custom options that may be unknown when we define the descriptors. - // This does not apply to services because they are not used by extensions. - FixAllDescriptorOptions(); + // We have to fix up the extensions after the message classes themselves, + // since they need to call static RegisterExtension() methods on these + // classes. + FixForeignFieldsInExtensions(); + // Descriptor options may have custom extensions. These custom options + // can only be successfully parsed after we register corresponding + // extensions. Therefore we parse all options again here to recognize + // custom options that may be unknown when we define the descriptors. + // This does not apply to services because they are not used by extensions. + FixAllDescriptorOptions(); - // Set serialized_start and serialized_end. - SetSerializedPbInterval(); + // Set serialized_start and serialized_end. + SetSerializedPbInterval(); - printer_->Outdent(); - } + printer_->Outdent(); if (HasGenericServices(file)) { printer_->Print( - "_builder.BuildServices(DESCRIPTOR, '$module_name$', globals())\n", + "_builder.BuildServices(DESCRIPTOR, '$module_name$', _globals)\n", "module_name", module_name); } @@ -323,13 +356,45 @@ bool Generator::Generate(const FileDescriptor* file, return !printer.failed(); } +// file output by this generator. +void Generator::PrintTopBoilerplate() const { + // TODO(robinson): Allow parameterization of Python version? + printer_->Print( + "# -*- coding: utf-8 -*-\n" + "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "# source: $filename$\n" + "\"\"\"Generated protocol buffer code.\"\"\"\n", + "filename", file_->name()); + if (!opensource_runtime_) { + // This import is needed so that compatibility proto1 compiler output + // inserted at protoc_insertion_point can refer to other protos like + // google3.a.b.c. Code generated by proto2 compiler doesn't do it, and + // instead uses aliases assigned when importing modules. + printer_->Print("import google3\n"); + } + printer_->Print( + "from $internal_package$ import builder as _builder\n" + "from $public_package$ import descriptor as _descriptor\n" + "from $public_package$ import descriptor_pool as _descriptor_pool\n" + "from $public_package$ import symbol_database as _symbol_database\n", + "internal_package", InternalPackage(), "public_package", PublicPackage()); + + printer_->Print("# @@protoc_insertion_point(imports)\n\n"); + printer_->Print("_sym_db = _symbol_database.Default()\n"); + printer_->Print("\n\n"); +} + // Prints Python imports for all modules imported by |file|. void Generator::PrintImports() const { for (int i = 0; i < file_->dependency_count(); ++i) { - const TProtoStringType& filename = file_->dependency(i)->name(); + y_absl::string_view filename = file_->dependency(i)->name(); TProtoStringType module_name = ModuleName(filename); TProtoStringType module_alias = ModuleAlias(filename); + if (!opensource_runtime_) { + module_name = + TProtoStringType(y_absl::StripPrefix(module_name, kThirdPartyPrefix)); + } if (ContainsPythonKeyword(module_name)) { // If the module path contains a Python keyword, we have to quote the // module name and import it using importlib. Otherwise the usual kind of @@ -339,15 +404,16 @@ void Generator::PrintImports() const { printer_->Print("$alias$ = importlib.import_module('$name$')\n", "alias", module_alias, "name", module_name); } else { - int last_dot_pos = module_name.rfind('.'); + size_t last_dot_pos = module_name.rfind('.'); TProtoStringType import_statement; if (last_dot_pos == TProtoStringType::npos) { // NOTE(petya): this is not tested as it would require a protocol buffer // outside of any package, and I don't think that is easily achievable. - import_statement = "import " + module_name; + import_statement = y_absl::StrCat("import ", module_name); } else { - import_statement = "from " + module_name.substr(0, last_dot_pos) + - " import " + module_name.substr(last_dot_pos + 1); + import_statement = + y_absl::StrCat("from ", module_name.substr(0, last_dot_pos), + " import ", module_name.substr(last_dot_pos + 1)); } printer_->Print("$statement$ as $alias$\n", "statement", import_statement, "alias", module_alias); @@ -360,6 +426,10 @@ void Generator::PrintImports() const { // Print public imports. for (int i = 0; i < file_->public_dependency_count(); ++i) { TProtoStringType module_name = ModuleName(file_->public_dependency(i)->name()); + if (!opensource_runtime_) { + module_name = + TProtoStringType(y_absl::StripPrefix(module_name, kThirdPartyPrefix)); + } printer_->Print("from $module$ import *\n", "module", module_name); } printer_->Print("\n"); @@ -367,13 +437,13 @@ void Generator::PrintImports() const { // Prints the single file descriptor for this file. void Generator::PrintFileDescriptor() const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_name"] = kDescriptorKey; m["name"] = file_->name(); m["package"] = file_->package(); m["syntax"] = StringifySyntax(file_->syntax()); m["options"] = OptionsValue(file_->options().SerializeAsString()); - m["serialized_descriptor"] = strings::CHexEscape(file_descriptor_serialized_); + m["serialized_descriptor"] = y_absl::CHexEscape(file_descriptor_serialized_); if (GeneratingDescriptorProto()) { printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); printer_->Indent(); @@ -389,30 +459,26 @@ void Generator::PrintFileDescriptor() const { " create_key=_descriptor._internal_create_key,\n"; printer_->Print(m, file_descriptor_template); printer_->Indent(); - if (pure_python_workable_) { - printer_->Print("serialized_pb=b'$value$'\n", "value", - strings::CHexEscape(file_descriptor_serialized_)); - if (file_->dependency_count() != 0) { - printer_->Print(",\ndependencies=["); - for (int i = 0; i < file_->dependency_count(); ++i) { - TProtoStringType module_alias = ModuleAlias(file_->dependency(i)->name()); - printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", - module_alias); - } - printer_->Print("]"); + printer_->Print("serialized_pb=b'$value$'\n", "value", + y_absl::CHexEscape(file_descriptor_serialized_)); + if (file_->dependency_count() != 0) { + printer_->Print(",\ndependencies=["); + for (int i = 0; i < file_->dependency_count(); ++i) { + TProtoStringType module_alias = ModuleAlias(file_->dependency(i)->name()); + printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", + module_alias); } - if (file_->public_dependency_count() > 0) { - printer_->Print(",\npublic_dependencies=["); - for (int i = 0; i < file_->public_dependency_count(); ++i) { - TProtoStringType module_alias = - ModuleAlias(file_->public_dependency(i)->name()); - printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", - module_alias); - } - printer_->Print("]"); + printer_->Print("]"); + } + if (file_->public_dependency_count() > 0) { + printer_->Print(",\npublic_dependencies=["); + for (int i = 0; i < file_->public_dependency_count(); ++i) { + TProtoStringType module_alias = + ModuleAlias(file_->public_dependency(i)->name()); + printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias", + module_alias); } - } else { - printer_->Print("serialized_pb=''\n"); + printer_->Print("]"); } // TODO(falk): Also print options and fix the message_type, enum_type, @@ -446,7 +512,7 @@ void Generator::PrintAllNestedEnumsInFile() const { // enum name to a Python EnumDescriptor object equivalent to // enum_descriptor. void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; TProtoStringType module_level_descriptor_name = ModuleLevelDescriptorName(enum_descriptor); m["descriptor_name"] = module_level_descriptor_name; @@ -467,11 +533,9 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { printer_->Indent(); printer_->Indent(); - if (pure_python_workable_) { - for (int i = 0; i < enum_descriptor.value_count(); ++i) { - PrintEnumValueDescriptor(*enum_descriptor.value(i)); - printer_->Print(",\n"); - } + for (int i = 0; i < enum_descriptor.value_count(); ++i) { + PrintEnumValueDescriptor(*enum_descriptor.value(i)); + printer_->Print(",\n"); } printer_->Outdent(); @@ -482,10 +546,8 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { EnumDescriptorProto edp; printer_->Outdent(); printer_->Print(")\n"); - if (pure_python_workable_) { - printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", - module_level_descriptor_name); - } + printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", + module_level_descriptor_name); printer_->Print("\n"); } @@ -525,7 +587,7 @@ void Generator::PrintServices() const { void Generator::PrintServiceDescriptor( const ServiceDescriptor& descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["service_name"] = ModuleLevelServiceDescriptorName(descriptor); m["name"] = descriptor.name(); m["file"] = kDescriptorKey; @@ -535,13 +597,13 @@ void Generator::PrintServiceDescriptor( void Generator::PrintDescriptorKeyAndModuleName( const ServiceDescriptor& descriptor) const { TProtoStringType name = ModuleLevelServiceDescriptorName(descriptor); - if (!pure_python_workable_) { - name = "_descriptor.ServiceDescriptor(full_name='" + - descriptor.full_name() + "')"; - } printer_->Print("$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", kDescriptorKey, "descriptor_name", name); TProtoStringType module_name = ModuleName(file_->name()); + if (!opensource_runtime_) { + module_name = + TProtoStringType(y_absl::StripPrefix(module_name, kThirdPartyPrefix)); + } printer_->Print("__module__ = '$module_name$'\n", "module_name", module_name); } @@ -575,7 +637,7 @@ void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { // // Mutually recursive with PrintNestedDescriptors(). void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["name"] = message_descriptor.name(); m["full_name"] = message_descriptor.full_name(); m["file"] = kDescriptorKey; @@ -634,8 +696,8 @@ 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", StrCat(range->start), - "end", StrCat(range->end)); + printer_->Print("($start$, $end$), ", "start", y_absl::StrCat(range->start), + "end", y_absl::StrCat(range->end)); } printer_->Print("],\n"); printer_->Print("oneofs=[\n"); @@ -645,12 +707,13 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { m.clear(); m["name"] = desc->name(); m["full_name"] = desc->full_name(); - m["index"] = StrCat(desc->index()); + m["index"] = y_absl::StrCat(desc->index()); options_string = OptionsValue(desc->options().SerializeAsString()); if (options_string == "None") { m["serialized_options"] = ""; } else { - m["serialized_options"] = ", serialized_options=" + options_string; + m["serialized_options"] = + y_absl::StrCat(", serialized_options=", options_string); } printer_->Print(m, "_descriptor.OneofDescriptor(\n" @@ -699,16 +762,16 @@ void Generator::PrintMessages() const { // Mutually recursive with PrintNestedMessages(). // Collect nested message names to_register for the symbol_database. void Generator::PrintMessage(const Descriptor& message_descriptor, - const TProtoStringType& prefix, + y_absl::string_view prefix, std::vector<TProtoStringType>* to_register, bool is_nested) const { TProtoStringType qualified_name; if (is_nested) { if (IsPythonKeyword(message_descriptor.name())) { - qualified_name = - "getattr(" + prefix + ", '" + message_descriptor.name() + "')"; + qualified_name = y_absl::StrCat("getattr(", prefix, ", '", + message_descriptor.name(), "')"); } else { - qualified_name = prefix + "." + message_descriptor.name(); + qualified_name = y_absl::StrCat(prefix, ".", message_descriptor.name()); } printer_->Print( "'$name$' : _reflection.GeneratedProtocolMessageType('$name$', " @@ -726,16 +789,15 @@ void Generator::PrintMessage(const Descriptor& message_descriptor, to_register->push_back(qualified_name); PrintNestedMessages(message_descriptor, qualified_name, to_register); - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_key"] = kDescriptorKey; - if (pure_python_workable_) { - m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); - } else { - m["descriptor_name"] = "_descriptor.Descriptor(full_name='" + - message_descriptor.full_name() + "')"; - } + m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); printer_->Print(m, "'$descriptor_key$' : $descriptor_name$,\n"); TProtoStringType module_name = ModuleName(file_->name()); + if (!opensource_runtime_) { + module_name = + TProtoStringType(y_absl::StripPrefix(module_name, kThirdPartyPrefix)); + } printer_->Print("'__module__' : '$module_name$'\n", "module_name", module_name); printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n", @@ -747,7 +809,7 @@ void Generator::PrintMessage(const Descriptor& message_descriptor, // Prints all nested messages within |containing_descriptor|. // Mutually recursive with PrintMessage(). void Generator::PrintNestedMessages( - const Descriptor& containing_descriptor, const TProtoStringType& prefix, + const Descriptor& containing_descriptor, y_absl::string_view prefix, std::vector<TProtoStringType>* to_register) const { for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { printer_->Print("\n"); @@ -782,7 +844,7 @@ void Generator::FixForeignFieldsInDescriptor( FixContainingTypeInDescriptor(enum_descriptor, &descriptor); } for (int i = 0; i < descriptor.oneof_decl_count(); ++i) { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; const OneofDescriptor* oneof = descriptor.oneof_decl(i); m["descriptor_name"] = ModuleLevelDescriptorName(descriptor); m["oneof_name"] = oneof->name(); @@ -801,7 +863,7 @@ void Generator::FixForeignFieldsInDescriptor( } void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_name"] = kDescriptorKey; m["message_name"] = descriptor.name(); m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor); @@ -813,7 +875,7 @@ void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { void Generator::AddServiceToFileDescriptor( const ServiceDescriptor& descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_name"] = kDescriptorKey; m["service_name"] = descriptor.name(); m["service_descriptor_name"] = ModuleLevelServiceDescriptorName(descriptor); @@ -825,7 +887,7 @@ void Generator::AddServiceToFileDescriptor( void Generator::AddEnumToFileDescriptor( const EnumDescriptor& descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_name"] = kDescriptorKey; m["enum_name"] = descriptor.name(); m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor); @@ -837,7 +899,7 @@ void Generator::AddEnumToFileDescriptor( void Generator::AddExtensionToFileDescriptor( const FieldDescriptor& descriptor) const { - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["descriptor_name"] = kDescriptorKey; m["field_name"] = descriptor.name(); m["resolved_name"] = ResolveKeyword(descriptor.name()); @@ -858,10 +920,10 @@ void Generator::AddExtensionToFileDescriptor( // is NULL. void Generator::FixForeignFieldsInField( const Descriptor* containing_type, const FieldDescriptor& field, - const TProtoStringType& python_dict_name) const { + y_absl::string_view python_dict_name) const { const TProtoStringType field_referencing_expression = FieldReferencingExpression(containing_type, field, python_dict_name); - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["field_ref"] = field_referencing_expression; const Descriptor* foreign_message_type = field.message_type(); if (foreign_message_type) { @@ -886,15 +948,15 @@ void Generator::FixForeignFieldsInField( // is NULL. TProtoStringType Generator::FieldReferencingExpression( const Descriptor* containing_type, const FieldDescriptor& field, - const TProtoStringType& python_dict_name) const { + y_absl::string_view python_dict_name) const { // We should only ever be looking up fields in the current file. // The only things we refer to from other files are message descriptors. - GOOGLE_CHECK_EQ(field.file(), file_) + Y_ABSL_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. " << file_->name(); if (!containing_type) { return ResolveKeyword(field.name()); } - return strings::Substitute("$0.$1['$2']", + return y_absl::Substitute("$0.$1['$2']", ModuleLevelDescriptorName(*containing_type), python_dict_name, field.name()); } @@ -955,9 +1017,9 @@ void Generator::FixForeignFieldsInExtensions() const { void Generator::FixForeignFieldsInExtension( const FieldDescriptor& extension_field) const { - GOOGLE_CHECK(extension_field.is_extension()); + Y_ABSL_CHECK(extension_field.is_extension()); - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; // Confusingly, for FieldDescriptors that happen to be extensions, // containing_type() means "extended type." // On the other hand, extension_scope() will give us what we normally @@ -989,10 +1051,10 @@ void Generator::PrintEnumValueDescriptor( // More circular references. ::sigh:: TProtoStringType options_string; descriptor.options().SerializeToString(&options_string); - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["name"] = descriptor.name(); - m["index"] = StrCat(descriptor.index()); - m["number"] = StrCat(descriptor.number()); + m["index"] = y_absl::StrCat(descriptor.index()); + m["number"] = y_absl::StrCat(descriptor.number()); m["options"] = OptionsValue(options_string); printer_->Print(m, "_descriptor.EnumValueDescriptor(\n" @@ -1004,11 +1066,11 @@ void Generator::PrintEnumValueDescriptor( // Returns a CEscaped string of serialized_options. TProtoStringType Generator::OptionsValue( - const TProtoStringType& serialized_options) const { + y_absl::string_view serialized_options) const { if (serialized_options.length() == 0 || GeneratingDescriptorProto()) { return "None"; } else { - return "b'" + CEscape(serialized_options) + "'"; + return y_absl::StrCat("b'", y_absl::CEscape(serialized_options), "'"); } } @@ -1017,20 +1079,21 @@ void Generator::PrintFieldDescriptor(const FieldDescriptor& field, bool is_extension) const { TProtoStringType options_string; field.options().SerializeToString(&options_string); - std::map<TProtoStringType, TProtoStringType> m; + y_absl::flat_hash_map<y_absl::string_view, TProtoStringType> m; m["name"] = field.name(); m["full_name"] = field.full_name(); - m["index"] = StrCat(field.index()); - m["number"] = StrCat(field.number()); - m["type"] = StrCat(field.type()); - m["cpp_type"] = StrCat(field.cpp_type()); - m["label"] = StrCat(field.label()); + m["index"] = y_absl::StrCat(field.index()); + m["number"] = y_absl::StrCat(field.number()); + m["type"] = y_absl::StrCat(field.type()); + m["cpp_type"] = y_absl::StrCat(field.cpp_type()); + m["label"] = y_absl::StrCat(field.label()); m["has_default_value"] = field.has_default_value() ? "True" : "False"; m["default_value"] = StringifyDefaultValue(field); m["is_extension"] = is_extension ? "True" : "False"; m["serialized_options"] = OptionsValue(options_string); - m["json_name"] = - field.has_json_name() ? ", json_name='" + field.json_name() + "'" : ""; + m["json_name"] = field.has_json_name() + ? y_absl::StrCat(", json_name='", field.json_name(), "'") + : ""; // We always set message_type and enum_type to None at this point, and then // these fields in correctly after all referenced descriptors have been // defined and/or imported (see FixForeignFieldsInDescriptors()). @@ -1050,8 +1113,8 @@ void Generator::PrintFieldDescriptor(const FieldDescriptor& field, // Helper for Print{Fields,Extensions}InDescriptor(). void Generator::PrintFieldDescriptorsInDescriptor( const Descriptor& message_descriptor, bool is_extension, - const TProtoStringType& list_variable_name, int (Descriptor::*CountFn)() const, - const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const { + y_absl::string_view list_variable_name, int (Descriptor::*CountFn)() const, + const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const { printer_->Print("$list$=[\n", "list", list_variable_name); printer_->Indent(); for (int i = 0; i < (message_descriptor.*CountFn)(); ++i) { @@ -1106,14 +1169,14 @@ TProtoStringType Generator::ModuleLevelDescriptorName( // The C++ implementation doesn't guard against this either. Leaving // it for now... TProtoStringType name = NamePrefixedWithNestedTypes(descriptor, "_"); - ToUpper(&name); + y_absl::AsciiStrToUpper(&name); // Module-private for now. Easy to make public later; almost impossible // to make private later. - name = "_" + name; + name = y_absl::StrCat("_", name); // We now have the name relative to its own module. Also qualify with // the module name iff this descriptor is from a different .proto file. if (descriptor.file() != file_) { - name = ModuleAlias(descriptor.file()->name()) + "." + name; + name = y_absl::StrCat(ModuleAlias(descriptor.file()->name()), ".", name); } return name; } @@ -1126,7 +1189,7 @@ TProtoStringType Generator::ModuleLevelMessageName( const Descriptor& descriptor) const { TProtoStringType name = NamePrefixedWithNestedTypes(descriptor, "."); if (descriptor.file() != file_) { - name = ModuleAlias(descriptor.file()->name()) + "." + name; + name = y_absl::StrCat(ModuleAlias(descriptor.file()->name()), ".", name); } return name; } @@ -1135,15 +1198,24 @@ TProtoStringType Generator::ModuleLevelMessageName( // descriptor. TProtoStringType Generator::ModuleLevelServiceDescriptorName( const ServiceDescriptor& descriptor) const { - TProtoStringType name = descriptor.name(); - ToUpper(&name); - name = "_" + name; + TProtoStringType name = y_absl::StrCat("_", descriptor.name()); + y_absl::AsciiStrToUpper(&name); if (descriptor.file() != file_) { - name = ModuleAlias(descriptor.file()->name()) + "." + name; + name = y_absl::StrCat(ModuleAlias(descriptor.file()->name()), ".", name); } return name; } +TProtoStringType Generator::PublicPackage() const { + return opensource_runtime_ ? "google.protobuf" + : "google3.net.google.protobuf.python.public"; +} + +TProtoStringType Generator::InternalPackage() const { + return opensource_runtime_ ? "google.protobuf.internal" + : "google3.net.google.protobuf.python.internal"; +} + // Prints standard constructor arguments serialized_start and serialized_end. // Args: // descriptor: The cpp descriptor to have a serialized reference. @@ -1155,23 +1227,23 @@ TProtoStringType Generator::ModuleLevelServiceDescriptorName( template <typename DescriptorT, typename DescriptorProtoT> void Generator::PrintSerializedPbInterval(const DescriptorT& descriptor, DescriptorProtoT& proto, - const TProtoStringType& name) const { + y_absl::string_view name) const { descriptor.CopyTo(&proto); TProtoStringType sp; proto.SerializeToString(&sp); int offset = file_descriptor_serialized_.find(sp); - GOOGLE_CHECK_GE(offset, 0); + Y_ABSL_CHECK_GE(offset, 0); printer_->Print( - "$name$._serialized_start=$serialized_start$\n" - "$name$._serialized_end=$serialized_end$\n", - "name", name, "serialized_start", StrCat(offset), "serialized_end", - StrCat(offset + sp.size())); + "_globals['$name$']._serialized_start=$serialized_start$\n" + "_globals['$name$']._serialized_end=$serialized_end$\n", + "name", name, "serialized_start", y_absl::StrCat(offset), "serialized_end", + y_absl::StrCat(offset + sp.size())); } namespace { -void PrintDescriptorOptionsFixingCode(const TProtoStringType& descriptor, - const TProtoStringType& options, +void PrintDescriptorOptionsFixingCode(y_absl::string_view descriptor, + y_absl::string_view options, io::Printer* printer) { // Reset the _options to None thus DescriptorBase.GetOptions() can // parse _options again after extensions are registered. @@ -1256,7 +1328,7 @@ void Generator::FixAllDescriptorOptions() const { void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const { TProtoStringType oneof_options = OptionsValue(oneof.options().SerializeAsString()); if (oneof_options != "None") { - TProtoStringType oneof_name = strings::Substitute( + TProtoStringType oneof_name = y_absl::Substitute( "$0.$1['$2']", ModuleLevelDescriptorName(*oneof.containing_type()), "oneofs_by_name", oneof.name()); PrintDescriptorOptionsFixingCode(oneof_name, oneof_options, printer_); @@ -1278,7 +1350,7 @@ void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { OptionsValue(value_descriptor.options().SerializeAsString()); if (value_options != "None") { PrintDescriptorOptionsFixingCode( - StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), + y_absl::StrFormat("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), value_descriptor.name().c_str()), value_options, printer_); } @@ -1303,8 +1375,8 @@ void Generator::FixOptionsForService( TProtoStringType method_options = OptionsValue(method->options().SerializeAsString()); if (method_options != "None") { - TProtoStringType method_name = - descriptor_name + ".methods_by_name['" + method->name() + "']"; + TProtoStringType method_name = y_absl::StrCat( + descriptor_name, ".methods_by_name['", method->name(), "']"); PrintDescriptorOptionsFixingCode(method_name, method_options, printer_); } } @@ -1370,7 +1442,7 @@ void Generator::FixOptionsForMessage(const Descriptor& descriptor) const { // If a dependency forwards other files through public dependencies, let's // copy over the corresponding module aliases. void Generator::CopyPublicDependenciesAliases( - const TProtoStringType& copy_from, const FileDescriptor* file) const { + y_absl::string_view copy_from, const FileDescriptor* file) const { for (int i = 0; i < file->public_dependency_count(); ++i) { TProtoStringType module_name = ModuleName(file->public_dependency(i)->name()); TProtoStringType module_alias = ModuleAlias(file->public_dependency(i)->name()); diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.h index 8111bf733fc..8691b552219 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/generator.h @@ -36,12 +36,14 @@ #define GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ #include <string> +#include <vector> -#include <google/protobuf/stubs/mutex.h> -#include <google/protobuf/compiler/code_generator.h> +#include "y_absl/strings/string_view.h" +#include "y_absl/synchronization/mutex.h" +#include "google/protobuf/compiler/code_generator.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -64,9 +66,18 @@ 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. + +struct GeneratorOptions { + bool generate_pyi = false; + bool annotate_pyi = false; + bool bootstrap = false; +}; + class PROTOC_EXPORT Generator : public CodeGenerator { public: Generator(); + Generator(const Generator&) = delete; + Generator& operator=(const Generator&) = delete; ~Generator() override; // CodeGenerator methods. @@ -76,7 +87,13 @@ class PROTOC_EXPORT Generator : public CodeGenerator { uint64_t GetSupportedFeatures() const override; + void set_opensource_runtime(bool opensource) { + opensource_runtime_ = opensource; + } + private: + GeneratorOptions ParseParameter(y_absl::string_view parameter, + TProtoStringType* error) const; void PrintImports() const; void PrintFileDescriptor() const; void PrintAllNestedEnumsInFile() const; @@ -87,8 +104,8 @@ class PROTOC_EXPORT Generator : public CodeGenerator { bool is_extension) const; void PrintFieldDescriptorsInDescriptor( const Descriptor& message_descriptor, bool is_extension, - const TProtoStringType& list_variable_name, int (Descriptor::*CountFn)() const, - const FieldDescriptor* (Descriptor::*GetterFn)(int)const) const; + y_absl::string_view list_variable_name, int (Descriptor::*CountFn)() const, + const FieldDescriptor* (Descriptor::*GetterFn)(int) const) const; void PrintFieldsInDescriptor(const Descriptor& message_descriptor) const; void PrintExtensionsInDescriptor(const Descriptor& message_descriptor) const; void PrintMessageDescriptors() const; @@ -97,11 +114,11 @@ class PROTOC_EXPORT Generator : public CodeGenerator { void PrintMessages() const; void PrintMessage(const Descriptor& message_descriptor, - const TProtoStringType& prefix, + y_absl::string_view prefix, std::vector<TProtoStringType>* to_register, bool is_nested) const; void PrintNestedMessages(const Descriptor& containing_descriptor, - const TProtoStringType& prefix, + y_absl::string_view prefix, std::vector<TProtoStringType>* to_register) const; void FixForeignFieldsInDescriptors() const; @@ -110,14 +127,14 @@ class PROTOC_EXPORT Generator : public CodeGenerator { const Descriptor* containing_descriptor) const; void FixForeignFieldsInField(const Descriptor* containing_type, const FieldDescriptor& field, - const TProtoStringType& python_dict_name) const; + y_absl::string_view 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; TProtoStringType FieldReferencingExpression( const Descriptor* containing_type, const FieldDescriptor& field, - const TProtoStringType& python_dict_name) const; + y_absl::string_view python_dict_name) const; template <typename DescriptorT> void FixContainingTypeInDescriptor( const DescriptorT& descriptor, @@ -128,6 +145,7 @@ class PROTOC_EXPORT Generator : public CodeGenerator { const FieldDescriptor& extension_field) const; void FixForeignFieldsInNestedExtensions(const Descriptor& descriptor) const; + void PrintTopBoilerplate() const; void PrintServices() const; void PrintServiceDescriptors() const; void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const; @@ -137,7 +155,7 @@ class PROTOC_EXPORT Generator : public CodeGenerator { const ServiceDescriptor& descriptor) const; void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const; - TProtoStringType OptionsValue(const TProtoStringType& serialized_options) const; + TProtoStringType OptionsValue(y_absl::string_view serialized_options) const; bool GeneratingDescriptorProto() const; template <typename DescriptorT> @@ -145,11 +163,13 @@ class PROTOC_EXPORT Generator : public CodeGenerator { TProtoStringType ModuleLevelMessageName(const Descriptor& descriptor) const; TProtoStringType ModuleLevelServiceDescriptorName( const ServiceDescriptor& descriptor) const; + TProtoStringType PublicPackage() const; + TProtoStringType InternalPackage() const; template <typename DescriptorT, typename DescriptorProtoT> void PrintSerializedPbInterval(const DescriptorT& descriptor, DescriptorProtoT& proto, - const TProtoStringType& name) const; + y_absl::string_view name) const; void FixAllDescriptorOptions() const; void FixOptionsForField(const FieldDescriptor& field) const; @@ -161,18 +181,17 @@ class PROTOC_EXPORT Generator : public CodeGenerator { void SetSerializedPbInterval() const; void SetMessagePbInterval(const Descriptor& descriptor) const; - void CopyPublicDependenciesAliases(const TProtoStringType& copy_from, + void CopyPublicDependenciesAliases(y_absl::string_view 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 y_absl::Mutex mutex_; mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_. mutable TProtoStringType file_descriptor_serialized_; mutable io::Printer* printer_; // Set in Generate(). Under mutex_. - mutable bool pure_python_workable_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator); + bool opensource_runtime_ = true; }; } // namespace python @@ -180,6 +199,6 @@ class PROTOC_EXPORT Generator : public CodeGenerator { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.cc b/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.cc index ee7461bc83c..f41603420cc 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.cc @@ -28,36 +28,45 @@ // (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/python/helpers.h> +#include "google/protobuf/compiler/python/helpers.h" #include <algorithm> - -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> +#include <string> +#include <vector> + +#include "y_absl/log/absl_check.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/strings/strip.h" +#include "google/protobuf/compiler/code_generator.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" namespace google { namespace protobuf { namespace compiler { namespace python { -TProtoStringType FixEv(const TProtoStringType& filename) { - if (HasSuffixString(filename, ".ev")) { - return StripSuffixString(filename, ".ev") + "_ev.proto"; - } - return filename; +TProtoStringType FixEv(TProtoStringType filename) { + constexpr auto kSuffixLen = 3; + if (filename.EndsWith(".ev")) { + return filename.substr(0, filename.length() - kSuffixLen) + "_ev.proto"; + } + return filename; } // Returns the Python module name expected for a given .proto filename. -TProtoStringType ModuleName(const TProtoStringType& filename) { - TProtoStringType basename = StripProto(FixEv(filename)); - ReplaceCharacters(&basename, "-", '_'); - ReplaceCharacters(&basename, "/", '.'); - return basename + "_pb2"; +TProtoStringType ModuleName(y_absl::string_view filename) { + TProtoStringType str(std::string{filename}); + TProtoStringType basename = StripProto(FixEv(str)); + y_absl::StrReplaceAll({{"-", "_"}, {"/", "."}}, &basename); + return y_absl::StrCat(basename, "_pb2"); } -TProtoStringType StrippedModuleName(const TProtoStringType& filename) { +TProtoStringType StrippedModuleName(y_absl::string_view filename) { TProtoStringType module_name = ModuleName(filename); return module_name; } @@ -74,8 +83,8 @@ const char* const kKeywords[] = { const char* const* kKeywordsEnd = kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0])); -bool ContainsPythonKeyword(const TProtoStringType& module_name) { - std::vector<TProtoStringType> tokens = Split(module_name, "."); +bool ContainsPythonKeyword(y_absl::string_view module_name) { + std::vector<y_absl::string_view> tokens = y_absl::StrSplit(module_name, '.'); for (int i = 0; i < static_cast<int>(tokens.size()); ++i) { if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) { return true; @@ -84,23 +93,23 @@ bool ContainsPythonKeyword(const TProtoStringType& module_name) { return false; } -bool IsPythonKeyword(const TProtoStringType& name) { +bool IsPythonKeyword(y_absl::string_view name) { return (std::find(kKeywords, kKeywordsEnd, name) != kKeywordsEnd); } -TProtoStringType ResolveKeyword(const TProtoStringType& name) { +TProtoStringType ResolveKeyword(y_absl::string_view name) { if (IsPythonKeyword(name)) { - return "globals()['" + name + "']"; + return y_absl::StrCat("globals()['", name, "']"); } - return name; + return TProtoStringType(name); } TProtoStringType GetFileName(const FileDescriptor* file_des, - const TProtoStringType& suffix) { + y_absl::string_view suffix) { TProtoStringType module_name = ModuleName(file_des->name()); TProtoStringType filename = module_name; - ReplaceCharacters(&filename, ".", '/'); - filename += suffix; + y_absl::StrReplaceAll({{".", "/"}}, &filename); + y_absl::StrAppend(&filename, suffix); return filename; } @@ -108,17 +117,23 @@ bool HasGenericServices(const FileDescriptor* file) { return file->service_count() > 0 && file->options().py_generic_services(); } +TProtoStringType GeneratedCodeToBase64(const GeneratedCodeInfo& annotations) { + TProtoStringType result; + y_absl::Base64Escape(annotations.SerializeAsString(), &result); + return result; +} + template <typename DescriptorT> TProtoStringType NamePrefixedWithNestedTypes(const DescriptorT& descriptor, - const TProtoStringType& separator) { + y_absl::string_view separator) { TProtoStringType name = descriptor.name(); const Descriptor* parent = descriptor.containing_type(); if (parent != nullptr) { TProtoStringType prefix = NamePrefixedWithNestedTypes(*parent, separator); if (separator == "." && IsPythonKeyword(name)) { - return "getattr(" + prefix + ", '" + name + "')"; + return y_absl::StrCat("getattr(", prefix, ", '", name, "')"); } else { - return prefix + separator + name; + return y_absl::StrCat(prefix, separator, name); } } if (separator == ".") { @@ -128,9 +143,9 @@ TProtoStringType NamePrefixedWithNestedTypes(const DescriptorT& descriptor, } template TProtoStringType NamePrefixedWithNestedTypes<Descriptor>( - const Descriptor& descriptor, const TProtoStringType& separator); + const Descriptor& descriptor, y_absl::string_view separator); template TProtoStringType NamePrefixedWithNestedTypes<EnumDescriptor>( - const EnumDescriptor& descriptor, const TProtoStringType& separator); + const EnumDescriptor& descriptor, y_absl::string_view separator); } // namespace python } // namespace compiler diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.h b/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.h index 8745698acf6..5d77d73394f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/helpers.h @@ -33,26 +33,29 @@ #include <string> -#include <google/protobuf/descriptor.h> +#include "y_absl/strings/str_replace.h" +#include "y_absl/strings/string_view.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" namespace google { namespace protobuf { namespace compiler { namespace python { - -TProtoStringType ModuleName(const TProtoStringType& filename); -TProtoStringType StrippedModuleName(const TProtoStringType& filename); -bool ContainsPythonKeyword(const TProtoStringType& module_name); -bool IsPythonKeyword(const TProtoStringType& name); -TProtoStringType ResolveKeyword(const TProtoStringType& name); +TProtoStringType ModuleName(y_absl::string_view filename); +TProtoStringType StrippedModuleName(y_absl::string_view filename); +bool ContainsPythonKeyword(y_absl::string_view module_name); +bool IsPythonKeyword(y_absl::string_view name); +TProtoStringType ResolveKeyword(y_absl::string_view name); TProtoStringType GetFileName(const FileDescriptor* file_des, - const TProtoStringType& suffix); + y_absl::string_view suffix); bool HasGenericServices(const FileDescriptor* file); +TProtoStringType GeneratedCodeToBase64(const GeneratedCodeInfo& annotations); template <typename DescriptorT> TProtoStringType NamePrefixedWithNestedTypes(const DescriptorT& descriptor, - const TProtoStringType& separator); + y_absl::string_view separator); } // namespace python } // namespace compiler diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.cc index 242cdd71f2c..3e7c2538958 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.cc @@ -28,61 +28,61 @@ // (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/python/pyi_generator.h> +#include "google/protobuf/compiler/python/pyi_generator.h" #include <string> - -#include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/compiler/python/helpers.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> +#include <utility> +#include <vector> + +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/ascii.h" +#include "y_absl/strings/match.h" +#include "y_absl/strings/str_split.h" +#include "google/protobuf/compiler/python/helpers.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { namespace compiler { namespace python { -template <typename DescriptorT> -struct SortByName { - bool operator()(const DescriptorT* l, const DescriptorT* r) const { - return l->name() < r->name(); - } -}; - PyiGenerator::PyiGenerator() : file_(nullptr) {} PyiGenerator::~PyiGenerator() {} -void PyiGenerator::PrintItemMap( - const std::map<TProtoStringType, TProtoStringType>& item_map) const { - for (const auto& entry : item_map) { - printer_->Print("$key$: $value$\n", "key", entry.first, "value", - entry.second); - } -} - template <typename DescriptorT> -TProtoStringType PyiGenerator::ModuleLevelName( - const DescriptorT& descriptor, - const std::map<TProtoStringType, TProtoStringType>& import_map) const { +TProtoStringType PyiGenerator::ModuleLevelName(const DescriptorT& descriptor) const { TProtoStringType name = NamePrefixedWithNestedTypes(descriptor, "."); if (descriptor.file() != file_) { TProtoStringType module_alias; TProtoStringType filename = descriptor.file()->name(); - if (import_map.find(filename) == import_map.end()) { + if (import_map_.find(filename) == import_map_.end()) { TProtoStringType module_name = ModuleName(descriptor.file()->name()); - std::vector<TProtoStringType> tokens = Split(module_name, "."); - module_alias = "_" + tokens.back(); + std::vector<y_absl::string_view> tokens = y_absl::StrSplit(module_name, '.'); + module_alias = y_absl::StrCat("_", tokens.back()); } else { - module_alias = import_map.at(filename); + module_alias = import_map_.at(filename); } - name = module_alias + "." + name; + name = y_absl::StrCat(module_alias, ".", name); } return name; } +TProtoStringType PyiGenerator::PublicPackage() const { + return opensource_runtime_ ? "google.protobuf" + : "google3.net.google.protobuf.python.public"; +} + +TProtoStringType PyiGenerator::InternalPackage() const { + return opensource_runtime_ ? "google.protobuf.internal" + : "google3.net.google.protobuf.python.internal"; +} + struct ImportModules { bool has_repeated = false; // _containers bool has_iterable = false; // typing.Iterable @@ -156,41 +156,40 @@ void CheckImportModules(const Descriptor* descriptor, void PyiGenerator::PrintImportForDescriptor( const FileDescriptor& desc, - std::map<TProtoStringType, TProtoStringType>* import_map, - std::set<TProtoStringType>* seen_aliases) const { + y_absl::flat_hash_set<TProtoStringType>* seen_aliases) const { const TProtoStringType& filename = desc.name(); - TProtoStringType module_name = StrippedModuleName(filename); + TProtoStringType module_name_owned = StrippedModuleName(filename); + y_absl::string_view module_name(module_name_owned); size_t last_dot_pos = module_name.rfind('.'); TProtoStringType import_statement; if (last_dot_pos == TProtoStringType::npos) { - import_statement = "import " + module_name; + import_statement = y_absl::StrCat("import ", module_name); } else { - import_statement = "from " + module_name.substr(0, last_dot_pos) + - " import " + module_name.substr(last_dot_pos + 1); + import_statement = + y_absl::StrCat("from ", module_name.substr(0, last_dot_pos), " import ", + module_name.substr(last_dot_pos + 1)); module_name = module_name.substr(last_dot_pos + 1); } - TProtoStringType alias = "_" + module_name; + TProtoStringType alias = y_absl::StrCat("_", module_name); // Generate a unique alias by adding _1 suffixes until we get an unused alias. while (seen_aliases->find(alias) != seen_aliases->end()) { - alias = alias + "_1"; + y_absl::StrAppend(&alias, "_1"); } printer_->Print("$statement$ as $alias$\n", "statement", import_statement, "alias", alias); - (*import_map)[filename] = alias; + import_map_[filename] = alias; seen_aliases->insert(alias); } -void PyiGenerator::PrintImports( - std::map<TProtoStringType, TProtoStringType>* item_map, - std::map<TProtoStringType, TProtoStringType>* import_map) const { +void PyiGenerator::PrintImports() const { // Prints imported dependent _pb2 files. - std::set<TProtoStringType> seen_aliases; + y_absl::flat_hash_set<TProtoStringType> seen_aliases; for (int i = 0; i < file_->dependency_count(); ++i) { const FileDescriptor* dep = file_->dependency(i); - PrintImportForDescriptor(*dep, import_map, &seen_aliases); + PrintImportForDescriptor(*dep, &seen_aliases); for (int j = 0; j < dep->public_dependency_count(); ++j) { PrintImportForDescriptor( - *dep->public_dependency(j), import_map, &seen_aliases); + *dep->public_dependency(j), &seen_aliases); } } @@ -202,6 +201,10 @@ void PyiGenerator::PrintImports( if (file_->enum_type_count() > 0) { import_modules.has_enums = true; } + if (!opensource_runtime_ && file_->service_count() > 0) { + import_modules.has_optional = true; + import_modules.has_union = true; + } for (int i = 0; i < file_->message_type_count(); i++) { CheckImportModules(file_->message_type(i), &import_modules); } @@ -210,37 +213,50 @@ void PyiGenerator::PrintImports( // required in the proto file. if (import_modules.has_repeated) { printer_->Print( - "from google.protobuf.internal import containers as " - "_containers\n"); + "from $internal_package$ import containers as _containers\n", + "internal_package", InternalPackage()); } if (import_modules.has_enums) { printer_->Print( - "from google.protobuf.internal import enum_type_wrapper" - " as _enum_type_wrapper\n"); + "from $internal_package$ import enum_type_wrapper as " + "_enum_type_wrapper\n", + "internal_package", InternalPackage()); } if (import_modules.has_extendable) { printer_->Print( - "from google.protobuf.internal import python_message" - " as _python_message\n"); + "from $internal_package$ import python_message as _python_message\n", + "internal_package", InternalPackage()); } if (import_modules.has_well_known_type) { printer_->Print( - "from google.protobuf.internal import well_known_types" - " as _well_known_types\n"); + "from $internal_package$ import well_known_types as " + "_well_known_types\n", + "internal_package", InternalPackage()); } - printer_->Print( - "from google.protobuf import" - " descriptor as _descriptor\n"); + printer_->Print("from $public_package$ import descriptor as _descriptor\n", + "public_package", PublicPackage()); if (import_modules.has_messages) { - printer_->Print( - "from google.protobuf import message as _message\n"); + printer_->Print("from $public_package$ import message as _message\n", + "public_package", PublicPackage()); } - if (HasGenericServices(file_)) { - printer_->Print( - "from google.protobuf import service as" - " _service\n"); + if (opensource_runtime_) { + if (HasGenericServices(file_)) { + printer_->Print("from $public_package$ import service as _service\n", + "public_package", PublicPackage()); + } + } else { + if (file_->service_count() > 0) { + printer_->Print( + "from google3.net.rpc.python import proto_python_api_2_stub as " + "_proto_python_api_2_stub\n" + "from google3.net.rpc.python import pywraprpc as _pywraprpc\n" + "from google3.net.rpc.python import rpcserver as _rpcserver\n"); + } } printer_->Print("from typing import "); + if (!opensource_runtime_ && file_->service_count() > 0) { + printer_->Print("Any as _Any, "); + } printer_->Print("ClassVar as _ClassVar"); if (import_modules.has_iterable) { printer_->Print(", Iterable as _Iterable"); @@ -254,7 +270,7 @@ void PyiGenerator::PrintImports( if (import_modules.has_union) { printer_->Print(", Union as _Union"); } - printer_->Print("\n\n"); + printer_->Print("\n"); // Public imports for (int i = 0; i < file_->public_dependency_count(); ++i) { @@ -272,17 +288,16 @@ void PyiGenerator::PrintImports( module_name, "enum_class", public_dep->enum_type(i)->name()); } - // Enum values for public imports - for (int i = 0; i < public_dep->enum_type_count(); ++i) { - const EnumDescriptor* enum_descriptor = public_dep->enum_type(i); - for (int j = 0; j < enum_descriptor->value_count(); ++j) { - (*item_map)[enum_descriptor->value(j)->name()] = - ModuleLevelName(*enum_descriptor, *import_map); - } - } - // Top level extensions for public imports - AddExtensions(*public_dep, item_map); } +printer_->Print("\n"); +} + +// Annotate wrapper for debugging purposes +// Print a message after Annotate to see what is annotated. +template <typename DescriptorT> +void PyiGenerator::Annotate(const TProtoStringType& label, + const DescriptorT* descriptor) const { +printer_->Annotate(label.c_str(), descriptor); } void PyiGenerator::PrintEnum(const EnumDescriptor& enum_descriptor) const { @@ -291,22 +306,31 @@ void PyiGenerator::PrintEnum(const EnumDescriptor& enum_descriptor) const { "class $enum_name$(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):\n" " __slots__ = []\n", "enum_name", enum_name); + Annotate("enum_name", &enum_descriptor); + printer_->Indent(); + PrintEnumValues(enum_descriptor, /* is_classvar = */ true); + printer_->Outdent(); } -// Adds enum value to item map which will be ordered and printed later. -void PyiGenerator::AddEnumValue( - const EnumDescriptor& enum_descriptor, - std::map<TProtoStringType, TProtoStringType>* item_map, - const std::map<TProtoStringType, TProtoStringType>& import_map) const { +void PyiGenerator::PrintEnumValues(const EnumDescriptor& enum_descriptor, + bool is_classvar) const { // enum values - TProtoStringType module_enum_name = ModuleLevelName(enum_descriptor, import_map); + TProtoStringType module_enum_name = ModuleLevelName(enum_descriptor); for (int j = 0; j < enum_descriptor.value_count(); ++j) { const EnumValueDescriptor* value_descriptor = enum_descriptor.value(j); - (*item_map)[value_descriptor->name()] = module_enum_name; + if (is_classvar) { + printer_->Print("$name$: _ClassVar[$module_enum_name$]\n", "name", + value_descriptor->name(), "module_enum_name", + module_enum_name); + } else { + printer_->Print("$name$: $module_enum_name$\n", "name", + value_descriptor->name(), "module_enum_name", + module_enum_name); + } + Annotate("name", value_descriptor); } } -// Prints top level enums void PyiGenerator::PrintTopLevelEnums() const { for (int i = 0; i < file_->enum_type_count(); ++i) { printer_->Print("\n"); @@ -314,25 +338,24 @@ void PyiGenerator::PrintTopLevelEnums() const { } } -// Add top level extensions to item_map which will be ordered and -// printed later. template <typename DescriptorT> -void PyiGenerator::AddExtensions( - const DescriptorT& descriptor, - std::map<TProtoStringType, TProtoStringType>* item_map) const { +void PyiGenerator::PrintExtensions(const DescriptorT& descriptor) const { for (int i = 0; i < descriptor.extension_count(); ++i) { const FieldDescriptor* extension_field = descriptor.extension(i); - TProtoStringType constant_name = extension_field->name() + "_FIELD_NUMBER"; - ToUpper(&constant_name); - (*item_map)[constant_name] = "_ClassVar[int]"; - (*item_map)[extension_field->name()] = "_descriptor.FieldDescriptor"; + TProtoStringType constant_name = + y_absl::StrCat(extension_field->name(), "_FIELD_NUMBER"); + y_absl::AsciiStrToUpper(&constant_name); + printer_->Print("$constant_name$: _ClassVar[int]\n", + "constant_name", constant_name); + printer_->Print("$name$: _descriptor.FieldDescriptor\n", + "name", extension_field->name()); + Annotate("name", extension_field); } } // Returns the string format of a field's cpp_type TProtoStringType PyiGenerator::GetFieldType( - const FieldDescriptor& field_des, const Descriptor& containing_des, - const std::map<TProtoStringType, TProtoStringType>& import_map) const { + const FieldDescriptor& field_des, const Descriptor& containing_des) const { switch (field_des.cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: case FieldDescriptor::CPPTYPE_UINT32: @@ -345,7 +368,7 @@ TProtoStringType PyiGenerator::GetFieldType( case FieldDescriptor::CPPTYPE_BOOL: return "bool"; case FieldDescriptor::CPPTYPE_ENUM: - return ModuleLevelName(*field_des.enum_type(), import_map); + return ModuleLevelName(*field_des.enum_type()); case FieldDescriptor::CPPTYPE_STRING: if (field_des.type() == FieldDescriptor::TYPE_STRING) { return "str"; @@ -356,23 +379,22 @@ TProtoStringType PyiGenerator::GetFieldType( // If the field is inside a nested message and the nested message has the // same name as a top-level message, then we need to prefix the field type // with the module name for disambiguation. - TProtoStringType name = ModuleLevelName(*field_des.message_type(), import_map); + TProtoStringType name = ModuleLevelName(*field_des.message_type()); if ((containing_des.containing_type() != nullptr && name == containing_des.name())) { TProtoStringType module = ModuleName(field_des.file()->name()); - name = module + "." + name; + name = y_absl::StrCat(module, ".", name); } return name; } default: - GOOGLE_LOG(FATAL) << "Unsupported field type."; + Y_ABSL_LOG(FATAL) << "Unsupported field type."; } return ""; } void PyiGenerator::PrintMessage( - const Descriptor& message_descriptor, bool is_nested, - const std::map<TProtoStringType, TProtoStringType>& import_map) const { + const Descriptor& message_descriptor, bool is_nested) const { if (!is_nested) { printer_->Print("\n"); } @@ -381,26 +403,21 @@ void PyiGenerator::PrintMessage( // A well-known type needs to inherit from its corresponding base class in // net/proto2/python/internal/well_known_types. if (IsWellKnownType(message_descriptor.full_name())) { - extra_base = ", _well_known_types." + message_descriptor.name(); + extra_base = + y_absl::StrCat(", _well_known_types.", message_descriptor.name()); } else { extra_base = ""; } printer_->Print("class $class_name$(_message.Message$extra_base$):\n", "class_name", class_name, "extra_base", extra_base); + Annotate("class_name", &message_descriptor); printer_->Indent(); - printer_->Indent(); - - std::vector<const FieldDescriptor*> fields; - fields.reserve(message_descriptor.field_count()); - for (int i = 0; i < message_descriptor.field_count(); ++i) { - fields.push_back(message_descriptor.field(i)); - } - std::sort(fields.begin(), fields.end(), SortByName<FieldDescriptor>()); // Prints slots printer_->Print("__slots__ = [", "class_name", class_name); bool first_item = true; - for (const auto& field_des : fields) { + for (int i = 0; i < message_descriptor.field_count(); ++i) { + const FieldDescriptor* field_des = message_descriptor.field(i); if (IsPythonKeyword(field_des->name())) { continue; } @@ -413,48 +430,34 @@ void PyiGenerator::PrintMessage( } printer_->Print("]\n"); - std::map<TProtoStringType, TProtoStringType> item_map; // Prints Extensions for extendable messages if (message_descriptor.extension_range_count() > 0) { - item_map["Extensions"] = "_python_message._ExtensionDict"; + printer_->Print("Extensions: _python_message._ExtensionDict\n"); } // Prints nested enums - std::vector<const EnumDescriptor*> nested_enums; - nested_enums.reserve(message_descriptor.enum_type_count()); for (int i = 0; i < message_descriptor.enum_type_count(); ++i) { - nested_enums.push_back(message_descriptor.enum_type(i)); - } - std::sort(nested_enums.begin(), nested_enums.end(), - SortByName<EnumDescriptor>()); - - for (const auto& entry : nested_enums) { - PrintEnum(*entry); - // Adds enum value to item_map which will be ordered and printed later - AddEnumValue(*entry, &item_map, import_map); + PrintEnum(*message_descriptor.enum_type(i)); + PrintEnumValues(*message_descriptor.enum_type(i)); } // Prints nested messages - std::vector<const Descriptor*> nested_messages; - nested_messages.reserve(message_descriptor.nested_type_count()); for (int i = 0; i < message_descriptor.nested_type_count(); ++i) { - nested_messages.push_back(message_descriptor.nested_type(i)); + PrintMessage(*message_descriptor.nested_type(i), true); } - std::sort(nested_messages.begin(), nested_messages.end(), - SortByName<Descriptor>()); - for (const auto& entry : nested_messages) { - PrintMessage(*entry, true, import_map); - } - - // Adds extensions to item_map which will be ordered and printed later - AddExtensions(message_descriptor, &item_map); + PrintExtensions(message_descriptor); - // Adds field number and field descriptor to item_map + // Prints field number + for (int i = 0; i < message_descriptor.field_count(); ++i) { + const FieldDescriptor& field_des = *message_descriptor.field(i); + printer_->Print( + "$field_number_name$: _ClassVar[int]\n", "field_number_name", + y_absl::StrCat(y_absl::AsciiStrToUpper(field_des.name()), "_FIELD_NUMBER")); + } + // Prints field name and type for (int i = 0; i < message_descriptor.field_count(); ++i) { const FieldDescriptor& field_des = *message_descriptor.field(i); - item_map[ToUpper(field_des.name()) + "_FIELD_NUMBER"] = - "_ClassVar[int]"; if (IsPythonKeyword(field_des.name())) { continue; } @@ -462,30 +465,29 @@ void PyiGenerator::PrintMessage( if (field_des.is_map()) { const FieldDescriptor* key_des = field_des.message_type()->field(0); const FieldDescriptor* value_des = field_des.message_type()->field(1); - field_type = (value_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE - ? "_containers.MessageMap[" - : "_containers.ScalarMap["); - field_type += GetFieldType(*key_des, message_descriptor, import_map); - field_type += ", "; - field_type += GetFieldType(*value_des, message_descriptor, import_map); + field_type = + y_absl::StrCat(value_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + ? "_containers.MessageMap[" + : "_containers.ScalarMap[", + GetFieldType(*key_des, message_descriptor), ", ", + GetFieldType(*value_des, message_descriptor)); } else { if (field_des.is_repeated()) { field_type = (field_des.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? "_containers.RepeatedCompositeFieldContainer[" : "_containers.RepeatedScalarFieldContainer["); } - field_type += GetFieldType(field_des, message_descriptor, import_map); + field_type += GetFieldType(field_des, message_descriptor); } if (field_des.is_repeated()) { - field_type += "]"; + y_absl::StrAppend(&field_type, "]"); } - item_map[field_des.name()] = field_type; + printer_->Print("$name$: $type$\n", + "name", field_des.name(), "type", field_type); + Annotate("name", &field_des); } - // Prints all items in item_map - PrintItemMap(item_map); - // Prints __init__ printer_->Print("def __init__(self"); bool has_key_words = false; @@ -505,6 +507,7 @@ void PyiGenerator::PrintMessage( } is_first = false; printer_->Print(", $field_name$: ", "field_name", field_name); + Annotate("field_name", field_des); if (field_des->is_repeated() || field_des->cpp_type() != FieldDescriptor::CPPTYPE_BOOL) { printer_->Print("_Optional["); @@ -513,9 +516,9 @@ void PyiGenerator::PrintMessage( const Descriptor* map_entry = field_des->message_type(); printer_->Print( "_Mapping[$key_type$, $value_type$]", "key_type", - GetFieldType(*map_entry->field(0), message_descriptor, import_map), + GetFieldType(*map_entry->field(0), message_descriptor), "value_type", - GetFieldType(*map_entry->field(1), message_descriptor, import_map)); + GetFieldType(*map_entry->field(1), message_descriptor)); } else { if (field_des->is_repeated()) { printer_->Print("_Iterable["); @@ -523,15 +526,15 @@ void PyiGenerator::PrintMessage( if (field_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { printer_->Print( "_Union[$type_name$, _Mapping]", "type_name", - GetFieldType(*field_des, message_descriptor, import_map)); + GetFieldType(*field_des, message_descriptor)); } else { if (field_des->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { printer_->Print("_Union[$type_name$, str]", "type_name", - ModuleLevelName(*field_des->enum_type(), import_map)); + ModuleLevelName(*field_des->enum_type())); } else { printer_->Print( "$type_name$", "type_name", - GetFieldType(*field_des, message_descriptor, import_map)); + GetFieldType(*field_des, message_descriptor)); } } if (field_des->is_repeated()) { @@ -548,83 +551,92 @@ void PyiGenerator::PrintMessage( printer_->Print(", **kwargs"); } printer_->Print(") -> None: ...\n"); - - printer_->Outdent(); printer_->Outdent(); } -void PyiGenerator::PrintMessages( - const std::map<TProtoStringType, TProtoStringType>& import_map) const { +void PyiGenerator::PrintMessages() const { // Deterministically order the descriptors. - std::vector<const Descriptor*> messages; - messages.reserve(file_->message_type_count()); for (int i = 0; i < file_->message_type_count(); ++i) { - messages.push_back(file_->message_type(i)); - } - std::sort(messages.begin(), messages.end(), SortByName<Descriptor>()); - - for (const auto& entry : messages) { - PrintMessage(*entry, false, import_map); + PrintMessage(*file_->message_type(i), false); } } void PyiGenerator::PrintServices() const { - std::vector<const ServiceDescriptor*> services; - services.reserve(file_->service_count()); - for (int i = 0; i < file_->service_count(); ++i) { - services.push_back(file_->service(i)); - } - std::sort(services.begin(), services.end(), SortByName<ServiceDescriptor>()); - // Prints $Service$ and $Service$_Stub classes - for (const auto& entry : services) { + for (int i = 0; i < file_->service_count(); ++i) { printer_->Print("\n"); printer_->Print( "class $service_name$(_service.service): ...\n\n" "class $service_name$_Stub($service_name$): ...\n", - "service_name", entry->name()); + "service_name", file_->service(i)->name()); } } + bool PyiGenerator::Generate(const FileDescriptor* file, const TProtoStringType& parameter, GeneratorContext* context, TProtoStringType* error) const { - MutexLock lock(&mutex_); + y_absl::MutexLock lock(&mutex_); + import_map_.clear(); // Calculate file name. file_ = file; - TProtoStringType filename = - parameter.empty() ? GetFileName(file, ".pyi") : parameter; + // In google3, devtools/python/blaze/pytype/pytype_impl.bzl uses --pyi_out to + // directly set the output file name. + std::vector<std::pair<TProtoStringType, TProtoStringType> > options; + ParseGeneratorParameter(parameter, &options); + + TProtoStringType filename; + bool annotate_code = false; + for (const std::pair<TProtoStringType, TProtoStringType>& option : options) { + if (option.first == "annotate_code") { + annotate_code = true; + } else if (y_absl::EndsWith(option.first, ".pyi")) { + filename = option.first; + } else { + *error = y_absl::StrCat("Unknown generator option: ", option.first); + return false; + } + } + + if (filename.empty()) { + filename = GetFileName(file, ".pyi"); + } std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename)); - GOOGLE_CHECK(output.get()); - io::Printer printer(output.get(), '$'); + Y_ABSL_CHECK(output.get()); + GeneratedCodeInfo annotations; + io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector( + &annotations); + io::Printer::Options printer_opt( + '$', annotate_code ? &annotation_collector : nullptr); + printer_opt.spaces_per_indent = 4; + io::Printer printer(output.get(), printer_opt); printer_ = &printer; - // item map will store "DESCRIPTOR", top level extensions, top level enum - // values. The items will be sorted and printed later. - std::map<TProtoStringType, TProtoStringType> item_map; - - // Adds "DESCRIPTOR" into item_map. - item_map["DESCRIPTOR"] = "_descriptor.FileDescriptor"; + PrintImports(); + printer_->Print("DESCRIPTOR: _descriptor.FileDescriptor\n"); - // import_map will be a mapping from filename to module alias, e.g. - // "google3/foo/bar.py" -> "_bar" - std::map<TProtoStringType, TProtoStringType> import_map; + // Prints extensions and enums from imports. + for (int i = 0; i < file_->public_dependency_count(); ++i) { + const FileDescriptor* public_dep = file_->public_dependency(i); + PrintExtensions(*public_dep); + for (int i = 0; i < public_dep->enum_type_count(); ++i) { + const EnumDescriptor* enum_descriptor = public_dep->enum_type(i); + PrintEnumValues(*enum_descriptor); + } + } - PrintImports(&item_map, &import_map); - // Adds top level enum values to item_map. + PrintTopLevelEnums(); + // Prints top level enum values for (int i = 0; i < file_->enum_type_count(); ++i) { - AddEnumValue(*file_->enum_type(i), &item_map, import_map); + PrintEnumValues(*file_->enum_type(i)); } - // Adds top level extensions to item_map. - AddExtensions(*file_, &item_map); - // Prints item map - PrintItemMap(item_map); + // Prints top level Extensions + PrintExtensions(*file_); + PrintMessages(); - PrintMessages(import_map); - PrintTopLevelEnums(); - if (HasGenericServices(file)) { + if (opensource_runtime_ && HasGenericServices(file)) { PrintServices(); } return true; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.h index c9bf2961665..091a252c4bd 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/python/pyi_generator.h @@ -35,15 +35,15 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__ #define GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__ -#include <map> -#include <set> #include <string> -#include <google/protobuf/stubs/mutex.h> -#include <google/protobuf/compiler/code_generator.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/synchronization/mutex.h" +#include "google/protobuf/compiler/code_generator.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -63,6 +63,8 @@ namespace python { class PROTOC_EXPORT PyiGenerator : public google::protobuf::compiler::CodeGenerator { public: PyiGenerator(); + PyiGenerator(const PyiGenerator&) = delete; + PyiGenerator& operator=(const PyiGenerator&) = delete; ~PyiGenerator() override; // CodeGenerator methods. @@ -75,39 +77,38 @@ class PROTOC_EXPORT PyiGenerator : public google::protobuf::compiler::CodeGenera TProtoStringType* error) const override; private: - void PrintImportForDescriptor(const FileDescriptor& desc, - std::map<TProtoStringType, TProtoStringType>* import_map, - std::set<TProtoStringType>* seen_aliases) const; - void PrintImports(std::map<TProtoStringType, TProtoStringType>* item_map, - std::map<TProtoStringType, TProtoStringType>* import_map) const; - void PrintEnum(const EnumDescriptor& enum_descriptor) const; - void AddEnumValue(const EnumDescriptor& enum_descriptor, - std::map<TProtoStringType, TProtoStringType>* item_map, - const std::map<TProtoStringType, TProtoStringType>& import_map) const; + void PrintImportForDescriptor( + const FileDescriptor& desc, + y_absl::flat_hash_set<TProtoStringType>* seen_aliases) const; + template <typename DescriptorT> + void Annotate(const TProtoStringType& label, const DescriptorT* descriptor) const; + void PrintImports() const; void PrintTopLevelEnums() const; + void PrintEnum(const EnumDescriptor& enum_descriptor) const; + void PrintEnumValues(const EnumDescriptor& enum_descriptor, + bool is_classvar = false) const; template <typename DescriptorT> - void AddExtensions(const DescriptorT& descriptor, - std::map<TProtoStringType, TProtoStringType>* item_map) const; - void PrintMessages( - const std::map<TProtoStringType, TProtoStringType>& import_map) const; - void PrintMessage(const Descriptor& message_descriptor, bool is_nested, - const std::map<TProtoStringType, TProtoStringType>& import_map) const; + void PrintExtensions(const DescriptorT& descriptor) const; + void PrintMessages() const; + void PrintMessage(const Descriptor& message_descriptor, bool is_nested) const; void PrintServices() const; - void PrintItemMap(const std::map<TProtoStringType, TProtoStringType>& item_map) const; TProtoStringType GetFieldType( - const FieldDescriptor& field_des, const Descriptor& containing_des, - const std::map<TProtoStringType, TProtoStringType>& import_map) const; + const FieldDescriptor& field_des, const Descriptor& containing_des) const; template <typename DescriptorT> - TProtoStringType ModuleLevelName( - const DescriptorT& descriptor, - const std::map<TProtoStringType, TProtoStringType>& import_map) const; + TProtoStringType ModuleLevelName(const DescriptorT& descriptor) const; + TProtoStringType PublicPackage() const; + TProtoStringType InternalPackage() const; + + bool opensource_runtime_ = true; // Very coarse-grained lock to ensure that Generate() is reentrant. - // Guards file_ and printer_. - mutable Mutex mutex_; + // Guards file_, printer_, and import_map_. + mutable y_absl::Mutex mutex_; mutable const FileDescriptor* file_; // Set in Generate(). Under mutex_. mutable io::Printer* printer_; // Set in Generate(). Under mutex_. - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PyiGenerator); + // import_map will be a mapping from filename to module alias, e.g. + // "google3/foo/bar.py" -> "_bar" + mutable y_absl::flat_hash_map<TProtoStringType, TProtoStringType> import_map_; }; } // namespace python @@ -115,6 +116,6 @@ class PROTOC_EXPORT PyiGenerator : public google::protobuf::compiler::CodeGenera } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/retention.cc b/contrib/libs/protoc/src/google/protobuf/compiler/retention.cc new file mode 100644 index 00000000000..f49971a7e3d --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/retention.cc @@ -0,0 +1,104 @@ +// 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/retention.h" + +#include <memory> +#include <string> +#include <vector> + +#include "google/protobuf/descriptor.h" +#include "google/protobuf/dynamic_message.h" + +namespace google { +namespace protobuf { +namespace compiler { + +namespace { +// Recursively strips any options with source retention from the message. +void StripMessage(Message& m) { + const Reflection* reflection = m.GetReflection(); + std::vector<const FieldDescriptor*> fields; + reflection->ListFields(m, &fields); + for (const FieldDescriptor* field : fields) { + if (field->options().retention() == FieldOptions::RETENTION_SOURCE) { + reflection->ClearField(&m, field); + } else if (field->type() == FieldDescriptor::TYPE_MESSAGE) { + if (field->is_repeated()) { + int field_size = reflection->FieldSize(m, field); + for (int i = 0; i < field_size; ++i) { + StripMessage(*reflection->MutableRepeatedMessage(&m, field, i)); + } + } else { + StripMessage(*reflection->MutableMessage(&m, field)); + } + } + } +} +} // namespace + +FileDescriptorProto StripSourceRetentionOptions(const FileDescriptor& file) { + FileDescriptorProto file_proto; + file.CopyTo(&file_proto); + + // We need to look up the descriptor in file.pool() so that we can get a + // descriptor which knows about any custom options that were used in the + // .proto file. + const Descriptor* descriptor = + file.pool()->FindMessageTypeByName(FileDescriptorProto().GetTypeName()); + + if (descriptor == nullptr) { + // If the pool does not contain the descriptor for FileDescriptorProto, + // then this proto file does not transitively depend on descriptor.proto, + // in which case we know there are no custom options to worry about. + StripMessage(file_proto); + } else { + // The options message may have custom options set on it, and these would + // ordinarily appear as unknown fields since they are not linked into + // protoc. Using a dynamic message allows us to see these custom options. + // To convert back and forth between the generated type and the dynamic + // message, we have to serialize one and parse that into the other. + DynamicMessageFactory factory; + std::unique_ptr<Message> dynamic_message( + factory.GetPrototype(descriptor)->New()); + TProtoStringType serialized; + Y_ABSL_CHECK(file_proto.SerializeToString(&serialized)); + Y_ABSL_CHECK(dynamic_message->ParseFromString(serialized)); + StripMessage(*dynamic_message); + Y_ABSL_CHECK(dynamic_message->SerializeToString(&serialized)); + Y_ABSL_CHECK(file_proto.ParseFromString(serialized)); + } + + return file_proto; +} + +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/retention.h b/contrib/libs/protoc/src/google/protobuf/compiler/retention.h new file mode 100644 index 00000000000..b97ab1e73a9 --- /dev/null +++ b/contrib/libs/protoc/src/google/protobuf/compiler/retention.h @@ -0,0 +1,55 @@ +// 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_RETENTION_H__ +#define GOOGLE_PROTOBUF_COMPILER_RETENTION_H__ + +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" + +// Must appear last +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { + +// Returns a FileDescriptorProto for this file, with all RETENTION_SOURCE +// options stripped out. +PROTOC_EXPORT FileDescriptorProto +StripSourceRetentionOptions(const FileDescriptor& file); + +} // namespace compiler +} // namespace protobuf +} // namespace google + +#include "google/protobuf/port_undef.inc" + +#endif // GOOGLE_PROTOBUF_COMPILER_RETENTION_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/ruby/ruby_generator.cc b/contrib/libs/protoc/src/google/protobuf/compiler/ruby/ruby_generator.cc index 4a26b6d951f..bf02333ed48 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -28,17 +28,19 @@ // (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/ruby/ruby_generator.h" + #include <iomanip> +#include <memory> #include <sstream> -#include <google/protobuf/compiler/code_generator.h> -#include <google/protobuf/compiler/plugin.h> -#include <google/protobuf/descriptor.h> -#include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/io/printer.h> -#include <google/protobuf/io/zero_copy_stream.h> - -#include <google/protobuf/compiler/ruby/ruby_generator.h> +#include "google/protobuf/compiler/code_generator.h" +#include "y_absl/log/absl_log.h" +#include "google/protobuf/compiler/plugin.h" +#include "google/protobuf/descriptor.h" +#include "google/protobuf/descriptor.pb.h" +#include "google/protobuf/io/printer.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { @@ -48,15 +50,15 @@ namespace ruby { // Forward decls. template <class numeric_type> TProtoStringType NumberToString(numeric_type value); -TProtoStringType GetRequireName(const TProtoStringType& proto_file); +TProtoStringType GetRequireName(y_absl::string_view proto_file); TProtoStringType LabelForField(FieldDescriptor* field); TProtoStringType TypeName(FieldDescriptor* field); bool GenerateMessage(const Descriptor* message, io::Printer* printer, TProtoStringType* error); void GenerateEnum(const EnumDescriptor* en, io::Printer* printer); -void GenerateMessageAssignment(const TProtoStringType& prefix, +void GenerateMessageAssignment(y_absl::string_view prefix, const Descriptor* message, io::Printer* printer); -void GenerateEnumAssignment(const TProtoStringType& prefix, const EnumDescriptor* en, +void GenerateEnumAssignment(y_absl::string_view prefix, const EnumDescriptor* en, io::Printer* printer); TProtoStringType DefaultValueForField(const FieldDescriptor* field); @@ -67,13 +69,13 @@ TProtoStringType NumberToString(numeric_type value) { return TProtoStringType{os.str()}; } -TProtoStringType GetRequireName(const TProtoStringType& proto_file) { - int lastindex = proto_file.find_last_of("."); - return proto_file.substr(0, lastindex) + "_pb"; +TProtoStringType GetRequireName(y_absl::string_view proto_file) { + size_t lastindex = proto_file.find_last_of('.'); + return y_absl::StrCat(proto_file.substr(0, lastindex), "_pb"); } -TProtoStringType GetOutputFilename(const TProtoStringType& proto_file) { - return GetRequireName(proto_file) + ".rb"; +TProtoStringType GetOutputFilename(y_absl::string_view proto_file) { + return y_absl::StrCat(GetRequireName(proto_file), ".rb"); } TProtoStringType LabelForField(const FieldDescriptor* field) { @@ -121,8 +123,8 @@ TProtoStringType StringifySyntax(FileDescriptor::Syntax syntax) { return "proto3"; case FileDescriptor::SYNTAX_UNKNOWN: default: - GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports " - "proto2 and proto3 syntax."; + Y_ABSL_LOG(FATAL) << "Unsupported syntax; this generator only supports " + "proto2 and proto3 syntax."; return ""; } } @@ -247,7 +249,8 @@ void GenerateOneof(const OneofDescriptor* oneof, io::Printer* printer) { bool GenerateMessage(const Descriptor* message, io::Printer* printer, TProtoStringType* error) { if (message->extension_range_count() > 0 || message->extension_count() > 0) { - GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files."; + Y_ABSL_LOG(WARNING) + << "Extensions are not yet supported for proto2 .proto files."; } // Don't generate MapEntry messages -- we use the Ruby extension's native @@ -321,7 +324,7 @@ char UpperChar(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; } // names must be PascalCased. // // foo_bar_baz -> FooBarBaz -TProtoStringType PackageToModule(const TProtoStringType& name) { +TProtoStringType PackageToModule(y_absl::string_view name) { bool next_upper = true; TProtoStringType result; result.reserve(name.size()); @@ -346,8 +349,8 @@ TProtoStringType PackageToModule(const TProtoStringType& name) { // since there is nothing enforcing this we need to ensure that they are valid // Ruby constants. That mainly means making sure that the first character is // an upper-case letter. -TProtoStringType RubifyConstant(const TProtoStringType& name) { - TProtoStringType ret = name; +TProtoStringType RubifyConstant(y_absl::string_view name) { + TProtoStringType ret(name); if (!ret.empty()) { if (IsLower(ret[0])) { // If it starts with a lowercase letter, capitalize it. @@ -358,14 +361,14 @@ TProtoStringType RubifyConstant(const TProtoStringType& name) { // here, e.g. try to strip leading underscores, but this may cause other // problems if the user really intended the name. So let's just prepend a // well-known suffix. - ret = "PB_" + ret; + return y_absl::StrCat("PB_", ret); } } return ret; } -void GenerateMessageAssignment(const TProtoStringType& prefix, +void GenerateMessageAssignment(y_absl::string_view prefix, const Descriptor* message, io::Printer* printer) { // Don't generate MapEntry messages -- we use the Ruby extension's native @@ -383,7 +386,8 @@ void GenerateMessageAssignment(const TProtoStringType& prefix, "lookup(\"$full_name$\").msgclass\n", "full_name", message->full_name()); - TProtoStringType nested_prefix = prefix + RubifyConstant(message->name()) + "::"; + TProtoStringType nested_prefix = + y_absl::StrCat(prefix, RubifyConstant(message->name()), "::"); for (int i = 0; i < message->nested_type_count(); i++) { GenerateMessageAssignment(nested_prefix, message->nested_type(i), printer); } @@ -392,7 +396,7 @@ void GenerateMessageAssignment(const TProtoStringType& prefix, } } -void GenerateEnumAssignment(const TProtoStringType& prefix, const EnumDescriptor* en, +void GenerateEnumAssignment(y_absl::string_view prefix, const EnumDescriptor* en, io::Printer* printer) { printer->Print( "$prefix$$name$ = ", @@ -421,9 +425,9 @@ int GeneratePackageModules(const FileDescriptor* file, io::Printer* printer) { // -> A.B.C if (package_name.find("::") != TProtoStringType::npos) { need_change_to_module = false; - } else if (package_name.find(".") != TProtoStringType::npos) { - GOOGLE_LOG(WARNING) << "ruby_package option should be in the form of:" - << " 'A::B::C' and not 'A.B.C'"; + } else if (package_name.find('.') != TProtoStringType::npos) { + Y_ABSL_LOG(WARNING) << "ruby_package option should be in the form of:" + << " 'A::B::C' and not 'A.B.C'"; } } else { package_name = file->package(); @@ -519,7 +523,8 @@ bool GenerateFile(const FileDescriptor* file, io::Printer* printer, // TODO: Remove this when ruby supports extensions for proto2 syntax. if (file->syntax() == FileDescriptor::SYNTAX_PROTO2 && file->extension_count() > 0) { - GOOGLE_LOG(WARNING) << "Extensions are not yet supported for proto2 .proto files."; + Y_ABSL_LOG(WARNING) + << "Extensions are not yet supported for proto2 .proto files."; } bool use_raw_descriptor = file->name() == "google/protobuf/descriptor.proto"; diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/ruby/ruby_generator.h b/contrib/libs/protoc/src/google/protobuf/compiler/ruby/ruby_generator.h index 4bda18da2d5..0559413e322 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/ruby/ruby_generator.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/ruby/ruby_generator.h @@ -35,9 +35,9 @@ #include <string> -#include <google/protobuf/compiler/code_generator.h> +#include "google/protobuf/compiler/code_generator.h" -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -62,6 +62,6 @@ class PROTOC_EXPORT Generator : public CodeGenerator { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_RUBY_GENERATOR_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/scc.h b/contrib/libs/protoc/src/google/protobuf/compiler/scc.h index 7b95689d7ac..87c3f9fa8fe 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/scc.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/scc.h @@ -31,14 +31,16 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_SCC_H__ #define GOOGLE_PROTOBUF_COMPILER_SCC_H__ -#include <map> +#include <memory> -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/descriptor.h> +#include "y_absl/container/flat_hash_map.h" +#include "y_absl/container/flat_hash_set.h" +#include "y_absl/log/absl_check.h" +#include "y_absl/memory/memory.h" +#include "google/protobuf/descriptor.h" // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -64,10 +66,15 @@ template <class DepsGenerator> class PROTOC_EXPORT SCCAnalyzer { public: explicit SCCAnalyzer() : index_(0) {} + SCCAnalyzer(const SCCAnalyzer&) = delete; + SCCAnalyzer& operator=(const SCCAnalyzer&) = delete; const SCC* GetSCC(const Descriptor* descriptor) { - if (cache_.count(descriptor)) return cache_[descriptor].scc; - return DFS(descriptor).scc; + auto it = cache_.find(descriptor); + if (it == cache_.end()) { + return DFS(descriptor).scc; + } + return it->second->scc; } private: @@ -77,7 +84,7 @@ class PROTOC_EXPORT SCCAnalyzer { int lowlink; }; - std::map<const Descriptor*, NodeData> cache_; + y_absl::flat_hash_map<const Descriptor*, std::unique_ptr<NodeData>> cache_; std::vector<const Descriptor*> stack_; int index_; std::vector<std::unique_ptr<SCC>> garbage_bin_; @@ -89,24 +96,25 @@ class PROTOC_EXPORT SCCAnalyzer { // Tarjan's Strongly Connected Components algo NodeData 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]; + auto ins = cache_.try_emplace(descriptor, y_absl::make_unique<NodeData>()); + // Must not have visited already. + Y_ABSL_DCHECK(ins.second); + NodeData& result = *ins.first->second; // Initialize data structures. result.index = result.lowlink = index_++; stack_.push_back(descriptor); // Recurse the fields / nodes in graph - for (auto dep : DepsGenerator()(descriptor)) { - GOOGLE_CHECK(dep); - if (cache_.count(dep) == 0) { + for (const auto* dep : DepsGenerator()(descriptor)) { + Y_ABSL_CHECK(dep); + auto it = cache_.find(dep); + if (it == cache_.end()) { // unexplored node NodeData child_data = DFS(dep); result.lowlink = std::min(result.lowlink, child_data.lowlink); } else { - NodeData child_data = cache_[dep]; + NodeData& child_data = *it->second; if (child_data.scc == nullptr) { // Still in the stack_ so we found a back edge result.lowlink = std::min(result.lowlink, child_data.index); @@ -121,7 +129,7 @@ class PROTOC_EXPORT SCCAnalyzer { scc->descriptors.push_back(scc_desc); // Remove from stack stack_.pop_back(); - cache_[scc_desc].scc = scc; + cache_[scc_desc]->scc = scc; if (scc_desc == descriptor) break; } @@ -139,10 +147,10 @@ class PROTOC_EXPORT SCCAnalyzer { // Add the SCC's that are children of this SCC to its children. void AddChildren(SCC* scc) { - std::set<const SCC*> seen; + y_absl::flat_hash_set<const SCC*> seen; for (auto descriptor : scc->descriptors) { for (auto child_msg : DepsGenerator()(descriptor)) { - GOOGLE_CHECK(child_msg); + Y_ABSL_CHECK(child_msg); const SCC* child = GetSCC(child_msg); if (child == scc) continue; if (seen.insert(child).second) { @@ -151,15 +159,12 @@ class PROTOC_EXPORT SCCAnalyzer { } } } - - // 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> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_SCC_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/subprocess.cc b/contrib/libs/protoc/src/google/protobuf/compiler/subprocess.cc index d09ceed9dc2..639f01b734e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/subprocess.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/subprocess.cc @@ -30,7 +30,7 @@ // Author: [email protected] (Kenton Varda) -#include <google/protobuf/compiler/subprocess.h> +#include "google/protobuf/compiler/subprocess.h" #include <algorithm> #include <cstring> @@ -43,31 +43,24 @@ #include <sys/wait.h> #endif -#include <google/protobuf/stubs/logging.h> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/stubs/substitute.h> -#include <google/protobuf/message.h> +#include "y_absl/log/absl_check.h" +#include "y_absl/log/absl_log.h" +#include "y_absl/strings/escaping.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/substitute.h" +#include "google/protobuf/io/io_win32.h" +#include "google/protobuf/message.h" namespace google { namespace protobuf { namespace compiler { -namespace { -char* portable_strdup(const char* s) { - char* ns = (char*)malloc(strlen(s) + 1); - if (ns != nullptr) { - strcpy(ns, s); - } - return ns; -} -} // namespace - #ifdef _WIN32 static void CloseHandleOrDie(HANDLE handle) { if (!CloseHandle(handle)) { - GOOGLE_LOG(FATAL) << "CloseHandle: " - << Subprocess::Win32ErrorMessage(GetLastError()); + Y_ABSL_LOG(FATAL) << "CloseHandle: " + << Subprocess::Win32ErrorMessage(GetLastError()); } } @@ -94,26 +87,26 @@ void Subprocess::Start(const TProtoStringType& program, SearchMode search_mode) HANDLE stdout_pipe_write; if (!CreatePipe(&stdin_pipe_read, &stdin_pipe_write, nullptr, 0)) { - GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); + Y_ABSL_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); } if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, nullptr, 0)) { - GOOGLE_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); + Y_ABSL_LOG(FATAL) << "CreatePipe: " << Win32ErrorMessage(GetLastError()); } // Make child side of the pipes inheritable. if (!SetHandleInformation(stdin_pipe_read, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { - GOOGLE_LOG(FATAL) << "SetHandleInformation: " - << Win32ErrorMessage(GetLastError()); + Y_ABSL_LOG(FATAL) << "SetHandleInformation: " + << Win32ErrorMessage(GetLastError()); } if (!SetHandleInformation(stdout_pipe_write, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { - GOOGLE_LOG(FATAL) << "SetHandleInformation: " - << Win32ErrorMessage(GetLastError()); + Y_ABSL_LOG(FATAL) << "SetHandleInformation: " + << Win32ErrorMessage(GetLastError()); } // Setup STARTUPINFO to redirect handles. - STARTUPINFOA startup_info; + STARTUPINFOW startup_info; ZeroMemory(&startup_info, sizeof(startup_info)); startup_info.cb = sizeof(startup_info); startup_info.dwFlags = STARTF_USESTDHANDLES; @@ -122,20 +115,33 @@ void Subprocess::Start(const TProtoStringType& program, SearchMode search_mode) startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); if (startup_info.hStdError == INVALID_HANDLE_VALUE) { - GOOGLE_LOG(FATAL) << "GetStdHandle: " << Win32ErrorMessage(GetLastError()); + Y_ABSL_LOG(FATAL) << "GetStdHandle: " << Win32ErrorMessage(GetLastError()); + } + + // get wide string version of program as the path may contain non-ascii characters + std::wstring wprogram; + if (!io::win32::strings::utf8_to_wcs(program.c_str(), &wprogram)) { + Y_ABSL_LOG(FATAL) << "utf8_to_wcs: " << Win32ErrorMessage(GetLastError()); } // Invoking cmd.exe allows for '.bat' files from the path as well as '.exe'. + TProtoStringType command_line = y_absl::StrCat("cmd.exe /c \"", program, "\""); + + // get wide string version of command line as the path may contain non-ascii characters + std::wstring wcommand_line; + if (!io::win32::strings::utf8_to_wcs(command_line.c_str(), &wcommand_line)) { + Y_ABSL_LOG(FATAL) << "utf8_to_wcs: " << Win32ErrorMessage(GetLastError()); + } + // Using a malloc'ed string because CreateProcess() can mutate its second // parameter. - char* command_line = - portable_strdup(("cmd.exe /c \"" + program + "\"").c_str()); + wchar_t *wcommand_line_copy = _wcsdup(wcommand_line.c_str()); // Create the process. PROCESS_INFORMATION process_info; - if (CreateProcessA((search_mode == SEARCH_PATH) ? nullptr : program.c_str(), - (search_mode == SEARCH_PATH) ? command_line : nullptr, + if (CreateProcessW((search_mode == SEARCH_PATH) ? nullptr : wprogram.c_str(), + (search_mode == SEARCH_PATH) ? wcommand_line_copy : NULL, nullptr, // process security attributes nullptr, // thread security attributes TRUE, // inherit handles? @@ -155,7 +161,7 @@ void Subprocess::Start(const TProtoStringType& program, SearchMode search_mode) CloseHandleOrDie(stdin_pipe_read); CloseHandleOrDie(stdout_pipe_write); - free(command_line); + free(wcommand_line_copy); } bool Subprocess::Communicate(const Message& input, Message* output, @@ -165,7 +171,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, return false; } - GOOGLE_CHECK(child_handle_ != nullptr) << "Must call Start() first."; + Y_ABSL_CHECK(child_handle_ != nullptr) << "Must call Start() first."; TProtoStringType input_data; if (!input.SerializeToString(&input_data)) { @@ -195,11 +201,11 @@ bool Subprocess::Communicate(const Message& input, Message* output, wait_result < WAIT_OBJECT_0 + handle_count) { signaled_handle = handles[wait_result - WAIT_OBJECT_0]; } else if (wait_result == WAIT_FAILED) { - GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: " - << Win32ErrorMessage(GetLastError()); + Y_ABSL_LOG(FATAL) << "WaitForMultipleObjects: " + << Win32ErrorMessage(GetLastError()); } else { - GOOGLE_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: " - << wait_result; + Y_ABSL_LOG(FATAL) << "WaitForMultipleObjects: Unexpected return code: " + << wait_result; } if (signaled_handle == child_stdin_) { @@ -242,29 +248,30 @@ bool Subprocess::Communicate(const Message& input, Message* output, DWORD wait_result = WaitForSingleObject(child_handle_, INFINITE); if (wait_result == WAIT_FAILED) { - GOOGLE_LOG(FATAL) << "WaitForSingleObject: " - << Win32ErrorMessage(GetLastError()); + Y_ABSL_LOG(FATAL) << "WaitForSingleObject: " + << Win32ErrorMessage(GetLastError()); } else if (wait_result != WAIT_OBJECT_0) { - GOOGLE_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: " - << wait_result; + Y_ABSL_LOG(FATAL) << "WaitForSingleObject: Unexpected return code: " + << wait_result; } DWORD exit_code; if (!GetExitCodeProcess(child_handle_, &exit_code)) { - GOOGLE_LOG(FATAL) << "GetExitCodeProcess: " - << Win32ErrorMessage(GetLastError()); + Y_ABSL_LOG(FATAL) << "GetExitCodeProcess: " + << Win32ErrorMessage(GetLastError()); } CloseHandleOrDie(child_handle_); child_handle_ = nullptr; if (exit_code != 0) { - *error = strings::Substitute("Plugin failed with status code $0.", exit_code); + *error = y_absl::Substitute("Plugin failed with status code $0.", exit_code); return false; } if (!output->ParseFromString(output_data)) { - *error = "Plugin output is unparseable: " + CEscape(output_data); + *error = y_absl::StrCat("Plugin output is unparseable: ", + y_absl::CEscape(output_data)); return false; } @@ -303,6 +310,16 @@ Subprocess::~Subprocess() { } } +namespace { +char* portable_strdup(const char* s) { + char* ns = (char*)malloc(strlen(s) + 1); + if (ns != nullptr) { + strcpy(ns, s); + } + return ns; +} +} // namespace + void Subprocess::Start(const TProtoStringType& program, SearchMode search_mode) { // Note that we assume that there are no other threads, thus we don't have to // do crazy stuff like using socket pairs or avoiding libc locks. @@ -311,14 +328,14 @@ void Subprocess::Start(const TProtoStringType& program, SearchMode search_mode) int stdin_pipe[2]; int stdout_pipe[2]; - GOOGLE_CHECK(pipe(stdin_pipe) != -1); - GOOGLE_CHECK(pipe(stdout_pipe) != -1); + Y_ABSL_CHECK(pipe(stdin_pipe) != -1); + Y_ABSL_CHECK(pipe(stdout_pipe) != -1); char* argv[2] = {portable_strdup(program.c_str()), nullptr}; child_pid_ = fork(); if (child_pid_ == -1) { - GOOGLE_LOG(FATAL) << "fork: " << strerror(errno); + Y_ABSL_LOG(FATAL) << "fork: " << strerror(errno); } else if (child_pid_ == 0) { // We are the child. dup2(stdin_pipe[0], STDIN_FILENO); @@ -365,7 +382,7 @@ void Subprocess::Start(const TProtoStringType& program, SearchMode search_mode) bool Subprocess::Communicate(const Message& input, Message* output, TProtoStringType* error) { - GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first."; + Y_ABSL_CHECK_NE(child_stdin_, -1) << "Must call Start() first."; // The "sighandler_t" typedef is GNU-specific, so define our own. typedef void SignalHandler(int); @@ -400,7 +417,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, // Interrupted by signal. Try again. continue; } else { - GOOGLE_LOG(FATAL) << "select: " << strerror(errno); + Y_ABSL_LOG(FATAL) << "select: " << strerror(errno); } } @@ -446,7 +463,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, int status; while (waitpid(child_pid_, &status, 0) == -1) { if (errno != EINTR) { - GOOGLE_LOG(FATAL) << "waitpid: " << strerror(errno); + Y_ABSL_LOG(FATAL) << "waitpid: " << strerror(errno); } } @@ -457,12 +474,12 @@ bool Subprocess::Communicate(const Message& input, Message* output, if (WEXITSTATUS(status) != 0) { int error_code = WEXITSTATUS(status); *error = - strings::Substitute("Plugin failed with status code $0.", error_code); + y_absl::Substitute("Plugin failed with status code $0.", error_code); return false; } } else if (WIFSIGNALED(status)) { int signal = WTERMSIG(status); - *error = strings::Substitute("Plugin killed by signal $0.", signal); + *error = y_absl::Substitute("Plugin killed by signal $0.", signal); return false; } else { *error = "Neither WEXITSTATUS nor WTERMSIG is true?"; @@ -470,7 +487,8 @@ bool Subprocess::Communicate(const Message& input, Message* output, } if (!output->ParseFromString(output_data)) { - *error = "Plugin output is unparseable: " + CEscape(output_data); + *error = y_absl::StrCat("Plugin output is unparseable: ", + y_absl::CEscape(output_data)); return false; } diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/subprocess.h b/contrib/libs/protoc/src/google/protobuf/compiler/subprocess.h index a6a320ab47a..6289462e98f 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/subprocess.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/subprocess.h @@ -42,12 +42,12 @@ #include <sys/types.h> #include <unistd.h> #endif // !_WIN32 -#include <google/protobuf/stubs/common.h> - #include <string> +#include "google/protobuf/port.h" + // Must be included last. -#include <google/protobuf/port_def.inc> +#include "google/protobuf/port_def.inc" namespace google { namespace protobuf { @@ -109,6 +109,6 @@ class PROTOC_EXPORT Subprocess { } // namespace protobuf } // namespace google -#include <google/protobuf/port_undef.inc> +#include "google/protobuf/port_undef.inc" #endif // GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__ diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/zip_writer.cc b/contrib/libs/protoc/src/google/protobuf/compiler/zip_writer.cc index 37feced21f8..415eb94f86e 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/zip_writer.cc +++ b/contrib/libs/protoc/src/google/protobuf/compiler/zip_writer.cc @@ -33,11 +33,11 @@ // // Based on http://www.pkware.com/documents/casestudies/APPNOTE.TXT -#include <google/protobuf/compiler/zip_writer.h> +#include "google/protobuf/compiler/zip_writer.h" #include <cstdint> -#include <google/protobuf/io/coded_stream.h> +#include "google/protobuf/io/coded_stream.h" namespace google { namespace protobuf { diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/zip_writer.h b/contrib/libs/protoc/src/google/protobuf/compiler/zip_writer.h index c25a1e096aa..1adc578539a 100644 --- a/contrib/libs/protoc/src/google/protobuf/compiler/zip_writer.h +++ b/contrib/libs/protoc/src/google/protobuf/compiler/zip_writer.h @@ -35,8 +35,8 @@ #include <cstdint> #include <vector> -#include <google/protobuf/stubs/common.h> -#include <google/protobuf/io/zero_copy_stream.h> +#include "google/protobuf/stubs/common.h" +#include "google/protobuf/io/zero_copy_stream.h" namespace google { namespace protobuf { |