1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 // Author: kenton@google.com (Kenton Varda)
9 // Based on original Protocol Buffers design by
10 // Sanjay Ghemawat, Jeff Dean, and others.
11
12 #include <memory>
13 #include <string>
14 #include <vector>
15
16 #include "absl/log/absl_check.h"
17 #include "absl/memory/memory.h"
18 #include "absl/strings/str_cat.h"
19 #include "google/protobuf/compiler/cpp/field.h"
20 #include "google/protobuf/compiler/cpp/field_generators/generators.h"
21 #include "google/protobuf/compiler/cpp/helpers.h"
22 #include "google/protobuf/compiler/cpp/options.h"
23 #include "google/protobuf/descriptor.h"
24 #include "google/protobuf/descriptor.pb.h"
25 #include "google/protobuf/io/printer.h"
26
27 namespace google {
28 namespace protobuf {
29 namespace compiler {
30 namespace cpp {
31 namespace {
32 using ::google::protobuf::internal::cpp::HasHasbit;
33 using ::google::protobuf::io::AnnotationCollector;
34 using Sub = ::google::protobuf::io::Printer::Sub;
35
Vars(const FieldDescriptor * field,const Options & opts)36 std::vector<Sub> Vars(const FieldDescriptor* field, const Options& opts) {
37 auto trivial_default =
38 absl::StrCat("::", ProtobufNamespace(opts),
39 "::internal::GetEmptyStringAlreadyInited()");
40 auto lazy_var =
41 absl::StrCat(QualifiedClassName(field->containing_type(), opts),
42 "::", MakeDefaultFieldName(field));
43
44 bool empty_default = field->default_value_string().empty();
45 bool bytes = field->type() == FieldDescriptor::TYPE_BYTES;
46
47 return {
48 {"kDefault", DefaultValue(opts, field)},
49 {"kDefaultLen", field->default_value_string().size()},
50 {"default_variable_name", MakeDefaultName(field)},
51 {"default_variable_field", MakeDefaultFieldName(field)},
52
53 {"kDefaultStr",
54 !empty_default ? absl::StrCat(lazy_var, ".get()") : trivial_default},
55 {"kDefaultValue",
56 !empty_default ? "nullptr" : absl::StrCat("&", trivial_default)},
57
58 {"lazy_var", lazy_var},
59 Sub{"lazy_args", !empty_default ? absl::StrCat(lazy_var, ",") : ""}
60 .WithSuffix(","),
61
62 {"Set", bytes ? "SetBytes" : "Set"},
63 };
64 }
65
66 class SingularString : public FieldGeneratorBase {
67 public:
SingularString(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)68 SingularString(const FieldDescriptor* field, const Options& opts,
69 MessageSCCAnalyzer* scc)
70 : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
71 ~SingularString() override = default;
72
MakeVars() const73 std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
74
IsInlined() const75 bool IsInlined() const override { return is_inlined(); }
76
NeedsArenaDestructor() const77 ArenaDtorNeeds NeedsArenaDestructor() const override {
78 return is_inlined() ? ArenaDtorNeeds::kOnDemand : ArenaDtorNeeds::kNone;
79 }
80
GeneratePrivateMembers(io::Printer * p) const81 void GeneratePrivateMembers(io::Printer* p) const override {
82 // Skips the automatic destruction if inlined; rather calls it explicitly if
83 // allocating arena is null.
84 p->Emit({{"Str", is_inlined() ? "InlinedStringField" : "ArenaStringPtr"}},
85 R"cc(
86 $pbi$::$Str$ $name$_;
87 )cc");
88 }
89
RequiresArena(GeneratorFunction function) const90 bool RequiresArena(GeneratorFunction function) const override {
91 switch (function) {
92 case GeneratorFunction::kMergeFrom:
93 return is_oneof();
94 }
95 return false;
96 }
97
GenerateMergingCode(io::Printer * p) const98 void GenerateMergingCode(io::Printer* p) const override {
99 if (is_oneof()) {
100 p->Emit(R"cc(
101 if (oneof_needs_init) {
102 _this->$field_$.InitDefault();
103 }
104 _this->$field_$.Set(from._internal_$name$(), arena);
105 )cc");
106 } else {
107 p->Emit(R"cc(
108 _this->_internal_set_$name$(from._internal_$name$());
109 )cc");
110 }
111 }
112
GenerateArenaDestructorCode(io::Printer * p) const113 void GenerateArenaDestructorCode(io::Printer* p) const override {
114 if (!is_inlined()) return;
115
116 p->Emit(R"cc(
117 if (!_this->_internal_$name$_donated()) {
118 _this->$field_$.~InlinedStringField();
119 }
120 )cc");
121 }
122
GenerateNonInlineAccessorDefinitions(io::Printer * p) const123 void GenerateNonInlineAccessorDefinitions(io::Printer* p) const override {
124 if (EmptyDefault()) return;
125 p->Emit(R"cc(
126 /*static*/ const ::_pbi::LazyString $Msg$::$default_variable_field${
127 {{$kDefault$, $kDefaultLen$}},
128 {nullptr},
129 };
130 )cc");
131 }
132
GenerateByteSize(io::Printer * p) const133 void GenerateByteSize(io::Printer* p) const override {
134 p->Emit(R"cc(
135 total_size += $kTagBytes$ + $pbi$::WireFormatLite::$DeclaredType$Size(
136 this_._internal_$name$());
137 )cc");
138 }
139
GenerateCopyAggregateInitializer(io::Printer * p) const140 void GenerateCopyAggregateInitializer(io::Printer* p) const override {
141 p->Emit(R"cc(
142 decltype($field_$){},
143 )cc");
144 }
145
GenerateMemberConstexprConstructor(io::Printer * p) const146 void GenerateMemberConstexprConstructor(io::Printer* p) const override {
147 if (is_inlined()) {
148 p->Emit("$name$_(nullptr, false)");
149 } else {
150 p->Emit(
151 "$name$_(\n"
152 " &$pbi$::fixed_address_empty_string,\n"
153 " ::_pbi::ConstantInitialized())");
154 }
155 }
156
GenerateMemberConstructor(io::Printer * p) const157 void GenerateMemberConstructor(io::Printer* p) const override {
158 if (is_inlined()) {
159 p->Emit("$name$_{}");
160 } else if (EmptyDefault()) {
161 p->Emit("$name$_(arena)");
162 } else {
163 p->Emit("$name$_(arena, $default_variable_field$)");
164 }
165 }
166
GenerateMemberCopyConstructor(io::Printer * p) const167 void GenerateMemberCopyConstructor(io::Printer* p) const override {
168 if (is_inlined() || EmptyDefault()) {
169 p->Emit("$name$_(arena, from.$name$_)");
170 } else {
171 p->Emit("$name$_(arena, from.$name$_, $default_variable_name$)");
172 }
173 }
174
GenerateOneofCopyConstruct(io::Printer * p) const175 void GenerateOneofCopyConstruct(io::Printer* p) const override {
176 if (is_inlined() || EmptyDefault()) {
177 p->Emit("new (&$field$) decltype($field$){arena, from.$field$};\n");
178 } else {
179 p->Emit(
180 "new (&$field$) decltype($field$){arena, from.$field$,"
181 " $default_variable_field$};\n");
182 }
183 }
184
185 void GenerateStaticMembers(io::Printer* p) const override;
186 void GenerateAccessorDeclarations(io::Printer* p) const override;
187 void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
188 void GenerateClearingCode(io::Printer* p) const override;
189 void GenerateMessageClearingCode(io::Printer* p) const override;
190 void GenerateSwappingCode(io::Printer* p) const override;
191 void GenerateConstructorCode(io::Printer* p) const override;
192 void GenerateCopyConstructorCode(io::Printer* p) const override;
193 void GenerateDestructorCode(io::Printer* p) const override;
194 void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override;
195 void GenerateConstexprAggregateInitializer(io::Printer* p) const override;
196 void GenerateAggregateInitializer(io::Printer* p) const override;
197
198 private:
EmptyDefault() const199 bool EmptyDefault() const { return field_->default_value_string().empty(); }
200 void ReleaseImpl(io::Printer* p) const;
201 void SetAllocatedImpl(io::Printer* p) const;
202
203 const Options* opts_;
204 };
205
GenerateStaticMembers(io::Printer * p) const206 void SingularString::GenerateStaticMembers(io::Printer* p) const {
207 if (!EmptyDefault()) {
208 p->Emit(R"cc(
209 static const $pbi$::LazyString $default_variable_name$;
210 )cc");
211 }
212 if (is_inlined()) {
213 // `_init_inline_xxx` is used for initializing default instances.
214 p->Emit(R"cc(
215 static std::true_type _init_inline_$name$_;
216 )cc");
217 }
218 }
219
GenerateAccessorDeclarations(io::Printer * p) const220 void SingularString::GenerateAccessorDeclarations(io::Printer* p) const {
221 // If we're using SingularString for a field with a ctype, it's
222 // because that ctype isn't actually implemented. In particular, this is
223 // true of ctype=CORD and ctype=STRING_PIECE in the open source release.
224 // We aren't releasing Cord because it has too many Google-specific
225 // dependencies and we aren't releasing StringPiece because it's hardly
226 // useful outside of Google and because it would get confusing to have
227 // multiple instances of the StringPiece class in different libraries (PCRE
228 // already includes it for their C++ bindings, which came from Google).
229 //
230 // In any case, we make all the accessors private while still actually
231 // using a string to represent the field internally. This way, we can
232 // guarantee that if we do ever implement the ctype, it won't break any
233 // existing users who might be -- for whatever reason -- already using .proto
234 // files that applied the ctype. The field can still be accessed via the
235 // reflection interface since the reflection interface is independent of
236 // the string's underlying representation.
237 bool unknown_ctype =
238 field_->options().ctype() != internal::cpp::EffectiveStringCType(field_);
239
240 if (unknown_ctype) {
241 p->Emit(R"cc(
242 private: // Hidden due to unknown ctype option.
243 )cc");
244 }
245
246 auto vars = AnnotatedAccessors(field_, {"", "set_allocated_"});
247 vars.push_back(Sub{
248 "release_name",
249 SafeFunctionName(field_->containing_type(), field_, "release_"),
250 }
251 .AnnotatedAs(field_));
252 auto v1 = p->WithVars(vars);
253 auto v2 = p->WithVars(
254 AnnotatedAccessors(field_, {"set_"}, AnnotationCollector::kSet));
255 auto v3 = p->WithVars(
256 AnnotatedAccessors(field_, {"mutable_"}, AnnotationCollector::kAlias));
257
258 p->Emit(
259 {{"donated",
260 [&] {
261 if (!is_inlined()) return;
262 p->Emit(R"cc(
263 inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() const;
264 )cc");
265 }}},
266 R"cc(
267 $DEPRECATED$ const std::string& $name$() const;
268 //~ Using `Arg_ = const std::string&` will make the type of `arg`
269 //~ default to `const std::string&`, due to reference collapse. This is
270 //~ necessary because there are a handful of users that rely on this
271 //~ default.
272 template <typename Arg_ = const std::string&, typename... Args_>
273 $DEPRECATED$ void $set_name$(Arg_&& arg, Args_... args);
274 $DEPRECATED$ std::string* $mutable_name$();
275 $DEPRECATED$ PROTOBUF_NODISCARD std::string* $release_name$();
276 $DEPRECATED$ void $set_allocated_name$(std::string* value);
277
278 private:
279 const std::string& _internal_$name$() const;
280 inline PROTOBUF_ALWAYS_INLINE void _internal_set_$name$(
281 const std::string& value);
282 std::string* _internal_mutable_$name$();
283 $donated$;
284
285 public:
286 )cc");
287 }
288
UpdateHasbitSet(io::Printer * p,bool is_oneof)289 void UpdateHasbitSet(io::Printer* p, bool is_oneof) {
290 if (!is_oneof) {
291 p->Emit(R"cc(
292 $set_hasbit$;
293 )cc");
294 return;
295 }
296
297 p->Emit(R"cc(
298 if ($not_has_field$) {
299 clear_$oneof_name$();
300
301 set_has_$name_internal$();
302 $field_$.InitDefault();
303 }
304 )cc");
305 }
306
ArgsForSetter(io::Printer * p,bool inlined)307 void ArgsForSetter(io::Printer* p, bool inlined) {
308 if (!inlined) {
309 p->Emit("GetArena()");
310 return;
311 }
312 p->Emit(
313 "GetArena(), _internal_$name_internal$_donated(), "
314 "&$donating_states_word$, $mask_for_undonate$, this");
315 }
316
ReleaseImpl(io::Printer * p) const317 void SingularString::ReleaseImpl(io::Printer* p) const {
318 if (is_oneof()) {
319 p->Emit(R"cc(
320 if ($not_has_field$) {
321 return nullptr;
322 }
323 clear_has_$oneof_name$();
324 return $field_$.Release();
325 )cc");
326 return;
327 }
328
329 if (!HasHasbit(field_)) {
330 p->Emit(R"cc(
331 return $field_$.Release();
332 )cc");
333 return;
334 }
335
336 if (is_inlined()) {
337 p->Emit(R"cc(
338 if (($has_hasbit$) == 0) {
339 return nullptr;
340 }
341 $clear_hasbit$;
342
343 return $field_$.Release(GetArena(), _internal_$name_internal$_donated());
344 )cc");
345 return;
346 }
347
348 p->Emit(R"cc(
349 if (($has_hasbit$) == 0) {
350 return nullptr;
351 }
352 $clear_hasbit$;
353 )cc");
354
355 if (!EmptyDefault()) {
356 p->Emit(R"cc(
357 return $field_$.Release();
358 )cc");
359 return;
360 }
361
362 p->Emit(R"cc(
363 auto* released = $field_$.Release();
364 if ($pbi$::DebugHardenForceCopyDefaultString()) {
365 $field_$.Set("", $set_args$);
366 }
367 return released;
368 )cc");
369 }
370
SetAllocatedImpl(io::Printer * p) const371 void SingularString::SetAllocatedImpl(io::Printer* p) const {
372 if (is_oneof()) {
373 p->Emit(R"cc(
374 if (has_$oneof_name$()) {
375 clear_$oneof_name$();
376 }
377 if (value != nullptr) {
378 set_has_$name_internal$();
379 $field_$.InitAllocated(value, GetArena());
380 }
381 )cc");
382 return;
383 }
384
385 if (HasHasbit(field_)) {
386 p->Emit(R"cc(
387 if (value != nullptr) {
388 $set_hasbit$
389 } else {
390 $clear_hasbit$
391 }
392 )cc");
393 }
394
395 if (is_inlined()) {
396 // Currently, string fields with default value can't be inlined.
397 p->Emit(R"cc(
398 $field_$.SetAllocated(nullptr, value, $set_args$);
399 )cc");
400 return;
401 }
402
403 p->Emit(R"cc(
404 $field_$.SetAllocated(value, $set_args$);
405 )cc");
406
407 if (EmptyDefault()) {
408 p->Emit(R"cc(
409 if ($pbi$::DebugHardenForceCopyDefaultString() && $field_$.IsDefault()) {
410 $field_$.Set("", $set_args$);
411 }
412 )cc");
413 }
414 }
415
GenerateInlineAccessorDefinitions(io::Printer * p) const416 void SingularString::GenerateInlineAccessorDefinitions(io::Printer* p) const {
417 p->Emit(
418 {
419 {"if_IsDefault",
420 [&] {
421 if (EmptyDefault() || is_oneof()) return;
422 p->Emit(R"cc(
423 if ($field_$.IsDefault()) {
424 return $default_variable_field$.get();
425 }
426 )cc");
427 }},
428 {"update_hasbit", [&] { UpdateHasbitSet(p, is_oneof()); }},
429 {"set_args", [&] { ArgsForSetter(p, is_inlined()); }},
430 {"check_hasbit",
431 [&] {
432 if (!is_oneof()) return;
433 p->Emit(R"cc(
434 if ($not_has_field$) {
435 return $kDefaultStr$;
436 }
437 )cc");
438 }},
439 {"release_name",
440 SafeFunctionName(field_->containing_type(), field_, "release_")},
441 {"release_impl", [&] { ReleaseImpl(p); }},
442 {"set_allocated_impl", [&] { SetAllocatedImpl(p); }},
443 },
444 R"cc(
445 inline const std::string& $Msg$::$name$() const
446 ABSL_ATTRIBUTE_LIFETIME_BOUND {
447 $WeakDescriptorSelfPin$;
448 $annotate_get$;
449 // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
450 $if_IsDefault$;
451 return _internal_$name_internal$();
452 }
453 template <typename Arg_, typename... Args_>
454 inline PROTOBUF_ALWAYS_INLINE void $Msg$::set_$name$(Arg_&& arg,
455 Args_... args) {
456 $WeakDescriptorSelfPin$;
457 $TsanDetectConcurrentMutation$;
458 $PrepareSplitMessageForWrite$;
459 $update_hasbit$;
460 $field_$.$Set$(static_cast<Arg_&&>(arg), args..., $set_args$);
461 $annotate_set$;
462 // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
463 }
464 inline std::string* $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
465 $WeakDescriptorSelfPin$;
466 $PrepareSplitMessageForWrite$;
467 std::string* _s = _internal_mutable_$name_internal$();
468 $annotate_mutable$;
469 // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$)
470 return _s;
471 }
472 inline const std::string& $Msg$::_internal_$name_internal$() const {
473 $TsanDetectConcurrentRead$;
474 $check_hasbit$;
475 return $field_$.Get();
476 }
477 inline void $Msg$::_internal_set_$name_internal$(const std::string& value) {
478 $TsanDetectConcurrentMutation$;
479 $update_hasbit$;
480 //~ Don't use $Set$ here; we always want the std::string variant
481 //~ regardless of whether this is a `bytes` field.
482 $field_$.Set(value, $set_args$);
483 }
484 inline std::string* $Msg$::_internal_mutable_$name_internal$() {
485 $TsanDetectConcurrentMutation$;
486 $update_hasbit$;
487 return $field_$.Mutable($lazy_args$, $set_args$);
488 }
489 inline std::string* $Msg$::$release_name$() {
490 $WeakDescriptorSelfPin$;
491 $TsanDetectConcurrentMutation$;
492 $annotate_release$;
493 $PrepareSplitMessageForWrite$;
494 // @@protoc_insertion_point(field_release:$pkg.Msg.field$)
495 $release_impl$;
496 }
497 inline void $Msg$::set_allocated_$name$(std::string* value) {
498 $WeakDescriptorSelfPin$;
499 $TsanDetectConcurrentMutation$;
500 $PrepareSplitMessageForWrite$;
501 $set_allocated_impl$;
502 $annotate_set$;
503 // @@protoc_insertion_point(field_set_allocated:$pkg.Msg.field$)
504 }
505 )cc");
506
507 if (is_inlined()) {
508 p->Emit(R"cc(
509 inline bool $Msg$::_internal_$name_internal$_donated() const {
510 return $inlined_string_donated$;
511 }
512 )cc");
513 }
514 }
515
GenerateClearingCode(io::Printer * p) const516 void SingularString::GenerateClearingCode(io::Printer* p) const {
517 if (is_oneof()) {
518 p->Emit(R"cc(
519 $field_$.Destroy();
520 )cc");
521 return;
522 }
523
524 if (EmptyDefault()) {
525 p->Emit(R"cc(
526 $field_$.ClearToEmpty();
527 )cc");
528 return;
529 }
530
531 ABSL_DCHECK(!is_inlined());
532 p->Emit(R"cc(
533 $field_$.ClearToDefault($lazy_var$, GetArena());
534 )cc");
535 }
536
GenerateMessageClearingCode(io::Printer * p) const537 void SingularString::GenerateMessageClearingCode(io::Printer* p) const {
538 if (is_oneof()) {
539 p->Emit(R"cc(
540 $field_$.Destroy();
541 )cc");
542 return;
543 }
544
545 // Two-dimension specialization here: supporting arenas, field presence, or
546 // not, and default value is the empty string or not. Complexity here ensures
547 // the minimal number of branches / amount of extraneous code at runtime
548 // (given that the below methods are inlined one-liners)!
549
550 // If we have a hasbit, then the Clear() method of the protocol buffer
551 // will have checked that this field is set. If so, we can avoid redundant
552 // checks against the default variable.
553
554 if (is_inlined() && HasHasbit(field_)) {
555 // Calling mutable_$name$() gives us a string reference and sets the has bit
556 // for $name$ (in proto2). We may get here when the string field is inlined
557 // but the string's contents have not been changed by the user, so we cannot
558 // make an assertion about the contents of the string and could never make
559 // an assertion about the string instance.
560 //
561 // For non-inlined strings, we distinguish from non-default by comparing
562 // instances, rather than contents.
563 p->Emit(R"cc(
564 $DCHK$(!$field_$.IsDefault());
565 )cc");
566 }
567
568 if (!EmptyDefault()) {
569 // Clear to a non-empty default is more involved, as we try to use the
570 // Arena if one is present and may need to reallocate the string.
571 p->Emit(R"cc(
572 $field_$.ClearToDefault($lazy_var$, GetArena());
573 )cc");
574 return;
575 }
576
577 p->Emit({{"Clear",
578 HasHasbit(field_) ? "ClearNonDefaultToEmpty" : "ClearToEmpty"}},
579 R"cc(
580 $field_$.$Clear$();
581 )cc");
582 }
583
GenerateSwappingCode(io::Printer * p) const584 void SingularString::GenerateSwappingCode(io::Printer* p) const {
585 if (is_oneof()) {
586 // Don't print any swapping code. Swapping the union will swap this field.
587 return;
588 }
589
590 if (!is_inlined()) {
591 p->Emit(R"cc(
592 ::_pbi::ArenaStringPtr::InternalSwap(&$field_$, &other->$field_$, arena);
593 )cc");
594 return;
595 }
596
597 p->Emit(R"cc(
598 {
599 bool lhs_dtor_registered = ($inlined_string_donated_array$[0] & 1) == 0;
600 bool rhs_dtor_registered =
601 (other->$inlined_string_donated_array$[0] & 1) == 0;
602 ::_pbi::InlinedStringField::InternalSwap(
603 &$field_$, lhs_dtor_registered, this, &other->$field_$,
604 rhs_dtor_registered, other, arena);
605 }
606 )cc");
607 }
608
GenerateConstructorCode(io::Printer * p) const609 void SingularString::GenerateConstructorCode(io::Printer* p) const {
610 if ((is_inlined() && EmptyDefault()) || is_oneof()) return;
611 ABSL_DCHECK(!is_inlined());
612
613 p->Emit(R"cc(
614 $field_$.InitDefault();
615 )cc");
616
617 if (IsString(field_) && EmptyDefault()) {
618 p->Emit(R"cc(
619 if ($pbi$::DebugHardenForceCopyDefaultString()) {
620 $field_$.Set("", GetArena());
621 }
622 )cc");
623 }
624 }
625
GenerateCopyConstructorCode(io::Printer * p) const626 void SingularString::GenerateCopyConstructorCode(io::Printer* p) const {
627 GenerateConstructorCode(p);
628
629 if (is_inlined()) {
630 p->Emit(R"cc(
631 new (&_this->$field_$)::_pbi::InlinedStringField;
632 )cc");
633 }
634
635 p->Emit(
636 {{"hazzer",
637 [&] {
638 if (HasHasbit(field_)) {
639 p->Emit(R"cc((from.$has_hasbit$) != 0)cc");
640 } else {
641 p->Emit(R"cc(!from._internal_$name$().empty())cc");
642 }
643 }},
644 {"set_args",
645 [&] {
646 if (!is_inlined()) {
647 p->Emit("_this->GetArena()");
648 } else {
649 p->Emit(
650 "_this->GetArena(), "
651 "_this->_internal_$name$_donated(), "
652 "&_this->$donating_states_word$, $mask_for_undonate$, _this");
653 }
654 }}},
655 R"cc(
656 if ($hazzer$) {
657 _this->$field_$.Set(from._internal_$name$(), $set_args$);
658 }
659 )cc");
660 }
661
GenerateDestructorCode(io::Printer * p) const662 void SingularString::GenerateDestructorCode(io::Printer* p) const {
663 if (is_inlined()) {
664 ABSL_DCHECK(!should_split());
665 return;
666 }
667
668 if (should_split()) {
669 p->Emit(R"cc(
670 $cached_split_ptr$->$name$_.Destroy();
671 )cc");
672 return;
673 }
674
675 p->Emit(R"cc(
676 this_.$field_$.Destroy();
677 )cc");
678 }
679
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const680 void SingularString::GenerateSerializeWithCachedSizesToArray(
681 io::Printer* p) const {
682 p->Emit({{"utf8_check",
683 [&] {
684 GenerateUtf8CheckCodeForString(p, field_, options_, false,
685 "_s.data(), "
686 "static_cast<int>(_s.length()),");
687 }}},
688 R"cc(
689 const std::string& _s = this_._internal_$name$();
690 $utf8_check$;
691 target = stream->Write$DeclaredType$MaybeAliased($number$, _s, target);
692 )cc");
693 }
694
GenerateConstexprAggregateInitializer(io::Printer * p) const695 void SingularString::GenerateConstexprAggregateInitializer(
696 io::Printer* p) const {
697 if (is_inlined()) {
698 p->Emit(R"cc(
699 /*decltype($field_$)*/ {nullptr, false},
700 )cc");
701 } else {
702 p->Emit(R"cc(
703 /*decltype($field_$)*/ {
704 &::_pbi::fixed_address_empty_string,
705 ::_pbi::ConstantInitialized{},
706 },
707 )cc");
708 }
709 }
710
GenerateAggregateInitializer(io::Printer * p) const711 void SingularString::GenerateAggregateInitializer(io::Printer* p) const {
712 if (should_split()) {
713 ABSL_CHECK(!is_inlined());
714 p->Emit(R"cc(
715 decltype(Impl_::Split::$name$_){},
716 )cc");
717 } else if (!is_inlined()) {
718 p->Emit(R"cc(
719 decltype($field_$){},
720 )cc");
721 } else {
722 p->Emit(R"cc(
723 decltype($field_$){arena},
724 )cc");
725 }
726 }
727
728 class RepeatedString : public FieldGeneratorBase {
729 public:
RepeatedString(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)730 RepeatedString(const FieldDescriptor* field, const Options& opts,
731 MessageSCCAnalyzer* scc)
732 : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
733 ~RepeatedString() override = default;
734
MakeVars() const735 std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
736
GeneratePrivateMembers(io::Printer * p) const737 void GeneratePrivateMembers(io::Printer* p) const override {
738 if (should_split()) {
739 p->Emit(R"cc(
740 $pbi$::RawPtr<$pb$::RepeatedPtrField<std::string>> $name$_;
741 )cc");
742 } else {
743 p->Emit(R"cc(
744 $pb$::RepeatedPtrField<std::string> $name$_;
745 )cc");
746 }
747 }
748
GenerateClearingCode(io::Printer * p) const749 void GenerateClearingCode(io::Printer* p) const override {
750 if (should_split()) {
751 p->Emit("$field_$.ClearIfNotDefault();\n");
752 } else {
753 p->Emit("$field_$.Clear();\n");
754 }
755 }
756
GenerateMergingCode(io::Printer * p) const757 void GenerateMergingCode(io::Printer* p) const override {
758 // TODO: experiment with simplifying this to be
759 // `if (!from.empty()) { body(); }` for both split and non-split cases.
760 auto body = [&] {
761 p->Emit(R"cc(
762 _this->_internal_mutable_$name$()->MergeFrom(from._internal_$name$());
763 )cc");
764 };
765 if (!should_split()) {
766 body();
767 } else {
768 p->Emit({{"body", body}}, R"cc(
769 if (!from.$field_$.IsDefault()) {
770 $body$;
771 }
772 )cc");
773 }
774 }
775
GenerateSwappingCode(io::Printer * p) const776 void GenerateSwappingCode(io::Printer* p) const override {
777 ABSL_CHECK(!should_split());
778 p->Emit(R"cc(
779 $field_$.InternalSwap(&other->$field_$);
780 )cc");
781 }
782
GenerateDestructorCode(io::Printer * p) const783 void GenerateDestructorCode(io::Printer* p) const override {
784 if (should_split()) {
785 p->Emit(R"cc(
786 this_.$field_$.DeleteIfNotDefault();
787 )cc");
788 }
789 }
790
GenerateConstructorCode(io::Printer * p) const791 void GenerateConstructorCode(io::Printer* p) const override {}
792
GenerateCopyConstructorCode(io::Printer * p) const793 void GenerateCopyConstructorCode(io::Printer* p) const override {
794 if (should_split()) {
795 p->Emit(R"cc(
796 if (!from._internal_$name$().empty()) {
797 _internal_mutable_$name$()->MergeFrom(from._internal_$name$());
798 }
799 )cc");
800 }
801 }
802
GenerateByteSize(io::Printer * p) const803 void GenerateByteSize(io::Printer* p) const override {
804 p->Emit(R"cc(
805 total_size +=
806 $kTagBytes$ * $pbi$::FromIntSize(this_._internal_$name$().size());
807 for (int i = 0, n = this_._internal_$name$().size(); i < n; ++i) {
808 total_size += $pbi$::WireFormatLite::$DeclaredType$Size(
809 this_._internal_$name$().Get(i));
810 }
811 )cc");
812 }
813
814 void GenerateAccessorDeclarations(io::Printer* p) const override;
815 void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
816 void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override;
817
818 private:
819 const Options* opts_;
820 };
821
GenerateAccessorDeclarations(io::Printer * p) const822 void RepeatedString::GenerateAccessorDeclarations(io::Printer* p) const {
823 bool unknown_ctype =
824 field_->options().ctype() != internal::cpp::EffectiveStringCType(field_);
825
826 if (unknown_ctype) {
827 p->Emit(R"cc(
828 private: // Hidden due to unknown ctype option.
829 )cc");
830 }
831
832 auto v1 = p->WithVars(AnnotatedAccessors(field_, {"", "_internal_"}));
833 auto v2 = p->WithVars(
834 AnnotatedAccessors(field_, {"set_", "add_"}, AnnotationCollector::kSet));
835 auto v3 = p->WithVars(
836 AnnotatedAccessors(field_, {"mutable_"}, AnnotationCollector::kAlias));
837
838 p->Emit(R"cc(
839 $DEPRECATED$ const std::string& $name$(int index) const;
840 $DEPRECATED$ std::string* $mutable_name$(int index);
841 template <typename Arg_ = const std::string&, typename... Args_>
842 $DEPRECATED$ void set_$name$(int index, Arg_&& value, Args_... args);
843 $DEPRECATED$ std::string* $add_name$();
844 template <typename Arg_ = const std::string&, typename... Args_>
845 $DEPRECATED$ void $add_name$(Arg_&& value, Args_... args);
846 $DEPRECATED$ const $pb$::RepeatedPtrField<std::string>& $name$() const;
847 $DEPRECATED$ $pb$::RepeatedPtrField<std::string>* $mutable_name$();
848
849 private:
850 const $pb$::RepeatedPtrField<std::string>& _internal_$name$() const;
851 $pb$::RepeatedPtrField<std::string>* _internal_mutable_$name$();
852
853 public:
854 )cc");
855 }
856
GenerateInlineAccessorDefinitions(io::Printer * p) const857 void RepeatedString::GenerateInlineAccessorDefinitions(io::Printer* p) const {
858 bool bytes = field_->type() == FieldDescriptor::TYPE_BYTES;
859 p->Emit(
860 {
861 {"Get", opts_->safe_boundary_check ? "InternalCheckedGet" : "Get"},
862 {"GetExtraArg",
863 [&] {
864 p->Emit(opts_->safe_boundary_check
865 ? ", $pbi$::GetEmptyStringAlreadyInited()"
866 : "");
867 }},
868 {"bytes_tag",
869 [&] {
870 if (bytes) {
871 p->Emit(", $pbi$::BytesTag{}");
872 }
873 }},
874 },
875 R"cc(
876 inline std::string* $Msg$::add_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
877 $WeakDescriptorSelfPin$;
878 $TsanDetectConcurrentMutation$;
879 std::string* _s = _internal_mutable_$name_internal$()->Add();
880 $annotate_add_mutable$;
881 // @@protoc_insertion_point(field_add_mutable:$pkg.Msg.field$)
882 return _s;
883 }
884 inline const std::string& $Msg$::$name$(int index) const
885 ABSL_ATTRIBUTE_LIFETIME_BOUND {
886 $WeakDescriptorSelfPin$;
887 $annotate_get$;
888 // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
889 return _internal_$name_internal$().$Get$(index$GetExtraArg$);
890 }
891 inline std::string* $Msg$::mutable_$name$(int index)
892 ABSL_ATTRIBUTE_LIFETIME_BOUND {
893 $WeakDescriptorSelfPin$;
894 $annotate_mutable$;
895 // @@protoc_insertion_point(field_mutable:$pkg.Msg.field$)
896 return _internal_mutable_$name_internal$()->Mutable(index);
897 }
898 template <typename Arg_, typename... Args_>
899 inline void $Msg$::set_$name$(int index, Arg_&& value, Args_... args) {
900 $WeakDescriptorSelfPin$;
901 $pbi$::AssignToString(
902 *_internal_mutable_$name_internal$()->Mutable(index),
903 std::forward<Arg_>(value), args... $bytes_tag$);
904 $annotate_set$;
905 // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
906 }
907 template <typename Arg_, typename... Args_>
908 inline void $Msg$::add_$name$(Arg_&& value, Args_... args) {
909 $WeakDescriptorSelfPin$;
910 $TsanDetectConcurrentMutation$;
911 $pbi$::AddToRepeatedPtrField(*_internal_mutable_$name_internal$(),
912 std::forward<Arg_>(value),
913 args... $bytes_tag$);
914 $annotate_add$;
915 // @@protoc_insertion_point(field_add:$pkg.Msg.field$)
916 }
917 inline const ::$proto_ns$::RepeatedPtrField<std::string>&
918 $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
919 $WeakDescriptorSelfPin$;
920 $annotate_list$;
921 // @@protoc_insertion_point(field_list:$pkg.Msg.field$)
922 return _internal_$name_internal$();
923 }
924 inline ::$proto_ns$::RepeatedPtrField<std::string>*
925 $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
926 $WeakDescriptorSelfPin$;
927 $annotate_mutable_list$;
928 // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$)
929 $TsanDetectConcurrentMutation$;
930 return _internal_mutable_$name_internal$();
931 }
932 )cc");
933 if (should_split()) {
934 p->Emit(R"cc(
935 inline const $pb$::RepeatedPtrField<std::string>&
936 $Msg$::_internal_$name_internal$() const {
937 $TsanDetectConcurrentRead$;
938 return *$field_$;
939 }
940 inline $pb$::RepeatedPtrField<std::string>*
941 $Msg$::_internal_mutable_$name_internal$() {
942 $TsanDetectConcurrentRead$;
943 $PrepareSplitMessageForWrite$;
944 if ($field_$.IsDefault()) {
945 $field_$.Set($pb$::Arena::Create<$pb$::RepeatedPtrField<std::string>>(
946 GetArena()));
947 }
948 return $field_$.Get();
949 }
950 )cc");
951 } else {
952 p->Emit(R"cc(
953 inline const ::$proto_ns$::RepeatedPtrField<std::string>&
954 $Msg$::_internal_$name_internal$() const {
955 $TsanDetectConcurrentRead$;
956 return $field_$;
957 }
958 inline ::$proto_ns$::RepeatedPtrField<std::string>*
959 $Msg$::_internal_mutable_$name_internal$() {
960 $TsanDetectConcurrentRead$;
961 return &$field_$;
962 }
963 )cc");
964 }
965 }
966
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const967 void RepeatedString::GenerateSerializeWithCachedSizesToArray(
968 io::Printer* p) const {
969 p->Emit({{"utf8_check",
970 [&] {
971 GenerateUtf8CheckCodeForString(
972 p, field_, options_, false,
973 "s.data(), static_cast<int>(s.length()),");
974 }}},
975 R"cc(
976 for (int i = 0, n = this_._internal_$name$_size(); i < n; ++i) {
977 const auto& s = this_._internal_$name$().Get(i);
978 $utf8_check$;
979 target = stream->Write$DeclaredType$($number$, s, target);
980 }
981 )cc");
982 }
983 } // namespace
984
MakeSinguarStringGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)985 std::unique_ptr<FieldGeneratorBase> MakeSinguarStringGenerator(
986 const FieldDescriptor* desc, const Options& options,
987 MessageSCCAnalyzer* scc) {
988 return absl::make_unique<SingularString>(desc, options, scc);
989 }
990
MakeRepeatedStringGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)991 std::unique_ptr<FieldGeneratorBase> MakeRepeatedStringGenerator(
992 const FieldDescriptor* desc, const Options& options,
993 MessageSCCAnalyzer* scc) {
994 return absl::make_unique<RepeatedString>(desc, options, scc);
995 }
996
997 } // namespace cpp
998 } // namespace compiler
999 } // namespace protobuf
1000 } // namespace google
1001