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