xref: /aosp_15_r20/external/cronet/third_party/protobuf/src/google/protobuf/compiler/cpp/string_field.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: [email protected] (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/compiler/cpp/string_field.h>
36 
37 #include <google/protobuf/io/printer.h>
38 #include <google/protobuf/stubs/strutil.h>
39 #include <google/protobuf/compiler/cpp/helpers.h>
40 #include <google/protobuf/descriptor.pb.h>
41 
42 
43 namespace google {
44 namespace protobuf {
45 namespace compiler {
46 namespace cpp {
47 
48 namespace {
49 
SetStringVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables,const Options & options)50 void SetStringVariables(const FieldDescriptor* descriptor,
51                         std::map<std::string, std::string>* variables,
52                         const Options& options) {
53   SetCommonFieldVariables(descriptor, variables, options);
54 
55   const std::string kNS = "::" + (*variables)["proto_ns"] + "::internal::";
56   const std::string kArenaStringPtr = kNS + "ArenaStringPtr";
57 
58   (*variables)["default"] = DefaultValue(options, descriptor);
59   (*variables)["default_length"] =
60       StrCat(descriptor->default_value_string().length());
61   (*variables)["default_variable_name"] = MakeDefaultName(descriptor);
62   (*variables)["default_variable_field"] = MakeDefaultFieldName(descriptor);
63 
64   if (descriptor->default_value_string().empty()) {
65     (*variables)["default_string"] = kNS + "GetEmptyStringAlreadyInited()";
66     (*variables)["default_value"] = "&" + (*variables)["default_string"];
67     (*variables)["lazy_variable_args"] = "";
68   } else {
69     (*variables)["lazy_variable"] =
70         StrCat(QualifiedClassName(descriptor->containing_type(), options),
71                      "::", MakeDefaultFieldName(descriptor));
72 
73     (*variables)["default_string"] = (*variables)["lazy_variable"] + ".get()";
74     (*variables)["default_value"] = "nullptr";
75     (*variables)["lazy_variable_args"] = (*variables)["lazy_variable"] + ", ";
76   }
77 
78   (*variables)["pointer_type"] =
79       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
80   (*variables)["setter"] =
81       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "SetBytes" : "Set";
82   (*variables)["null_check"] = (*variables)["DCHK"] + "(value != nullptr);\n";
83   // NOTE: Escaped here to unblock proto1->proto2 migration.
84   // TODO(liujisi): Extend this to apply for other conflicting methods.
85   (*variables)["release_name"] =
86       SafeFunctionName(descriptor->containing_type(), descriptor, "release_");
87   (*variables)["full_name"] = descriptor->full_name();
88 
89   if (options.opensource_runtime) {
90     (*variables)["string_piece"] = "::std::string";
91   } else {
92     (*variables)["string_piece"] = "::StringPiece";
93   }
94 }
95 
96 }  // namespace
97 
98 // ===================================================================
99 
StringFieldGenerator(const FieldDescriptor * descriptor,const Options & options)100 StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
101                                            const Options& options)
102     : FieldGenerator(descriptor, options),
103       inlined_(IsStringInlined(descriptor, options)) {
104   SetStringVariables(descriptor, &variables_, options);
105 }
106 
~StringFieldGenerator()107 StringFieldGenerator::~StringFieldGenerator() {}
108 
GeneratePrivateMembers(io::Printer * printer) const109 void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
110   Formatter format(printer, variables_);
111   if (!inlined_) {
112     format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n");
113   } else {
114     // Skips the automatic destruction; rather calls it explicitly if
115     // allocating arena is null. This is required to support message-owned
116     // arena (go/path-to-arenas) where a root proto is destroyed but
117     // InlinedStringField may have arena-allocated memory.
118     format("::$proto_ns$::internal::InlinedStringField $name$_;\n");
119   }
120 }
121 
GenerateStaticMembers(io::Printer * printer) const122 void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const {
123   Formatter format(printer, variables_);
124   if (!descriptor_->default_value_string().empty()) {
125     format(
126         "static const ::$proto_ns$::internal::LazyString"
127         " $default_variable_name$;\n");
128   }
129   if (inlined_) {
130     // `_init_inline_xxx` is used for initializing default instances.
131     format("static std::true_type _init_inline_$name$_;\n");
132   }
133 }
134 
GenerateAccessorDeclarations(io::Printer * printer) const135 void StringFieldGenerator::GenerateAccessorDeclarations(
136     io::Printer* printer) const {
137   Formatter format(printer, variables_);
138   // If we're using StringFieldGenerator for a field with a ctype, it's
139   // because that ctype isn't actually implemented.  In particular, this is
140   // true of ctype=CORD and ctype=STRING_PIECE in the open source release.
141   // We aren't releasing Cord because it has too many Google-specific
142   // dependencies and we aren't releasing StringPiece because it's hardly
143   // useful outside of Google and because it would get confusing to have
144   // multiple instances of the StringPiece class in different libraries (PCRE
145   // already includes it for their C++ bindings, which came from Google).
146   //
147   // In any case, we make all the accessors private while still actually
148   // using a string to represent the field internally.  This way, we can
149   // guarantee that if we do ever implement the ctype, it won't break any
150   // existing users who might be -- for whatever reason -- already using .proto
151   // files that applied the ctype.  The field can still be accessed via the
152   // reflection interface since the reflection interface is independent of
153   // the string's underlying representation.
154 
155   bool unknown_ctype = descriptor_->options().ctype() !=
156                        EffectiveStringCType(descriptor_, options_);
157 
158   if (unknown_ctype) {
159     format.Outdent();
160     format(
161         " private:\n"
162         "  // Hidden due to unknown ctype option.\n");
163     format.Indent();
164   }
165 
166   format(
167       "$deprecated_attr$const std::string& ${1$$name$$}$() const;\n"
168       "template <typename ArgT0 = const std::string&, typename... ArgT>\n"
169       "$deprecated_attr$void ${1$set_$name$$}$(ArgT0&& arg0, ArgT... args);\n",
170       descriptor_);
171   format(
172       "$deprecated_attr$std::string* ${1$mutable_$name$$}$();\n"
173       "PROTOBUF_NODISCARD $deprecated_attr$std::string* "
174       "${1$$release_name$$}$();\n"
175       "$deprecated_attr$void ${1$set_allocated_$name$$}$(std::string* "
176       "$name$);\n",
177       descriptor_);
178   format(
179       "private:\n"
180       "const std::string& _internal_$name$() const;\n"
181       "inline PROTOBUF_ALWAYS_INLINE void "
182       "_internal_set_$name$(const std::string& value);\n"
183       "std::string* _internal_mutable_$name$();\n");
184   if (inlined_) {
185     format(
186         "inline PROTOBUF_ALWAYS_INLINE bool _internal_$name$_donated() "
187         "const;\n");
188   }
189   format("public:\n");
190 
191   if (unknown_ctype) {
192     format.Outdent();
193     format(" public:\n");
194     format.Indent();
195   }
196 }
197 
GenerateInlineAccessorDefinitions(io::Printer * printer) const198 void StringFieldGenerator::GenerateInlineAccessorDefinitions(
199     io::Printer* printer) const {
200   Formatter format(printer, variables_);
201   format(
202       "inline const std::string& $classname$::$name$() const {\n"
203       "$annotate_get$"
204       "  // @@protoc_insertion_point(field_get:$full_name$)\n");
205   if (!descriptor_->default_value_string().empty()) {
206     format(
207         "  if ($field$.IsDefault()) return "
208         "$default_variable_field$.get();\n");
209   }
210   format(
211       "  return _internal_$name$();\n"
212       "}\n");
213   if (!inlined_) {
214     format(
215         "template <typename ArgT0, typename... ArgT>\n"
216         "inline PROTOBUF_ALWAYS_INLINE\n"
217         "void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
218         "$maybe_prepare_split_message$"
219         " $set_hasbit$\n"
220         " $field$.$setter$(static_cast<ArgT0 &&>(arg0),"
221         " args..., GetArenaForAllocation());\n"
222         "$annotate_set$"
223         "  // @@protoc_insertion_point(field_set:$full_name$)\n"
224         "}\n");
225   } else {
226     format(
227         "template <typename ArgT0, typename... ArgT>\n"
228         "inline PROTOBUF_ALWAYS_INLINE\n"
229         "void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
230         "$maybe_prepare_split_message$"
231         " $set_hasbit$\n"
232         " $field$.$setter$(static_cast<ArgT0 &&>(arg0),"
233         " args..., GetArenaForAllocation(), _internal_$name$_donated(), "
234         "&$donating_states_word$, $mask_for_undonate$, this);\n"
235         "$annotate_set$"
236         "  // @@protoc_insertion_point(field_set:$full_name$)\n"
237         "}\n"
238         "inline bool $classname$::_internal_$name$_donated() const {\n"
239         "  bool value = $inlined_string_donated$\n"
240         "  return value;\n"
241         "}\n");
242   }
243   format(
244       "inline std::string* $classname$::mutable_$name$() {\n"
245       "$maybe_prepare_split_message$"
246       "  std::string* _s = _internal_mutable_$name$();\n"
247       "$annotate_mutable$"
248       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
249       "  return _s;\n"
250       "}\n"
251       "inline const std::string& $classname$::_internal_$name$() const {\n"
252       "  return $field$.Get();\n"
253       "}\n"
254       "inline void $classname$::_internal_set_$name$(const std::string& "
255       "value) {\n"
256       "  $set_hasbit$\n");
257   if (!inlined_) {
258     format(
259         "  $field$.Set(value, GetArenaForAllocation());\n"
260         "}\n");
261   } else {
262     format(
263         "  $field$.Set(value, GetArenaForAllocation(),\n"
264         "    _internal_$name$_donated(), &$donating_states_word$, "
265         "$mask_for_undonate$, this);\n"
266         "}\n");
267   }
268   format(
269       "inline std::string* $classname$::_internal_mutable_$name$() {\n"
270       "  $set_hasbit$\n");
271   if (!inlined_) {
272     format(
273         "  return $field$.Mutable($lazy_variable_args$"
274         "GetArenaForAllocation());\n"
275         "}\n");
276   } else {
277     format(
278         "  return $field$.Mutable($lazy_variable_args$"
279         "GetArenaForAllocation(), _internal_$name$_donated(), "
280         "&$donating_states_word$, $mask_for_undonate$, this);\n"
281         "}\n");
282   }
283   format(
284       "inline std::string* $classname$::$release_name$() {\n"
285       "$annotate_release$"
286       "$maybe_prepare_split_message$"
287       "  // @@protoc_insertion_point(field_release:$full_name$)\n");
288 
289   if (HasHasbit(descriptor_)) {
290     format(
291         "  if (!_internal_has_$name$()) {\n"
292         "    return nullptr;\n"
293         "  }\n"
294         "  $clear_hasbit$\n");
295     if (!inlined_) {
296       format("  auto* p = $field$.Release();\n");
297       if (descriptor_->default_value_string().empty()) {
298         format(
299             "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
300             "  if ($field$.IsDefault()) {\n"
301             "    $field$.Set(\"\", GetArenaForAllocation());\n"
302             "  }\n"
303             "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
304       }
305       format("  return p;\n");
306     } else {
307       format(
308           "  return $field$.Release(GetArenaForAllocation(), "
309           "_internal_$name$_donated());\n");
310     }
311   } else {
312     format("  return $field$.Release();\n");
313   }
314 
315   format(
316       "}\n"
317       "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
318       "$maybe_prepare_split_message$"
319       "  if ($name$ != nullptr) {\n"
320       "    $set_hasbit$\n"
321       "  } else {\n"
322       "    $clear_hasbit$\n"
323       "  }\n");
324   if (!inlined_) {
325     format("  $field$.SetAllocated($name$, GetArenaForAllocation());\n");
326     if (descriptor_->default_value_string().empty()) {
327       format(
328           "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
329           "  if ($field$.IsDefault()) {\n"
330           "    $field$.Set(\"\", GetArenaForAllocation());\n"
331           "  }\n"
332           "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
333     }
334   } else {
335     // Currently, string fields with default value can't be inlined.
336     format(
337         "    $field$.SetAllocated(nullptr, $name$, GetArenaForAllocation(), "
338         "_internal_$name$_donated(), &$donating_states_word$, "
339         "$mask_for_undonate$, this);\n");
340   }
341   format(
342       "$annotate_set$"
343       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
344       "}\n");
345 }
346 
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const347 void StringFieldGenerator::GenerateNonInlineAccessorDefinitions(
348     io::Printer* printer) const {
349   Formatter format(printer, variables_);
350   if (!descriptor_->default_value_string().empty()) {
351     format(
352         "const ::$proto_ns$::internal::LazyString "
353         "$classname$::$default_variable_field$"
354         "{{{$default$, $default_length$}}, {nullptr}};\n");
355   }
356 }
357 
GenerateClearingCode(io::Printer * printer) const358 void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
359   Formatter format(printer, variables_);
360   if (descriptor_->default_value_string().empty()) {
361     format("$field$.ClearToEmpty();\n");
362   } else {
363     GOOGLE_DCHECK(!inlined_);
364     format(
365         "$field$.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n");
366   }
367 }
368 
GenerateMessageClearingCode(io::Printer * printer) const369 void StringFieldGenerator::GenerateMessageClearingCode(
370     io::Printer* printer) const {
371   Formatter format(printer, variables_);
372   // Two-dimension specialization here: supporting arenas, field presence, or
373   // not, and default value is the empty string or not. Complexity here ensures
374   // the minimal number of branches / amount of extraneous code at runtime
375   // (given that the below methods are inlined one-liners)!
376 
377   // If we have a hasbit, then the Clear() method of the protocol buffer
378   // will have checked that this field is set.  If so, we can avoid redundant
379   // checks against the default variable.
380   const bool must_be_present = HasHasbit(descriptor_);
381 
382   if (inlined_ && must_be_present) {
383     // Calling mutable_$name$() gives us a string reference and sets the has bit
384     // for $name$ (in proto2).  We may get here when the string field is inlined
385     // but the string's contents have not been changed by the user, so we cannot
386     // make an assertion about the contents of the string and could never make
387     // an assertion about the string instance.
388     //
389     // For non-inlined strings, we distinguish from non-default by comparing
390     // instances, rather than contents.
391     format("$DCHK$(!$field$.IsDefault());\n");
392   }
393 
394   if (descriptor_->default_value_string().empty()) {
395     if (must_be_present) {
396       format("$field$.ClearNonDefaultToEmpty();\n");
397     } else {
398       format("$field$.ClearToEmpty();\n");
399     }
400   } else {
401     // Clear to a non-empty default is more involved, as we try to use the
402     // Arena if one is present and may need to reallocate the string.
403     format(
404         "$field$.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n ");
405   }
406 }
407 
GenerateMergingCode(io::Printer * printer) const408 void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
409   Formatter format(printer, variables_);
410   // TODO(gpike): improve this
411   format("_this->_internal_set_$name$(from._internal_$name$());\n");
412 }
413 
GenerateSwappingCode(io::Printer * printer) const414 void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
415   Formatter format(printer, variables_);
416   if (!inlined_) {
417     format(
418         "::$proto_ns$::internal::ArenaStringPtr::InternalSwap(\n"
419         "    &$field$, lhs_arena,\n"
420         "    &other->$field$, rhs_arena\n"
421         ");\n");
422   } else {
423     format(
424         "::$proto_ns$::internal::InlinedStringField::InternalSwap(\n"
425         "  &$field$, lhs_arena, "
426         "($inlined_string_donated_array$[0] & 0x1u) == 0, this,\n"
427         "  &other->$field$, rhs_arena, "
428         "(other->$inlined_string_donated_array$[0] & 0x1u) == 0, other);\n");
429   }
430 }
431 
GenerateConstructorCode(io::Printer * printer) const432 void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
433   Formatter format(printer, variables_);
434   if (inlined_ && descriptor_->default_value_string().empty()) {
435     return;
436   }
437   GOOGLE_DCHECK(!inlined_);
438   format("$field$.InitDefault();\n");
439   if (IsString(descriptor_, options_) &&
440       descriptor_->default_value_string().empty()) {
441     format(
442         "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
443         "  $field$.Set(\"\", GetArenaForAllocation());\n"
444         "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
445   }
446 }
447 
GenerateCreateSplitMessageCode(io::Printer * printer) const448 void StringFieldGenerator::GenerateCreateSplitMessageCode(
449     io::Printer* printer) const {
450   GOOGLE_CHECK(ShouldSplit(descriptor_, options_));
451   GOOGLE_CHECK(!inlined_);
452   Formatter format(printer, variables_);
453   format("ptr->$name$_.InitDefault();\n");
454   if (IsString(descriptor_, options_) &&
455       descriptor_->default_value_string().empty()) {
456     format(
457         "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
458         "  ptr->$name$_.Set(\"\", GetArenaForAllocation());\n"
459         "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
460   }
461 }
462 
GenerateCopyConstructorCode(io::Printer * printer) const463 void StringFieldGenerator::GenerateCopyConstructorCode(
464     io::Printer* printer) const {
465   Formatter format(printer, variables_);
466   GenerateConstructorCode(printer);
467   if (inlined_) {
468     format("new (&_this->$field$) ::_pbi::InlinedStringField();\n");
469   }
470 
471   if (HasHasbit(descriptor_)) {
472     format("if (from._internal_has_$name$()) {\n");
473   } else {
474     format("if (!from._internal_$name$().empty()) {\n");
475   }
476 
477   format.Indent();
478 
479   if (!inlined_) {
480     format(
481         "_this->$field$.Set(from._internal_$name$(), \n"
482         "  _this->GetArenaForAllocation());\n");
483   } else {
484     format(
485         "_this->$field$.Set(from._internal_$name$(),\n"
486         "  _this->GetArenaForAllocation(), _this->_internal_$name$_donated(), "
487         "&_this->$donating_states_word$, $mask_for_undonate$, _this);\n");
488   }
489 
490   format.Outdent();
491   format("}\n");
492 }
493 
GenerateDestructorCode(io::Printer * printer) const494 void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
495   Formatter format(printer, variables_);
496   if (!inlined_) {
497     if (ShouldSplit(descriptor_, options_)) {
498       format("$cached_split_ptr$->$name$_.Destroy();\n");
499       return;
500     }
501     format("$field$.Destroy();\n");
502     return;
503   }
504   // Explicitly calls ~InlinedStringField as its automatic call is disabled.
505   // Destructor has been implicitly skipped as a union, and even the
506   // message-owned arena is enabled, arena could still be missing for
507   // Arena::CreateMessage(nullptr).
508   GOOGLE_DCHECK(!ShouldSplit(descriptor_, options_));
509   format("$field$.~InlinedStringField();\n");
510 }
511 
NeedsArenaDestructor() const512 ArenaDtorNeeds StringFieldGenerator::NeedsArenaDestructor() const {
513   return inlined_ ? ArenaDtorNeeds::kOnDemand : ArenaDtorNeeds::kNone;
514 }
515 
GenerateArenaDestructorCode(io::Printer * printer) const516 void StringFieldGenerator::GenerateArenaDestructorCode(
517     io::Printer* printer) const {
518   if (!inlined_) return;
519   Formatter format(printer, variables_);
520   // _this is the object being destructed (we are inside a static method here).
521   format(
522       "if (!_this->_internal_$name$_donated()) {\n"
523       "  _this->$field$.~InlinedStringField();\n"
524       "}\n");
525 }
526 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const527 void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
528     io::Printer* printer) const {
529   Formatter format(printer, variables_);
530   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
531     GenerateUtf8CheckCodeForString(
532         descriptor_, options_, false,
533         "this->_internal_$name$().data(), "
534         "static_cast<int>(this->_internal_$name$().length()),\n",
535         format);
536   }
537   format(
538       "target = stream->Write$declared_type$MaybeAliased(\n"
539       "    $number$, this->_internal_$name$(), target);\n");
540 }
541 
GenerateByteSize(io::Printer * printer) const542 void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
543   Formatter format(printer, variables_);
544   format(
545       "total_size += $tag_size$ +\n"
546       "  ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
547       "    this->_internal_$name$());\n");
548 }
549 
GenerateConstexprAggregateInitializer(io::Printer * printer) const550 void StringFieldGenerator::GenerateConstexprAggregateInitializer(
551     io::Printer* printer) const {
552   Formatter format(printer, variables_);
553   if (inlined_) {
554     format("/*decltype($field$)*/{nullptr, false}");
555     return;
556   }
557   if (descriptor_->default_value_string().empty()) {
558     format(
559         "/*decltype($field$)*/{&::_pbi::fixed_address_empty_string, "
560         "::_pbi::ConstantInitialized{}}");
561   } else {
562     format("/*decltype($field$)*/{nullptr, ::_pbi::ConstantInitialized{}}");
563   }
564 }
565 
GenerateAggregateInitializer(io::Printer * printer) const566 void StringFieldGenerator::GenerateAggregateInitializer(
567     io::Printer* printer) const {
568   Formatter format(printer, variables_);
569   if (ShouldSplit(descriptor_, options_)) {
570     GOOGLE_CHECK(!inlined_);
571     format("decltype(Impl_::Split::$name$_){}");
572     return;
573   }
574   if (!inlined_) {
575     format("decltype($field$){}");
576   } else {
577     format("decltype($field$)(arena)");
578   }
579 }
580 
GenerateCopyAggregateInitializer(io::Printer * printer) const581 void StringFieldGenerator::GenerateCopyAggregateInitializer(
582     io::Printer* printer) const {
583   Formatter format(printer, variables_);
584   format("decltype($field$){}");
585 }
586 
587 // ===================================================================
588 
StringOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)589 StringOneofFieldGenerator::StringOneofFieldGenerator(
590     const FieldDescriptor* descriptor, const Options& options)
591     : StringFieldGenerator(descriptor, options) {
592   SetCommonOneofFieldVariables(descriptor, &variables_);
593   variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
594   variables_["oneof_index"] =
595       StrCat(descriptor->containing_oneof()->index());
596 }
597 
~StringOneofFieldGenerator()598 StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
599 
GenerateInlineAccessorDefinitions(io::Printer * printer) const600 void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
601     io::Printer* printer) const {
602   Formatter format(printer, variables_);
603   format(
604       "inline const std::string& $classname$::$name$() const {\n"
605       "$annotate_get$"
606       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
607       "  return _internal_$name$();\n"
608       "}\n"
609       "template <typename ArgT0, typename... ArgT>\n"
610       "inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
611       "  if (!_internal_has_$name$()) {\n"
612       "    clear_$oneof_name$();\n"
613       "    set_has_$name$();\n"
614       "    $field$.InitDefault();\n"
615       "  }\n"
616       "  $field$.$setter$("
617       " static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());\n"
618       "$annotate_set$"
619       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
620       "}\n"
621       "inline std::string* $classname$::mutable_$name$() {\n"
622       "  std::string* _s = _internal_mutable_$name$();\n"
623       "$annotate_mutable$"
624       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
625       "  return _s;\n"
626       "}\n"
627       "inline const std::string& $classname$::_internal_$name$() const {\n"
628       "  if (_internal_has_$name$()) {\n"
629       "    return $field$.Get();\n"
630       "  }\n"
631       "  return $default_string$;\n"
632       "}\n"
633       "inline void $classname$::_internal_set_$name$(const std::string& "
634       "value) {\n"
635       "  if (!_internal_has_$name$()) {\n"
636       "    clear_$oneof_name$();\n"
637       "    set_has_$name$();\n"
638       "    $field$.InitDefault();\n"
639       "  }\n"
640       "  $field$.Set(value, GetArenaForAllocation());\n"
641       "}\n");
642   format(
643       "inline std::string* $classname$::_internal_mutable_$name$() {\n"
644       "  if (!_internal_has_$name$()) {\n"
645       "    clear_$oneof_name$();\n"
646       "    set_has_$name$();\n"
647       "    $field$.InitDefault();\n"
648       "  }\n"
649       "  return $field$.Mutable($lazy_variable_args$"
650       "      GetArenaForAllocation());\n"
651       "}\n"
652       "inline std::string* $classname$::$release_name$() {\n"
653       "$annotate_release$"
654       "  // @@protoc_insertion_point(field_release:$full_name$)\n"
655       "  if (_internal_has_$name$()) {\n"
656       "    clear_has_$oneof_name$();\n"
657       "    return $field$.Release();\n"
658       "  } else {\n"
659       "    return nullptr;\n"
660       "  }\n"
661       "}\n"
662       "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
663       "  if (has_$oneof_name$()) {\n"
664       "    clear_$oneof_name$();\n"
665       "  }\n"
666       "  if ($name$ != nullptr) {\n"
667       "    set_has_$name$();\n"
668       "    $field$.InitAllocated($name$, GetArenaForAllocation());\n"
669       "  }\n"
670       "$annotate_set$"
671       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
672       "}\n");
673 }
674 
GenerateClearingCode(io::Printer * printer) const675 void StringOneofFieldGenerator::GenerateClearingCode(
676     io::Printer* printer) const {
677   Formatter format(printer, variables_);
678   format("$field$.Destroy();\n");
679 }
680 
GenerateMessageClearingCode(io::Printer * printer) const681 void StringOneofFieldGenerator::GenerateMessageClearingCode(
682     io::Printer* printer) const {
683   return GenerateClearingCode(printer);
684 }
685 
GenerateSwappingCode(io::Printer * printer) const686 void StringOneofFieldGenerator::GenerateSwappingCode(
687     io::Printer* printer) const {
688   // Don't print any swapping code. Swapping the union will swap this field.
689 }
690 
GenerateConstructorCode(io::Printer * printer) const691 void StringOneofFieldGenerator::GenerateConstructorCode(
692     io::Printer* printer) const {
693   // Nothing required here.
694 }
695 
696 // ===================================================================
697 
RepeatedStringFieldGenerator(const FieldDescriptor * descriptor,const Options & options)698 RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
699     const FieldDescriptor* descriptor, const Options& options)
700     : FieldGenerator(descriptor, options) {
701   SetStringVariables(descriptor, &variables_, options);
702 }
703 
~RepeatedStringFieldGenerator()704 RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
705 
GeneratePrivateMembers(io::Printer * printer) const706 void RepeatedStringFieldGenerator::GeneratePrivateMembers(
707     io::Printer* printer) const {
708   Formatter format(printer, variables_);
709   format("::$proto_ns$::RepeatedPtrField<std::string> $name$_;\n");
710 }
711 
GenerateAccessorDeclarations(io::Printer * printer) const712 void RepeatedStringFieldGenerator::GenerateAccessorDeclarations(
713     io::Printer* printer) const {
714   Formatter format(printer, variables_);
715   // See comment above about unknown ctypes.
716   bool unknown_ctype = descriptor_->options().ctype() !=
717                        EffectiveStringCType(descriptor_, options_);
718 
719   if (unknown_ctype) {
720     format.Outdent();
721     format(
722         " private:\n"
723         "  // Hidden due to unknown ctype option.\n");
724     format.Indent();
725   }
726 
727   format(
728       "$deprecated_attr$const std::string& ${1$$name$$}$(int index) const;\n"
729       "$deprecated_attr$std::string* ${1$mutable_$name$$}$(int index);\n"
730       "$deprecated_attr$void ${1$set_$name$$}$(int index, const "
731       "std::string& value);\n"
732       "$deprecated_attr$void ${1$set_$name$$}$(int index, std::string&& "
733       "value);\n"
734       "$deprecated_attr$void ${1$set_$name$$}$(int index, const "
735       "char* value);\n",
736       descriptor_);
737   if (!options_.opensource_runtime) {
738     format(
739         "$deprecated_attr$void ${1$set_$name$$}$(int index, "
740         "StringPiece value);\n",
741         descriptor_);
742   }
743   format(
744       "$deprecated_attr$void ${1$set_$name$$}$("
745       "int index, const $pointer_type$* value, size_t size);\n"
746       "$deprecated_attr$std::string* ${1$add_$name$$}$();\n"
747       "$deprecated_attr$void ${1$add_$name$$}$(const std::string& value);\n"
748       "$deprecated_attr$void ${1$add_$name$$}$(std::string&& value);\n"
749       "$deprecated_attr$void ${1$add_$name$$}$(const char* value);\n",
750       descriptor_);
751   if (!options_.opensource_runtime) {
752     format(
753         "$deprecated_attr$void ${1$add_$name$$}$(StringPiece value);\n",
754         descriptor_);
755   }
756   format(
757       "$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* "
758       "value, size_t size)"
759       ";\n"
760       "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField<std::string>& "
761       "${1$$name$$}$() "
762       "const;\n"
763       "$deprecated_attr$::$proto_ns$::RepeatedPtrField<std::string>* "
764       "${1$mutable_$name$$}$()"
765       ";\n"
766       "private:\n"
767       "const std::string& ${1$_internal_$name$$}$(int index) const;\n"
768       "std::string* _internal_add_$name$();\n"
769       "public:\n",
770       descriptor_);
771 
772   if (unknown_ctype) {
773     format.Outdent();
774     format(" public:\n");
775     format.Indent();
776   }
777 }
778 
GenerateInlineAccessorDefinitions(io::Printer * printer) const779 void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions(
780     io::Printer* printer) const {
781   Formatter format(printer, variables_);
782   format(
783       "inline std::string* $classname$::add_$name$() {\n"
784       "  std::string* _s = _internal_add_$name$();\n"
785       "$annotate_add_mutable$"
786       "  // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
787       "  return _s;\n"
788       "}\n");
789   if (options_.safe_boundary_check) {
790     format(
791         "inline const std::string& $classname$::_internal_$name$(int index) "
792         "const {\n"
793         "  return $field$.InternalCheckedGet(\n"
794         "      index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n"
795         "}\n");
796   } else {
797     format(
798         "inline const std::string& $classname$::_internal_$name$(int index) "
799         "const {\n"
800         "  return $field$.Get(index);\n"
801         "}\n");
802   }
803   format(
804       "inline const std::string& $classname$::$name$(int index) const {\n"
805       "$annotate_get$"
806       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
807       "  return _internal_$name$(index);\n"
808       "}\n"
809       "inline std::string* $classname$::mutable_$name$(int index) {\n"
810       "$annotate_mutable$"
811       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
812       "  return $field$.Mutable(index);\n"
813       "}\n"
814       "inline void $classname$::set_$name$(int index, const std::string& "
815       "value) "
816       "{\n"
817       "  $field$.Mutable(index)->assign(value);\n"
818       "$annotate_set$"
819       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
820       "}\n"
821       "inline void $classname$::set_$name$(int index, std::string&& value) {\n"
822       "  $field$.Mutable(index)->assign(std::move(value));\n"
823       "$annotate_set$"
824       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
825       "}\n"
826       "inline void $classname$::set_$name$(int index, const char* value) {\n"
827       "  $null_check$"
828       "  $field$.Mutable(index)->assign(value);\n"
829       "$annotate_set$"
830       "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
831       "}\n");
832   if (!options_.opensource_runtime) {
833     format(
834         "inline void "
835         "$classname$::set_$name$(int index, StringPiece value) {\n"
836         "  $field$.Mutable(index)->assign(value.data(), value.size());\n"
837         "$annotate_set$"
838         "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
839         "}\n");
840   }
841   format(
842       "inline void "
843       "$classname$::set_$name$"
844       "(int index, const $pointer_type$* value, size_t size) {\n"
845       "  $field$.Mutable(index)->assign(\n"
846       "    reinterpret_cast<const char*>(value), size);\n"
847       "$annotate_set$"
848       "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
849       "}\n"
850       "inline std::string* $classname$::_internal_add_$name$() {\n"
851       "  return $field$.Add();\n"
852       "}\n"
853       "inline void $classname$::add_$name$(const std::string& value) {\n"
854       "  $field$.Add()->assign(value);\n"
855       "$annotate_add$"
856       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
857       "}\n"
858       "inline void $classname$::add_$name$(std::string&& value) {\n"
859       "  $field$.Add(std::move(value));\n"
860       "$annotate_add$"
861       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
862       "}\n"
863       "inline void $classname$::add_$name$(const char* value) {\n"
864       "  $null_check$"
865       "  $field$.Add()->assign(value);\n"
866       "$annotate_add$"
867       "  // @@protoc_insertion_point(field_add_char:$full_name$)\n"
868       "}\n");
869   if (!options_.opensource_runtime) {
870     format(
871         "inline void $classname$::add_$name$(StringPiece value) {\n"
872         "  $field$.Add()->assign(value.data(), value.size());\n"
873         "$annotate_add$"
874         "  // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n"
875         "}\n");
876   }
877   format(
878       "inline void "
879       "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
880       "  $field$.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
881       "$annotate_add$"
882       "  // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
883       "}\n"
884       "inline const ::$proto_ns$::RepeatedPtrField<std::string>&\n"
885       "$classname$::$name$() const {\n"
886       "$annotate_list$"
887       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
888       "  return $field$;\n"
889       "}\n"
890       "inline ::$proto_ns$::RepeatedPtrField<std::string>*\n"
891       "$classname$::mutable_$name$() {\n"
892       "$annotate_mutable_list$"
893       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
894       "  return &$field$;\n"
895       "}\n");
896 }
897 
GenerateClearingCode(io::Printer * printer) const898 void RepeatedStringFieldGenerator::GenerateClearingCode(
899     io::Printer* printer) const {
900   Formatter format(printer, variables_);
901   format("$field$.Clear();\n");
902 }
903 
GenerateMergingCode(io::Printer * printer) const904 void RepeatedStringFieldGenerator::GenerateMergingCode(
905     io::Printer* printer) const {
906   Formatter format(printer, variables_);
907   format("_this->$field$.MergeFrom(from.$field$);\n");
908 }
909 
GenerateSwappingCode(io::Printer * printer) const910 void RepeatedStringFieldGenerator::GenerateSwappingCode(
911     io::Printer* printer) const {
912   Formatter format(printer, variables_);
913   format("$field$.InternalSwap(&other->$field$);\n");
914 }
915 
GenerateDestructorCode(io::Printer * printer) const916 void RepeatedStringFieldGenerator::GenerateDestructorCode(
917     io::Printer* printer) const {
918   Formatter format(printer, variables_);
919   format("$field$.~RepeatedPtrField();\n");
920 }
921 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const922 void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
923     io::Printer* printer) const {
924   Formatter format(printer, variables_);
925   format(
926       "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
927       "  const auto& s = this->_internal_$name$(i);\n");
928   // format("for (const std::string& s : this->$name$()) {\n");
929   format.Indent();
930   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
931     GenerateUtf8CheckCodeForString(descriptor_, options_, false,
932                                    "s.data(), static_cast<int>(s.length()),\n",
933                                    format);
934   }
935   format.Outdent();
936   format(
937       "  target = stream->Write$declared_type$($number$, s, target);\n"
938       "}\n");
939 }
940 
GenerateByteSize(io::Printer * printer) const941 void RepeatedStringFieldGenerator::GenerateByteSize(
942     io::Printer* printer) const {
943   Formatter format(printer, variables_);
944   format(
945       "total_size += $tag_size$ *\n"
946       "    ::$proto_ns$::internal::FromIntSize($field$.size());\n"
947       "for (int i = 0, n = $field$.size(); i < n; i++) {\n"
948       "  total_size += "
949       "::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
950       "    $field$.Get(i));\n"
951       "}\n");
952 }
953 
954 }  // namespace cpp
955 }  // namespace compiler
956 }  // namespace protobuf
957 }  // namespace google
958