• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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: kenton@google.com (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 (!variables_.at("set_hasbit").empty() ||
320       !variables_.at("clear_hasbit").empty()) {
321     format(
322         "  if ($name$ != nullptr) {\n"
323         "    $set_hasbit$\n"
324         "  } else {\n"
325         "    $clear_hasbit$\n"
326         "  }\n");
327   }
328   if (!inlined_) {
329     format("  $field$.SetAllocated($name$, GetArenaForAllocation());\n");
330     if (descriptor_->default_value_string().empty()) {
331       format(
332           "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
333           "  if ($field$.IsDefault()) {\n"
334           "    $field$.Set(\"\", GetArenaForAllocation());\n"
335           "  }\n"
336           "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
337     }
338   } else {
339     // Currently, string fields with default value can't be inlined.
340     format(
341         "    $field$.SetAllocated(nullptr, $name$, GetArenaForAllocation(), "
342         "_internal_$name$_donated(), &$donating_states_word$, "
343         "$mask_for_undonate$, this);\n");
344   }
345   format(
346       "$annotate_set$"
347       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
348       "}\n");
349 }
350 
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const351 void StringFieldGenerator::GenerateNonInlineAccessorDefinitions(
352     io::Printer* printer) const {
353   Formatter format(printer, variables_);
354   if (!descriptor_->default_value_string().empty()) {
355     format(
356         "const ::$proto_ns$::internal::LazyString "
357         "$classname$::$default_variable_field$"
358         "{{{$default$, $default_length$}}, {nullptr}};\n");
359   }
360 }
361 
GenerateClearingCode(io::Printer * printer) const362 void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
363   Formatter format(printer, variables_);
364   if (descriptor_->default_value_string().empty()) {
365     format("$field$.ClearToEmpty();\n");
366   } else {
367     GOOGLE_DCHECK(!inlined_);
368     format(
369         "$field$.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n");
370   }
371 }
372 
GenerateMessageClearingCode(io::Printer * printer) const373 void StringFieldGenerator::GenerateMessageClearingCode(
374     io::Printer* printer) const {
375   Formatter format(printer, variables_);
376   // Two-dimension specialization here: supporting arenas, field presence, or
377   // not, and default value is the empty string or not. Complexity here ensures
378   // the minimal number of branches / amount of extraneous code at runtime
379   // (given that the below methods are inlined one-liners)!
380 
381   // If we have a hasbit, then the Clear() method of the protocol buffer
382   // will have checked that this field is set.  If so, we can avoid redundant
383   // checks against the default variable.
384   const bool must_be_present = HasHasbit(descriptor_);
385 
386   if (inlined_ && must_be_present) {
387     // Calling mutable_$name$() gives us a string reference and sets the has bit
388     // for $name$ (in proto2).  We may get here when the string field is inlined
389     // but the string's contents have not been changed by the user, so we cannot
390     // make an assertion about the contents of the string and could never make
391     // an assertion about the string instance.
392     //
393     // For non-inlined strings, we distinguish from non-default by comparing
394     // instances, rather than contents.
395     format("$DCHK$(!$field$.IsDefault());\n");
396   }
397 
398   if (descriptor_->default_value_string().empty()) {
399     if (must_be_present) {
400       format("$field$.ClearNonDefaultToEmpty();\n");
401     } else {
402       format("$field$.ClearToEmpty();\n");
403     }
404   } else {
405     // Clear to a non-empty default is more involved, as we try to use the
406     // Arena if one is present and may need to reallocate the string.
407     format(
408         "$field$.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n ");
409   }
410 }
411 
GenerateMergingCode(io::Printer * printer) const412 void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
413   Formatter format(printer, variables_);
414   // TODO(gpike): improve this
415   format("_this->_internal_set_$name$(from._internal_$name$());\n");
416 }
417 
GenerateSwappingCode(io::Printer * printer) const418 void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
419   Formatter format(printer, variables_);
420   if (!inlined_) {
421     format(
422         "::$proto_ns$::internal::ArenaStringPtr::InternalSwap(\n"
423         "    &$field$, lhs_arena,\n"
424         "    &other->$field$, rhs_arena\n"
425         ");\n");
426   } else {
427     format(
428         "::$proto_ns$::internal::InlinedStringField::InternalSwap(\n"
429         "  &$field$, lhs_arena, "
430         "($inlined_string_donated_array$[0] & 0x1u) == 0, this,\n"
431         "  &other->$field$, rhs_arena, "
432         "(other->$inlined_string_donated_array$[0] & 0x1u) == 0, other);\n");
433   }
434 }
435 
GenerateConstructorCode(io::Printer * printer) const436 void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
437   Formatter format(printer, variables_);
438   if (inlined_ && descriptor_->default_value_string().empty()) {
439     return;
440   }
441   GOOGLE_DCHECK(!inlined_);
442   format("$field$.InitDefault();\n");
443   if (IsString(descriptor_, options_) &&
444       descriptor_->default_value_string().empty()) {
445     format(
446         "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
447         "  $field$.Set(\"\", GetArenaForAllocation());\n"
448         "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
449   }
450 }
451 
GenerateCreateSplitMessageCode(io::Printer * printer) const452 void StringFieldGenerator::GenerateCreateSplitMessageCode(
453     io::Printer* printer) const {
454   GOOGLE_CHECK(ShouldSplit(descriptor_, options_));
455   GOOGLE_CHECK(!inlined_);
456   Formatter format(printer, variables_);
457   format("ptr->$name$_.InitDefault();\n");
458   if (IsString(descriptor_, options_) &&
459       descriptor_->default_value_string().empty()) {
460     format(
461         "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
462         "  ptr->$name$_.Set(\"\", GetArenaForAllocation());\n"
463         "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
464   }
465 }
466 
GenerateCopyConstructorCode(io::Printer * printer) const467 void StringFieldGenerator::GenerateCopyConstructorCode(
468     io::Printer* printer) const {
469   Formatter format(printer, variables_);
470   GenerateConstructorCode(printer);
471   if (inlined_) {
472     format("new (&_this->$field$) ::_pbi::InlinedStringField();\n");
473   }
474 
475   if (HasHasbit(descriptor_)) {
476     format("if (from._internal_has_$name$()) {\n");
477   } else {
478     format("if (!from._internal_$name$().empty()) {\n");
479   }
480 
481   format.Indent();
482 
483   if (!inlined_) {
484     format(
485         "_this->$field$.Set(from._internal_$name$(), \n"
486         "  _this->GetArenaForAllocation());\n");
487   } else {
488     format(
489         "_this->$field$.Set(from._internal_$name$(),\n"
490         "  _this->GetArenaForAllocation(), _this->_internal_$name$_donated(), "
491         "&_this->$donating_states_word$, $mask_for_undonate$, _this);\n");
492   }
493 
494   format.Outdent();
495   format("}\n");
496 }
497 
GenerateDestructorCode(io::Printer * printer) const498 void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
499   Formatter format(printer, variables_);
500   if (!inlined_) {
501     if (ShouldSplit(descriptor_, options_)) {
502       format("$cached_split_ptr$->$name$_.Destroy();\n");
503       return;
504     }
505     format("$field$.Destroy();\n");
506     return;
507   }
508   // Explicitly calls ~InlinedStringField as its automatic call is disabled.
509   // Destructor has been implicitly skipped as a union, and even the
510   // message-owned arena is enabled, arena could still be missing for
511   // Arena::CreateMessage(nullptr).
512   GOOGLE_DCHECK(!ShouldSplit(descriptor_, options_));
513   format("$field$.~InlinedStringField();\n");
514 }
515 
NeedsArenaDestructor() const516 ArenaDtorNeeds StringFieldGenerator::NeedsArenaDestructor() const {
517   return inlined_ ? ArenaDtorNeeds::kOnDemand : ArenaDtorNeeds::kNone;
518 }
519 
GenerateArenaDestructorCode(io::Printer * printer) const520 void StringFieldGenerator::GenerateArenaDestructorCode(
521     io::Printer* printer) const {
522   if (!inlined_) return;
523   Formatter format(printer, variables_);
524   // _this is the object being destructed (we are inside a static method here).
525   format(
526       "if (!_this->_internal_$name$_donated()) {\n"
527       "  _this->$field$.~InlinedStringField();\n"
528       "}\n");
529 }
530 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const531 void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
532     io::Printer* printer) const {
533   Formatter format(printer, variables_);
534   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
535     GenerateUtf8CheckCodeForString(
536         descriptor_, options_, false,
537         "this->_internal_$name$().data(), "
538         "static_cast<int>(this->_internal_$name$().length()),\n",
539         format);
540   }
541   format(
542       "target = stream->Write$declared_type$MaybeAliased(\n"
543       "    $number$, this->_internal_$name$(), target);\n");
544 }
545 
GenerateByteSize(io::Printer * printer) const546 void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
547   Formatter format(printer, variables_);
548   format(
549       "total_size += $tag_size$ +\n"
550       "  ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
551       "    this->_internal_$name$());\n");
552 }
553 
GenerateConstexprAggregateInitializer(io::Printer * printer) const554 void StringFieldGenerator::GenerateConstexprAggregateInitializer(
555     io::Printer* printer) const {
556   Formatter format(printer, variables_);
557   if (inlined_) {
558     format("/*decltype($field$)*/{nullptr, false}");
559     return;
560   }
561   if (descriptor_->default_value_string().empty()) {
562     format(
563         "/*decltype($field$)*/{&::_pbi::fixed_address_empty_string, "
564         "::_pbi::ConstantInitialized{}}");
565   } else {
566     format("/*decltype($field$)*/{nullptr, ::_pbi::ConstantInitialized{}}");
567   }
568 }
569 
GenerateAggregateInitializer(io::Printer * printer) const570 void StringFieldGenerator::GenerateAggregateInitializer(
571     io::Printer* printer) const {
572   Formatter format(printer, variables_);
573   if (ShouldSplit(descriptor_, options_)) {
574     GOOGLE_CHECK(!inlined_);
575     format("decltype(Impl_::Split::$name$_){}");
576     return;
577   }
578   if (!inlined_) {
579     format("decltype($field$){}");
580   } else {
581     format("decltype($field$)(arena)");
582   }
583 }
584 
GenerateCopyAggregateInitializer(io::Printer * printer) const585 void StringFieldGenerator::GenerateCopyAggregateInitializer(
586     io::Printer* printer) const {
587   Formatter format(printer, variables_);
588   format("decltype($field$){}");
589 }
590 
591 // ===================================================================
592 
StringOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)593 StringOneofFieldGenerator::StringOneofFieldGenerator(
594     const FieldDescriptor* descriptor, const Options& options)
595     : StringFieldGenerator(descriptor, options) {
596   SetCommonOneofFieldVariables(descriptor, &variables_);
597   variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
598   variables_["oneof_index"] =
599       StrCat(descriptor->containing_oneof()->index());
600 }
601 
~StringOneofFieldGenerator()602 StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
603 
GenerateInlineAccessorDefinitions(io::Printer * printer) const604 void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
605     io::Printer* printer) const {
606   Formatter format(printer, variables_);
607   format(
608       "inline const std::string& $classname$::$name$() const {\n"
609       "$annotate_get$"
610       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
611       "  return _internal_$name$();\n"
612       "}\n"
613       "template <typename ArgT0, typename... ArgT>\n"
614       "inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
615       "  if (!_internal_has_$name$()) {\n"
616       "    clear_$oneof_name$();\n"
617       "    set_has_$name$();\n"
618       "    $field$.InitDefault();\n"
619       "  }\n"
620       "  $field$.$setter$("
621       " static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());\n"
622       "$annotate_set$"
623       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
624       "}\n"
625       "inline std::string* $classname$::mutable_$name$() {\n"
626       "  std::string* _s = _internal_mutable_$name$();\n"
627       "$annotate_mutable$"
628       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
629       "  return _s;\n"
630       "}\n"
631       "inline const std::string& $classname$::_internal_$name$() const {\n"
632       "  if (_internal_has_$name$()) {\n"
633       "    return $field$.Get();\n"
634       "  }\n"
635       "  return $default_string$;\n"
636       "}\n"
637       "inline void $classname$::_internal_set_$name$(const std::string& "
638       "value) {\n"
639       "  if (!_internal_has_$name$()) {\n"
640       "    clear_$oneof_name$();\n"
641       "    set_has_$name$();\n"
642       "    $field$.InitDefault();\n"
643       "  }\n"
644       "  $field$.Set(value, GetArenaForAllocation());\n"
645       "}\n");
646   format(
647       "inline std::string* $classname$::_internal_mutable_$name$() {\n"
648       "  if (!_internal_has_$name$()) {\n"
649       "    clear_$oneof_name$();\n"
650       "    set_has_$name$();\n"
651       "    $field$.InitDefault();\n"
652       "  }\n"
653       "  return $field$.Mutable($lazy_variable_args$"
654       "      GetArenaForAllocation());\n"
655       "}\n"
656       "inline std::string* $classname$::$release_name$() {\n"
657       "$annotate_release$"
658       "  // @@protoc_insertion_point(field_release:$full_name$)\n"
659       "  if (_internal_has_$name$()) {\n"
660       "    clear_has_$oneof_name$();\n"
661       "    return $field$.Release();\n"
662       "  } else {\n"
663       "    return nullptr;\n"
664       "  }\n"
665       "}\n"
666       "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
667       "  if (has_$oneof_name$()) {\n"
668       "    clear_$oneof_name$();\n"
669       "  }\n"
670       "  if ($name$ != nullptr) {\n"
671       "    set_has_$name$();\n"
672       "    $field$.InitAllocated($name$, GetArenaForAllocation());\n"
673       "  }\n"
674       "$annotate_set$"
675       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
676       "}\n");
677 }
678 
GenerateClearingCode(io::Printer * printer) const679 void StringOneofFieldGenerator::GenerateClearingCode(
680     io::Printer* printer) const {
681   Formatter format(printer, variables_);
682   format("$field$.Destroy();\n");
683 }
684 
GenerateMessageClearingCode(io::Printer * printer) const685 void StringOneofFieldGenerator::GenerateMessageClearingCode(
686     io::Printer* printer) const {
687   return GenerateClearingCode(printer);
688 }
689 
GenerateSwappingCode(io::Printer * printer) const690 void StringOneofFieldGenerator::GenerateSwappingCode(
691     io::Printer* printer) const {
692   // Don't print any swapping code. Swapping the union will swap this field.
693 }
694 
GenerateConstructorCode(io::Printer * printer) const695 void StringOneofFieldGenerator::GenerateConstructorCode(
696     io::Printer* printer) const {
697   // Nothing required here.
698 }
699 
700 // ===================================================================
701 
RepeatedStringFieldGenerator(const FieldDescriptor * descriptor,const Options & options)702 RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
703     const FieldDescriptor* descriptor, const Options& options)
704     : FieldGenerator(descriptor, options) {
705   SetStringVariables(descriptor, &variables_, options);
706 }
707 
~RepeatedStringFieldGenerator()708 RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
709 
GeneratePrivateMembers(io::Printer * printer) const710 void RepeatedStringFieldGenerator::GeneratePrivateMembers(
711     io::Printer* printer) const {
712   Formatter format(printer, variables_);
713   format("::$proto_ns$::RepeatedPtrField<std::string> $name$_;\n");
714 }
715 
GenerateAccessorDeclarations(io::Printer * printer) const716 void RepeatedStringFieldGenerator::GenerateAccessorDeclarations(
717     io::Printer* printer) const {
718   Formatter format(printer, variables_);
719   // See comment above about unknown ctypes.
720   bool unknown_ctype = descriptor_->options().ctype() !=
721                        EffectiveStringCType(descriptor_, options_);
722 
723   if (unknown_ctype) {
724     format.Outdent();
725     format(
726         " private:\n"
727         "  // Hidden due to unknown ctype option.\n");
728     format.Indent();
729   }
730 
731   format(
732       "$deprecated_attr$const std::string& ${1$$name$$}$(int index) const;\n"
733       "$deprecated_attr$std::string* ${1$mutable_$name$$}$(int index);\n"
734       "$deprecated_attr$void ${1$set_$name$$}$(int index, const "
735       "std::string& value);\n"
736       "$deprecated_attr$void ${1$set_$name$$}$(int index, std::string&& "
737       "value);\n"
738       "$deprecated_attr$void ${1$set_$name$$}$(int index, const "
739       "char* value);\n",
740       descriptor_);
741   if (!options_.opensource_runtime) {
742     format(
743         "$deprecated_attr$void ${1$set_$name$$}$(int index, "
744         "StringPiece value);\n",
745         descriptor_);
746   }
747   format(
748       "$deprecated_attr$void ${1$set_$name$$}$("
749       "int index, const $pointer_type$* value, size_t size);\n"
750       "$deprecated_attr$std::string* ${1$add_$name$$}$();\n"
751       "$deprecated_attr$void ${1$add_$name$$}$(const std::string& value);\n"
752       "$deprecated_attr$void ${1$add_$name$$}$(std::string&& value);\n"
753       "$deprecated_attr$void ${1$add_$name$$}$(const char* value);\n",
754       descriptor_);
755   if (!options_.opensource_runtime) {
756     format(
757         "$deprecated_attr$void ${1$add_$name$$}$(StringPiece value);\n",
758         descriptor_);
759   }
760   format(
761       "$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* "
762       "value, size_t size)"
763       ";\n"
764       "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField<std::string>& "
765       "${1$$name$$}$() "
766       "const;\n"
767       "$deprecated_attr$::$proto_ns$::RepeatedPtrField<std::string>* "
768       "${1$mutable_$name$$}$()"
769       ";\n"
770       "private:\n"
771       "const std::string& ${1$_internal_$name$$}$(int index) const;\n"
772       "std::string* _internal_add_$name$();\n"
773       "public:\n",
774       descriptor_);
775 
776   if (unknown_ctype) {
777     format.Outdent();
778     format(" public:\n");
779     format.Indent();
780   }
781 }
782 
GenerateInlineAccessorDefinitions(io::Printer * printer) const783 void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions(
784     io::Printer* printer) const {
785   Formatter format(printer, variables_);
786   format(
787       "inline std::string* $classname$::add_$name$() {\n"
788       "  std::string* _s = _internal_add_$name$();\n"
789       "$annotate_add_mutable$"
790       "  // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
791       "  return _s;\n"
792       "}\n");
793   if (options_.safe_boundary_check) {
794     format(
795         "inline const std::string& $classname$::_internal_$name$(int index) "
796         "const {\n"
797         "  return $field$.InternalCheckedGet(\n"
798         "      index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n"
799         "}\n");
800   } else {
801     format(
802         "inline const std::string& $classname$::_internal_$name$(int index) "
803         "const {\n"
804         "  return $field$.Get(index);\n"
805         "}\n");
806   }
807   format(
808       "inline const std::string& $classname$::$name$(int index) const {\n"
809       "$annotate_get$"
810       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
811       "  return _internal_$name$(index);\n"
812       "}\n"
813       "inline std::string* $classname$::mutable_$name$(int index) {\n"
814       "$annotate_mutable$"
815       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
816       "  return $field$.Mutable(index);\n"
817       "}\n"
818       "inline void $classname$::set_$name$(int index, const std::string& "
819       "value) "
820       "{\n"
821       "  $field$.Mutable(index)->assign(value);\n"
822       "$annotate_set$"
823       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
824       "}\n"
825       "inline void $classname$::set_$name$(int index, std::string&& value) {\n"
826       "  $field$.Mutable(index)->assign(std::move(value));\n"
827       "$annotate_set$"
828       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
829       "}\n"
830       "inline void $classname$::set_$name$(int index, const char* value) {\n"
831       "  $null_check$"
832       "  $field$.Mutable(index)->assign(value);\n"
833       "$annotate_set$"
834       "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
835       "}\n");
836   if (!options_.opensource_runtime) {
837     format(
838         "inline void "
839         "$classname$::set_$name$(int index, StringPiece value) {\n"
840         "  $field$.Mutable(index)->assign(value.data(), value.size());\n"
841         "$annotate_set$"
842         "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
843         "}\n");
844   }
845   format(
846       "inline void "
847       "$classname$::set_$name$"
848       "(int index, const $pointer_type$* value, size_t size) {\n"
849       "  $field$.Mutable(index)->assign(\n"
850       "    reinterpret_cast<const char*>(value), size);\n"
851       "$annotate_set$"
852       "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
853       "}\n"
854       "inline std::string* $classname$::_internal_add_$name$() {\n"
855       "  return $field$.Add();\n"
856       "}\n"
857       "inline void $classname$::add_$name$(const std::string& value) {\n"
858       "  $field$.Add()->assign(value);\n"
859       "$annotate_add$"
860       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
861       "}\n"
862       "inline void $classname$::add_$name$(std::string&& value) {\n"
863       "  $field$.Add(std::move(value));\n"
864       "$annotate_add$"
865       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
866       "}\n"
867       "inline void $classname$::add_$name$(const char* value) {\n"
868       "  $null_check$"
869       "  $field$.Add()->assign(value);\n"
870       "$annotate_add$"
871       "  // @@protoc_insertion_point(field_add_char:$full_name$)\n"
872       "}\n");
873   if (!options_.opensource_runtime) {
874     format(
875         "inline void $classname$::add_$name$(StringPiece value) {\n"
876         "  $field$.Add()->assign(value.data(), value.size());\n"
877         "$annotate_add$"
878         "  // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n"
879         "}\n");
880   }
881   format(
882       "inline void "
883       "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
884       "  $field$.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
885       "$annotate_add$"
886       "  // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
887       "}\n"
888       "inline const ::$proto_ns$::RepeatedPtrField<std::string>&\n"
889       "$classname$::$name$() const {\n"
890       "$annotate_list$"
891       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
892       "  return $field$;\n"
893       "}\n"
894       "inline ::$proto_ns$::RepeatedPtrField<std::string>*\n"
895       "$classname$::mutable_$name$() {\n"
896       "$annotate_mutable_list$"
897       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
898       "  return &$field$;\n"
899       "}\n");
900 }
901 
GenerateClearingCode(io::Printer * printer) const902 void RepeatedStringFieldGenerator::GenerateClearingCode(
903     io::Printer* printer) const {
904   Formatter format(printer, variables_);
905   format("$field$.Clear();\n");
906 }
907 
GenerateMergingCode(io::Printer * printer) const908 void RepeatedStringFieldGenerator::GenerateMergingCode(
909     io::Printer* printer) const {
910   Formatter format(printer, variables_);
911   format("_this->$field$.MergeFrom(from.$field$);\n");
912 }
913 
GenerateSwappingCode(io::Printer * printer) const914 void RepeatedStringFieldGenerator::GenerateSwappingCode(
915     io::Printer* printer) const {
916   Formatter format(printer, variables_);
917   format("$field$.InternalSwap(&other->$field$);\n");
918 }
919 
GenerateDestructorCode(io::Printer * printer) const920 void RepeatedStringFieldGenerator::GenerateDestructorCode(
921     io::Printer* printer) const {
922   Formatter format(printer, variables_);
923   format("$field$.~RepeatedPtrField();\n");
924 }
925 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const926 void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
927     io::Printer* printer) const {
928   Formatter format(printer, variables_);
929   format(
930       "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
931       "  const auto& s = this->_internal_$name$(i);\n");
932   // format("for (const std::string& s : this->$name$()) {\n");
933   format.Indent();
934   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
935     GenerateUtf8CheckCodeForString(descriptor_, options_, false,
936                                    "s.data(), static_cast<int>(s.length()),\n",
937                                    format);
938   }
939   format.Outdent();
940   format(
941       "  target = stream->Write$declared_type$($number$, s, target);\n"
942       "}\n");
943 }
944 
GenerateByteSize(io::Printer * printer) const945 void RepeatedStringFieldGenerator::GenerateByteSize(
946     io::Printer* printer) const {
947   Formatter format(printer, variables_);
948   format(
949       "total_size += $tag_size$ *\n"
950       "    ::$proto_ns$::internal::FromIntSize($field$.size());\n"
951       "for (int i = 0, n = $field$.size(); i < n; i++) {\n"
952       "  total_size += "
953       "::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
954       "    $field$.Get(i));\n"
955       "}\n");
956 }
957 
958 }  // namespace cpp
959 }  // namespace compiler
960 }  // namespace protobuf
961 }  // namespace google
962