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