|
|
|
@ -2659,71 +2659,6 @@ void MessageGenerator::GenerateConstexprConstructor(io::Printer* p) { |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MessageGenerator::GenerateCopyConstructorBody(io::Printer* p) const { |
|
|
|
|
Formatter format(p); |
|
|
|
|
|
|
|
|
|
const RunMap runs = |
|
|
|
|
FindRuns(optimized_order_, [this](const FieldDescriptor* field) { |
|
|
|
|
return IsPOD(field) && !ShouldSplit(field, options_); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
std::string pod_template = |
|
|
|
|
"::memcpy(&$first$, &from.$first$,\n" |
|
|
|
|
" static_cast<::size_t>(reinterpret_cast<char*>(&$last$) -\n" |
|
|
|
|
" reinterpret_cast<char*>(&$first$)) + sizeof($last$));\n"; |
|
|
|
|
|
|
|
|
|
if (ShouldForceAllocationOnConstruction(descriptor_, options_)) { |
|
|
|
|
format( |
|
|
|
|
"#ifdef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION\n" |
|
|
|
|
"$mutable_unknown_fields$;\n" |
|
|
|
|
"#endif // PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION\n"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < optimized_order_.size(); ++i) { |
|
|
|
|
const FieldDescriptor* field = optimized_order_[i]; |
|
|
|
|
if (ShouldSplit(field, options_)) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
const auto it = runs.find(field); |
|
|
|
|
|
|
|
|
|
// We only apply the memset technique to runs of more than one field, as
|
|
|
|
|
// assignment is better than memset for generated code clarity.
|
|
|
|
|
if (it != runs.end() && it->second > 1) { |
|
|
|
|
// Use a memset, then skip run_length fields.
|
|
|
|
|
const size_t run_length = it->second; |
|
|
|
|
const std::string first_field_name = |
|
|
|
|
FieldMemberName(field, /*cold=*/false); |
|
|
|
|
const std::string last_field_name = |
|
|
|
|
FieldMemberName(optimized_order_[i + run_length - 1], /*cold=*/false); |
|
|
|
|
|
|
|
|
|
auto v = p->WithVars({ |
|
|
|
|
{"first", first_field_name}, |
|
|
|
|
{"last", last_field_name}, |
|
|
|
|
}); |
|
|
|
|
format(pod_template.c_str()); |
|
|
|
|
|
|
|
|
|
i += run_length - 1; |
|
|
|
|
// ++i at the top of the loop.
|
|
|
|
|
} else { |
|
|
|
|
field_generators_.get(field).GenerateCopyConstructorCode(p); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ShouldSplit(descriptor_, options_)) { |
|
|
|
|
format("if (PROTOBUF_PREDICT_FALSE(!from.IsSplitMessageDefault())) {\n"); |
|
|
|
|
format.Indent(); |
|
|
|
|
format("_this->PrepareSplitMessageForWrite();\n"); |
|
|
|
|
// TODO: cache the split pointers.
|
|
|
|
|
for (auto field : optimized_order_) { |
|
|
|
|
if (ShouldSplit(field, options_)) { |
|
|
|
|
field_generators_.get(field).GenerateCopyConstructorCode(p); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
format.Outdent(); |
|
|
|
|
format("}\n"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool MessageGenerator::ImplHasCopyCtor() const { |
|
|
|
|
if (ShouldSplit(descriptor_, options_)) return false; |
|
|
|
|
if (HasSimpleBaseClass(descriptor_, options_)) return false; |
|
|
|
@ -2753,126 +2688,6 @@ bool MessageGenerator::ImplHasCopyCtor() const { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MessageGenerator::GenerateCopyConstructorBodyImpl(io::Printer* p) const { |
|
|
|
|
if (!HasImplData(descriptor_, options_)) return; |
|
|
|
|
|
|
|
|
|
p->Emit( |
|
|
|
|
{{"initializer", |
|
|
|
|
[&] { |
|
|
|
|
if (descriptor_->extension_range_count() > 0) { |
|
|
|
|
p->Emit(R"cc( |
|
|
|
|
/*decltype($extensions$)*/ {}, |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
if (!inlined_string_indices_.empty()) { |
|
|
|
|
// Do not copy inlined_string_donated_, because this is not an
|
|
|
|
|
// arena constructor.
|
|
|
|
|
p->Emit(R"cc( |
|
|
|
|
decltype($inlined_string_donated_array$){}, |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool need_to_emit_cached_size = |
|
|
|
|
!HasSimpleBaseClass(descriptor_, options_); |
|
|
|
|
if (!has_bit_indices_.empty()) { |
|
|
|
|
p->Emit(R"cc( |
|
|
|
|
decltype($has_bits$){from.$has_bits$}, |
|
|
|
|
)cc"); |
|
|
|
|
if (need_to_emit_cached_size) { |
|
|
|
|
p->Emit(R"cc( |
|
|
|
|
/*decltype($cached_size$)*/ {}, |
|
|
|
|
)cc"); |
|
|
|
|
need_to_emit_cached_size = false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Initialize member variables with arena constructor.
|
|
|
|
|
for (const auto* field : optimized_order_) { |
|
|
|
|
if (ShouldSplit(field, options_)) continue; |
|
|
|
|
field_generators_.get(field).GenerateCopyAggregateInitializer(p); |
|
|
|
|
} |
|
|
|
|
if (ShouldSplit(descriptor_, options_)) { |
|
|
|
|
p->Emit({{"name", DefaultInstanceName(descriptor_, options_, |
|
|
|
|
/*split=*/true)}}, |
|
|
|
|
R"cc( |
|
|
|
|
decltype($split$){const_cast<Impl_::Split*>( |
|
|
|
|
reinterpret_cast<const Impl_::Split*>(&$name$))}, |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
for (auto oneof : OneOfRange(descriptor_)) { |
|
|
|
|
p->Emit({{"name", oneof->name()}}, |
|
|
|
|
R"cc( |
|
|
|
|
decltype(_impl_.$name$_){}, |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
if (need_to_emit_cached_size) { |
|
|
|
|
p->Emit(R"cc( |
|
|
|
|
/*decltype($cached_size$)*/ {}, |
|
|
|
|
)cc"); |
|
|
|
|
need_to_emit_cached_size = false; |
|
|
|
|
} |
|
|
|
|
if (descriptor_->real_oneof_decl_count() > 0) { |
|
|
|
|
p->Emit(R"cc( |
|
|
|
|
/*decltype($oneof_case$)*/ {}, |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
if (num_weak_fields_ > 0) { |
|
|
|
|
p->Emit(R"cc( |
|
|
|
|
decltype($weak_field_map$){from.$weak_field_map$}, |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
if (IsAnyMessage(descriptor_)) { |
|
|
|
|
p->Emit(R"cc( |
|
|
|
|
/*decltype($any_metadata$)*/ { |
|
|
|
|
&_impl_.type_url_, |
|
|
|
|
&_impl_.value_, |
|
|
|
|
}, |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
}}}, |
|
|
|
|
R"cc( |
|
|
|
|
new (&_impl_) Impl_{ |
|
|
|
|
$initializer$, |
|
|
|
|
}; |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MessageGenerator::GenerateCopyConstructorBodyOneofs(io::Printer* p) const { |
|
|
|
|
// Copy oneof fields. Oneof field requires oneof case check.
|
|
|
|
|
for (const auto* oneof : OneOfRange(descriptor_)) { |
|
|
|
|
p->Emit( |
|
|
|
|
{ |
|
|
|
|
{"name", oneof->name()}, |
|
|
|
|
{"NAME", absl::AsciiStrToUpper(oneof->name())}, |
|
|
|
|
{"cases", |
|
|
|
|
[&] { |
|
|
|
|
for (const auto* field : FieldRange(oneof)) { |
|
|
|
|
p->Emit( |
|
|
|
|
{{"Name", UnderscoresToCamelCase(field->name(), true)}, |
|
|
|
|
{"body", |
|
|
|
|
[&] { |
|
|
|
|
field_generators_.get(field).GenerateMergingCode(p); |
|
|
|
|
}}}, |
|
|
|
|
R"cc( |
|
|
|
|
case k$Name$: { |
|
|
|
|
$body$; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
}}, |
|
|
|
|
}, |
|
|
|
|
R"cc( |
|
|
|
|
clear_has_$name$(); |
|
|
|
|
switch (from.$name$_case()) { |
|
|
|
|
$cases$; |
|
|
|
|
case $NAME$_NOT_SET: { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
)cc"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MessageGenerator::GenerateCopyInitFields(io::Printer* p) const { |
|
|
|
|
auto begin = optimized_order_.begin(); |
|
|
|
|
auto end = optimized_order_.end(); |
|
|
|
|