in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/compiler/cpp/cpp_message.cc [1339:1988]
void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
Formatter format(printer, variables_);
format.Set("class_final",
ShouldMarkClassAsFinal(descriptor_, options_) ? "final" : "");
if (IsMapEntryMessage(descriptor_)) {
std::map<std::string, std::string> vars;
CollectMapInfo(options_, descriptor_, &vars);
vars["lite"] =
HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite";
format.AddMap(vars);
format(
"class $classname$ : public "
"::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
" $key_cpp$, $val_cpp$,\n"
" ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
" ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> {\n"
"public:\n"
" typedef ::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
" $key_cpp$, $val_cpp$,\n"
" ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
" ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
"SuperType;\n"
" $classname$();\n"
" explicit constexpr $classname$(\n"
" ::$proto_ns$::internal::ConstantInitialized);\n"
" explicit $classname$(::$proto_ns$::Arena* arena);\n"
" void MergeFrom(const $classname$& other);\n"
" static const $classname$* internal_default_instance() { return "
"reinterpret_cast<const "
"$classname$*>(&_$classname$_default_instance_); }\n");
auto utf8_check = GetUtf8CheckMode(descriptor_->field(0), options_);
if (descriptor_->field(0)->type() == FieldDescriptor::TYPE_STRING &&
utf8_check != Utf8CheckMode::kNone) {
if (utf8_check == Utf8CheckMode::kStrict) {
format(
" static bool ValidateKey(std::string* s) {\n"
" return ::$proto_ns$::internal::WireFormatLite::"
"VerifyUtf8String(s->data(), static_cast<int>(s->size()), "
"::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n"
" }\n",
descriptor_->field(0)->full_name());
} else {
GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify);
format(
" static bool ValidateKey(std::string* s) {\n"
"#ifndef NDEBUG\n"
" ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n"
" s->data(), static_cast<int>(s->size()), "
"::$proto_ns$::internal::"
"WireFormatLite::PARSE, \"$1$\");\n"
"#else\n"
" (void) s;\n"
"#endif\n"
" return true;\n"
" }\n",
descriptor_->field(0)->full_name());
}
} else {
format(" static bool ValidateKey(void*) { return true; }\n");
}
if (descriptor_->field(1)->type() == FieldDescriptor::TYPE_STRING &&
utf8_check != Utf8CheckMode::kNone) {
if (utf8_check == Utf8CheckMode::kStrict) {
format(
" static bool ValidateValue(std::string* s) {\n"
" return ::$proto_ns$::internal::WireFormatLite::"
"VerifyUtf8String(s->data(), static_cast<int>(s->size()), "
"::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n"
" }\n",
descriptor_->field(1)->full_name());
} else {
GOOGLE_CHECK(utf8_check == Utf8CheckMode::kVerify);
format(
" static bool ValidateValue(std::string* s) {\n"
"#ifndef NDEBUG\n"
" ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n"
" s->data(), static_cast<int>(s->size()), "
"::$proto_ns$::internal::"
"WireFormatLite::PARSE, \"$1$\");\n"
"#else\n"
" (void) s;\n"
"#endif\n"
" return true;\n"
" }\n",
descriptor_->field(1)->full_name());
}
} else {
format(" static bool ValidateValue(void*) { return true; }\n");
}
if (HasDescriptorMethods(descriptor_->file(), options_)) {
format(
" using ::$proto_ns$::Message::MergeFrom;\n"
""
" ::$proto_ns$::Metadata GetMetadata() const final;\n");
}
format("};\n");
return;
}
format(
"class $dllexport_decl $${1$$classname$$}$$ class_final$ :\n"
" public $superclass$ /* @@protoc_insertion_point("
"class_definition:$full_name$) */ {\n",
descriptor_);
format(" public:\n");
format.Indent();
if (EnableMessageOwnedArena(descriptor_)) {
format(
"inline $classname$() : $classname$("
"::$proto_ns$::Arena::InternalHelper<$classname$>::\n"
" CreateMessageOwnedArena(), true) {}\n");
} else {
format("inline $classname$() : $classname$(nullptr) {}\n");
}
if (!HasSimpleBaseClass(descriptor_, options_)) {
format("~$classname$() override;\n");
}
format(
"explicit constexpr "
"$classname$(::$proto_ns$::internal::ConstantInitialized);\n"
"\n"
"$classname$(const $classname$& from);\n"
"$classname$($classname$&& from) noexcept\n"
" : $classname$() {\n"
" *this = ::std::move(from);\n"
"}\n"
"\n"
"inline $classname$& operator=(const $classname$& from) {\n"
" CopyFrom(from);\n"
" return *this;\n"
"}\n"
"inline $classname$& operator=($classname$&& from) noexcept {\n"
" if (this == &from) return *this;\n"
" if (GetOwningArena() == from.GetOwningArena()\n"
"#ifdef PROTOBUF_FORCE_COPY_IN_MOVE\n"
" && GetOwningArena() != nullptr\n"
"#endif // !PROTOBUF_FORCE_COPY_IN_MOVE\n"
" ) {\n"
" InternalSwap(&from);\n"
" } else {\n"
" CopyFrom(from);\n"
" }\n"
" return *this;\n"
"}\n"
"\n");
if (options_.table_driven_serialization) {
format(
"private:\n"
"const void* InternalGetTable() const override;\n"
"public:\n"
"\n");
}
if (PublicUnknownFieldsAccessors(descriptor_)) {
format(
"inline const $unknown_fields_type$& unknown_fields() const {\n"
" return $unknown_fields$;\n"
"}\n"
"inline $unknown_fields_type$* mutable_unknown_fields() {\n"
" return $mutable_unknown_fields$;\n"
"}\n"
"\n");
}
// Only generate this member if it's not disabled.
if (HasDescriptorMethods(descriptor_->file(), options_) &&
!descriptor_->options().no_standard_descriptor_accessor()) {
format(
"static const ::$proto_ns$::Descriptor* descriptor() {\n"
" return GetDescriptor();\n"
"}\n");
}
if (HasDescriptorMethods(descriptor_->file(), options_)) {
// These shadow non-static methods of the same names in Message. We
// redefine them here because calls directly on the generated class can be
// statically analyzed -- we know what descriptor types are being requested.
// It also avoids a vtable dispatch.
//
// We would eventually like to eliminate the methods in Message, and having
// this separate also lets us track calls to the base class methods
// separately.
format(
"static const ::$proto_ns$::Descriptor* GetDescriptor() {\n"
" return default_instance().GetMetadata().descriptor;\n"
"}\n"
"static const ::$proto_ns$::Reflection* GetReflection() {\n"
" return default_instance().GetMetadata().reflection;\n"
"}\n");
}
format(
"static const $classname$& default_instance() {\n"
" return *internal_default_instance();\n"
"}\n");
// Generate enum values for every field in oneofs. One list is generated for
// each oneof with an additional *_NOT_SET value.
for (auto oneof : OneOfRange(descriptor_)) {
format("enum $1$Case {\n", UnderscoresToCamelCase(oneof->name(), true));
format.Indent();
for (auto field : FieldRange(oneof)) {
format("$1$ = $2$,\n", OneofCaseConstantName(field), // 1
field->number()); // 2
}
format("$1$_NOT_SET = 0,\n", ToUpper(oneof->name()));
format.Outdent();
format(
"};\n"
"\n");
}
// TODO(gerbens) make this private, while still granting other protos access.
format(
"static inline const $classname$* internal_default_instance() {\n"
" return reinterpret_cast<const $classname$*>(\n"
" &_$classname$_default_instance_);\n"
"}\n"
"static constexpr int kIndexInFileMessages =\n"
" $1$;\n"
"\n",
index_in_file_messages_);
if (IsAnyMessage(descriptor_, options_)) {
format(
"// implements Any -----------------------------------------------\n"
"\n");
if (HasDescriptorMethods(descriptor_->file(), options_)) {
format(
"bool PackFrom(const ::$proto_ns$::Message& message) {\n"
" return _any_metadata_.PackFrom(GetArena(), message);\n"
"}\n"
"bool PackFrom(const ::$proto_ns$::Message& message,\n"
" ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
"type_url_prefix) {\n"
" return _any_metadata_.PackFrom(GetArena(), message, "
"type_url_prefix);\n"
"}\n"
"bool UnpackTo(::$proto_ns$::Message* message) const {\n"
" return _any_metadata_.UnpackTo(message);\n"
"}\n"
"static bool GetAnyFieldDescriptors(\n"
" const ::$proto_ns$::Message& message,\n"
" const ::$proto_ns$::FieldDescriptor** type_url_field,\n"
" const ::$proto_ns$::FieldDescriptor** value_field);\n"
"template <typename T, class = typename std::enable_if<"
"!std::is_convertible<T, const ::$proto_ns$::Message&>"
"::value>::type>\n"
"bool PackFrom(const T& message) {\n"
" return _any_metadata_.PackFrom<T>(GetArena(), message);\n"
"}\n"
"template <typename T, class = typename std::enable_if<"
"!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"
" return _any_metadata_.PackFrom<T>(GetArena(), message, "
"type_url_prefix);"
"}\n"
"template <typename T, class = typename std::enable_if<"
"!std::is_convertible<T, const ::$proto_ns$::Message&>"
"::value>::type>\n"
"bool UnpackTo(T* message) const {\n"
" return _any_metadata_.UnpackTo<T>(message);\n"
"}\n");
} else {
format(
"template <typename T>\n"
"bool PackFrom(const T& message) {\n"
" return _any_metadata_.PackFrom(GetArena(), message);\n"
"}\n"
"template <typename T>\n"
"bool PackFrom(const T& message,\n"
" ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
"type_url_prefix) {\n"
" return _any_metadata_.PackFrom(GetArena(), message, "
"type_url_prefix);\n"
"}\n"
"template <typename T>\n"
"bool UnpackTo(T* message) const {\n"
" return _any_metadata_.UnpackTo(message);\n"
"}\n");
}
format(
"template<typename T> bool Is() const {\n"
" return _any_metadata_.Is<T>();\n"
"}\n"
"static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam "
"type_url,\n"
" std::string* full_type_name);\n");
}
format(
"friend void swap($classname$& a, $classname$& b) {\n"
" a.Swap(&b);\n"
"}\n"
"inline void Swap($classname$* other) {\n"
" if (other == this) return;\n"
"#ifdef PROTOBUF_FORCE_COPY_IN_SWAP\n"
" if (GetOwningArena() != nullptr &&\n"
" GetOwningArena() == other->GetOwningArena()) {\n "
"#else // PROTOBUF_FORCE_COPY_IN_SWAP\n"
" if (GetOwningArena() == other->GetOwningArena()) {\n"
"#endif // !PROTOBUF_FORCE_COPY_IN_SWAP\n"
" InternalSwap(other);\n"
" } else {\n"
" ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n"
" }\n"
"}\n"
"void UnsafeArenaSwap($classname$* other) {\n"
" if (other == this) return;\n"
" $DCHK$(GetOwningArena() == other->GetOwningArena());\n"
" InternalSwap(other);\n"
"}\n");
format(
"\n"
"// implements Message ----------------------------------------------\n"
"\n"
"$classname$* New(::$proto_ns$::Arena* arena = nullptr) const final {\n"
" return CreateMaybeMessage<$classname$>(arena);\n"
"}\n");
// For instances that derive from Message (rather than MessageLite), some
// methods are virtual and should be marked as final.
format.Set("full_final", HasDescriptorMethods(descriptor_->file(), options_)
? "final"
: "");
if (HasGeneratedMethods(descriptor_->file(), options_)) {
if (HasDescriptorMethods(descriptor_->file(), options_)) {
if (!HasSimpleBaseClass(descriptor_, options_)) {
format(
// Use Message's built-in MergeFrom and CopyFrom when the passed-in
// argument is a generic Message instance, and only define the
// custom MergeFrom and CopyFrom instances when the source of the
// merge/copy is known to be the same class as the destination.
// TODO(jorg): Define MergeFrom in terms of MergeImpl, rather than
// the other way around, to save even more code size.
"using $superclass$::CopyFrom;\n"
"void CopyFrom(const $classname$& from);\n"
""
"using $superclass$::MergeFrom;\n"
"void MergeFrom(const $classname$& from);\n"
"private:\n"
"static void MergeImpl(::$proto_ns$::Message* to, const "
"::$proto_ns$::Message& from);\n"
"public:\n");
} else {
format(
"using $superclass$::CopyFrom;\n"
"inline void CopyFrom(const $classname$& from) {\n"
" $superclass$::CopyImpl(this, from);\n"
"}\n"
""
"using $superclass$::MergeFrom;\n"
"void MergeFrom(const $classname$& from) {\n"
" $superclass$::MergeImpl(this, from);\n"
"}\n"
"public:\n");
}
} else {
format(
"void CheckTypeAndMergeFrom(const ::$proto_ns$::MessageLite& from)"
" final;\n"
"void CopyFrom(const $classname$& from);\n"
"void MergeFrom(const $classname$& from);\n");
}
if (!HasSimpleBaseClass(descriptor_, options_)) {
format(
"PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;\n"
"bool IsInitialized() const final;\n"
"\n"
"size_t ByteSizeLong() const final;\n");
parse_function_generator_->GenerateMethodDecls(printer);
format(
"$uint8$* _InternalSerialize(\n"
" $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
"const final;\n");
}
}
if (options_.field_listener_options.inject_field_listener_events) {
format("static constexpr int _kInternalFieldNumber = $1$;\n",
descriptor_->field_count());
}
if (!HasSimpleBaseClass(descriptor_, options_)) {
format(
"int GetCachedSize() const final { return _cached_size_.Get(); }"
"\n\nprivate:\n"
"void SharedCtor();\n"
"void SharedDtor();\n"
"void SetCachedSize(int size) const$ full_final$;\n"
"void InternalSwap($classname$* other);\n");
}
format(
// Friend AnyMetadata so that it can call this FullMessageName() method.
"\nprivate:\n"
"friend class ::$proto_ns$::internal::AnyMetadata;\n"
"static $1$ FullMessageName() {\n"
" return \"$full_name$\";\n"
"}\n",
options_.opensource_runtime ? "::PROTOBUF_NAMESPACE_ID::StringPiece"
: "::StringPiece");
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"
"private:\n");
if (!HasSimpleBaseClass(descriptor_, options_)) {
format(
"static void ArenaDtor(void* object);\n"
"inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n");
}
format(
"public:\n"
"\n");
if (HasDescriptorMethods(descriptor_->file(), options_)) {
if (HasGeneratedMethods(descriptor_->file(), options_)) {
format(
"static const ClassData _class_data_;\n"
"const ::$proto_ns$::Message::ClassData*"
"GetClassData() const final;\n"
"\n");
}
format(
"::$proto_ns$::Metadata GetMetadata() const final;\n"
"\n");
} else {
format(
"std::string GetTypeName() const final;\n"
"\n");
}
format(
"// nested types ----------------------------------------------------\n"
"\n");
// Import all nested message classes into this class's scope with typedefs.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
const Descriptor* nested_type = descriptor_->nested_type(i);
if (!IsMapEntryMessage(nested_type)) {
format.Set("nested_full_name", ClassName(nested_type, false));
format.Set("nested_name", ResolveKeyword(nested_type->name()));
format("typedef ${1$$nested_full_name$$}$ ${1$$nested_name$$}$;\n",
nested_type);
}
}
if (descriptor_->nested_type_count() > 0) {
format("\n");
}
// Import all nested enums and their values into this class's scope with
// typedefs and constants.
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
enum_generators_[i]->GenerateSymbolImports(printer);
format("\n");
}
format(
"// accessors -------------------------------------------------------\n"
"\n");
// Generate accessor methods for all fields.
GenerateFieldAccessorDeclarations(printer);
// Declare extension identifiers.
for (int i = 0; i < descriptor_->extension_count(); i++) {
extension_generators_[i]->GenerateDeclaration(printer);
}
format("// @@protoc_insertion_point(class_scope:$full_name$)\n");
// Generate private members.
format.Outdent();
format(" private:\n");
format.Indent();
// TODO(seongkim): Remove hack to track field access and remove this class.
format("class _Internal;\n");
for (auto field : FieldRange(descriptor_)) {
// set_has_***() generated in all oneofs.
if (!field->is_repeated() && !field->options().weak() &&
field->real_containing_oneof()) {
format("void set_has_$1$();\n", FieldName(field));
}
}
format("\n");
// Generate oneof function declarations
for (auto oneof : OneOfRange(descriptor_)) {
format(
"inline bool has_$1$() const;\n"
"inline void clear_has_$1$();\n\n",
oneof->name());
}
if (HasGeneratedMethods(descriptor_->file(), options_) &&
!descriptor_->options().message_set_wire_format() &&
num_required_fields_ > 1) {
format(
"// helper for ByteSizeLong()\n"
"size_t RequiredFieldsByteSizeFallback() const;\n\n");
}
if (HasGeneratedMethods(descriptor_->file(), options_)) {
parse_function_generator_->GenerateDataDecls(printer);
}
// Prepare decls for _cached_size_ and _has_bits_. Their position in the
// output will be determined later.
bool need_to_emit_cached_size = true;
const std::string cached_size_decl =
"mutable ::$proto_ns$::internal::CachedSize _cached_size_;\n";
const size_t sizeof_has_bits = HasBitsSize();
const std::string has_bits_decl =
sizeof_has_bits == 0 ? ""
: StrCat("::$proto_ns$::internal::HasBits<",
sizeof_has_bits, "> _has_bits_;\n");
// To minimize padding, data members are divided into three sections:
// (1) members assumed to align to 8 bytes
// (2) members corresponding to message fields, re-ordered to optimize
// alignment.
// (3) members assumed to align to 4 bytes.
// Members assumed to align to 8 bytes:
if (descriptor_->extension_range_count() > 0) {
format(
"::$proto_ns$::internal::ExtensionSet _extensions_;\n"
"\n");
}
if (options_.field_listener_options.inject_field_listener_events &&
descriptor_->file()->options().optimize_for() !=
google::protobuf::FileOptions::LITE_RUNTIME) {
format("static ::$proto_ns$::AccessListener<$1$> _tracker_;\n",
ClassName(descriptor_));
}
// Generate _inlined_string_donated_ for inlined string type.
// TODO(congliu): To avoid affecting the locality of `_has_bits_`, should this
// be below or above `_has_bits_`?
if (!inlined_string_indices_.empty()) {
format("::$proto_ns$::internal::HasBits<$1$> _inlined_string_donated_;\n",
InlinedStringDonatedSize());
}
format(
"template <typename T> friend class "
"::$proto_ns$::Arena::InternalHelper;\n"
"typedef void InternalArenaConstructable_;\n"
"typedef void DestructorSkippable_;\n");
if (!has_bit_indices_.empty()) {
// _has_bits_ is frequently accessed, so to reduce code size and improve
// speed, it should be close to the start of the object. Placing
// _cached_size_ together with _has_bits_ improves cache locality despite
// potential alignment padding.
format(has_bits_decl.c_str());
format(cached_size_decl.c_str());
need_to_emit_cached_size = false;
}
// Field members:
// Emit some private and static members
for (auto field : optimized_order_) {
const FieldGenerator& generator = field_generators_.get(field);
generator.GenerateStaticMembers(printer);
generator.GeneratePrivateMembers(printer);
}
// For each oneof generate a union
for (auto oneof : OneOfRange(descriptor_)) {
std::string camel_oneof_name = UnderscoresToCamelCase(oneof->name(), true);
format("union $1$Union {\n", camel_oneof_name);
format.Indent();
format(
// explicit empty constructor is needed when union contains
// ArenaStringPtr members for string fields.
"constexpr $1$Union() : _constinit_{} {}\n"
" ::$proto_ns$::internal::ConstantInitialized _constinit_;\n",
camel_oneof_name);
for (auto field : FieldRange(oneof)) {
if (!IsFieldStripped(field, options_)) {
field_generators_.get(field).GeneratePrivateMembers(printer);
}
}
format.Outdent();
format("} $1$_;\n", oneof->name());
for (auto field : FieldRange(oneof)) {
if (!IsFieldStripped(field, options_)) {
field_generators_.get(field).GenerateStaticMembers(printer);
}
}
}
// Members assumed to align to 4 bytes:
if (need_to_emit_cached_size) {
format(cached_size_decl.c_str());
need_to_emit_cached_size = false;
}
// Generate _oneof_case_.
if (descriptor_->real_oneof_decl_count() > 0) {
format(
"$uint32$ _oneof_case_[$1$];\n"
"\n",
descriptor_->real_oneof_decl_count());
}
if (num_weak_fields_) {
format("::$proto_ns$::internal::WeakFieldMap _weak_field_map_;\n");
}
// Generate _any_metadata_ for the Any type.
if (IsAnyMessage(descriptor_, options_)) {
format("::$proto_ns$::internal::AnyMetadata _any_metadata_;\n");
}
// The TableStruct struct needs access to the private parts, in order to
// construct the offsets of all members.
format("friend struct ::$tablename$;\n");
format.Outdent();
format("};");
GOOGLE_DCHECK(!need_to_emit_cached_size);
} // NOLINT(readability/fn_size)