35 #include <google/protobuf/compiler/cpp/cpp_message.h>
42 #include <unordered_map>
46 #include <google/protobuf/stubs/common.h>
47 #include <google/protobuf/compiler/cpp/cpp_enum.h>
48 #include <google/protobuf/compiler/cpp/cpp_extension.h>
49 #include <google/protobuf/compiler/cpp/cpp_field.h>
50 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
51 #include <google/protobuf/compiler/cpp/cpp_padding_optimizer.h>
53 #include <google/protobuf/descriptor.pb.h>
54 #include <google/protobuf/io/coded_stream.h>
55 #include <google/protobuf/io/printer.h>
56 #include <google/protobuf/descriptor.h>
57 #include <google/protobuf/generated_message_table_driven.h>
58 #include <google/protobuf/generated_message_util.h>
59 #include <google/protobuf/map_entry_lite.h>
60 #include <google/protobuf/wire_format.h>
61 #include <google/protobuf/stubs/strutil.h>
62 #include <google/protobuf/stubs/substitute.h>
63 #include <google/protobuf/stubs/hash.h>
67 #include <google/protobuf/port_def.inc>
74 using internal::WireFormat;
75 using internal::WireFormatLite;
79 static constexpr
int kNoHasbit = -1;
86 const std::vector<uint32_t>& masks,
bool return_success =
true,
87 StringPiece has_bits_var =
"_has_bits_") {
88 std::vector<std::string> parts;
89 for (
int i = 0;
i < masks.size();
i++) {
90 if (masks[i] == 0)
continue;
94 StrCat(
"((", has_bits_var,
"[", i,
"] & ",
m,
") ^ ",
m,
")"));
102 return result + (return_success ?
" == 0" :
" != 0");
106 const std::vector<int>& has_bit_indices,
107 io::Printer* printer,
int* cached_has_word_index) {
108 if (!
field->options().weak()) {
109 int has_bit_index = has_bit_indices[
field->index()];
110 if (*cached_has_word_index != (has_bit_index / 32)) {
111 *cached_has_word_index = (has_bit_index / 32);
112 format(
"cached_has_bits = _has_bits_[$1$];\n", *cached_has_word_index);
116 format(
"if (cached_has_bits & 0x$1$u) {\n", mask);
123 struct FieldOrderingByNumber {
126 return a->number() <
b->number();
138 std::sort(
fields.begin(),
fields.end(), FieldOrderingByNumber());
143 struct ExtensionRangeSorter {
144 bool operator()(
const Descriptor::ExtensionRange* left,
145 const Descriptor::ExtensionRange* right)
const {
146 return left->start < right->start;
151 if (
field->is_repeated() ||
field->is_extension())
return false;
152 switch (
field->cpp_type()) {
174 MessageSCCAnalyzer* scc_analyzer) {
187 return haystack.find(needle) != std::string::npos;
194 using RunMap = std::unordered_map<const FieldDescriptor*, size_t>;
195 RunMap FindRuns(
const std::vector<const FieldDescriptor*>&
fields,
201 if (predicate(
field)) {
202 if (last_start ==
nullptr) {
208 last_start =
nullptr;
218 bool EmitFieldNonDefaultCondition(
io::Printer* printer,
227 if (!
field->is_repeated() && !
field->containing_oneof()) {
229 format(
"if (!$prefix$_internal_$name$().empty()) {\n");
232 format(
"if ($prefix$_internal_has_$name$()) {\n");
235 "static_assert(sizeof(uint32_t) == sizeof(float), \"Code assumes "
236 "uint32_t and float are the same size.\");\n"
237 "float tmp_$name$ = $prefix$_internal_$name$();\n"
238 "uint32_t raw_$name$;\n"
239 "memcpy(&raw_$name$, &tmp_$name$, sizeof(tmp_$name$));\n"
240 "if (raw_$name$ != 0) {\n");
243 "static_assert(sizeof(uint64_t) == sizeof(double), \"Code assumes "
244 "uint64_t and double are the same size.\");\n"
245 "double tmp_$name$ = $prefix$_internal_$name$();\n"
246 "uint64_t raw_$name$;\n"
247 "memcpy(&raw_$name$, &tmp_$name$, sizeof(tmp_$name$));\n"
248 "if (raw_$name$ != 0) {\n");
250 format(
"if ($prefix$_internal_$name$() != 0) {\n");
254 }
else if (
field->real_containing_oneof()) {
255 format(
"if (_internal_has_$name$()) {\n");
271 field->has_optional_keyword() ||
field->real_containing_oneof();
276 std::map<std::string, std::string>* variables) {
278 std::map<std::string, std::string>& vars = *variables;
282 switch (val->cpp_type()) {
287 vars[
"val_cpp"] =
ClassName(val->enum_type(),
true);
292 vars[
"key_wire_type"] =
294 vars[
"val_wire_type"] =
328 MessageSCCAnalyzer* scc_analyzer) {
329 if (!
options.table_driven_parsing) {
336 bool has_hasbit =
false;
344 if (!has_hasbit)
return false;
346 const double table_sparseness = 0.5;
347 int max_field_number = 0;
349 if (max_field_number < field->
number()) {
350 max_field_number =
field->number();
365 if (max_field_number >= (2 << 14)) {
372 if (max_field_number * table_sparseness >
descriptor->field_count()) {
385 if (!
field->is_map()) {
396 if (IsCrossFileMapField(
field)) {
403 bool IsRequired(
const std::vector<const FieldDescriptor*>&
v) {
404 return v.front()->is_required();
410 !
field->is_repeated() && !
field->real_containing_oneof()) {
418 template <
typename Predicate>
419 std::vector<std::vector<const FieldDescriptor*>> CollectFields(
420 const std::vector<const FieldDescriptor*>&
fields,
421 const Predicate& equivalent) {
422 std::vector<std::vector<const FieldDescriptor*>> chunks;
425 chunks.emplace_back();
427 chunks.back().push_back(
field);
435 uint32_t GenChunkMask(
const std::vector<const FieldDescriptor*>&
fields,
436 const std::vector<int>& has_bit_indices) {
438 int first_index_offset = has_bit_indices[
fields.front()->index()] / 32;
462 class ColdChunkSkipper {
466 const std::vector<std::vector<const FieldDescriptor*>>& chunks,
467 const std::vector<int>& has_bit_indices,
const double cold_threshold)
478 void OnStartChunk(
int chunk,
int cached_has_word_index,
483 bool IsColdChunk(
int chunk);
485 int HasbitWord(
int chunk,
int offset) {
489 const std::vector<std::vector<const FieldDescriptor*>>&
chunks_;
498 const double kColdRatio = 0.005;
500 bool ColdChunkSkipper::IsColdChunk(
int chunk) {
507 void ColdChunkSkipper::OnStartChunk(
int chunk,
int cached_has_word_index,
516 }
else if (!IsColdChunk(chunk)) {
534 format(
"if (PROTOBUF_PREDICT_FALSE(");
535 int first_word = HasbitWord(chunk, 0);
538 int this_word = HasbitWord(chunk, 0);
540 for (; chunk <
limit_chunk_ && HasbitWord(chunk, 0) == this_word; chunk++) {
545 mask |= 1 << (hasbit_index % 32);
549 if (this_word != first_word) {
553 if (this_word == cached_has_word_index) {
554 format(
"(cached_has_bits & 0x$mask$u) != 0");
556 format(
"($1$_has_bits_[$2$] & 0x$mask$u) != 0",
from, this_word);
563 bool ColdChunkSkipper::OnEndChunk(
int chunk,
io::Printer* printer) {
573 void MaySetAnnotationVariable(
const Options&
options,
574 StringPiece annotation_name,
575 StringPiece injector_template_prefix,
576 StringPiece injector_template_suffix,
577 std::map<std::string, std::string>* variables) {
578 if (
options.field_listener_options.forbidden_field_listener_events.count(
582 StrCat(injector_template_prefix, injector_template_suffix),
583 (*variables)[
"classtype"]);
586 void GenerateExtensionAnnotations(
588 std::map<std::string, std::string>* variables) {
589 const std::map<std::string, std::string> accessor_annotations_to_hooks = {
590 {
"annotate_extension_has",
"OnHasExtension"},
591 {
"annotate_extension_clear",
"OnClearExtension"},
592 {
"annotate_extension_repeated_size",
"OnExtensionSize"},
593 {
"annotate_extension_get",
"OnGetExtension"},
594 {
"annotate_extension_mutable",
"OnMutableExtension"},
595 {
"annotate_extension_set",
"OnSetExtension"},
596 {
"annotate_extension_release",
"OnReleaseExtension"},
597 {
"annotate_repeated_extension_get",
"OnGetExtension"},
598 {
"annotate_repeated_extension_mutable",
"OnMutableExtension"},
599 {
"annotate_repeated_extension_set",
"OnSetExtension"},
600 {
"annotate_repeated_extension_add",
"OnAddExtension"},
601 {
"annotate_repeated_extension_add_mutable",
"OnAddMutableExtension"},
602 {
"annotate_repeated_extension_list",
"OnListExtension"},
603 {
"annotate_repeated_extension_list_mutable",
"OnMutableListExtension"},
605 for (
const auto& annotation : accessor_annotations_to_hooks) {
606 (*variables)[annotation.first] =
"";
608 if (!
options.field_listener_options.inject_field_listener_events ||
609 descriptor->file()->options().optimize_for() ==
610 google::protobuf::FileOptions::LITE_RUNTIME) {
613 for (
const auto& annotation : accessor_annotations_to_hooks) {
614 const std::string& annotation_name = annotation.first;
615 const std::string& listener_call = annotation.second;
621 (*variables)[annotation_name] =
StrCat(
622 " _tracker_.", listener_call,
623 "(this, id.number(), _proto_TypeTraits::GetPtr(id.number(), "
624 "_extensions_, id.default_value_ref()));");
625 }
else if (
StrContains(annotation_name,
"repeated") &&
631 str_index =
"_extensions_.ExtensionSize(id.number()) - 1";
633 (*variables)[annotation_name] =
634 StrCat(
" _tracker_.", listener_call,
635 "(this, id.number(), "
636 "_proto_TypeTraits::GetPtr(id.number(), _extensions_, ",
641 (*variables)[annotation_name] =
StrCat(
642 " _tracker_.", listener_call,
643 "(this, id.number(), _proto_TypeTraits::GetRepeatedPtr(id.number(), "
661 const std::map<std::string, std::string>& vars,
int index_in_file_messages,
662 const Options&
options, MessageSCCAnalyzer* scc_analyzer)
664 index_in_file_messages_(index_in_file_messages),
668 max_has_bit_index_(0),
669 max_inlined_string_index_(0),
671 scc_analyzer_(scc_analyzer),
673 if (!message_layout_helper_) {
674 message_layout_helper_.reset(
new PaddingOptimizer());
688 if (
options.field_listener_options.inject_field_listener_events &&
689 descriptor->file()->options().optimize_for() !=
690 google::protobuf::FileOptions::LITE_RUNTIME) {
691 const std::string injector_template =
" _tracker_.";
693 MaySetAnnotationVariable(
options,
"serialize", injector_template,
695 MaySetAnnotationVariable(
options,
"deserialize", injector_template,
701 MaySetAnnotationVariable(
options,
"reflection", injector_template,
703 MaySetAnnotationVariable(
options,
"bytesize", injector_template,
705 MaySetAnnotationVariable(
options,
"mergefrom", injector_template,
722 }
else if (!
field->real_containing_oneof()) {
723 optimized_order_.push_back(
field);
727 message_layout_helper_->OptimizeLayout(&optimized_order_,
options_,
731 for (
auto field : optimized_order_) {
739 if (inlined_string_indices_.empty()) {
740 inlined_string_indices_.resize(
descriptor_->field_count(), kNoHasbit);
742 inlined_string_indices_[
field->index()] = max_inlined_string_index_++;
750 if (!inlined_string_indices_.empty()) {
751 field_generators_.SetInlinedStringIndices(inlined_string_indices_);
754 num_required_fields_ = 0;
757 ++num_required_fields_;
763 parse_function_generator_.reset(
new ParseFunctionGenerator(
768 MessageGenerator::~MessageGenerator() =
default;
770 size_t MessageGenerator::HasBitsSize()
const {
771 return (max_has_bit_index_ + 31) / 32;
774 size_t MessageGenerator::InlinedStringDonatedSize()
const {
775 return (max_inlined_string_index_ + 31) / 32;
784 int hasbit = HasBitIndex(
field);
785 return hasbit == kNoHasbit ? kNoHasbit : hasbit / 8;
789 int hasbit = HasBitIndex(
field);
790 return hasbit == kNoHasbit ? kNoHasbit : hasbit / 32;
793 void MessageGenerator::AddGenerators(
794 std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
795 std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators) {
797 enum_generators->emplace_back(
799 enum_generators_.push_back(enum_generators->back().get());
802 extension_generators->emplace_back(
new ExtensionGenerator(
804 extension_generators_.push_back(extension_generators->back().get());
808 void MessageGenerator::GenerateFieldAccessorDeclarations(
io::Printer* printer) {
817 std::vector<const FieldDescriptor*> ordered_fields;
818 ordered_fields.reserve(
descriptor_->field_count());
820 ordered_fields.insert(ordered_fields.begin(), optimized_order_.begin(),
821 optimized_order_.end());
823 if (!
field->real_containing_oneof() && !
field->options().weak() &&
827 ordered_fields.push_back(
field);
830 if (!ordered_fields.empty()) {
832 for (
auto field : ordered_fields) {
835 std::map<std::string, std::string> vars;
842 for (
auto field : ordered_fields) {
847 std::map<std::string, std::string> vars;
851 if (
field->is_repeated()) {
852 format(
"$deprecated_attr$int ${1$$name$_size$}$() const$2$\n",
field,
857 "int ${1$_internal_$name$_size$}$() const;\n"
861 }
else if (HasHasMethod(
field)) {
862 format(
"$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n",
field,
867 "bool _internal_has_$name$() const;\n"
870 }
else if (HasPrivateHasMethod(
field)) {
874 "bool ${1$_internal_has_$name$$}$() const;\n"
879 format(
"$deprecated_attr$void ${1$clear_$name$$}$()$2$\n",
field,
883 field_generators_.get(
field).GenerateAccessorDeclarations(printer);
899 template <typename _proto_TypeTraits,
900 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
902 inline bool HasExtension(
903 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
904 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
905 $annotate_extension_has$
906 return _extensions_.Has(id.number());
909 template <typename _proto_TypeTraits,
910 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
912 inline void ClearExtension(
913 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
914 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
915 _extensions_.ClearExtension(id.number());
916 $annotate_extension_clear$
919 template <typename _proto_TypeTraits,
920 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
922 inline int ExtensionSize(
923 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
924 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
925 $annotate_extension_repeated_size$
926 return _extensions_.ExtensionSize(id.number());
929 template <typename _proto_TypeTraits,
930 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
932 inline typename _proto_TypeTraits::Singular::ConstType GetExtension(
933 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
934 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
935 $annotate_extension_get$
936 return _proto_TypeTraits::Get(id.number(), _extensions_,
940 template <typename _proto_TypeTraits,
941 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
943 inline typename _proto_TypeTraits::Singular::MutableType MutableExtension(
944 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
945 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
946 $annotate_extension_mutable$
947 return _proto_TypeTraits::Mutable(id.number(), _field_type,
951 template <typename _proto_TypeTraits,
952 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
954 inline void SetExtension(
955 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
956 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
957 typename _proto_TypeTraits::Singular::ConstType value) {
958 _proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_);
959 $annotate_extension_set$
962 template <typename _proto_TypeTraits,
963 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
965 inline void SetAllocatedExtension(
966 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
967 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
968 typename _proto_TypeTraits::Singular::MutableType value) {
969 _proto_TypeTraits::SetAllocated(id.number(), _field_type, value,
971 $annotate_extension_set$
973 template <typename _proto_TypeTraits,
974 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
976 inline void UnsafeArenaSetAllocatedExtension(
977 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
978 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
979 typename _proto_TypeTraits::Singular::MutableType value) {
980 _proto_TypeTraits::UnsafeArenaSetAllocated(id.number(), _field_type,
981 value, &_extensions_);
982 $annotate_extension_set$
984 template <typename _proto_TypeTraits,
985 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
987 PROTOBUF_NODISCARD inline
988 typename _proto_TypeTraits::Singular::MutableType
990 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
991 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
992 $annotate_extension_release$
993 return _proto_TypeTraits::Release(id.number(), _field_type,
996 template <typename _proto_TypeTraits,
997 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
999 inline typename _proto_TypeTraits::Singular::MutableType
1000 UnsafeArenaReleaseExtension(
1001 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1002 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
1003 $annotate_extension_release$
1004 return _proto_TypeTraits::UnsafeArenaRelease(id.number(), _field_type,
1008 template <typename _proto_TypeTraits,
1009 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
1011 inline typename _proto_TypeTraits::Repeated::ConstType GetExtension(
1012 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1013 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
1015 $annotate_repeated_extension_get$
1016 return _proto_TypeTraits::Get(id.number(), _extensions_, index);
1019 template <typename _proto_TypeTraits,
1020 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
1022 inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension(
1023 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1024 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
1026 $annotate_repeated_extension_mutable$
1027 return _proto_TypeTraits::Mutable(id.number(), index, &_extensions_);
1030 template <typename _proto_TypeTraits,
1031 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
1033 inline void SetExtension(
1034 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1035 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
1036 int index, typename _proto_TypeTraits::Repeated::ConstType value) {
1037 _proto_TypeTraits::Set(id.number(), index, value, &_extensions_);
1038 $annotate_repeated_extension_set$
1041 template <typename _proto_TypeTraits,
1042 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
1044 inline typename _proto_TypeTraits::Repeated::MutableType AddExtension(
1045 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1046 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
1047 typename _proto_TypeTraits::Repeated::MutableType to_add =
1048 _proto_TypeTraits::Add(id.number(), _field_type, &_extensions_);
1049 $annotate_repeated_extension_add_mutable$
1053 template <typename _proto_TypeTraits,
1054 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
1056 inline void AddExtension(
1057 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1058 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id,
1059 typename _proto_TypeTraits::Repeated::ConstType value) {
1060 _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, value,
1062 $annotate_repeated_extension_add$
1065 template <typename _proto_TypeTraits,
1066 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
1068 inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType&
1069 GetRepeatedExtension(
1070 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1071 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) const {
1072 $annotate_repeated_extension_list$
1073 return _proto_TypeTraits::GetRepeated(id.number(), _extensions_);
1076 template <typename _proto_TypeTraits,
1077 ::PROTOBUF_NAMESPACE_ID::internal::FieldType _field_type,
1079 inline typename _proto_TypeTraits::Repeated::RepeatedFieldType*
1080 MutableRepeatedExtension(
1081 const ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier<
1082 $classname$, _proto_TypeTraits, _field_type, _is_packed>& id) {
1083 $annotate_repeated_extension_list_mutable$
1084 return _proto_TypeTraits::MutableRepeated(id.number(), _field_type,
1085 _is_packed, &_extensions_);
1092 if (
descriptor_->options().message_set_wire_format() &&
1095 format(
"GOOGLE_PROTOBUF_EXTENSION_MESSAGE_SET_ACCESSORS($classname$)\n");
1100 Formatter::SaveState saver(&
format);
1101 format.Set(
"oneof_name", oneof->name());
1104 "void ${1$clear_$oneof_name$$}$();\n"
1105 "$camel_oneof_name$Case $oneof_name$_case() const;\n",
1110 void MessageGenerator::GenerateSingularFieldHasBits(
1114 "inline bool $classname$::has_$name$() const { "
1115 "__builtin_trap(); }\n");
1118 if (
field->options().weak()) {
1120 "inline bool $classname$::has_$name$() const {\n"
1122 " return _weak_field_map_.Has($number$);\n"
1127 int has_bit_index = HasBitIndex(
field);
1130 format.Set(
"has_array_index", has_bit_index / 32);
1134 "inline bool $classname$::_internal_has_$name$() const {\n"
1136 "(_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n");
1138 if (
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
1143 format(
" PROTOBUF_ASSUME(!value || $name$_ != nullptr);\n");
1149 "inline bool $classname$::has_$name$() const {\n"
1151 " return _internal_has_$name$();\n"
1153 }
else if (
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
1157 "inline bool $classname$::_internal_has_$name$() const {\n"
1158 " return !$name$_.IsCleared();\n"
1162 "inline bool $classname$::_internal_has_$name$() const {\n"
1163 " return this != internal_default_instance() "
1164 "&& $name$_ != nullptr;\n"
1168 "inline bool $classname$::has_$name$() const {\n"
1170 " return _internal_has_$name$();\n"
1175 void MessageGenerator::GenerateOneofHasBits(
io::Printer* printer) {
1178 format.Set(
"oneof_name", oneof->name());
1179 format.Set(
"oneof_index", oneof->index());
1182 "inline bool $classname$::has_$oneof_name$() const {\n"
1183 " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
1185 "inline void $classname$::clear_has_$oneof_name$() {\n"
1186 " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n"
1194 if (HasHasMethod(
field)) {
1196 "inline bool $classname$::has_$name$() const { "
1197 "__builtin_trap(); }\n");
1200 "inline void $classname$::set_has_$name$() { __builtin_trap(); "
1213 if (HasHasMethod(
field)) {
1215 "inline bool $classname$::_internal_has_$name$() const {\n"
1216 " return $oneof_name$_case() == k$field_name$;\n"
1218 "inline bool $classname$::has_$name$() const {\n"
1220 " return _internal_has_$name$();\n"
1222 }
else if (HasPrivateHasMethod(
field)) {
1224 "inline bool $classname$::_internal_has_$name$() const {\n"
1225 " return $oneof_name$_case() == k$field_name$;\n"
1231 "inline void $classname$::set_has_$name$() {\n"
1232 " _oneof_case_[$oneof_index$] = k$field_name$;\n"
1239 format(
"void $classname$::clear_$name$() { __builtin_trap(); }\n");
1247 format(
"void $classname$::clear_$name$() {\n");
1251 if (
field->real_containing_oneof()) {
1254 format(
"if (_internal_has_$name$()) {\n");
1256 field_generators_.get(
field).GenerateClearingCode(
format.printer());
1257 format(
"clear_has_$oneof_name$();\n");
1261 field_generators_.get(
field).GenerateClearingCode(
format.printer());
1263 int has_bit_index = HasBitIndex(
field);
1264 format.Set(
"has_array_index", has_bit_index / 32);
1267 format(
"_has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n");
1270 format(
"$annotate_clear$");
1275 void MessageGenerator::GenerateFieldAccessorDefinitions(
io::Printer* printer) {
1277 format(
"// $classname$\n\n");
1286 std::map<std::string, std::string> vars;
1289 Formatter::SaveState saver(&
format);
1293 if (
field->is_repeated()) {
1296 "inline int $classname$::$name$_size() const { "
1297 "__builtin_trap(); }\n");
1300 "inline int $classname$::_internal_$name$_size() const {\n"
1301 " return $name$_$1$.size();\n"
1303 "inline int $classname$::$name$_size() const {\n"
1305 " return _internal_$name$_size();\n"
1308 field->message_type()
1312 }
else if (
field->real_containing_oneof()) {
1314 format.Set(
"oneof_name",
field->containing_oneof()->name());
1315 format.Set(
"oneof_index",
1323 if (!IsCrossFileMaybeMap(
field)) {
1329 field_generators_.get(
field).GenerateInlineAccessorDefinitions(printer);
1336 GenerateOneofHasBits(printer);
1339 void MessageGenerator::GenerateClassDefinition(
io::Printer* printer) {
1341 format.Set(
"class_final",
1345 std::map<std::string, std::string> vars;
1351 "class $classname$ : public "
1352 "::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
1353 " $key_cpp$, $val_cpp$,\n"
1354 " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
1355 " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> {\n"
1357 " typedef ::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
1358 " $key_cpp$, $val_cpp$,\n"
1359 " ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
1360 " ::$proto_ns$::internal::WireFormatLite::$val_wire_type$> "
1363 " explicit constexpr $classname$(\n"
1364 " ::$proto_ns$::internal::ConstantInitialized);\n"
1365 " explicit $classname$(::$proto_ns$::Arena* arena);\n"
1366 " void MergeFrom(const $classname$& other);\n"
1367 " static const $classname$* internal_default_instance() { return "
1368 "reinterpret_cast<const "
1369 "$classname$*>(&_$classname$_default_instance_); }\n");
1371 if (
descriptor_->field(0)->type() == FieldDescriptor::TYPE_STRING &&
1372 utf8_check != Utf8CheckMode::kNone) {
1373 if (utf8_check == Utf8CheckMode::kStrict) {
1375 " static bool ValidateKey(std::string* s) {\n"
1376 " return ::$proto_ns$::internal::WireFormatLite::"
1377 "VerifyUtf8String(s->data(), static_cast<int>(s->size()), "
1378 "::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n"
1384 " static bool ValidateKey(std::string* s) {\n"
1386 " ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n"
1387 " s->data(), static_cast<int>(s->size()), "
1388 "::$proto_ns$::internal::"
1389 "WireFormatLite::PARSE, \"$1$\");\n"
1398 format(
" static bool ValidateKey(void*) { return true; }\n");
1400 if (
descriptor_->field(1)->type() == FieldDescriptor::TYPE_STRING &&
1401 utf8_check != Utf8CheckMode::kNone) {
1402 if (utf8_check == Utf8CheckMode::kStrict) {
1404 " static bool ValidateValue(std::string* s) {\n"
1405 " return ::$proto_ns$::internal::WireFormatLite::"
1406 "VerifyUtf8String(s->data(), static_cast<int>(s->size()), "
1407 "::$proto_ns$::internal::WireFormatLite::PARSE, \"$1$\");\n"
1413 " static bool ValidateValue(std::string* s) {\n"
1415 " ::$proto_ns$::internal::WireFormatLite::VerifyUtf8String(\n"
1416 " s->data(), static_cast<int>(s->size()), "
1417 "::$proto_ns$::internal::"
1418 "WireFormatLite::PARSE, \"$1$\");\n"
1427 format(
" static bool ValidateValue(void*) { return true; }\n");
1431 " using ::$proto_ns$::Message::MergeFrom;\n"
1433 " ::$proto_ns$::Metadata GetMetadata() const final;\n");
1440 "class $dllexport_decl $${1$$classname$$}$$ class_final$ :\n"
1441 " public $superclass$ /* @@protoc_insertion_point("
1442 "class_definition:$full_name$) */ {\n",
1449 "inline $classname$() : $classname$("
1450 "::$proto_ns$::Arena::InternalHelper<$classname$>::\n"
1451 " CreateMessageOwnedArena(), true) {}\n");
1453 format(
"inline $classname$() : $classname$(nullptr) {}\n");
1456 format(
"~$classname$() override;\n");
1459 "explicit constexpr "
1460 "$classname$(::$proto_ns$::internal::ConstantInitialized);\n"
1462 "$classname$(const $classname$& from);\n"
1463 "$classname$($classname$&& from) noexcept\n"
1464 " : $classname$() {\n"
1465 " *this = ::std::move(from);\n"
1468 "inline $classname$& operator=(const $classname$& from) {\n"
1469 " CopyFrom(from);\n"
1472 "inline $classname$& operator=($classname$&& from) noexcept {\n"
1473 " if (this == &from) return *this;\n"
1474 " if (GetOwningArena() == from.GetOwningArena()\n"
1475 "#ifdef PROTOBUF_FORCE_COPY_IN_MOVE\n"
1476 " && GetOwningArena() != nullptr\n"
1477 "#endif // !PROTOBUF_FORCE_COPY_IN_MOVE\n"
1479 " InternalSwap(&from);\n"
1481 " CopyFrom(from);\n"
1487 if (
options_.table_driven_serialization) {
1490 "const void* InternalGetTable() const override;\n"
1497 "inline const $unknown_fields_type$& unknown_fields() const {\n"
1498 " return $unknown_fields$;\n"
1500 "inline $unknown_fields_type$* mutable_unknown_fields() {\n"
1501 " return $mutable_unknown_fields$;\n"
1508 !
descriptor_->options().no_standard_descriptor_accessor()) {
1510 "static const ::$proto_ns$::Descriptor* descriptor() {\n"
1511 " return GetDescriptor();\n"
1525 "static const ::$proto_ns$::Descriptor* GetDescriptor() {\n"
1526 " return default_instance().GetMetadata().descriptor;\n"
1528 "static const ::$proto_ns$::Reflection* GetReflection() {\n"
1529 " return default_instance().GetMetadata().reflection;\n"
1534 "static const $classname$& default_instance() {\n"
1535 " return *internal_default_instance();\n"
1556 "static inline const $classname$* internal_default_instance() {\n"
1557 " return reinterpret_cast<const $classname$*>(\n"
1558 " &_$classname$_default_instance_);\n"
1560 "static constexpr int kIndexInFileMessages =\n"
1563 index_in_file_messages_);
1567 "// implements Any -----------------------------------------------\n"
1571 "bool PackFrom(const ::$proto_ns$::Message& message) {\n"
1572 " return _any_metadata_.PackFrom(GetArena(), message);\n"
1574 "bool PackFrom(const ::$proto_ns$::Message& message,\n"
1575 " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
1576 "type_url_prefix) {\n"
1577 " return _any_metadata_.PackFrom(GetArena(), message, "
1578 "type_url_prefix);\n"
1580 "bool UnpackTo(::$proto_ns$::Message* message) const {\n"
1581 " return _any_metadata_.UnpackTo(message);\n"
1583 "static bool GetAnyFieldDescriptors(\n"
1584 " const ::$proto_ns$::Message& message,\n"
1585 " const ::$proto_ns$::FieldDescriptor** type_url_field,\n"
1586 " const ::$proto_ns$::FieldDescriptor** value_field);\n"
1587 "template <typename T, class = typename std::enable_if<"
1588 "!std::is_convertible<T, const ::$proto_ns$::Message&>"
1590 "bool PackFrom(const T& message) {\n"
1591 " return _any_metadata_.PackFrom<T>(GetArena(), message);\n"
1593 "template <typename T, class = typename std::enable_if<"
1594 "!std::is_convertible<T, const ::$proto_ns$::Message&>"
1596 "bool PackFrom(const T& message,\n"
1597 " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
1598 "type_url_prefix) {\n"
1599 " return _any_metadata_.PackFrom<T>(GetArena(), message, "
1602 "template <typename T, class = typename std::enable_if<"
1603 "!std::is_convertible<T, const ::$proto_ns$::Message&>"
1605 "bool UnpackTo(T* message) const {\n"
1606 " return _any_metadata_.UnpackTo<T>(message);\n"
1610 "template <typename T>\n"
1611 "bool PackFrom(const T& message) {\n"
1612 " return _any_metadata_.PackFrom(GetArena(), message);\n"
1614 "template <typename T>\n"
1615 "bool PackFrom(const T& message,\n"
1616 " ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
1617 "type_url_prefix) {\n"
1618 " return _any_metadata_.PackFrom(GetArena(), message, "
1619 "type_url_prefix);\n"
1621 "template <typename T>\n"
1622 "bool UnpackTo(T* message) const {\n"
1623 " return _any_metadata_.UnpackTo(message);\n"
1627 "template<typename T> bool Is() const {\n"
1628 " return _any_metadata_.Is<T>();\n"
1630 "static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam "
1632 " std::string* full_type_name);\n");
1636 "friend void swap($classname$& a, $classname$& b) {\n"
1639 "inline void Swap($classname$* other) {\n"
1640 " if (other == this) return;\n"
1641 "#ifdef PROTOBUF_FORCE_COPY_IN_SWAP\n"
1642 " if (GetOwningArena() != nullptr &&\n"
1643 " GetOwningArena() == other->GetOwningArena()) {\n "
1644 "#else // PROTOBUF_FORCE_COPY_IN_SWAP\n"
1645 " if (GetOwningArena() == other->GetOwningArena()) {\n"
1646 "#endif // !PROTOBUF_FORCE_COPY_IN_SWAP\n"
1647 " InternalSwap(other);\n"
1649 " ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);\n"
1652 "void UnsafeArenaSwap($classname$* other) {\n"
1653 " if (other == this) return;\n"
1654 " $DCHK$(GetOwningArena() == other->GetOwningArena());\n"
1655 " InternalSwap(other);\n"
1660 "// implements Message ----------------------------------------------\n"
1662 "$classname$* New(::$proto_ns$::Arena* arena = nullptr) const final {\n"
1663 " return CreateMaybeMessage<$classname$>(arena);\n"
1682 "using $superclass$::CopyFrom;\n"
1683 "void CopyFrom(const $classname$& from);\n"
1685 "using $superclass$::MergeFrom;\n"
1686 "void MergeFrom(const $classname$& from);\n"
1688 "static void MergeImpl(::$proto_ns$::Message* to, const "
1689 "::$proto_ns$::Message& from);\n"
1693 "using $superclass$::CopyFrom;\n"
1694 "inline void CopyFrom(const $classname$& from) {\n"
1695 " $superclass$::CopyImpl(this, from);\n"
1698 "using $superclass$::MergeFrom;\n"
1699 "void MergeFrom(const $classname$& from) {\n"
1700 " $superclass$::MergeImpl(this, from);\n"
1706 "void CheckTypeAndMergeFrom(const ::$proto_ns$::MessageLite& from)"
1708 "void CopyFrom(const $classname$& from);\n"
1709 "void MergeFrom(const $classname$& from);\n");
1714 "PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;\n"
1715 "bool IsInitialized() const final;\n"
1717 "size_t ByteSizeLong() const final;\n");
1719 parse_function_generator_->GenerateMethodDecls(printer);
1722 "$uint8$* _InternalSerialize(\n"
1723 " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
1728 if (
options_.field_listener_options.inject_field_listener_events) {
1729 format(
"static constexpr int _kInternalFieldNumber = $1$;\n",
1735 "int GetCachedSize() const final { return _cached_size_.Get(); }"
1737 "void SharedCtor();\n"
1738 "void SharedDtor();\n"
1739 "void SetCachedSize(int size) const$ full_final$;\n"
1740 "void InternalSwap($classname$* other);\n");
1746 "friend class ::$proto_ns$::internal::AnyMetadata;\n"
1747 "static $1$ FullMessageName() {\n"
1748 " return \"$full_name$\";\n"
1750 options_.opensource_runtime ?
"::PROTOBUF_NAMESPACE_ID::StringPiece"
1758 "explicit $classname$(::$proto_ns$::Arena* arena,\n"
1759 " bool is_message_owned = false);\n"
1764 "static void ArenaDtor(void* object);\n"
1765 "inline void RegisterArenaDtor(::$proto_ns$::Arena* arena);\n");
1775 "static const ClassData _class_data_;\n"
1776 "const ::$proto_ns$::Message::ClassData*"
1777 "GetClassData() const final;\n"
1781 "::$proto_ns$::Metadata GetMetadata() const final;\n"
1785 "std::string GetTypeName() const final;\n"
1790 "// nested types ----------------------------------------------------\n"
1799 format(
"typedef ${1$$nested_full_name$$}$ ${1$$nested_name$$}$;\n",
1811 enum_generators_[
i]->GenerateSymbolImports(printer);
1816 "// accessors -------------------------------------------------------\n"
1820 GenerateFieldAccessorDeclarations(printer);
1824 extension_generators_[
i]->GenerateDeclaration(printer);
1828 format(
"// @@protoc_insertion_point(class_scope:$full_name$)\n");
1835 format(
"class _Internal;\n");
1839 if (!
field->is_repeated() && !
field->options().weak() &&
1840 field->real_containing_oneof()) {
1849 "inline bool has_$1$() const;\n"
1850 "inline void clear_has_$1$();\n\n",
1855 !
descriptor_->options().message_set_wire_format() &&
1856 num_required_fields_ > 1) {
1858 "// helper for ByteSizeLong()\n"
1859 "size_t RequiredFieldsByteSizeFallback() const;\n\n");
1863 parse_function_generator_->GenerateDataDecls(printer);
1869 bool need_to_emit_cached_size =
true;
1871 "mutable ::$proto_ns$::internal::CachedSize _cached_size_;\n";
1873 const size_t sizeof_has_bits = HasBitsSize();
1875 sizeof_has_bits == 0 ?
""
1876 :
StrCat(
"::$proto_ns$::internal::HasBits<",
1877 sizeof_has_bits,
"> _has_bits_;\n");
1889 "::$proto_ns$::internal::ExtensionSet _extensions_;\n"
1893 if (
options_.field_listener_options.inject_field_listener_events &&
1895 google::protobuf::FileOptions::LITE_RUNTIME) {
1896 format(
"static ::$proto_ns$::AccessListener<$1$> _tracker_;\n",
1903 if (!inlined_string_indices_.empty()) {
1904 format(
"::$proto_ns$::internal::HasBits<$1$> _inlined_string_donated_;\n",
1905 InlinedStringDonatedSize());
1909 "template <typename T> friend class "
1910 "::$proto_ns$::Arena::InternalHelper;\n"
1911 "typedef void InternalArenaConstructable_;\n"
1912 "typedef void DestructorSkippable_;\n");
1919 format(has_bits_decl.c_str());
1920 format(cached_size_decl.c_str());
1921 need_to_emit_cached_size =
false;
1927 for (
auto field : optimized_order_) {
1928 const FieldGenerator& generator = field_generators_.get(
field);
1929 generator.GenerateStaticMembers(printer);
1930 generator.GeneratePrivateMembers(printer);
1936 format(
"union $1$Union {\n", camel_oneof_name);
1941 "constexpr $1$Union() : _constinit_{} {}\n"
1942 " ::$proto_ns$::internal::ConstantInitialized _constinit_;\n",
1946 field_generators_.get(
field).GeneratePrivateMembers(printer);
1950 format(
"} $1$_;\n", oneof->name());
1953 field_generators_.get(
field).GenerateStaticMembers(printer);
1960 if (need_to_emit_cached_size) {
1961 format(cached_size_decl.c_str());
1962 need_to_emit_cached_size =
false;
1968 "$uint32$ _oneof_case_[$1$];\n"
1973 if (num_weak_fields_) {
1974 format(
"::$proto_ns$::internal::WeakFieldMap _weak_field_map_;\n");
1978 format(
"::$proto_ns$::internal::AnyMetadata _any_metadata_;\n");
1983 format(
"friend struct ::$tablename$;\n");
1990 void MessageGenerator::GenerateInlineMethods(
io::Printer* printer) {
1992 GenerateFieldAccessorDefinitions(printer);
1998 format.Set(
"oneof_name", oneof->name());
1999 format.Set(
"oneof_index", oneof->index());
2001 "inline $classname$::$camel_oneof_name$Case $classname$::"
2002 "${1$$oneof_name$_case$}$() const {\n"
2003 " return $classname$::$camel_oneof_name$Case("
2004 "_oneof_case_[$oneof_index$]);\n"
2011 size_t aux_offset) {
2014 if (!table_driven_) {
2015 format(
"{ nullptr, nullptr, 0, -1, -1, -1, -1, nullptr, false },\n");
2019 int max_field_number = 0;
2021 if (max_field_number < field->
number()) {
2022 max_field_number =
field->number();
2030 "$tablename$::entries + $1$,\n"
2031 "$tablename$::aux + $2$,\n"
2033 offset, aux_offset, max_field_number);
2039 format(
"PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
2043 format(
"PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_),\n");
2045 format(
"-1, // no _oneof_case_\n");
2049 format(
"PROTOBUF_FIELD_OFFSET($classtype$, _extensions_),\n");
2051 format(
"-1, // no _extensions_\n");
2057 "PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_),\n"
2058 "&$package_ns$::_$classname$_default_instance_,\n");
2077 int inlined_string_indices_offset;
2078 if (inlined_string_indices_.empty()) {
2079 inlined_string_indices_offset = -1;
2086 format(
"{ $1$, $2$, $3$, sizeof($classtype$)},\n",
offset, has_offset,
2087 inlined_string_indices_offset);
2094 uint32_t CalcFieldNum(
const FieldGenerator& generator,
2098 if (
type == FieldDescriptor::TYPE_STRING ||
2099 type == FieldDescriptor::TYPE_BYTES) {
2101 if (generator.IsInlined()) {
2102 type = internal::FieldMetadata::kInlinedType;
2104 type = internal::FieldMetadata::kCordType;
2106 type = internal::FieldMetadata::kStringPieceType;
2110 if (
field->real_containing_oneof()) {
2111 return internal::FieldMetadata::CalculateType(
2112 type, internal::FieldMetadata::kOneOf);
2113 }
else if (
field->is_packed()) {
2114 return internal::FieldMetadata::CalculateType(
2115 type, internal::FieldMetadata::kPacked);
2116 }
else if (
field->is_repeated()) {
2117 return internal::FieldMetadata::CalculateType(
2118 type, internal::FieldMetadata::kRepeated);
2120 return internal::FieldMetadata::CalculateType(
2121 type, internal::FieldMetadata::kPresence);
2123 return internal::FieldMetadata::CalculateType(
2129 std::vector<const Descriptor*>
flatten =
2137 int MessageGenerator::GenerateFieldMetadata(
io::Printer* printer) {
2139 if (!
options_.table_driven_serialization) {
2145 for (
int i = 0;
i < 2;
i++) {
2147 const FieldGenerator& generator = field_generators_.get(
field);
2150 field->number(), WireFormat::WireTypeForFieldType(
field->type()));
2152 std::map<std::string, std::string> vars;
2158 vars[
"ptr"] =
"nullptr";
2159 if (
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2163 "::serialization_table + " +
2164 StrCat(FindMessageIndexInFile(
field->message_type()));
2166 Formatter::SaveState saver(&
format);
2169 "{PROTOBUF_FIELD_OFFSET("
2170 "::$proto_ns$::internal::MapEntryHelper<$classtype$::"
2171 "SuperType>, $field_name$_), $tag$,"
2172 "PROTOBUF_FIELD_OFFSET("
2173 "::$proto_ns$::internal::MapEntryHelper<$classtype$::"
2174 "SuperType>, _has_bits_) * 8 + $hasbit$, $type$, "
2180 "{PROTOBUF_FIELD_OFFSET($classtype$, _cached_size_),"
2181 " 0, 0, 0, nullptr},\n");
2182 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
2183 sorted_extensions.reserve(
descriptor_->extension_range_count());
2185 sorted_extensions.push_back(
descriptor_->extension_range(
i));
2187 std::sort(sorted_extensions.begin(), sorted_extensions.end(),
2188 ExtensionRangeSorter());
2189 for (
int i = 0, extension_idx = 0; ;
i++) {
2190 for (; extension_idx < sorted_extensions.size() &&
2191 (
i == sorted.size() ||
2192 sorted_extensions[extension_idx]->start < sorted[
i]->number());
2194 const Descriptor::ExtensionRange*
range =
2195 sorted_extensions[extension_idx];
2197 "{PROTOBUF_FIELD_OFFSET($classtype$, _extensions_), "
2198 "$1$, $2$, ::$proto_ns$::internal::FieldMetadata::kSpecial, "
2199 "reinterpret_cast<const "
2200 "void*>(::$proto_ns$::internal::ExtensionSerializer)},\n",
2203 if (
i == sorted.size())
break;
2207 field->number(), WireFormat::WireTypeForFieldType(
field->type()));
2208 if (
field->is_packed()) {
2209 tag = internal::WireFormatLite::MakeTag(
2214 if (
field->real_containing_oneof()) {
2215 classfieldname =
field->containing_oneof()->name();
2217 format.Set(
"field_name", classfieldname);
2219 if (
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2222 "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), $1$, $2$, "
2223 "::$proto_ns$::internal::FieldMetadata::kSpecial, "
2224 "reinterpret_cast<const void*>(static_cast< "
2225 "::$proto_ns$::internal::SpecialSerializer>("
2226 "::$proto_ns$::internal::MapFieldSerializer< "
2227 "::$proto_ns$::internal::MapEntryToMapField<"
2228 "$3$>::MapFieldType, "
2229 "$tablename$::serialization_table>))},\n",
2230 tag, FindMessageIndexInFile(
field->message_type()),
2233 }
else if (!
field->message_type()->options().message_set_wire_format()) {
2238 "::serialization_table + " +
2239 StrCat(FindMessageIndexInFile(
field->message_type()));
2243 const FieldGenerator& generator = field_generators_.get(
field);
2247 type = internal::FieldMetadata::kSpecial;
2248 ptr =
"reinterpret_cast<const void*>(::" +
variables_[
"proto_ns"] +
2249 "::internal::LazyFieldSerializer";
2250 if (
field->real_containing_oneof()) {
2253 ptr +=
"NoPresence";
2258 if (
field->options().weak()) {
2261 "{PROTOBUF_FIELD_OFFSET("
2262 "$classtype$, _weak_field_map_), $1$, $1$, "
2263 "::$proto_ns$::internal::FieldMetadata::kSpecial, "
2264 "reinterpret_cast<const "
2265 "void*>(::$proto_ns$::internal::WeakFieldSerializer)},\n",
2267 }
else if (
field->real_containing_oneof()) {
2268 format.Set(
"oneofoffset",
2271 "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), $1$,"
2272 " PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_) + "
2273 "$oneofoffset$, $2$, $3$},\n",
2278 "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), "
2279 "$1$, PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_) * 8 + "
2280 "$hasbitsoffset$, $2$, $3$},\n",
2284 "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), "
2285 "$1$, ~0u, $2$, $3$},\n",
2289 int num_field_metadata = 1 + sorted.size() + sorted_extensions.size();
2290 num_field_metadata++;
2292 ?
"UnknownFieldSetSerializer"
2293 :
"UnknownFieldSerializerLite";
2295 "{PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_), 0, ~0u, "
2296 "::$proto_ns$::internal::FieldMetadata::kSpecial, reinterpret_cast<const "
2297 "void*>(::$proto_ns$::internal::$1$)},\n",
2299 return num_field_metadata;
2302 void MessageGenerator::GenerateClassMethods(
io::Printer* printer) {
2306 "$classname$::$classname$() {}\n"
2307 "$classname$::$classname$(::$proto_ns$::Arena* arena)\n"
2308 " : SuperType(arena) {}\n"
2309 "void $classname$::MergeFrom(const $classname$& other) {\n"
2310 " MergeFromInternal(other);\n"
2315 "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
2316 "$annotate_reflection$"
2317 " return ::$proto_ns$::internal::AssignDescriptors(\n"
2318 " &$desc_table$_getter, &$desc_table$_once,\n"
2319 " $file_level_metadata$[$1$]);\n"
2321 index_in_file_messages_);
2324 "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
2325 " return ::$proto_ns$::internal::AssignDescriptors(\n"
2326 " &$desc_table$_getter, &$desc_table$_once,\n"
2327 " $file_level_metadata$[$1$]);\n"
2329 index_in_file_messages_);
2338 "bool $classname$::GetAnyFieldDescriptors(\n"
2339 " const ::$proto_ns$::Message& message,\n"
2340 " const ::$proto_ns$::FieldDescriptor** type_url_field,\n"
2341 " const ::$proto_ns$::FieldDescriptor** value_field) {\n"
2342 " return ::$proto_ns$::internal::GetAnyFieldDescriptors(\n"
2343 " message, type_url_field, value_field);\n"
2347 "bool $classname$::ParseAnyTypeUrl(\n"
2348 " ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,\n"
2349 " std::string* full_type_name) {\n"
2350 " return ::$proto_ns$::internal::ParseAnyTypeUrl(type_url,\n"
2351 " full_type_name);\n"
2357 "class $classname$::_Internal {\n"
2362 "using HasBits = decltype(std::declval<$classname$>()._has_bits_);\n");
2365 field_generators_.get(
field).GenerateInternalAccessorDeclarations(printer);
2370 int has_bit_index = HasBitIndex(
field);
2373 "static void set_has_$1$(HasBits* has_bits) {\n"
2374 " (*has_bits)[$2$] |= $3$u;\n"
2379 if (num_required_fields_ > 0) {
2380 const std::vector<uint32_t> masks_for_has_bits = RequiredFieldsBitMask();
2382 "static bool MissingRequiredFields(const HasBits& has_bits) "
2393 field_generators_.get(
field).GenerateInternalAccessorDefinitions(printer);
2402 field_generators_.get(
field).GenerateNonInlineAccessorDefinitions(printer);
2403 if (IsCrossFileMaybeMap(
field)) {
2404 Formatter::SaveState saver(&
format);
2405 std::map<std::string, std::string> vars;
2407 if (
field->real_containing_oneof()) {
2415 GenerateStructors(printer);
2419 GenerateOneofClear(printer);
2424 GenerateClear(printer);
2428 parse_function_generator_->GenerateMethodImpls(printer);
2431 parse_function_generator_->GenerateDataDefinitions(printer);
2434 GenerateSerializeWithCachedSizesToArray(printer);
2437 GenerateByteSize(printer);
2440 GenerateMergeFrom(printer);
2443 GenerateClassSpecificMergeFrom(printer);
2446 GenerateCopyFrom(printer);
2449 GenerateIsInitialized(printer);
2453 GenerateVerify(printer);
2455 GenerateSwap(printer);
2458 if (
options_.table_driven_serialization) {
2460 "const void* $classname$::InternalGetTable() const {\n"
2461 " return ::$tablename$::serialization_table + $1$;\n"
2464 index_in_file_messages_);
2469 "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
2470 "$annotate_reflection$"
2471 " return ::$proto_ns$::internal::AssignDescriptors(\n"
2472 " &$desc_table$_getter, &$desc_table$_once,\n"
2473 " $file_level_metadata$[$1$]);\n"
2475 index_in_file_messages_);
2478 "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
2479 " return ::$proto_ns$::internal::AssignDescriptors(\n"
2480 " &$desc_table$_getter, &$desc_table$_once,\n"
2481 " $file_level_metadata$[$1$]);\n"
2483 index_in_file_messages_);
2487 "std::string $classname$::GetTypeName() const {\n"
2488 " return \"$full_name$\";\n"
2493 if (
options_.field_listener_options.inject_field_listener_events &&
2495 google::protobuf::FileOptions::LITE_RUNTIME) {
2497 "::$proto_ns$::AccessListener<$classtype$> "
2498 "$1$::_tracker_(&FullMessageName);\n",
2503 size_t MessageGenerator::GenerateParseOffsets(
io::Printer* printer) {
2506 if (!table_driven_) {
2512 format(
"{0, 0, 0, ::$proto_ns$::internal::kInvalidMask, 0, 0},\n");
2513 int last_field_number = 1;
2515 std::vector<const FieldDescriptor*> ordered_fields =
2518 for (
auto field : ordered_fields) {
2519 Formatter::SaveState saver(&
format);
2522 for (; last_field_number <
field->number(); last_field_number++) {
2524 "{ 0, 0, ::$proto_ns$::internal::kInvalidMask,\n"
2525 " ::$proto_ns$::internal::kInvalidMask, 0, 0 },\n");
2527 last_field_number++;
2529 unsigned char normal_wiretype, packed_wiretype, processing_type;
2530 normal_wiretype = WireFormat::WireTypeForFieldType(
field->type());
2532 if (
field->is_packable()) {
2538 processing_type =
static_cast<unsigned>(
field->type());
2539 const FieldGenerator& generator = field_generators_.get(
field);
2540 if (
field->type() == FieldDescriptor::TYPE_STRING) {
2543 if (generator.IsInlined()) {
2554 }
else if (
field->type() == FieldDescriptor::TYPE_BYTES) {
2557 if (generator.IsInlined()) {
2570 processing_type |=
static_cast<unsigned>(
2572 processing_type |=
static_cast<unsigned>(
2575 if (
field->is_map()) {
2579 const unsigned char tag_size =
2580 WireFormat::TagSize(
field->number(),
field->type());
2582 std::map<std::string, std::string> vars;
2583 if (
field->real_containing_oneof()) {
2584 vars[
"name"] =
field->containing_oneof()->name();
2585 vars[
"presence"] =
StrCat(
field->containing_oneof()->index());
2590 vars[
"nwtype"] =
StrCat(normal_wiretype);
2591 vars[
"pwtype"] =
StrCat(packed_wiretype);
2592 vars[
"ptype"] =
StrCat(processing_type);
2593 vars[
"tag_size"] =
StrCat(tag_size);
2599 " PROTOBUF_FIELD_OFFSET($classtype$, $name$_),\n"
2600 " static_cast<$uint32$>($presence$),\n"
2601 " $nwtype$, $pwtype$, $ptype$, $tag_size$\n"
2605 return last_field_number;
2608 size_t MessageGenerator::GenerateParseAuxTable(
io::Printer* printer) {
2611 if (!table_driven_) {
2615 std::vector<const FieldDescriptor*> ordered_fields =
2618 format(
"::$proto_ns$::internal::AuxiliaryParseTableField(),\n");
2619 int last_field_number = 1;
2620 for (
auto field : ordered_fields) {
2621 Formatter::SaveState saver(&
format);
2624 for (; last_field_number <
field->number(); last_field_number++) {
2625 format(
"::$proto_ns$::internal::AuxiliaryParseTableField(),\n");
2628 std::map<std::string, std::string> vars;
2632 switch (
field->cpp_type()) {
2633 case FieldDescriptor::CPPTYPE_ENUM:
2636 "{::$proto_ns$::internal::AuxiliaryParseTableField::enum_aux{"
2640 "{::$proto_ns$::internal::AuxiliaryParseTableField::enum_aux{"
2644 last_field_number++;
2646 case FieldDescriptor::CPPTYPE_MESSAGE: {
2647 if (
field->is_map()) {
2649 "{::$proto_ns$::internal::AuxiliaryParseTableField::map_"
2650 "aux{&::$proto_ns$::internal::ParseMap<$1$>}},\n",
2652 last_field_number++;
2660 "{::$proto_ns$::internal::AuxiliaryParseTableField::message_aux{\n"
2661 " &$default_instance$}},\n");
2662 last_field_number++;
2665 case FieldDescriptor::CPPTYPE_STRING: {
2669 default_val =
field->default_value_string().empty()
2671 "::internal::fixed_address_empty_string"
2683 "{::$proto_ns$::internal::AuxiliaryParseTableField::string_aux{\n"
2687 default_val,
field->full_name());
2688 last_field_number++;
2696 return last_field_number;
2699 std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
2704 format(
"PROTOBUF_FIELD_OFFSET($classtype$, _has_bits_),\n");
2706 format(
"~0u, // no _has_bits_\n");
2708 format(
"PROTOBUF_FIELD_OFFSET($classtype$, _internal_metadata_),\n");
2710 format(
"PROTOBUF_FIELD_OFFSET($classtype$, _extensions_),\n");
2712 format(
"~0u, // no _extensions_\n");
2715 format(
"PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_[0]),\n");
2717 format(
"~0u, // no _oneof_case_\n");
2719 if (num_weak_fields_ > 0) {
2720 format(
"PROTOBUF_FIELD_OFFSET($classtype$, _weak_field_map_),\n");
2722 format(
"~0u, // no _weak_field_map_\n");
2724 if (!inlined_string_indices_.empty()) {
2725 format(
"PROTOBUF_FIELD_OFFSET($classtype$, _inlined_string_donated_),\n");
2727 format(
"~0u, // no _inlined_string_donated_\n");
2729 const int kNumGenericOffsets = 6;
2730 const size_t offsets = kNumGenericOffsets +
descriptor_->field_count() +
2732 size_t entries = offsets;
2735 format(
"~0u, // stripped\n");
2740 if (
field->options().weak() ||
field->real_containing_oneof()) {
2743 format(
"::$proto_ns$::internal::kInvalidFieldOffsetTag");
2755 format(
" | 0x80000000u // unused\n");
2761 format(
" | 0x1u // eagerly verified lazy\n");
2763 format(
" | 0x1u // inlined\n");
2770 format(
"PROTOBUF_FIELD_OFFSET($classtype$, $1$_),\n", oneof->name());
2788 if (!inlined_string_indices_.empty()) {
2789 entries += inlined_string_indices_.size();
2790 for (
int inlined_string_indice : inlined_string_indices_) {
2792 ?
StrCat(inlined_string_indice)
2798 return std::make_pair(entries, offsets);
2801 void MessageGenerator::GenerateSharedConstructorCode(
io::Printer* printer) {
2805 format(
"inline void $classname$::SharedCtor() {\n");
2807 std::vector<bool> processed(optimized_order_.size(),
false);
2808 GenerateConstructorBody(printer, processed,
false);
2811 format(
"clear_has_$1$();\n", oneof->name());
2817 void MessageGenerator::GenerateSharedDestructorCode(
io::Printer* printer) {
2821 format(
"inline void $classname$::SharedDtor() {\n");
2823 format(
"$DCHK$(GetArenaForAllocation() == nullptr);\n");
2826 for (
auto field : optimized_order_) {
2827 field_generators_.get(
field).GenerateDestructorCode(printer);
2833 "if (has_$1$()) {\n"
2839 if (num_weak_fields_) {
2840 format(
"_weak_field_map_.ClearAll();\n");
2848 void MessageGenerator::GenerateArenaDestructorCode(
io::Printer* printer) {
2854 format(
"void $classname$::ArenaDtor(void* object) {\n");
2862 "$classname$* _this = reinterpret_cast< $classname$* >(object);\n"
2866 bool need_registration =
false;
2868 for (
auto field : optimized_order_) {
2869 if (field_generators_.get(
field).GenerateArenaDestructorCode(printer)) {
2870 need_registration =
true;
2881 field_generators_.get(
field).GenerateArenaDestructorCode(printer)) {
2882 need_registration =
true;
2890 if (need_registration) {
2892 "inline void $classname$::RegisterArenaDtor(::$proto_ns$::Arena* "
2894 " if (arena != nullptr) {\n"
2895 " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n"
2900 "void $classname$::RegisterArenaDtor(::$proto_ns$::Arena*) {\n"
2905 void MessageGenerator::GenerateConstexprConstructor(
io::Printer* printer) {
2909 "constexpr $classname$::$classname$(\n"
2910 " ::$proto_ns$::internal::ConstantInitialized)");
2912 const char* field_sep =
":";
2913 const auto put_sep = [&] {
2914 format(
"\n$1$ ", field_sep);
2920 for (
auto field : optimized_order_) {
2921 auto&
gen = field_generators_.get(
field);
2923 gen.GenerateConstinitInitializer(printer);
2928 format(
"_any_metadata_(&type_url_, &value_)");
2933 format(
"_oneof_case_{}");
2941 void MessageGenerator::GenerateConstructorBody(
io::Printer* printer,
2942 std::vector<bool> processed,
2943 bool copy_constructor)
const {
2946 const RunMap runs = FindRuns(
2948 return (copy_constructor && IsPOD(
field)) ||
2949 (!copy_constructor &&
2950 CanBeManipulatedAsRawBytes(
field,
options_, scc_analyzer_));
2954 if (copy_constructor) {
2956 "::memcpy(&$first$_, &from.$first$_,\n"
2957 " static_cast<size_t>(reinterpret_cast<char*>(&$last$_) -\n"
2958 " reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n";
2961 "::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(\n"
2962 " reinterpret_cast<char*>(&$first$_) - "
2963 "reinterpret_cast<char*>(this)),\n"
2964 " 0, static_cast<size_t>(reinterpret_cast<char*>(&$last$_) -\n"
2965 " reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n";
2968 for (
int i = 0;
i < optimized_order_.size(); ++
i) {
2974 const auto it = runs.find(
field);
2978 if (
it != runs.end() &&
it->second > 1) {
2980 const size_t run_length =
it->second;
2983 FieldName(optimized_order_[
i + run_length - 1]);
2985 format.Set(
"first", first_field_name);
2986 format.Set(
"last", last_field_name);
2988 format(pod_template.c_str());
2990 i += run_length - 1;
2993 if (copy_constructor) {
2994 field_generators_.get(
field).GenerateCopyConstructorCode(printer);
2996 field_generators_.get(
field).GenerateConstructorCode(printer);
3002 void MessageGenerator::GenerateStructors(
io::Printer* printer) {
3007 std::string initializer_with_arena = superclass +
"(arena, is_message_owned)";
3010 initializer_with_arena +=
",\n _extensions_(arena)";
3014 for (
auto field : optimized_order_) {
3016 bool has_arena_constructor =
field->is_repeated();
3017 if (!
field->real_containing_oneof() &&
3021 has_arena_constructor =
true;
3023 if (has_arena_constructor) {
3024 initializer_with_arena +=
3030 initializer_with_arena +=
",\n _any_metadata_(&type_url_, &value_)";
3032 if (num_weak_fields_ > 0) {
3033 initializer_with_arena +=
", _weak_field_map_(arena)";
3038 initializer_null +=
", _any_metadata_(&type_url_, &value_)";
3040 if (num_weak_fields_ > 0) {
3041 initializer_null +=
", _weak_field_map_(nullptr)";
3045 "$classname$::$classname$(::$proto_ns$::Arena* arena,\n"
3046 " bool is_message_owned)\n"
3048 initializer_with_arena);
3050 if (!inlined_string_indices_.empty()) {
3052 format(
" if (arena != nullptr) {\n");
3053 for (
size_t i = 0;
i < InlinedStringDonatedSize(); ++
i) {
3054 format(
" _inlined_string_donated_[$1$] = ~0u;\n",
i);
3062 " if (!is_message_owned) {\n"
3063 " RegisterArenaDtor(arena);\n"
3067 " // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
3070 std::map<std::string, std::string> vars;
3081 "$classname$::$classname$(const $classname$& from)\n"
3082 " : $classname$() {\n"
3083 " MergeFrom(from);\n"
3087 "$classname$::$classname$(const $classname$& from)\n"
3088 " : $superclass$()");
3097 format(
",\n_has_bits_(from._has_bits_)");
3100 std::vector<bool> processed(optimized_order_.size(),
false);
3101 for (
int i = 0;
i < optimized_order_.size();
i++) {
3102 auto field = optimized_order_[
i];
3103 if (!(
field->is_repeated() && !(
field->is_map())) &&
3108 processed[
i] =
true;
3113 format(
",\n_any_metadata_(&type_url_, &value_)");
3115 if (num_weak_fields_ > 0) {
3116 format(
",\n_weak_field_map_(from._weak_field_map_)");
3124 "_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_"
3129 "_extensions_.MergeFrom(internal_default_instance(), "
3130 "from._extensions_);\n");
3133 GenerateConstructorBody(printer, processed,
true);
3138 "clear_has_$1$();\n"
3139 "switch (from.$1$_case()) {\n",
3146 field_generators_.get(
field).GenerateMergingCode(printer);
3153 "case $1$_NOT_SET: {\n"
3163 " // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
3169 GenerateSharedConstructorCode(printer);
3174 "$classname$::~$classname$() {\n"
3175 " // @@protoc_insertion_point(destructor:$full_name$)\n"
3176 " if (GetArenaForAllocation() != nullptr) return;\n"
3178 " _internal_metadata_.Delete<$unknown_fields_type$>();\n"
3190 GenerateSharedDestructorCode(printer);
3193 GenerateArenaDestructorCode(printer);
3198 "void $classname$::SetCachedSize(int size) const {\n"
3199 " _cached_size_.Set(size);\n"
3204 void MessageGenerator::GenerateSourceInProto2Namespace(
io::Printer* printer) {
3208 "PROTOBUF_NOINLINE "
3209 "$classtype$* Arena::CreateMaybeMessage< $classtype$ >(Arena* arena) {\n"
3210 " return Arena::CreateMessageInternal< $classtype$ >(arena);\n"
3214 void MessageGenerator::GenerateClear(
io::Printer* printer) {
3220 const int kMaxUnconditionalPrimitiveBytesClear = 4;
3223 "void $classname$::Clear() {\n"
3224 "// @@protoc_insertion_point(message_clear_start:$full_name$)\n");
3230 "$uint32$ cached_has_bits = 0;\n"
3231 "// Prevent compiler warnings about cached_has_bits being unused\n"
3232 "(void) cached_has_bits;\n\n");
3235 format(
"_extensions_.Clear();\n");
3240 int zero_init_bytes = 0;
3241 for (
const auto&
field : optimized_order_) {
3246 bool merge_zero_init = zero_init_bytes > kMaxUnconditionalPrimitiveBytesClear;
3247 int chunk_count = 0;
3249 std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
3255 bool same = HasByteIndex(
a) == HasByteIndex(
b) &&
3256 a->is_repeated() ==
b->is_repeated() &&
3259 (chunk_count == 1 || merge_zero_init)));
3260 if (!same) chunk_count = 0;
3265 int cached_has_word_index = -1;
3267 for (
int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
3268 std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
3269 cold_skipper.OnStartChunk(chunk_index, cached_has_word_index,
"", printer);
3273 bool saw_non_zero_init =
false;
3275 for (
const auto&
field : chunk) {
3278 if (!memset_start) memset_start =
field;
3281 saw_non_zero_init =
true;
3290 const bool have_outer_if = HasBitIndex(chunk.front()) != kNoHasbit &&
3292 (memset_end != chunk.back() || merge_zero_init);
3294 if (have_outer_if) {
3306 if (cached_has_word_index != HasWordIndex(chunk.front())) {
3307 cached_has_word_index = HasWordIndex(chunk.front());
3308 format(
"cached_has_bits = _has_bits_[$1$];\n", cached_has_word_index);
3310 format(
"if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str);
3315 if (memset_start == memset_end) {
3317 field_generators_.get(memset_start)
3318 .GenerateMessageClearingCode(printer);
3321 "::memset(&$1$_, 0, static_cast<size_t>(\n"
3322 " reinterpret_cast<char*>(&$2$_) -\n"
3323 " reinterpret_cast<char*>(&$1$_)) + sizeof($2$_));\n",
3329 for (
const auto&
field : chunk) {
3335 bool have_enclosing_if =
3336 HasBitIndex(
field) != kNoHasbit &&
3337 (
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
3338 field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
3340 if (have_enclosing_if) {
3342 &cached_has_word_index);
3345 field_generators_.get(
field).GenerateMessageClearingCode(printer);
3347 if (have_enclosing_if) {
3353 if (have_outer_if) {
3358 if (cold_skipper.OnEndChunk(chunk_index, printer)) {
3360 cached_has_word_index = -1;
3366 format(
"clear_$1$();\n", oneof->name());
3369 if (num_weak_fields_) {
3370 format(
"_weak_field_map_.ClearAll();\n");
3377 format(
"_has_bits_.Clear();\n");
3380 std::map<std::string, std::string> vars;
3383 format(
"_internal_metadata_.Clear<$unknown_fields_type$>();\n");
3389 void MessageGenerator::GenerateOneofClear(
io::Printer* printer) {
3394 format.Set(
"oneofname", oneof->name());
3397 "void $classname$::clear_$oneofname$() {\n"
3398 "// @@protoc_insertion_point(one_of_clear_start:$full_name$)\n");
3400 format(
"switch ($oneofname$_case()) {\n");
3407 format(
"// No need to clear\n");
3409 field_generators_.get(
field).GenerateClearingCode(printer);
3416 "case $1$_NOT_SET: {\n"
3423 "_oneof_case_[$1$] = $2$_NOT_SET;\n",
3433 void MessageGenerator::GenerateSwap(
io::Printer* printer) {
3437 format(
"void $classname$::InternalSwap($classname$* other) {\n");
3439 format(
"using std::swap;\n");
3443 format(
"_extensions_.InternalSwap(&other->_extensions_);\n");
3446 std::map<std::string, std::string> vars;
3451 "auto* lhs_arena = GetArenaForAllocation();\n"
3452 "auto* rhs_arena = other->GetArenaForAllocation();\n");
3454 format(
"_internal_metadata_.InternalSwap(&other->_internal_metadata_);\n");
3457 for (
int i = 0;
i < HasBitsSize(); ++
i) {
3458 format(
"swap(_has_bits_[$1$], other->_has_bits_[$1$]);\n",
i);
3465 return CanBeManipulatedAsRawBytes(
field,
options_, scc_analyzer_);
3468 for (
int i = 0;
i < optimized_order_.size(); ++
i) {
3470 const auto it = runs.find(
field);
3475 if (
it != runs.end() &&
it->second > 1) {
3477 const size_t run_length =
it->second;
3480 FieldName(optimized_order_[
i + run_length - 1]);
3482 format.Set(
"first", first_field_name);
3483 format.Set(
"last", last_field_name);
3486 "::PROTOBUF_NAMESPACE_ID::internal::memswap<\n"
3487 " PROTOBUF_FIELD_OFFSET($classname$, $last$_)\n"
3488 " + sizeof($classname$::$last$_)\n"
3489 " - PROTOBUF_FIELD_OFFSET($classname$, $first$_)>(\n"
3490 " reinterpret_cast<char*>(&$first$_),\n"
3491 " reinterpret_cast<char*>(&other->$first$_));\n");
3493 i += run_length - 1;
3496 field_generators_.get(
field).GenerateSwappingCode(printer);
3501 format(
"swap($1$_, other->$1$_);\n", oneof->name());
3505 format(
"swap(_oneof_case_[$1$], other->_oneof_case_[$1$]);\n",
i);
3508 if (num_weak_fields_) {
3509 format(
"_weak_field_map_.UnsafeArenaSwap(&other->_weak_field_map_);\n");
3512 format(
"GetReflection()->Swap(this, other);");
3519 void MessageGenerator::GenerateMergeFrom(
io::Printer* printer) {
3533 "const ::$proto_ns$::Message::ClassData "
3534 "$classname$::_class_data_ = {\n"
3535 " ::$proto_ns$::Message::CopyWithSizeCheck,\n"
3536 " $classname$::MergeImpl\n"
3538 "const ::$proto_ns$::Message::ClassData*"
3539 "$classname$::GetClassData() const { return &_class_data_; }\n"
3541 "void $classname$::MergeImpl(::$proto_ns$::Message* to,\n"
3542 " const ::$proto_ns$::Message& from) {\n"
3543 " static_cast<$classname$ *>(to)->MergeFrom(\n"
3544 " static_cast<const $classname$ &>(from));\n"
3550 "void $classname$::CheckTypeAndMergeFrom(\n"
3551 " const ::$proto_ns$::MessageLite& from) {\n"
3552 " MergeFrom(*::$proto_ns$::internal::DownCast<const $classname$*>(\n"
3560 "const ::$proto_ns$::Message::ClassData "
3561 "$classname$::_class_data_ = {\n"
3562 " $superclass$::CopyImpl,\n"
3563 " $superclass$::MergeImpl,\n"
3565 "const ::$proto_ns$::Message::ClassData*"
3566 "$classname$::GetClassData() const { return &_class_data_; }\n"
3572 void MessageGenerator::GenerateClassSpecificMergeFrom(
io::Printer* printer) {
3577 "void $classname$::MergeFrom(const $classname$& from) {\n"
3578 "$annotate_mergefrom$"
3579 "// @@protoc_insertion_point(class_specific_merge_from_start:"
3581 " $DCHK$_NE(&from, this);\n");
3585 "$uint32$ cached_has_bits = 0;\n"
3586 "(void) cached_has_bits;\n\n");
3588 std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
3591 return HasByteIndex(
a) == HasByteIndex(
b);
3599 int cached_has_word_index = -1;
3601 for (
int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
3602 const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
3603 bool have_outer_if =
3604 chunk.size() > 1 && HasByteIndex(chunk.front()) != kNoHasbit;
3605 cold_skipper.OnStartChunk(chunk_index, cached_has_word_index,
"from.",
3608 if (have_outer_if) {
3620 if (cached_has_word_index != HasWordIndex(chunk.front())) {
3621 cached_has_word_index = HasWordIndex(chunk.front());
3622 format(
"cached_has_bits = from._has_bits_[$1$];\n",
3623 cached_has_word_index);
3626 format(
"if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str);
3631 bool deferred_has_bit_changes =
false;
3632 for (
const auto field : chunk) {
3635 if (
field->is_repeated()) {
3640 bool have_enclosing_if =
3641 EmitFieldNonDefaultCondition(printer,
"from.",
field);
3643 if (have_enclosing_if) {
3647 }
else if (
field->options().weak() ||
3648 cached_has_word_index != HasWordIndex(
field)) {
3662 format(
"if (cached_has_bits & 0x$1$u) {\n", mask);
3665 if (have_outer_if && IsPOD(
field)) {
3668 deferred_has_bit_changes =
true;
3679 if (have_outer_if) {
3680 if (deferred_has_bit_changes) {
3683 format(
"_has_bits_[$1$] |= cached_has_bits;\n", cached_has_word_index);
3690 if (cold_skipper.OnEndChunk(chunk_index, printer)) {
3692 cached_has_word_index = -1;
3698 format(
"switch (from.$1$_case()) {\n", oneof->name());
3704 field_generators_.get(
field).GenerateMergingCode(printer);
3711 "case $1$_NOT_SET: {\n"
3718 if (num_weak_fields_) {
3719 format(
"_weak_field_map_.MergeFrom(from._weak_field_map_);\n");
3726 "_extensions_.MergeFrom(internal_default_instance(), "
3727 "from._extensions_);\n");
3731 "_internal_metadata_.MergeFrom<$unknown_fields_type$>(from._internal_"
3738 void MessageGenerator::GenerateCopyFrom(
io::Printer* printer) {
3756 "void $classname$::CopyFrom(const $classname$& from) {\n"
3757 "// @@protoc_insertion_point(class_specific_copy_from_start:"
3761 format(
"if (&from == this) return;\n");
3763 if (!
options_.opensource_runtime) {
3768 "size_t from_size = from.ByteSizeLong();\n"
3772 "$CHK$_EQ(from_size, from.ByteSizeLong())\n"
3773 " << \"Source of CopyFrom changed when clearing target. Either \"\n"
3774 " \"source is a nested message in target (not allowed), or \"\n"
3775 " \"another thread is modifying the source.\";\n"
3780 format(
"MergeFrom(from);\n");
3789 void MessageGenerator::GenerateSerializeOneofFields(
3793 if (
fields.size() == 1) {
3794 GenerateSerializeOneField(printer,
fields[0], -1);
3799 format(
"switch ($1$_case()) {\n", oneof->
name());
3804 field_generators_.get(
field).GenerateSerializeWithCachedSizesToArray(
3817 void MessageGenerator::GenerateSerializeOneField(
io::Printer* printer,
3819 int cached_has_bits_index) {
3821 if (!
field->options().weak()) {
3826 bool have_enclosing_if =
false;
3827 if (
field->options().weak()) {
3830 int has_bit_index = HasBitIndex(
field);
3831 if (cached_has_bits_index == has_bit_index / 32) {
3835 format(
"if (cached_has_bits & 0x$1$u) {\n", mask);
3841 have_enclosing_if =
true;
3843 have_enclosing_if = EmitFieldNonDefaultCondition(printer,
"this->",
field);
3846 field_generators_.get(
field).GenerateSerializeWithCachedSizesToArray(printer);
3848 if (have_enclosing_if) {
3855 void MessageGenerator::GenerateSerializeOneExtensionRange(
3857 std::map<std::string, std::string> vars =
variables_;
3861 format(
"// Extension range [$start$, $end$)\n");
3863 "target = _extensions_._InternalSerialize(\n"
3864 "internal_default_instance(), $start$, $end$, target, stream);\n\n");
3867 void MessageGenerator::GenerateSerializeWithCachedSizesToArray(
3871 if (
descriptor_->options().message_set_wire_format()) {
3874 "$uint8$* $classname$::_InternalSerialize(\n"
3875 " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
3877 "$annotate_serialize$"
3878 " target = _extensions_."
3879 "InternalSerializeMessageSetWithCachedSizesToArray(\n"
3880 "internal_default_instance(), target, stream);\n");
3881 std::map<std::string, std::string> vars;
3885 " target = ::$proto_ns$::internal::"
3886 "InternalSerializeUnknownMessageSetItemsToArray(\n"
3887 " $unknown_fields$, target, stream);\n");
3895 "$uint8$* $classname$::_InternalSerialize(\n"
3896 " $uint8$* target, ::$proto_ns$::io::EpsCopyOutputStream* stream) "
3898 "$annotate_serialize$");
3901 format(
"// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n");
3905 format(
"#ifdef NDEBUG\n");
3909 GenerateSerializeWithCachedSizesBody(printer);
3913 format(
"#else // NDEBUG\n");
3916 GenerateSerializeWithCachedSizesBodyShuffled(printer);
3919 format(
"#endif // !NDEBUG\n");
3923 format(
"// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n");
3931 void MessageGenerator::GenerateSerializeWithCachedSizesBody(
3940 class LazySerializerEmitter {
3942 LazySerializerEmitter(MessageGenerator* mg,
io::Printer* printer)
3946 cached_has_bit_index_(kNoHasbit) {}
3948 ~LazySerializerEmitter() { Flush(); }
3953 if (eager_ || MustFlush(
field)) {
3956 if (!
field->real_containing_oneof()) {
3959 if (!
field->options().weak() && !
field->is_repeated() && !eager_) {
3963 int has_bit_index = mg_->has_bit_indices_[
field->index()];
3964 if (cached_has_bit_index_ != has_bit_index / 32) {
3966 int new_index = has_bit_index / 32;
3968 format_(
"cached_has_bits = _has_bits_[$1$];\n", new_index);
3970 cached_has_bit_index_ = new_index;
3974 mg_->GenerateSerializeOneField(format_.printer(),
field,
3975 cached_has_bit_index_);
3977 v_.push_back(
field);
3982 if (
field !=
nullptr) {
3989 mg_->GenerateSerializeOneofFields(format_.printer(), v_);
3998 return !v_.empty() &&
3999 v_[0]->containing_oneof() !=
field->containing_oneof();
4002 MessageGenerator* mg_;
4005 std::vector<const FieldDescriptor*> v_;
4010 int cached_has_bit_index_;
4013 class LazyExtensionRangeEmitter {
4015 LazyExtensionRangeEmitter(MessageGenerator* mg,
io::Printer* printer)
4016 : mg_(mg), format_(printer) {}
4018 void AddToRange(
const Descriptor::ExtensionRange*
range) {
4019 if (!has_current_range_) {
4020 current_combined_range_ = *
range;
4021 has_current_range_ =
true;
4023 current_combined_range_.start =
4025 current_combined_range_.end =
4031 if (has_current_range_) {
4032 mg_->GenerateSerializeOneExtensionRange(format_.printer(),
4033 ¤t_combined_range_);
4035 has_current_range_ =
false;
4039 MessageGenerator* mg_;
4041 bool has_current_range_ =
false;
4042 Descriptor::ExtensionRange current_combined_range_;
4051 class LargestWeakFieldHolder {
4059 if (field_ ==
nullptr || field_->number() <
field->number()) {
4068 std::vector<const FieldDescriptor*> ordered_fields =
4071 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
4072 sorted_extensions.reserve(
descriptor_->extension_range_count());
4074 sorted_extensions.push_back(
descriptor_->extension_range(
i));
4076 std::sort(sorted_extensions.begin(), sorted_extensions.end(),
4077 ExtensionRangeSorter());
4078 if (num_weak_fields_) {
4080 "::$proto_ns$::internal::WeakFieldMap::FieldWriter field_writer("
4081 "_weak_field_map_);\n");
4085 "$uint32$ cached_has_bits = 0;\n"
4086 "(void) cached_has_bits;\n\n");
4090 LazySerializerEmitter
e(
this, printer);
4091 LazyExtensionRangeEmitter re(
this, printer);
4092 LargestWeakFieldHolder largest_weak_field;
4095 i < ordered_fields.size() || j < sorted_extensions.size();) {
4096 if ((j == sorted_extensions.size()) ||
4097 (i < descriptor_->field_count() &&
4098 ordered_fields[
i]->
number() < sorted_extensions[j]->
start)) {
4104 if (
field->options().weak()) {
4105 largest_weak_field.ReplaceIfLarger(
field);
4108 e.EmitIfNotNull(largest_weak_field.Release());
4112 e.EmitIfNotNull(largest_weak_field.Release());
4114 re.AddToRange(sorted_extensions[j++]);
4118 e.EmitIfNotNull(largest_weak_field.Release());
4121 std::map<std::string, std::string> vars;
4124 format(
"if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
4129 "::$proto_ns$::internal::WireFormat::"
4130 "InternalSerializeUnknownFieldsToArray(\n"
4131 " $unknown_fields$, target, stream);\n");
4134 "target = stream->WriteRaw($unknown_fields$.data(),\n"
4135 " static_cast<int>($unknown_fields$.size()), target);\n");
4141 void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled(
4145 std::vector<const FieldDescriptor*> ordered_fields =
4147 ordered_fields.erase(
4148 std::remove_if(ordered_fields.begin(), ordered_fields.end(),
4150 return !IsFieldUsed(f, options_);
4152 ordered_fields.end());
4154 std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
4155 sorted_extensions.reserve(
descriptor_->extension_range_count());
4157 sorted_extensions.push_back(
descriptor_->extension_range(
i));
4159 std::sort(sorted_extensions.begin(), sorted_extensions.end(),
4160 ExtensionRangeSorter());
4162 int num_fields = ordered_fields.size() + sorted_extensions.size();
4163 constexpr
int kLargePrime = 1000003;
4165 <<
"Prime offset must be greater than the number of fields to ensure "
4166 "those are coprime.";
4168 if (num_weak_fields_) {
4170 "::$proto_ns$::internal::WeakFieldMap::FieldWriter field_writer("
4171 "_weak_field_map_);\n");
4174 format(
"for (int i = $1$; i >= 0; i-- ) {\n", num_fields - 1);
4181 for (
const auto*
f : ordered_fields) {
4185 GenerateSerializeOneField(printer,
f, -1);
4192 for (
const auto*
r : sorted_extensions) {
4196 GenerateSerializeOneExtensionRange(printer,
r);
4205 " $DCHK$(false) << \"Unexpected index: \" << i;\n"
4213 std::map<std::string, std::string> vars;
4216 format(
"if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
4221 "::$proto_ns$::internal::WireFormat::"
4222 "InternalSerializeUnknownFieldsToArray(\n"
4223 " $unknown_fields$, target, stream);\n");
4226 "target = stream->WriteRaw($unknown_fields$.data(),\n"
4227 " static_cast<int>($unknown_fields$.size()), target);\n");
4233 std::vector<uint32_t> MessageGenerator::RequiredFieldsBitMask()
const {
4234 const int array_size = HasBitsSize();
4235 std::vector<uint32_t> masks(array_size, 0);
4238 if (!
field->is_required()) {
4243 masks[has_bit_index / 32] |=
static_cast<uint32_t>(1)
4244 << (has_bit_index % 32);
4249 void MessageGenerator::GenerateByteSize(
io::Printer* printer) {
4253 if (
descriptor_->options().message_set_wire_format()) {
4255 std::map<std::string, std::string> vars;
4259 "size_t $classname$::ByteSizeLong() const {\n"
4260 "$annotate_bytesize$"
4261 "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n"
4262 " size_t total_size = _extensions_.MessageSetByteSize();\n"
4263 " if ($have_unknown_fields$) {\n"
4264 " total_size += ::$proto_ns$::internal::\n"
4265 " ComputeUnknownMessageSetItemsSize($unknown_fields$);\n"
4267 " int cached_size = "
4268 "::$proto_ns$::internal::ToCachedSize(total_size);\n"
4269 " SetCachedSize(cached_size);\n"
4270 " return total_size;\n"
4275 if (num_required_fields_ > 1) {
4279 "size_t $classname$::RequiredFieldsByteSizeFallback() const {\n"
4280 "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:"
4283 format(
"size_t total_size = 0;\n");
4284 for (
auto field : optimized_order_) {
4285 if (
field->is_required()) {
4288 "if (_internal_has_$1$()) {\n",
4292 field_generators_.get(
field).GenerateByteSize(printer);
4299 "return total_size;\n");
4305 "size_t $classname$::ByteSizeLong() const {\n"
4306 "$annotate_bytesize$"
4307 "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n");
4310 "size_t total_size = 0;\n"
4315 "total_size += _extensions_.ByteSize();\n"
4319 std::map<std::string, std::string> vars;
4326 if (num_required_fields_ > 1) {
4328 const std::vector<uint32_t> masks_for_has_bits = RequiredFieldsBitMask();
4329 format(
"if ($1$) { // All required fields are present.\n",
4334 for (
auto field : optimized_order_) {
4335 if (!
field->is_required())
continue;
4337 field_generators_.get(
field).GenerateByteSize(printer);
4343 " total_size += RequiredFieldsByteSizeFallback();\n"
4347 for (
auto field : optimized_order_) {
4348 if (!
field->is_required())
continue;
4352 field_generators_.get(
field).GenerateByteSize(printer);
4358 std::vector<std::vector<const FieldDescriptor*>> chunks = CollectFields(
4361 return a->label() ==
b->label() && HasByteIndex(
a) == HasByteIndex(
b);
4365 chunks.erase(std::remove_if(chunks.begin(), chunks.end(), IsRequired),
4369 int cached_has_word_index = -1;
4372 "$uint32$ cached_has_bits = 0;\n"
4373 "// Prevent compiler warnings about cached_has_bits being unused\n"
4374 "(void) cached_has_bits;\n\n");
4376 for (
int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
4377 const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
4378 const bool have_outer_if =
4379 chunk.size() > 1 && HasWordIndex(chunk[0]) != kNoHasbit;
4380 cold_skipper.OnStartChunk(chunk_index, cached_has_word_index,
"", printer);
4382 if (have_outer_if) {
4394 if (cached_has_word_index != HasWordIndex(chunk.front())) {
4395 cached_has_word_index = HasWordIndex(chunk.front());
4396 format(
"cached_has_bits = _has_bits_[$1$];\n", cached_has_word_index);
4398 format(
"if (cached_has_bits & 0x$1$u) {\n", chunk_mask_str);
4403 for (
int j = 0;
j < chunk.size();
j++) {
4405 const FieldGenerator& generator = field_generators_.get(
field);
4406 bool have_enclosing_if =
false;
4407 bool need_extra_newline =
false;
4411 if (
field->is_repeated()) {
4413 need_extra_newline =
true;
4416 &cached_has_word_index);
4417 have_enclosing_if =
true;
4422 EmitFieldNonDefaultCondition(printer,
"this->",
field);
4425 generator.GenerateByteSize(printer);
4427 if (have_enclosing_if) {
4433 if (need_extra_newline) {
4438 if (have_outer_if) {
4443 if (cold_skipper.OnEndChunk(chunk_index, printer)) {
4445 cached_has_word_index = -1;
4452 format(
"switch ($1$_case()) {\n", oneof->
name());
4459 field_generators_.get(
field).GenerateByteSize(printer);
4466 "case $1$_NOT_SET: {\n"
4474 if (num_weak_fields_) {
4476 format(
"total_size += _weak_field_map_.ByteSizeLong();\n");
4484 "return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_);\n");
4486 format(
"if (PROTOBUF_PREDICT_FALSE($have_unknown_fields$)) {\n");
4487 format(
" total_size += $unknown_fields$.size();\n");
4499 "int cached_size = ::$proto_ns$::internal::ToCachedSize(total_size);\n"
4500 "SetCachedSize(cached_size);\n"
4501 "return total_size;\n");
4508 void MessageGenerator::GenerateIsInitialized(
io::Printer* printer) {
4511 format(
"bool $classname$::IsInitialized() const {\n");
4516 "if (!_extensions_.IsInitialized()) {\n"
4521 if (num_required_fields_ > 0) {
4523 "if (_Internal::MissingRequiredFields(_has_bits_))"
4524 " return false;\n");
4528 for (
auto field : optimized_order_) {
4529 field_generators_.get(
field).GenerateIsInitialized(printer);
4531 if (num_weak_fields_) {
4533 format(
"if (!_weak_field_map_.IsInitialized()) return false;\n");
4538 bool has_required_fields =
false;
4540 if (
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
4542 scc_analyzer_->HasRequiredFields(
field->message_type())) {
4543 has_required_fields =
true;
4548 if (!has_required_fields) {
4552 format(
"switch ($1$_case()) {\n", oneof->
name());
4558 field_generators_.get(
field).GenerateIsInitialized(printer);
4565 "case $1$_NOT_SET: {\n"
4584 #include <google/protobuf/port_undef.inc>