summaryrefslogtreecommitdiffstats
path: root/contrib/libs/protoc/src/google/protobuf/compiler/cpp
diff options
context:
space:
mode:
authornechda <[email protected]>2024-08-29 23:50:27 +0300
committernechda <[email protected]>2024-08-30 00:05:25 +0300
commite10d6638f07a82edae3ea8197b9f5c0affcc07ea (patch)
tree571c38cec05813766a1ad290c9d51ce7ace52919 /contrib/libs/protoc/src/google/protobuf/compiler/cpp
parente79b38f2bbbf78d295d1901d2a79f898022d5224 (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/compiler/cpp')
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.cc782
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum.h57
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.cc451
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/enum_field.h125
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.cc37
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/extension.h12
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.cc522
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/field.h496
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/enum_field.cc471
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/generators.h98
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/map_field.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.cc)86
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/message_field.cc (renamed from contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.cc)344
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/primitive_field.cc582
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/field_generators/string_field.cc922
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.cc1958
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/file.h137
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.cc264
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/generator.h28
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.cc850
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/helpers.h387
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/map_field.h83
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.cc1947
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/message.h161
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_field.h148
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/message_layout_helper.h4
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/names.h40
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/options.h12
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.cc107
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/padding_optimizer.h2
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.cc1067
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/parse_function_generator.h73
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.cc539
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/primitive_field.h126
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.cc488
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/service.h64
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.cc957
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/string_field.h136
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.cc339
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/tracker.h58
39 files changed, 7397 insertions, 7563 deletions
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(),
- &current_combined_range_);
+ mg_->GenerateSerializeOneExtensionRange(p_, &current_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__