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/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/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     //
119     // `_init_inline_xxx` is used for initializing default instances.
120     format(
121         "union { ::$proto_ns$::internal::InlinedStringField $name$_; };\n"
122         "static std::true_type _init_inline_$name$_;\n");
123   }
124 }
125 
GenerateStaticMembers(io::Printer * printer) const126 void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const {
127   Formatter format(printer, variables_);
128   if (!descriptor_->default_value_string().empty()) {
129     format(
130         "static const ::$proto_ns$::internal::LazyString"
131         " $default_variable_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         " $set_hasbit$\n"
219         " $field$.$setter$(static_cast<ArgT0 &&>(arg0),"
220         " args..., GetArenaForAllocation());\n"
221         "$annotate_set$"
222         "  // @@protoc_insertion_point(field_set:$full_name$)\n"
223         "}\n");
224   } else {
225     format(
226         "template <typename ArgT0, typename... ArgT>\n"
227         "inline PROTOBUF_ALWAYS_INLINE\n"
228         "void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
229         " $set_hasbit$\n"
230         " $field$.$setter$(static_cast<ArgT0 &&>(arg0),"
231         " args..., GetArenaForAllocation(), _internal_$name$_donated(), "
232         "&$donating_states_word$, $mask_for_undonate$, this);\n"
233         "$annotate_set$"
234         "  // @@protoc_insertion_point(field_set:$full_name$)\n"
235         "}\n"
236         "inline bool $classname$::_internal_$name$_donated() const {\n"
237         "  bool value = $inlined_string_donated$\n"
238         "  return value;\n"
239         "}\n");
240   }
241   format(
242       "inline std::string* $classname$::mutable_$name$() {\n"
243       "  std::string* _s = _internal_mutable_$name$();\n"
244       "$annotate_mutable$"
245       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
246       "  return _s;\n"
247       "}\n"
248       "inline const std::string& $classname$::_internal_$name$() const {\n"
249       "  return $field$.Get();\n"
250       "}\n"
251       "inline void $classname$::_internal_set_$name$(const std::string& "
252       "value) {\n"
253       "  $set_hasbit$\n");
254   if (!inlined_) {
255     format(
256         "  $field$.Set(value, GetArenaForAllocation());\n"
257         "}\n");
258   } else {
259     format(
260         "  $field$.Set(value, GetArenaForAllocation(),\n"
261         "    _internal_$name$_donated(), &$donating_states_word$, "
262         "$mask_for_undonate$, this);\n"
263         "}\n");
264   }
265   format(
266       "inline std::string* $classname$::_internal_mutable_$name$() {\n"
267       "  $set_hasbit$\n");
268   if (!inlined_) {
269     format(
270         "  return $field$.Mutable($lazy_variable_args$"
271         "GetArenaForAllocation());\n"
272         "}\n");
273   } else {
274     format(
275         "  return $field$.Mutable($lazy_variable_args$"
276         "GetArenaForAllocation(), _internal_$name$_donated(), "
277         "&$donating_states_word$, $mask_for_undonate$, this);\n"
278         "}\n");
279   }
280   format(
281       "inline std::string* $classname$::$release_name$() {\n"
282       "$annotate_release$"
283       "  // @@protoc_insertion_point(field_release:$full_name$)\n");
284 
285   if (HasHasbit(descriptor_)) {
286     format(
287         "  if (!_internal_has_$name$()) {\n"
288         "    return nullptr;\n"
289         "  }\n"
290         "  $clear_hasbit$\n");
291     if (!inlined_) {
292       format("  auto* p = $field$.Release();\n");
293       if (descriptor_->default_value_string().empty()) {
294         format(
295             "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
296             "  if ($field$.IsDefault()) {\n"
297             "    $field$.Set(\"\", GetArenaForAllocation());\n"
298             "  }\n"
299             "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
300       }
301       format("  return p;\n");
302     } else {
303       format(
304           "  return $field$.Release(GetArenaForAllocation(), "
305           "_internal_$name$_donated());\n");
306     }
307   } else {
308     format("  return $field$.Release();\n");
309   }
310 
311   format(
312       "}\n"
313       "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
314       "  if ($name$ != nullptr) {\n"
315       "    $set_hasbit$\n"
316       "  } else {\n"
317       "    $clear_hasbit$\n"
318       "  }\n");
319   if (!inlined_) {
320     format("  $field$.SetAllocated($name$, GetArenaForAllocation());\n");
321     if (descriptor_->default_value_string().empty()) {
322       format(
323           "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
324           "  if ($field$.IsDefault()) {\n"
325           "    $field$.Set(\"\", GetArenaForAllocation());\n"
326           "  }\n"
327           "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
328     }
329   } else {
330     // Currently, string fields with default value can't be inlined.
331     format(
332         "    $field$.SetAllocated(nullptr, $name$, GetArenaForAllocation(), "
333         "_internal_$name$_donated(), &$donating_states_word$, "
334         "$mask_for_undonate$, this);\n");
335   }
336   format(
337       "$annotate_set$"
338       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
339       "}\n");
340 }
341 
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const342 void StringFieldGenerator::GenerateNonInlineAccessorDefinitions(
343     io::Printer* printer) const {
344   Formatter format(printer, variables_);
345   if (!descriptor_->default_value_string().empty()) {
346     format(
347         "const ::$proto_ns$::internal::LazyString "
348         "$classname$::$default_variable_field$"
349         "{{{$default$, $default_length$}}, {nullptr}};\n");
350   }
351 }
352 
GenerateClearingCode(io::Printer * printer) const353 void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
354   Formatter format(printer, variables_);
355   if (descriptor_->default_value_string().empty()) {
356     format("$field$.ClearToEmpty();\n");
357   } else {
358     GOOGLE_DCHECK(!inlined_);
359     format(
360         "$field$.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n");
361   }
362 }
363 
GenerateMessageClearingCode(io::Printer * printer) const364 void StringFieldGenerator::GenerateMessageClearingCode(
365     io::Printer* printer) const {
366   Formatter format(printer, variables_);
367   // Two-dimension specialization here: supporting arenas, field presence, or
368   // not, and default value is the empty string or not. Complexity here ensures
369   // the minimal number of branches / amount of extraneous code at runtime
370   // (given that the below methods are inlined one-liners)!
371 
372   // If we have a hasbit, then the Clear() method of the protocol buffer
373   // will have checked that this field is set.  If so, we can avoid redundant
374   // checks against the default variable.
375   const bool must_be_present = HasHasbit(descriptor_);
376 
377   if (inlined_ && must_be_present) {
378     // Calling mutable_$name$() gives us a string reference and sets the has bit
379     // for $name$ (in proto2).  We may get here when the string field is inlined
380     // but the string's contents have not been changed by the user, so we cannot
381     // make an assertion about the contents of the string and could never make
382     // an assertion about the string instance.
383     //
384     // For non-inlined strings, we distinguish from non-default by comparing
385     // instances, rather than contents.
386     format("$DCHK$(!$field$.IsDefault());\n");
387   }
388 
389   if (descriptor_->default_value_string().empty()) {
390     if (must_be_present) {
391       format("$field$.ClearNonDefaultToEmpty();\n");
392     } else {
393       format("$field$.ClearToEmpty();\n");
394     }
395   } else {
396     // Clear to a non-empty default is more involved, as we try to use the
397     // Arena if one is present and may need to reallocate the string.
398     format(
399         "$field$.ClearToDefault($lazy_variable$, GetArenaForAllocation());\n ");
400   }
401 }
402 
GenerateMergingCode(io::Printer * printer) const403 void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
404   Formatter format(printer, variables_);
405   // TODO(gpike): improve this
406   format("_internal_set_$name$(from._internal_$name$());\n");
407 }
408 
GenerateSwappingCode(io::Printer * printer) const409 void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
410   Formatter format(printer, variables_);
411   if (!inlined_) {
412     format(
413         "::$proto_ns$::internal::ArenaStringPtr::InternalSwap(\n"
414         "    &$field$, lhs_arena,\n"
415         "    &other->$field$, rhs_arena\n"
416         ");\n");
417   } else {
418     format(
419         "::$proto_ns$::internal::InlinedStringField::InternalSwap(\n"
420         "  &$field$, lhs_arena, "
421         "($inlined_string_donated_array$[0] & 0x1u) == 0, this,\n"
422         "  &other->$field$, rhs_arena, "
423         "(other->$inlined_string_donated_array$[0] & 0x1u) == 0, other);\n");
424   }
425 }
426 
GenerateConstructorCode(io::Printer * printer) const427 void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
428   Formatter format(printer, variables_);
429   if (inlined_ && descriptor_->default_value_string().empty()) {
430     return;
431   }
432   GOOGLE_DCHECK(!inlined_);
433   format("$field$.InitDefault();\n");
434   if (IsString(descriptor_, options_) &&
435       descriptor_->default_value_string().empty()) {
436     format(
437         "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
438         "  $field$.Set(\"\", GetArenaForAllocation());\n"
439         "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
440   }
441 }
442 
GenerateCopyConstructorCode(io::Printer * printer) const443 void StringFieldGenerator::GenerateCopyConstructorCode(
444     io::Printer* printer) const {
445   Formatter format(printer, variables_);
446   GenerateConstructorCode(printer);
447   if (inlined_) {
448     format("new (&$field$) ::_pbi::InlinedStringField();\n");
449   }
450 
451   if (HasHasbit(descriptor_)) {
452     format("if (from._internal_has_$name$()) {\n");
453   } else {
454     format("if (!from._internal_$name$().empty()) {\n");
455   }
456 
457   format.Indent();
458 
459   if (!inlined_) {
460     format(
461         "$field$.Set(from._internal_$name$(), \n"
462         "  GetArenaForAllocation());\n");
463   } else {
464     format(
465         "$field$.Set(from._internal_$name$(),\n"
466         "  GetArenaForAllocation(), _internal_$name$_donated(), "
467         "&$donating_states_word$, $mask_for_undonate$, this);\n");
468   }
469 
470   format.Outdent();
471   format("}\n");
472 }
473 
GenerateDestructorCode(io::Printer * printer) const474 void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
475   Formatter format(printer, variables_);
476   if (!inlined_) {
477     format("$field$.Destroy();\n");
478     return;
479   }
480   // Explicitly calls ~InlinedStringField as its automatic call is disabled.
481   // Destructor has been implicitly skipped as a union, and even the
482   // message-owned arena is enabled, arena could still be missing for
483   // Arena::CreateMessage(nullptr).
484   format("$field$.~InlinedStringField();\n");
485 }
486 
NeedsArenaDestructor() const487 ArenaDtorNeeds StringFieldGenerator::NeedsArenaDestructor() const {
488   return inlined_ ? ArenaDtorNeeds::kOnDemand : ArenaDtorNeeds::kNone;
489 }
490 
GenerateArenaDestructorCode(io::Printer * printer) const491 void StringFieldGenerator::GenerateArenaDestructorCode(
492     io::Printer* printer) const {
493   if (!inlined_) return;
494   Formatter format(printer, variables_);
495   // _this is the object being destructed (we are inside a static method here).
496   format(
497       "if (!_this->_internal_$name$_donated()) {\n"
498       "  _this->$field$.~InlinedStringField();\n"
499       "}\n");
500 }
501 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const502 void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
503     io::Printer* printer) const {
504   Formatter format(printer, variables_);
505   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
506     GenerateUtf8CheckCodeForString(
507         descriptor_, options_, false,
508         "this->_internal_$name$().data(), "
509         "static_cast<int>(this->_internal_$name$().length()),\n",
510         format);
511   }
512   format(
513       "target = stream->Write$declared_type$MaybeAliased(\n"
514       "    $number$, this->_internal_$name$(), target);\n");
515 }
516 
GenerateByteSize(io::Printer * printer) const517 void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
518   Formatter format(printer, variables_);
519   format(
520       "total_size += $tag_size$ +\n"
521       "  ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
522       "    this->_internal_$name$());\n");
523 }
524 
GenerateConstinitInitializer(io::Printer * printer) const525 void StringFieldGenerator::GenerateConstinitInitializer(
526     io::Printer* printer) const {
527   Formatter format(printer, variables_);
528   if (inlined_) {
529     format("$name$_(nullptr, false)");
530     return;
531   }
532   if (descriptor_->default_value_string().empty()) {
533     format(
534         "$name$_(&::_pbi::fixed_address_empty_string, "
535         "::_pbi::ConstantInitialized{})");
536   } else {
537     format("$name$_(nullptr, ::_pbi::ConstantInitialized{})");
538   }
539 }
540 
541 // ===================================================================
542 
StringOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)543 StringOneofFieldGenerator::StringOneofFieldGenerator(
544     const FieldDescriptor* descriptor, const Options& options)
545     : StringFieldGenerator(descriptor, options) {
546   SetCommonOneofFieldVariables(descriptor, &variables_);
547   variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
548   variables_["oneof_index"] =
549       StrCat(descriptor->containing_oneof()->index());
550 }
551 
~StringOneofFieldGenerator()552 StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
553 
GenerateInlineAccessorDefinitions(io::Printer * printer) const554 void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
555     io::Printer* printer) const {
556   Formatter format(printer, variables_);
557   format(
558       "inline const std::string& $classname$::$name$() const {\n"
559       "$annotate_get$"
560       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
561       "  return _internal_$name$();\n"
562       "}\n"
563       "template <typename ArgT0, typename... ArgT>\n"
564       "inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
565       "  if (!_internal_has_$name$()) {\n"
566       "    clear_$oneof_name$();\n"
567       "    set_has_$name$();\n"
568       "    $field$.InitDefault();\n"
569       "  }\n"
570       "  $field$.$setter$("
571       " static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());\n"
572       "$annotate_set$"
573       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
574       "}\n"
575       "inline std::string* $classname$::mutable_$name$() {\n"
576       "  std::string* _s = _internal_mutable_$name$();\n"
577       "$annotate_mutable$"
578       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
579       "  return _s;\n"
580       "}\n"
581       "inline const std::string& $classname$::_internal_$name$() const {\n"
582       "  if (_internal_has_$name$()) {\n"
583       "    return $field$.Get();\n"
584       "  }\n"
585       "  return $default_string$;\n"
586       "}\n"
587       "inline void $classname$::_internal_set_$name$(const std::string& "
588       "value) {\n"
589       "  if (!_internal_has_$name$()) {\n"
590       "    clear_$oneof_name$();\n"
591       "    set_has_$name$();\n"
592       "    $field$.InitDefault();\n"
593       "  }\n"
594       "  $field$.Set(value, GetArenaForAllocation());\n"
595       "}\n");
596   format(
597       "inline std::string* $classname$::_internal_mutable_$name$() {\n"
598       "  if (!_internal_has_$name$()) {\n"
599       "    clear_$oneof_name$();\n"
600       "    set_has_$name$();\n"
601       "    $field$.InitDefault();\n"
602       "  }\n"
603       "  return $field$.Mutable($lazy_variable_args$"
604       "      GetArenaForAllocation());\n"
605       "}\n"
606       "inline std::string* $classname$::$release_name$() {\n"
607       "$annotate_release$"
608       "  // @@protoc_insertion_point(field_release:$full_name$)\n"
609       "  if (_internal_has_$name$()) {\n"
610       "    clear_has_$oneof_name$();\n"
611       "    return $field$.Release();\n"
612       "  } else {\n"
613       "    return nullptr;\n"
614       "  }\n"
615       "}\n"
616       "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
617       "  if (has_$oneof_name$()) {\n"
618       "    clear_$oneof_name$();\n"
619       "  }\n"
620       "  if ($name$ != nullptr) {\n"
621       "    set_has_$name$();\n"
622       "    $field$.InitAllocated($name$, GetArenaForAllocation());\n"
623       "  }\n"
624       "$annotate_set$"
625       "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
626       "}\n");
627 }
628 
GenerateClearingCode(io::Printer * printer) const629 void StringOneofFieldGenerator::GenerateClearingCode(
630     io::Printer* printer) const {
631   Formatter format(printer, variables_);
632   format("$field$.Destroy();\n");
633 }
634 
GenerateMessageClearingCode(io::Printer * printer) const635 void StringOneofFieldGenerator::GenerateMessageClearingCode(
636     io::Printer* printer) const {
637   return GenerateClearingCode(printer);
638 }
639 
GenerateSwappingCode(io::Printer * printer) const640 void StringOneofFieldGenerator::GenerateSwappingCode(
641     io::Printer* printer) const {
642   // Don't print any swapping code. Swapping the union will swap this field.
643 }
644 
GenerateConstructorCode(io::Printer * printer) const645 void StringOneofFieldGenerator::GenerateConstructorCode(
646     io::Printer* printer) const {
647   // Nothing required here.
648 }
649 
650 // ===================================================================
651 
RepeatedStringFieldGenerator(const FieldDescriptor * descriptor,const Options & options)652 RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
653     const FieldDescriptor* descriptor, const Options& options)
654     : FieldGenerator(descriptor, options) {
655   SetStringVariables(descriptor, &variables_, options);
656 }
657 
~RepeatedStringFieldGenerator()658 RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
659 
GeneratePrivateMembers(io::Printer * printer) const660 void RepeatedStringFieldGenerator::GeneratePrivateMembers(
661     io::Printer* printer) const {
662   Formatter format(printer, variables_);
663   format("::$proto_ns$::RepeatedPtrField<std::string> $name$_;\n");
664 }
665 
GenerateAccessorDeclarations(io::Printer * printer) const666 void RepeatedStringFieldGenerator::GenerateAccessorDeclarations(
667     io::Printer* printer) const {
668   Formatter format(printer, variables_);
669   // See comment above about unknown ctypes.
670   bool unknown_ctype = descriptor_->options().ctype() !=
671                        EffectiveStringCType(descriptor_, options_);
672 
673   if (unknown_ctype) {
674     format.Outdent();
675     format(
676         " private:\n"
677         "  // Hidden due to unknown ctype option.\n");
678     format.Indent();
679   }
680 
681   format(
682       "$deprecated_attr$const std::string& ${1$$name$$}$(int index) const;\n"
683       "$deprecated_attr$std::string* ${1$mutable_$name$$}$(int index);\n"
684       "$deprecated_attr$void ${1$set_$name$$}$(int index, const "
685       "std::string& value);\n"
686       "$deprecated_attr$void ${1$set_$name$$}$(int index, std::string&& "
687       "value);\n"
688       "$deprecated_attr$void ${1$set_$name$$}$(int index, const "
689       "char* value);\n",
690       descriptor_);
691   if (!options_.opensource_runtime) {
692     format(
693         "$deprecated_attr$void ${1$set_$name$$}$(int index, "
694         "StringPiece value);\n",
695         descriptor_);
696   }
697   format(
698       "$deprecated_attr$void ${1$set_$name$$}$("
699       "int index, const $pointer_type$* value, size_t size);\n"
700       "$deprecated_attr$std::string* ${1$add_$name$$}$();\n"
701       "$deprecated_attr$void ${1$add_$name$$}$(const std::string& value);\n"
702       "$deprecated_attr$void ${1$add_$name$$}$(std::string&& value);\n"
703       "$deprecated_attr$void ${1$add_$name$$}$(const char* value);\n",
704       descriptor_);
705   if (!options_.opensource_runtime) {
706     format(
707         "$deprecated_attr$void ${1$add_$name$$}$(StringPiece value);\n",
708         descriptor_);
709   }
710   format(
711       "$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* "
712       "value, size_t size)"
713       ";\n"
714       "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField<std::string>& "
715       "${1$$name$$}$() "
716       "const;\n"
717       "$deprecated_attr$::$proto_ns$::RepeatedPtrField<std::string>* "
718       "${1$mutable_$name$$}$()"
719       ";\n"
720       "private:\n"
721       "const std::string& ${1$_internal_$name$$}$(int index) const;\n"
722       "std::string* _internal_add_$name$();\n"
723       "public:\n",
724       descriptor_);
725 
726   if (unknown_ctype) {
727     format.Outdent();
728     format(" public:\n");
729     format.Indent();
730   }
731 }
732 
GenerateInlineAccessorDefinitions(io::Printer * printer) const733 void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions(
734     io::Printer* printer) const {
735   Formatter format(printer, variables_);
736   format(
737       "inline std::string* $classname$::add_$name$() {\n"
738       "  std::string* _s = _internal_add_$name$();\n"
739       "$annotate_add_mutable$"
740       "  // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
741       "  return _s;\n"
742       "}\n");
743   if (options_.safe_boundary_check) {
744     format(
745         "inline const std::string& $classname$::_internal_$name$(int index) "
746         "const {\n"
747         "  return $field$.InternalCheckedGet(\n"
748         "      index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n"
749         "}\n");
750   } else {
751     format(
752         "inline const std::string& $classname$::_internal_$name$(int index) "
753         "const {\n"
754         "  return $field$.Get(index);\n"
755         "}\n");
756   }
757   format(
758       "inline const std::string& $classname$::$name$(int index) const {\n"
759       "$annotate_get$"
760       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
761       "  return _internal_$name$(index);\n"
762       "}\n"
763       "inline std::string* $classname$::mutable_$name$(int index) {\n"
764       "$annotate_mutable$"
765       "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
766       "  return $field$.Mutable(index);\n"
767       "}\n"
768       "inline void $classname$::set_$name$(int index, const std::string& "
769       "value) "
770       "{\n"
771       "  $field$.Mutable(index)->assign(value);\n"
772       "$annotate_set$"
773       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
774       "}\n"
775       "inline void $classname$::set_$name$(int index, std::string&& value) {\n"
776       "  $field$.Mutable(index)->assign(std::move(value));\n"
777       "$annotate_set$"
778       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
779       "}\n"
780       "inline void $classname$::set_$name$(int index, const char* value) {\n"
781       "  $null_check$"
782       "  $field$.Mutable(index)->assign(value);\n"
783       "$annotate_set$"
784       "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
785       "}\n");
786   if (!options_.opensource_runtime) {
787     format(
788         "inline void "
789         "$classname$::set_$name$(int index, StringPiece value) {\n"
790         "  $field$.Mutable(index)->assign(value.data(), value.size());\n"
791         "$annotate_set$"
792         "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
793         "}\n");
794   }
795   format(
796       "inline void "
797       "$classname$::set_$name$"
798       "(int index, const $pointer_type$* value, size_t size) {\n"
799       "  $field$.Mutable(index)->assign(\n"
800       "    reinterpret_cast<const char*>(value), size);\n"
801       "$annotate_set$"
802       "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
803       "}\n"
804       "inline std::string* $classname$::_internal_add_$name$() {\n"
805       "  return $field$.Add();\n"
806       "}\n"
807       "inline void $classname$::add_$name$(const std::string& value) {\n"
808       "  $field$.Add()->assign(value);\n"
809       "$annotate_add$"
810       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
811       "}\n"
812       "inline void $classname$::add_$name$(std::string&& value) {\n"
813       "  $field$.Add(std::move(value));\n"
814       "$annotate_add$"
815       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
816       "}\n"
817       "inline void $classname$::add_$name$(const char* value) {\n"
818       "  $null_check$"
819       "  $field$.Add()->assign(value);\n"
820       "$annotate_add$"
821       "  // @@protoc_insertion_point(field_add_char:$full_name$)\n"
822       "}\n");
823   if (!options_.opensource_runtime) {
824     format(
825         "inline void $classname$::add_$name$(StringPiece value) {\n"
826         "  $field$.Add()->assign(value.data(), value.size());\n"
827         "$annotate_add$"
828         "  // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n"
829         "}\n");
830   }
831   format(
832       "inline void "
833       "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
834       "  $field$.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
835       "$annotate_add$"
836       "  // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
837       "}\n"
838       "inline const ::$proto_ns$::RepeatedPtrField<std::string>&\n"
839       "$classname$::$name$() const {\n"
840       "$annotate_list$"
841       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
842       "  return $field$;\n"
843       "}\n"
844       "inline ::$proto_ns$::RepeatedPtrField<std::string>*\n"
845       "$classname$::mutable_$name$() {\n"
846       "$annotate_mutable_list$"
847       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
848       "  return &$field$;\n"
849       "}\n");
850 }
851 
GenerateClearingCode(io::Printer * printer) const852 void RepeatedStringFieldGenerator::GenerateClearingCode(
853     io::Printer* printer) const {
854   Formatter format(printer, variables_);
855   format("$field$.Clear();\n");
856 }
857 
GenerateMergingCode(io::Printer * printer) const858 void RepeatedStringFieldGenerator::GenerateMergingCode(
859     io::Printer* printer) const {
860   Formatter format(printer, variables_);
861   format("$field$.MergeFrom(from.$field$);\n");
862 }
863 
GenerateSwappingCode(io::Printer * printer) const864 void RepeatedStringFieldGenerator::GenerateSwappingCode(
865     io::Printer* printer) const {
866   Formatter format(printer, variables_);
867   format("$field$.InternalSwap(&other->$field$);\n");
868 }
869 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const870 void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
871     io::Printer* printer) const {
872   Formatter format(printer, variables_);
873   format(
874       "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
875       "  const auto& s = this->_internal_$name$(i);\n");
876   // format("for (const std::string& s : this->$name$()) {\n");
877   format.Indent();
878   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
879     GenerateUtf8CheckCodeForString(descriptor_, options_, false,
880                                    "s.data(), static_cast<int>(s.length()),\n",
881                                    format);
882   }
883   format.Outdent();
884   format(
885       "  target = stream->Write$declared_type$($number$, s, target);\n"
886       "}\n");
887 }
888 
GenerateByteSize(io::Printer * printer) const889 void RepeatedStringFieldGenerator::GenerateByteSize(
890     io::Printer* printer) const {
891   Formatter format(printer, variables_);
892   format(
893       "total_size += $tag_size$ *\n"
894       "    ::$proto_ns$::internal::FromIntSize($field$.size());\n"
895       "for (int i = 0, n = $field$.size(); i < n; i++) {\n"
896       "  total_size += "
897       "::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
898       "    $field$.Get(i));\n"
899       "}\n");
900 }
901 
GenerateConstinitInitializer(io::Printer * printer) const902 void RepeatedStringFieldGenerator::GenerateConstinitInitializer(
903     io::Printer* printer) const {
904   Formatter format(printer, variables_);
905   format("$name$_()");
906 }
907 
908 }  // namespace cpp
909 }  // namespace compiler
910 }  // namespace protobuf
911 }  // namespace google
912