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/helpers.h"
21 #include "google/protobuf/compiler/cpp/options.h"
22 #include "google/protobuf/descriptor.h"
23 #include "google/protobuf/descriptor.pb.h"
24 #include "google/protobuf/io/printer.h"
25
26 namespace google {
27 namespace protobuf {
28 namespace compiler {
29 namespace cpp {
30 namespace {
31 using ::google::protobuf::internal::cpp::HasHasbit;
32 using ::google::protobuf::io::AnnotationCollector;
33 using Sub = ::google::protobuf::io::Printer::Sub;
34
Vars(const FieldDescriptor * field,const Options & opts)35 std::vector<Sub> Vars(const FieldDescriptor* field, const Options& opts) {
36 auto trivial_default =
37 absl::StrCat("::", ProtobufNamespace(opts),
38 "::internal::GetEmptyStringAlreadyInited()");
39 auto lazy_var =
40 absl::StrCat(QualifiedClassName(field->containing_type(), opts),
41 "::", MakeDefaultFieldName(field));
42
43 bool empty_default = field->default_value_string().empty();
44 bool bytes = field->type() == FieldDescriptor::TYPE_BYTES;
45
46 return {
47 {"kDefault", DefaultValue(opts, field)},
48 {"kDefaultLen", field->default_value_string().size()},
49 {"default_variable_name", MakeDefaultName(field)},
50 {"default_variable_field", MakeDefaultFieldName(field)},
51
52 {"kDefaultStr",
53 !empty_default ? absl::StrCat(lazy_var, ".get()") : trivial_default},
54 {"kDefaultValue",
55 !empty_default ? "nullptr" : absl::StrCat("&", trivial_default)},
56
57 {"lazy_var", lazy_var},
58 Sub{"lazy_args", !empty_default ? absl::StrCat(lazy_var, ",") : ""}
59 .WithSuffix(","),
60
61 {"byte", bytes ? "void" : "char"},
62 {"Set", bytes ? "SetBytes" : "Set"},
63 };
64 }
65
66 class SingularStringView : public FieldGeneratorBase {
67 public:
SingularStringView(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)68 SingularStringView(const FieldDescriptor* field, const Options& opts,
69 MessageSCCAnalyzer* scc)
70 : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
71 ~SingularStringView() 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
201 const Options* opts_;
202 };
203
GenerateStaticMembers(io::Printer * p) const204 void SingularStringView::GenerateStaticMembers(io::Printer* p) const {
205 if (!EmptyDefault()) {
206 p->Emit(R"cc(
207 static const $pbi$::LazyString $default_variable_name$;
208 )cc");
209 }
210 if (is_inlined()) {
211 // `_init_inline_xxx` is used for initializing default instances.
212 p->Emit(R"cc(
213 static std::true_type _init_inline_$name$_;
214 )cc");
215 }
216 }
217
GenerateAccessorDeclarations(io::Printer * p) const218 void SingularStringView::GenerateAccessorDeclarations(io::Printer* p) const {
219 auto v1 = p->WithVars(AnnotatedAccessors(field_, {""}));
220 auto v2 = p->WithVars(
221 AnnotatedAccessors(field_, {"set_"}, AnnotationCollector::kSet));
222
223 p->Emit(
224 {{"donated",
225 [&] {
226 if (!is_inlined()) return;
227 p->Emit(R"cc(
228 inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() const;
229 )cc");
230 }}},
231 R"cc(
232 $DEPRECATED$ absl::string_view $name$() const;
233 template <typename Arg_ = std::string&&>
234 $DEPRECATED$ void $set_name$(Arg_&& arg);
235
236 private:
237 const std::string& _internal_$name$() const;
238 inline PROTOBUF_ALWAYS_INLINE void _internal_set_$name$(
239 absl::string_view value);
240 $donated$;
241
242 public:
243 )cc");
244 }
245
UpdateHasbitSet(io::Printer * p,bool is_oneof)246 void UpdateHasbitSet(io::Printer* p, bool is_oneof) {
247 if (!is_oneof) {
248 p->Emit(R"cc(
249 $set_hasbit$;
250 )cc");
251 return;
252 }
253
254 p->Emit(R"cc(
255 if ($not_has_field$) {
256 clear_$oneof_name$();
257
258 set_has_$name_internal$();
259 $field_$.InitDefault();
260 }
261 )cc");
262 }
263
ArgsForSetter(io::Printer * p,bool inlined)264 void ArgsForSetter(io::Printer* p, bool inlined) {
265 if (!inlined) {
266 p->Emit("GetArena()");
267 return;
268 }
269 p->Emit(
270 "GetArena(), _internal_$name_internal$_donated(), "
271 "&$donating_states_word$, $mask_for_undonate$, this");
272 }
273
GenerateInlineAccessorDefinitions(io::Printer * p) const274 void SingularStringView::GenerateInlineAccessorDefinitions(
275 io::Printer* p) const {
276 p->Emit(
277 {
278 {"if_IsDefault",
279 [&] {
280 if (EmptyDefault() || is_oneof()) return;
281 p->Emit(R"cc(
282 if ($field_$.IsDefault()) {
283 return $default_variable_field$.get();
284 }
285 )cc");
286 }},
287 {"update_hasbit", [&] { UpdateHasbitSet(p, is_oneof()); }},
288 {"set_args", [&] { ArgsForSetter(p, is_inlined()); }},
289 {"check_hasbit",
290 [&] {
291 if (!is_oneof()) return;
292 p->Emit(R"cc(
293 if ($not_has_field$) {
294 return $kDefaultStr$;
295 }
296 )cc");
297 }},
298 },
299 R"cc(
300 inline absl::string_view $Msg$::$name$() const
301 ABSL_ATTRIBUTE_LIFETIME_BOUND {
302 $WeakDescriptorSelfPin$;
303 $annotate_get$;
304 // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
305 $if_IsDefault$;
306 return _internal_$name_internal$();
307 }
308 template <typename Arg_>
309 inline PROTOBUF_ALWAYS_INLINE void $Msg$::set_$name$(Arg_&& arg) {
310 $WeakDescriptorSelfPin$;
311 $TsanDetectConcurrentMutation$;
312 $PrepareSplitMessageForWrite$;
313 $update_hasbit$;
314 $field_$.$Set$(static_cast<Arg_&&>(arg), $set_args$);
315 $annotate_set$;
316 // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
317 }
318 inline const std::string& $Msg$::_internal_$name_internal$() const {
319 $TsanDetectConcurrentRead$;
320 $check_hasbit$;
321 return $field_$.Get();
322 }
323 inline void $Msg$::_internal_set_$name_internal$(absl::string_view value) {
324 $TsanDetectConcurrentMutation$;
325 $update_hasbit$;
326 //~ Don't use $Set$ here; we always want the std::string variant
327 //~ regardless of whether this is a `bytes` field.
328 $field_$.Set(value, $set_args$);
329 }
330 )cc");
331
332 if (is_inlined()) {
333 p->Emit(R"cc(
334 inline bool $Msg$::_internal_$name_internal$_donated() const {
335 return $inlined_string_donated$;
336 }
337 )cc");
338 }
339 }
340
GenerateClearingCode(io::Printer * p) const341 void SingularStringView::GenerateClearingCode(io::Printer* p) const {
342 if (is_oneof()) {
343 p->Emit(R"cc(
344 $field_$.Destroy();
345 )cc");
346 return;
347 }
348
349 if (EmptyDefault()) {
350 p->Emit(R"cc(
351 $field_$.ClearToEmpty();
352 )cc");
353 return;
354 }
355
356 ABSL_DCHECK(!is_inlined());
357 p->Emit(R"cc(
358 $field_$.ClearToDefault($lazy_var$, GetArena());
359 )cc");
360 }
361
GenerateMessageClearingCode(io::Printer * p) const362 void SingularStringView::GenerateMessageClearingCode(io::Printer* p) const {
363 if (is_oneof()) {
364 p->Emit(R"cc(
365 $field_$.Destroy();
366 )cc");
367 return;
368 }
369
370 // Two-dimension specialization here: supporting arenas, field presence, or
371 // not, and default value is the empty string or not. Complexity here ensures
372 // the minimal number of branches / amount of extraneous code at runtime
373 // (given that the below methods are inlined one-liners)!
374
375 // If we have a hasbit, then the Clear() method of the protocol buffer
376 // will have checked that this field is set. If so, we can avoid redundant
377 // checks against the default variable.
378
379 if (is_inlined() && HasHasbit(field_)) {
380 p->Emit(R"cc(
381 $DCHK$(!$field_$.IsDefault());
382 )cc");
383 }
384
385 if (!EmptyDefault()) {
386 // Clear to a non-empty default is more involved, as we try to use the
387 // Arena if one is present and may need to reallocate the string.
388 p->Emit(R"cc(
389 $field_$.ClearToDefault($lazy_var$, GetArena());
390 )cc");
391 return;
392 }
393
394 p->Emit({{"Clear",
395 HasHasbit(field_) ? "ClearNonDefaultToEmpty" : "ClearToEmpty"}},
396 R"cc(
397 $field_$.$Clear$();
398 )cc");
399 }
400
GenerateSwappingCode(io::Printer * p) const401 void SingularStringView::GenerateSwappingCode(io::Printer* p) const {
402 if (is_oneof()) {
403 // Don't print any swapping code. Swapping the union will swap this field.
404 return;
405 }
406
407 if (!is_inlined()) {
408 p->Emit(R"cc(
409 ::_pbi::ArenaStringPtr::InternalSwap(&$field_$, &other->$field_$, arena);
410 )cc");
411 return;
412 }
413
414 p->Emit(R"cc(
415 {
416 bool lhs_dtor_registered = ($inlined_string_donated_array$[0] & 1) == 0;
417 bool rhs_dtor_registered =
418 (other->$inlined_string_donated_array$[0] & 1) == 0;
419 ::_pbi::InlinedStringField::InternalSwap(
420 &$field_$, lhs_dtor_registered, this, &other->$field_$,
421 rhs_dtor_registered, other, arena);
422 }
423 )cc");
424 }
425
GenerateConstructorCode(io::Printer * p) const426 void SingularStringView::GenerateConstructorCode(io::Printer* p) const {
427 if ((is_inlined() && EmptyDefault()) || is_oneof()) return;
428 ABSL_DCHECK(!is_inlined());
429
430 p->Emit(R"cc(
431 $field_$.InitDefault();
432 )cc");
433
434 if (EmptyDefault()) {
435 p->Emit(R"cc(
436 if ($pbi$::DebugHardenForceCopyDefaultString()) {
437 $field_$.Set("", GetArena());
438 }
439 )cc");
440 }
441 }
442
GenerateCopyConstructorCode(io::Printer * p) const443 void SingularStringView::GenerateCopyConstructorCode(io::Printer* p) const {
444 GenerateConstructorCode(p);
445
446 if (is_inlined()) {
447 p->Emit(R"cc(
448 new (&_this->$field_$)::_pbi::InlinedStringField;
449 )cc");
450 }
451
452 p->Emit(
453 {{"hazzer",
454 [&] {
455 if (HasHasbit(field_)) {
456 p->Emit(R"cc((from.$has_hasbit$) != 0)cc");
457 } else {
458 p->Emit(R"cc(!from._internal_$name$().empty())cc");
459 }
460 }},
461 {"set_args",
462 [&] {
463 if (!is_inlined()) {
464 p->Emit("_this->GetArena()");
465 } else {
466 p->Emit(
467 "_this->GetArena(), "
468 "_this->_internal_$name$_donated(), "
469 "&_this->$donating_states_word$, $mask_for_undonate$, _this");
470 }
471 }}},
472 R"cc(
473 if ($hazzer$) {
474 _this->$field_$.Set(from._internal_$name$(), $set_args$);
475 }
476 )cc");
477 }
478
GenerateDestructorCode(io::Printer * p) const479 void SingularStringView::GenerateDestructorCode(io::Printer* p) const {
480 if (is_inlined()) {
481 ABSL_DCHECK(!should_split());
482 return;
483 }
484
485 if (should_split()) {
486 p->Emit(R"cc(
487 $cached_split_ptr$->$name$_.Destroy();
488 )cc");
489 return;
490 }
491
492 p->Emit(R"cc(
493 this_.$field_$.Destroy();
494 )cc");
495 }
496
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const497 void SingularStringView::GenerateSerializeWithCachedSizesToArray(
498 io::Printer* p) const {
499 p->Emit({{"utf8_check",
500 [&] {
501 GenerateUtf8CheckCodeForString(p, field_, options_, false,
502 "_s.data(), "
503 "static_cast<int>(_s.length()),");
504 }}},
505 R"cc(
506 const std::string& _s = this_._internal_$name$();
507 $utf8_check$;
508 target = stream->Write$DeclaredType$MaybeAliased($number$, _s, target);
509 )cc");
510 }
511
GenerateConstexprAggregateInitializer(io::Printer * p) const512 void SingularStringView::GenerateConstexprAggregateInitializer(
513 io::Printer* p) const {
514 if (is_inlined()) {
515 p->Emit(R"cc(
516 /*decltype($field_$)*/ {nullptr, false},
517 )cc");
518 } else {
519 p->Emit(R"cc(
520 /*decltype($field_$)*/ {
521 &::_pbi::fixed_address_empty_string,
522 ::_pbi::ConstantInitialized{},
523 },
524 )cc");
525 }
526 }
527
GenerateAggregateInitializer(io::Printer * p) const528 void SingularStringView::GenerateAggregateInitializer(io::Printer* p) const {
529 if (should_split()) {
530 ABSL_CHECK(!is_inlined());
531 p->Emit(R"cc(
532 decltype(Impl_::Split::$name$_){},
533 )cc");
534 } else if (!is_inlined()) {
535 p->Emit(R"cc(
536 decltype($field_$){},
537 )cc");
538 } else {
539 p->Emit(R"cc(
540 decltype($field_$){arena},
541 )cc");
542 }
543 }
544
545 class RepeatedStringView : public FieldGeneratorBase {
546 public:
RepeatedStringView(const FieldDescriptor * field,const Options & opts,MessageSCCAnalyzer * scc)547 RepeatedStringView(const FieldDescriptor* field, const Options& opts,
548 MessageSCCAnalyzer* scc)
549 : FieldGeneratorBase(field, opts, scc), opts_(&opts) {}
550 ~RepeatedStringView() override = default;
551
MakeVars() const552 std::vector<Sub> MakeVars() const override { return Vars(field_, *opts_); }
553
GeneratePrivateMembers(io::Printer * p) const554 void GeneratePrivateMembers(io::Printer* p) const override {
555 if (should_split()) {
556 p->Emit(R"cc(
557 $pbi$::RawPtr<$pb$::RepeatedPtrField<std::string>> $name$_;
558 )cc");
559 } else {
560 p->Emit(R"cc(
561 $pb$::RepeatedPtrField<std::string> $name$_;
562 )cc");
563 }
564 }
565
GenerateClearingCode(io::Printer * p) const566 void GenerateClearingCode(io::Printer* p) const override {
567 if (should_split()) {
568 p->Emit("$field_$.ClearIfNotDefault();\n");
569 } else {
570 p->Emit("$field_$.Clear();\n");
571 }
572 }
573
GenerateMergingCode(io::Printer * p) const574 void GenerateMergingCode(io::Printer* p) const override {
575 // TODO: experiment with simplifying this to be
576 // `if (!from.empty()) { body(); }` for both split and non-split cases.
577 auto body = [&] {
578 p->Emit(R"cc(
579 _this->_internal_mutable_$name$()->MergeFrom(from._internal_$name$());
580 )cc");
581 };
582 if (!should_split()) {
583 body();
584 } else {
585 p->Emit({{"body", body}}, R"cc(
586 if (!from.$field_$.IsDefault()) {
587 $body$;
588 }
589 )cc");
590 }
591 }
592
GenerateSwappingCode(io::Printer * p) const593 void GenerateSwappingCode(io::Printer* p) const override {
594 ABSL_CHECK(!should_split());
595 p->Emit(R"cc(
596 $field_$.InternalSwap(&other->$field_$);
597 )cc");
598 }
599
GenerateDestructorCode(io::Printer * p) const600 void GenerateDestructorCode(io::Printer* p) const override {
601 if (should_split()) {
602 p->Emit(R"cc(
603 this_.$field_$.DeleteIfNotDefault();
604 )cc");
605 }
606 }
607
GenerateConstructorCode(io::Printer * p) const608 void GenerateConstructorCode(io::Printer* p) const override {}
609
GenerateCopyConstructorCode(io::Printer * p) const610 void GenerateCopyConstructorCode(io::Printer* p) const override {
611 if (should_split()) {
612 p->Emit(R"cc(
613 if (!from._internal_$name$().empty()) {
614 _internal_mutable_$name$()->MergeFrom(from._internal_$name$());
615 }
616 )cc");
617 }
618 }
619
GenerateByteSize(io::Printer * p) const620 void GenerateByteSize(io::Printer* p) const override {
621 p->Emit(R"cc(
622 total_size +=
623 $kTagBytes$ * $pbi$::FromIntSize(this_._internal_$name$().size());
624 for (int i = 0, n = this_._internal_$name$().size(); i < n; ++i) {
625 total_size += $pbi$::WireFormatLite::$DeclaredType$Size(
626 this_._internal_$name$().Get(i));
627 }
628 )cc");
629 }
630
631 void GenerateAccessorDeclarations(io::Printer* p) const override;
632 void GenerateInlineAccessorDefinitions(io::Printer* p) const override;
633 void GenerateSerializeWithCachedSizesToArray(io::Printer* p) const override;
634
635 private:
636 const Options* opts_;
637 };
638
GenerateAccessorDeclarations(io::Printer * p) const639 void RepeatedStringView::GenerateAccessorDeclarations(io::Printer* p) const {
640 bool unknown_ctype =
641 field_->options().ctype() != internal::cpp::EffectiveStringCType(field_);
642
643 if (unknown_ctype) {
644 p->Emit(R"cc(
645 private: // Hidden due to unknown ctype option.
646 )cc");
647 }
648
649 auto v1 = p->WithVars(AnnotatedAccessors(field_, {"", "_internal_"}));
650 auto v2 = p->WithVars(
651 AnnotatedAccessors(field_, {"set_", "add_"}, AnnotationCollector::kSet));
652 auto v3 = p->WithVars(
653 AnnotatedAccessors(field_, {"mutable_"}, AnnotationCollector::kAlias));
654
655 p->Emit(R"cc(
656 $DEPRECATED$ absl::string_view $name$(int index) const;
657 $DEPRECATED$ void $set_name$(int index, const std::string& value);
658 $DEPRECATED$ void $set_name$(int index, std::string&& value);
659 $DEPRECATED$ void $set_name$(int index, const char* value);
660 $DEPRECATED$ void $set_name$(int index, absl::string_view value);
661 $DEPRECATED$ void $add_name$(const std::string& value);
662 $DEPRECATED$ void $add_name$(std::string&& value);
663 $DEPRECATED$ void $add_name$(const char* value);
664 $DEPRECATED$ void $add_name$(absl::string_view value);
665 $DEPRECATED$ const $pb$::RepeatedPtrField<std::string>& $name$() const;
666 $DEPRECATED$ $pb$::RepeatedPtrField<std::string>* $mutable_name$();
667
668 private:
669 const $pb$::RepeatedPtrField<std::string>& _internal_$name$() const;
670 $pb$::RepeatedPtrField<std::string>* _internal_mutable_$name$();
671
672 public:
673 )cc");
674 }
675
GenerateInlineAccessorDefinitions(io::Printer * p) const676 void RepeatedStringView::GenerateInlineAccessorDefinitions(
677 io::Printer* p) const {
678 p->Emit({{"Get", opts_->safe_boundary_check ? "InternalCheckedGet" : "Get"},
679 {"GetExtraArg",
680 [&] {
681 p->Emit(opts_->safe_boundary_check
682 ? ", $pbi$::GetEmptyStringAlreadyInited()"
683 : "");
684 }}},
685 R"cc(
686 inline absl::string_view $Msg$::$name$(int index) const
687 ABSL_ATTRIBUTE_LIFETIME_BOUND {
688 $WeakDescriptorSelfPin$;
689 $annotate_get$;
690 // @@protoc_insertion_point(field_get:$pkg.Msg.field$)
691 return _internal_$name_internal$().$Get$(index$GetExtraArg$);
692 }
693 inline void $Msg$::set_$name$(int index, const std::string& value) {
694 $WeakDescriptorSelfPin$;
695 _internal_mutable_$name_internal$()->Mutable(index)->assign(value);
696 $annotate_set$;
697 // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
698 }
699 inline void $Msg$::set_$name$(int index, std::string&& value) {
700 $WeakDescriptorSelfPin$;
701 _internal_mutable_$name_internal$()->Mutable(index)->assign(std::move(value));
702 $annotate_set$;
703 // @@protoc_insertion_point(field_set:$pkg.Msg.field$)
704 }
705 inline void $Msg$::set_$name$(int index, const char* value) {
706 $WeakDescriptorSelfPin$;
707 $DCHK$(value != nullptr);
708 _internal_mutable_$name_internal$()->Mutable(index)->assign(value);
709 $annotate_set$;
710 // @@protoc_insertion_point(field_set_char:$pkg.Msg.field$)
711 }
712 inline void $Msg$::set_$name$(int index, absl::string_view value) {
713 $WeakDescriptorSelfPin$;
714 _internal_mutable_$name_internal$()->Mutable(index)->assign(
715 value.data(), value.size());
716 $annotate_set$;
717 // @@protoc_insertion_point(field_set_string_piece:$pkg.Msg.field$)
718 }
719 inline void $Msg$::add_$name$(const std::string& value) {
720 $WeakDescriptorSelfPin$;
721 $TsanDetectConcurrentMutation$;
722 _internal_mutable_$name_internal$()->Add()->assign(value);
723 $annotate_add$;
724 // @@protoc_insertion_point(field_add:$pkg.Msg.field$)
725 }
726 inline void $Msg$::add_$name$(std::string&& value) {
727 $WeakDescriptorSelfPin$;
728 $TsanDetectConcurrentMutation$;
729 _internal_mutable_$name_internal$()->Add(std::move(value));
730 $annotate_add$;
731 // @@protoc_insertion_point(field_add:$pkg.Msg.field$)
732 }
733 inline void $Msg$::add_$name$(const char* value) {
734 $WeakDescriptorSelfPin$;
735 $DCHK$(value != nullptr);
736 $TsanDetectConcurrentMutation$;
737 _internal_mutable_$name_internal$()->Add()->assign(value);
738 $annotate_add$;
739 // @@protoc_insertion_point(field_add_char:$pkg.Msg.field$)
740 }
741 inline void $Msg$::add_$name$(absl::string_view value) {
742 $WeakDescriptorSelfPin$;
743 $TsanDetectConcurrentMutation$;
744 _internal_mutable_$name_internal$()->Add()->assign(value.data(),
745 value.size());
746 $annotate_add$;
747 // @@protoc_insertion_point(field_add_string_piece:$pkg.Msg.field$)
748 }
749 inline const ::$proto_ns$::RepeatedPtrField<std::string>&
750 $Msg$::$name$() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
751 $WeakDescriptorSelfPin$;
752 $annotate_list$;
753 // @@protoc_insertion_point(field_list:$pkg.Msg.field$)
754 return _internal_$name_internal$();
755 }
756 inline ::$proto_ns$::RepeatedPtrField<std::string>*
757 $Msg$::mutable_$name$() ABSL_ATTRIBUTE_LIFETIME_BOUND {
758 $WeakDescriptorSelfPin$;
759 $annotate_mutable_list$;
760 // @@protoc_insertion_point(field_mutable_list:$pkg.Msg.field$)
761 $TsanDetectConcurrentMutation$;
762 return _internal_mutable_$name_internal$();
763 }
764 )cc");
765 if (should_split()) {
766 p->Emit(R"cc(
767 inline const $pb$::RepeatedPtrField<std::string>&
768 $Msg$::_internal_$name_internal$() const {
769 $TsanDetectConcurrentRead$;
770 return *$field_$;
771 }
772 inline $pb$::RepeatedPtrField<std::string>*
773 $Msg$::_internal_mutable_$name_internal$() {
774 $TsanDetectConcurrentRead$;
775 $PrepareSplitMessageForWrite$;
776 if ($field_$.IsDefault()) {
777 $field_$.Set($pb$::Arena::Create<$pb$::RepeatedPtrField<std::string>>(
778 GetArena()));
779 }
780 return $field_$.Get();
781 }
782 )cc");
783 } else {
784 p->Emit(R"cc(
785 inline const ::$proto_ns$::RepeatedPtrField<std::string>&
786 $Msg$::_internal_$name_internal$() const {
787 $TsanDetectConcurrentRead$;
788 return $field_$;
789 }
790 inline ::$proto_ns$::RepeatedPtrField<std::string>*
791 $Msg$::_internal_mutable_$name_internal$() {
792 $TsanDetectConcurrentRead$;
793 return &$field_$;
794 }
795 )cc");
796 }
797 }
798
GenerateSerializeWithCachedSizesToArray(io::Printer * p) const799 void RepeatedStringView::GenerateSerializeWithCachedSizesToArray(
800 io::Printer* p) const {
801 p->Emit({{"utf8_check",
802 [&] {
803 GenerateUtf8CheckCodeForString(
804 p, field_, options_, false,
805 "s.data(), static_cast<int>(s.length()),");
806 }}},
807 R"cc(
808 for (int i = 0, n = this_._internal_$name$_size(); i < n; ++i) {
809 const auto& s = this_._internal_$name$().Get(i);
810 $utf8_check$;
811 target = stream->Write$DeclaredType$($number$, s, target);
812 }
813 )cc");
814 }
815 } // namespace
816
MakeSingularStringViewGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)817 std::unique_ptr<FieldGeneratorBase> MakeSingularStringViewGenerator(
818 const FieldDescriptor* desc, const Options& options,
819 MessageSCCAnalyzer* scc) {
820 return absl::make_unique<SingularStringView>(desc, options, scc);
821 }
822
MakeRepeatedStringViewGenerator(const FieldDescriptor * desc,const Options & options,MessageSCCAnalyzer * scc)823 std::unique_ptr<FieldGeneratorBase> MakeRepeatedStringViewGenerator(
824 const FieldDescriptor* desc, const Options& options,
825 MessageSCCAnalyzer* scc) {
826 return absl::make_unique<RepeatedStringView>(desc, options, scc);
827 }
828
829 } // namespace cpp
830 } // namespace compiler
831 } // namespace protobuf
832 } // namespace google
833