summaryrefslogtreecommitdiffstats
path: root/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.cc
diff options
context:
space:
mode:
authorDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.cc
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.cc')
-rw-r--r--contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.cc403
1 files changed, 403 insertions, 0 deletions
diff --git a/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.cc b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.cc
new file mode 100644
index 00000000000..09261aaddc0
--- /dev/null
+++ b/contrib/libs/protoc/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -0,0 +1,403 @@
+// 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/cpp_field.h>
+
+#include <cstdint>
+#include <memory>
+#include <string>
+
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
+#include <google/protobuf/compiler/cpp/cpp_string_field.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_enum_field.h>
+#include <google/protobuf/compiler/cpp/cpp_map_field.h>
+#include <google/protobuf/compiler/cpp/cpp_message_field.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 {
+
+TProtoStringType GenerateAnnotation(StringPiece substitute_template_prefix,
+ StringPiece prepared_template,
+ StringPiece substitute_template_suffix,
+ int field_index, StringPiece lambda_args,
+ StringPiece access_type) {
+ return strings::Substitute(
+ StrCat(substitute_template_prefix, prepared_template,
+ substitute_template_suffix),
+ field_index, access_type, lambda_args);
+}
+
+TProtoStringType GenerateTemplateForOneofString(const FieldDescriptor* descriptor,
+ StringPiece proto_ns,
+ StringPiece field_member) {
+ TProtoStringType field_pointer =
+ descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
+ ? "$0.GetPointer()"
+ : "$0";
+
+ if (descriptor->default_value_string().empty()) {
+ return strings::Substitute(
+ StrCat("_internal_has_",
+ google::protobuf::compiler::cpp::FieldName(descriptor),
+ "()? _listener_->ExtractFieldInfo(", field_pointer,
+ "): ::", proto_ns, "::FieldAccessListener::AddressInfo()"),
+ field_member);
+ }
+
+ if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING_PIECE) {
+ return StrCat("_listener_->ExtractFieldInfo(_internal_",
+ google::protobuf::compiler::cpp::FieldName(descriptor), "())");
+ }
+
+ TProtoStringType default_value_pointer =
+ descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
+ ? "&$1.get()"
+ : "&$1";
+ return strings::Substitute(
+ StrCat("_listener_->ExtractFieldInfo(_internal_has_",
+ google::protobuf::compiler::cpp::FieldName(descriptor), "()? ",
+ field_pointer, " : ", default_value_pointer, ")"),
+ field_member, MakeDefaultName(descriptor));
+}
+
+TProtoStringType GenerateTemplateForSingleString(const FieldDescriptor* descriptor,
+ StringPiece field_member) {
+ if (descriptor->default_value_string().empty()) {
+ return strings::Substitute("_listener_->ExtractFieldInfo(&$0)", field_member);
+ }
+
+ if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING) {
+ return strings::Substitute(
+ "_listener_->ExtractFieldInfo($0.IsDefault("
+ "nullptr) ? &$1.get() : $0.GetPointer())",
+ field_member, MakeDefaultName(descriptor));
+ }
+
+ return strings::Substitute("_listener_->ExtractFieldInfo(&$0)", 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",
+ };
+ 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.inject_field_listener_events) {
+ return;
+ }
+ if (descriptor->file()->options().optimize_for() ==
+ google::protobuf::FileOptions::LITE_RUNTIME) {
+ return;
+ }
+ TProtoStringType field_member = (*variables)["field_member"];
+ const google::protobuf::OneofDescriptor* oneof_member =
+ descriptor->real_containing_oneof();
+ if (oneof_member) {
+ field_member = StrCat(oneof_member->name(), "_.", field_member);
+ }
+ const TProtoStringType proto_ns = (*variables)["proto_ns"];
+ TProtoStringType lambda_args = "_listener_, this";
+ TProtoStringType lambda_flat_args = "_listener_, this";
+ const TProtoStringType substitute_template_prefix = StrCat(
+ " {\n"
+ " auto _listener_ = ::",
+ proto_ns,
+ "::FieldAccessListener::GetListener();\n"
+ " if (_listener_) _listener_->OnFieldAccess([$2] { return ");
+ const TProtoStringType substitute_template_suffix = StrCat(
+ "; }, "
+ "GetDescriptor()->field($0), "
+ "::",
+ proto_ns,
+ "::FieldAccessListener::FieldAccessType::$1);\n"
+ " }\n");
+ 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(jianzhouzh): Fix all forward declared messages and deal with the
+ // weak fields.
+ if (descriptor->is_repeated() && !descriptor->is_map()) {
+ if (descriptor->type() != FieldDescriptor::TYPE_MESSAGE &&
+ descriptor->type() != FieldDescriptor::TYPE_GROUP) {
+ lambda_args = "_listener_, this, index";
+ prepared_template = strings::Substitute(
+ "_listener_->ExtractFieldInfo(&$0.Get(index))", field_member);
+ prepared_add_template = strings::Substitute(
+ "_listener_->ExtractFieldInfo(&$0.Get($0.size() - 1))", field_member);
+ } else {
+ prepared_template =
+ StrCat("::", proto_ns, "::FieldAccessListener::AddressInfo()");
+ prepared_add_template =
+ StrCat("::", proto_ns, "::FieldAccessListener::AddressInfo()");
+ }
+ } else if (descriptor->is_map()) {
+ prepared_template =
+ StrCat("::", proto_ns, "::FieldAccessListener::AddressInfo()");
+ } else if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE &&
+ !descriptor->options().lazy()) {
+ prepared_template =
+ StrCat("::", proto_ns, "::FieldAccessListener::AddressInfo()");
+ } 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 =
+ strings::Substitute("_listener_->ExtractFieldInfo(&$0)", field_member);
+ }
+ if (descriptor->is_repeated() && !descriptor->is_map() &&
+ descriptor->type() != FieldDescriptor::TYPE_MESSAGE &&
+ descriptor->type() != FieldDescriptor::TYPE_GROUP) {
+ prepared_flat_template =
+ strings::Substitute("_listener_->ExtractFieldInfo(&$0)", field_member);
+ } else {
+ prepared_flat_template = prepared_template;
+ }
+ (*variables)["annotate_get"] = GenerateAnnotation(
+ substitute_template_prefix, prepared_template, substitute_template_suffix,
+ descriptor->index(), lambda_args, "kGet");
+ (*variables)["annotate_set"] = GenerateAnnotation(
+ substitute_template_prefix, prepared_template, substitute_template_suffix,
+ descriptor->index(), lambda_args, "kSet");
+ (*variables)["annotate_has"] = GenerateAnnotation(
+ substitute_template_prefix, prepared_template, substitute_template_suffix,
+ descriptor->index(), lambda_args, "kHas");
+ (*variables)["annotate_mutable"] = GenerateAnnotation(
+ substitute_template_prefix, prepared_template, substitute_template_suffix,
+ descriptor->index(), lambda_args, "kMutable");
+ (*variables)["annotate_release"] = GenerateAnnotation(
+ substitute_template_prefix, prepared_template, substitute_template_suffix,
+ descriptor->index(), lambda_args, "kRelease");
+ (*variables)["annotate_clear"] =
+ GenerateAnnotation(substitute_template_prefix, prepared_flat_template,
+ substitute_template_suffix, descriptor->index(),
+ lambda_flat_args, "kClear");
+ (*variables)["annotate_size"] =
+ GenerateAnnotation(substitute_template_prefix, prepared_flat_template,
+ substitute_template_suffix, descriptor->index(),
+ lambda_flat_args, "kSize");
+ (*variables)["annotate_list"] =
+ GenerateAnnotation(substitute_template_prefix, prepared_flat_template,
+ substitute_template_suffix, descriptor->index(),
+ lambda_flat_args, "kList");
+ (*variables)["annotate_mutable_list"] =
+ GenerateAnnotation(substitute_template_prefix, prepared_flat_template,
+ substitute_template_suffix, descriptor->index(),
+ lambda_flat_args, "kMutableList");
+ (*variables)["annotate_add"] =
+ GenerateAnnotation(substitute_template_prefix, prepared_add_template,
+ substitute_template_suffix, descriptor->index(),
+ lambda_flat_args, "kAdd");
+ (*variables)["annotate_add_mutable"] =
+ GenerateAnnotation(substitute_template_prefix, prepared_add_template,
+ substitute_template_suffix, descriptor->index(),
+ lambda_flat_args, "kAddMutable");
+}
+
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+ std::map<TProtoStringType, TProtoStringType>* variables,
+ const Options& options) {
+ SetCommonVars(options, 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());
+ (*variables)["field_member"] = FieldName(descriptor) + "_";
+
+ (*variables)["tag_size"] = StrCat(
+ WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ (*variables)["deprecated_attr"] = DeprecatedAttribute(options, descriptor);
+
+ (*variables)["set_hasbit"] = "";
+ (*variables)["clear_hasbit"] = "";
+ if (HasHasbit(descriptor)) {
+ (*variables)["set_hasbit_io"] =
+ "_Internal::set_has_" + FieldName(descriptor) + "(&_has_bits_);";
+ } else {
+ (*variables)["set_hasbit_io"] = "";
+ }
+
+ 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(int32_t has_bit_index) {
+ if (!HasHasbit(descriptor_)) {
+ GOOGLE_CHECK_EQ(has_bit_index, -1);
+ return;
+ }
+ variables_["set_hasbit"] = StrCat(
+ "_has_bits_[", has_bit_index / 32, "] |= 0x",
+ strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
+ variables_["clear_hasbit"] = StrCat(
+ "_has_bits_[", has_bit_index / 32, "] &= ~0x",
+ strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
+}
+
+void SetCommonOneofFieldVariables(
+ const FieldDescriptor* descriptor,
+ std::map<TProtoStringType, TProtoStringType>* variables) {
+ const TProtoStringType prefix = descriptor->containing_oneof()->name() + "_.";
+ (*variables)["oneof_name"] = descriptor->containing_oneof()->name();
+ (*variables)["field_member"] =
+ StrCat(prefix, (*variables)["name"], "_");
+}
+
+FieldGenerator::~FieldGenerator() {}
+
+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));
+ }
+}
+
+FieldGenerator* FieldGeneratorMap::MakeGoogleInternalGenerator(
+ const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+
+ return nullptr;
+}
+
+FieldGenerator* FieldGeneratorMap::MakeGenerator(
+ const FieldDescriptor* field, const Options& options,
+ MessageSCCAnalyzer* scc_analyzer) {
+ FieldGenerator* generator =
+ MakeGoogleInternalGenerator(field, options, scc_analyzer);
+ if (generator) {
+ return generator;
+ }
+
+ if (field->is_repeated()) {
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ if (field->is_map()) {
+ return new MapFieldGenerator(field, options);
+ } 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);
+ case FieldDescriptor::CPPTYPE_STRING:
+ return new StringFieldGenerator(field, options);
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return new EnumFieldGenerator(field, options);
+ default:
+ return new PrimitiveFieldGenerator(field, options);
+ }
+ }
+}
+
+FieldGeneratorMap::~FieldGeneratorMap() {}
+
+const FieldGenerator& FieldGeneratorMap::get(
+ const FieldDescriptor* field) const {
+ GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
+ return *field_generators_[field->index()];
+}
+
+} // namespace cpp
+} // namespace compiler
+} // namespace protobuf
+} // namespace google