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 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
37 #include <google/protobuf/descriptor.pb.h>
38 #include <google/protobuf/io/printer.h>
39 #include <google/protobuf/stubs/strutil.h>
40
41
42 namespace google {
43 namespace protobuf {
44 namespace compiler {
45 namespace cpp {
46
47 namespace {
48
SetStringVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables,const Options & options)49 void SetStringVariables(const FieldDescriptor* descriptor,
50 std::map<std::string, std::string>* variables,
51 const Options& options) {
52 SetCommonFieldVariables(descriptor, variables, options);
53 (*variables)["default"] = DefaultValue(options, descriptor);
54 (*variables)["default_length"] =
55 StrCat(descriptor->default_value_string().length());
56 std::string default_variable_string = MakeDefaultName(descriptor);
57 (*variables)["default_variable_name"] = default_variable_string;
58
59 if (!descriptor->default_value_string().empty()) {
60 (*variables)["lazy_variable"] =
61 QualifiedClassName(descriptor->containing_type(), options) +
62 "::" + default_variable_string;
63 }
64
65 (*variables)["default_string"] =
66 descriptor->default_value_string().empty()
67 ? "::" + (*variables)["proto_ns"] +
68 "::internal::GetEmptyStringAlreadyInited()"
69 : (*variables)["lazy_variable"] + ".get()";
70 (*variables)["init_value"] =
71 descriptor->default_value_string().empty()
72 ? "&::" + (*variables)["proto_ns"] +
73 "::internal::GetEmptyStringAlreadyInited()"
74 : "nullptr";
75 (*variables)["default_value_tag"] =
76 "::" + (*variables)["proto_ns"] + "::internal::ArenaStringPtr::" +
77 (descriptor->default_value_string().empty() ? "Empty" : "NonEmpty") +
78 "Default{}";
79 (*variables)["default_variable_or_tag"] =
80 (*variables)[descriptor->default_value_string().empty()
81 ? "default_value_tag"
82 : "lazy_variable"];
83 (*variables)["pointer_type"] =
84 descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
85 (*variables)["null_check"] = (*variables)["DCHK"] + "(value != nullptr);\n";
86 // NOTE: Escaped here to unblock proto1->proto2 migration.
87 // TODO(liujisi): Extend this to apply for other conflicting methods.
88 (*variables)["release_name"] =
89 SafeFunctionName(descriptor->containing_type(), descriptor, "release_");
90 (*variables)["full_name"] = descriptor->full_name();
91
92 if (options.opensource_runtime) {
93 (*variables)["string_piece"] = "::std::string";
94 } else {
95 (*variables)["string_piece"] = "::StringPiece";
96 }
97 }
98
99 } // namespace
100
101 // ===================================================================
102
StringFieldGenerator(const FieldDescriptor * descriptor,const Options & options)103 StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
104 const Options& options)
105 : FieldGenerator(descriptor, options) {
106 SetStringVariables(descriptor, &variables_, options);
107 }
108
~StringFieldGenerator()109 StringFieldGenerator::~StringFieldGenerator() {}
110
GeneratePrivateMembers(io::Printer * printer) const111 void StringFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
112 Formatter format(printer, variables_);
113 format("::$proto_ns$::internal::ArenaStringPtr $name$_;\n");
114 }
115
GenerateStaticMembers(io::Printer * printer) const116 void StringFieldGenerator::GenerateStaticMembers(io::Printer* printer) const {
117 Formatter format(printer, variables_);
118 if (!descriptor_->default_value_string().empty()) {
119 format(
120 "static const ::$proto_ns$::internal::LazyString"
121 " $default_variable_name$;\n");
122 }
123 }
124
GenerateAccessorDeclarations(io::Printer * printer) const125 void StringFieldGenerator::GenerateAccessorDeclarations(
126 io::Printer* printer) const {
127 Formatter format(printer, variables_);
128 // If we're using StringFieldGenerator for a field with a ctype, it's
129 // because that ctype isn't actually implemented. In particular, this is
130 // true of ctype=CORD and ctype=STRING_PIECE in the open source release.
131 // We aren't releasing Cord because it has too many Google-specific
132 // dependencies and we aren't releasing StringPiece because it's hardly
133 // useful outside of Google and because it would get confusing to have
134 // multiple instances of the StringPiece class in different libraries (PCRE
135 // already includes it for their C++ bindings, which came from Google).
136 //
137 // In any case, we make all the accessors private while still actually
138 // using a string to represent the field internally. This way, we can
139 // guarantee that if we do ever implement the ctype, it won't break any
140 // existing users who might be -- for whatever reason -- already using .proto
141 // files that applied the ctype. The field can still be accessed via the
142 // reflection interface since the reflection interface is independent of
143 // the string's underlying representation.
144
145 bool unknown_ctype = descriptor_->options().ctype() !=
146 EffectiveStringCType(descriptor_, options_);
147
148 if (unknown_ctype) {
149 format.Outdent();
150 format(
151 " private:\n"
152 " // Hidden due to unknown ctype option.\n");
153 format.Indent();
154 }
155
156 format(
157 "$deprecated_attr$const std::string& ${1$$name$$}$() const;\n"
158 "$deprecated_attr$void ${1$set_$name$$}$(const std::string& value);\n"
159 "$deprecated_attr$void ${1$set_$name$$}$(std::string&& value);\n"
160 "$deprecated_attr$void ${1$set_$name$$}$(const char* value);\n",
161 descriptor_);
162 if (!options_.opensource_runtime) {
163 format(
164 "$deprecated_attr$void ${1$set_$name$$}$(::StringPiece value);\n",
165 descriptor_);
166 }
167 format(
168 "$deprecated_attr$void ${1$set_$name$$}$(const $pointer_type$* "
169 "value, size_t size)"
170 ";\n"
171 "$deprecated_attr$std::string* ${1$mutable_$name$$}$();\n"
172 "$deprecated_attr$std::string* ${1$$release_name$$}$();\n"
173 "$deprecated_attr$void ${1$set_allocated_$name$$}$(std::string* "
174 "$name$);\n",
175 descriptor_);
176 format(
177 "private:\n"
178 "const std::string& _internal_$name$() const;\n"
179 "void _internal_set_$name$(const std::string& value);\n"
180 "std::string* _internal_mutable_$name$();\n"
181 "public:\n");
182
183 if (unknown_ctype) {
184 format.Outdent();
185 format(" public:\n");
186 format.Indent();
187 }
188 }
189
GenerateInlineAccessorDefinitions(io::Printer * printer) const190 void StringFieldGenerator::GenerateInlineAccessorDefinitions(
191 io::Printer* printer) const {
192 Formatter format(printer, variables_);
193 format(
194 "inline const std::string& $classname$::$name$() const {\n"
195 "$annotate_accessor$"
196 " // @@protoc_insertion_point(field_get:$full_name$)\n");
197 if (!descriptor_->default_value_string().empty()) {
198 format(
199 " if ($name$_.IsDefault(nullptr)) return "
200 "$default_variable_name$.get();\n");
201 }
202 format(
203 " return _internal_$name$();\n"
204 "}\n"
205 "inline void $classname$::set_$name$(const std::string& value) {\n"
206 "$annotate_accessor$"
207 " _internal_set_$name$(value);\n"
208 " // @@protoc_insertion_point(field_set:$full_name$)\n"
209 "}\n"
210 "inline std::string* $classname$::mutable_$name$() {\n"
211 "$annotate_accessor$"
212 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
213 " return _internal_mutable_$name$();\n"
214 "}\n"
215 "inline const std::string& $classname$::_internal_$name$() const {\n"
216 " return $name$_.Get();\n"
217 "}\n"
218 "inline void $classname$::_internal_set_$name$(const std::string& "
219 "value) {\n"
220 " $set_hasbit$\n"
221 " $name$_.Set($default_value_tag$, value, GetArena());\n"
222 "}\n"
223 "inline void $classname$::set_$name$(std::string&& value) {\n"
224 "$annotate_accessor$"
225 " $set_hasbit$\n"
226 " $name$_.Set(\n"
227 " $default_value_tag$, ::std::move(value), GetArena());\n"
228 " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
229 "}\n"
230 "inline void $classname$::set_$name$(const char* value) {\n"
231 "$annotate_accessor$"
232 " $null_check$"
233 " $set_hasbit$\n"
234 " $name$_.Set($default_value_tag$, $string_piece$(value), GetArena());\n"
235 " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
236 "}\n");
237 if (!options_.opensource_runtime) {
238 format(
239 "inline void $classname$::set_$name$(::StringPiece value) {\n"
240 "$annotate_accessor$"
241 " $set_hasbit$\n"
242 " $name$_.Set($default_value_tag$, value,GetArena());\n"
243 " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
244 "}\n");
245 }
246 format(
247 "inline "
248 "void $classname$::set_$name$(const $pointer_type$* value,\n"
249 " size_t size) {\n"
250 "$annotate_accessor$"
251 " $set_hasbit$\n"
252 " $name$_.Set($default_value_tag$, $string_piece$(\n"
253 " reinterpret_cast<const char*>(value), size), GetArena());\n"
254 " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
255 "}\n"
256 "inline std::string* $classname$::_internal_mutable_$name$() {\n"
257 " $set_hasbit$\n"
258 " return $name$_.Mutable($default_variable_or_tag$, GetArena());\n"
259 "}\n"
260 "inline std::string* $classname$::$release_name$() {\n"
261 "$annotate_accessor$"
262 " // @@protoc_insertion_point(field_release:$full_name$)\n");
263
264 if (HasHasbit(descriptor_)) {
265 format(
266 " if (!_internal_has_$name$()) {\n"
267 " return nullptr;\n"
268 " }\n"
269 " $clear_hasbit$\n"
270 " return $name$_.ReleaseNonDefault($init_value$, GetArena());\n");
271 } else {
272 format(" return $name$_.Release($init_value$, GetArena());\n");
273 }
274
275 format(
276 "}\n"
277 "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
278 "$annotate_accessor$"
279 " if ($name$ != nullptr) {\n"
280 " $set_hasbit$\n"
281 " } else {\n"
282 " $clear_hasbit$\n"
283 " }\n"
284 " $name$_.SetAllocated($init_value$, $name$,\n"
285 " GetArena());\n"
286 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
287 "}\n");
288 }
289
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const290 void StringFieldGenerator::GenerateNonInlineAccessorDefinitions(
291 io::Printer* printer) const {
292 Formatter format(printer, variables_);
293 if (!descriptor_->default_value_string().empty()) {
294 format(
295 "const ::$proto_ns$::internal::LazyString "
296 "$classname$::$default_variable_name$"
297 "{{{$default$, $default_length$}}, {nullptr}};\n");
298 }
299 }
300
GenerateClearingCode(io::Printer * printer) const301 void StringFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
302 Formatter format(printer, variables_);
303 if (descriptor_->default_value_string().empty()) {
304 format("$name$_.ClearToEmpty();\n");
305 } else {
306 format("$name$_.ClearToDefault($lazy_variable$, GetArena());\n");
307 }
308 }
309
GenerateMessageClearingCode(io::Printer * printer) const310 void StringFieldGenerator::GenerateMessageClearingCode(
311 io::Printer* printer) const {
312 Formatter format(printer, variables_);
313 // Two-dimension specialization here: supporting arenas, field presence, or
314 // not, and default value is the empty string or not. Complexity here ensures
315 // the minimal number of branches / amount of extraneous code at runtime
316 // (given that the below methods are inlined one-liners)!
317
318 // If we have a hasbit, then the Clear() method of the protocol buffer
319 // will have checked that this field is set. If so, we can avoid redundant
320 // checks against the default variable.
321 const bool must_be_present = HasHasbit(descriptor_);
322
323 if (descriptor_->default_value_string().empty()) {
324 if (must_be_present) {
325 format("$name$_.ClearNonDefaultToEmpty();\n");
326 } else {
327 format("$name$_.ClearToEmpty();\n");
328 }
329 } else {
330 // Clear to a non-empty default is more involved, as we try to use the
331 // Arena if one is present and may need to reallocate the string.
332 format("$name$_.ClearToDefault($lazy_variable$, GetArena());\n ");
333 }
334 }
335
GenerateMergingCode(io::Printer * printer) const336 void StringFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
337 Formatter format(printer, variables_);
338 // TODO(gpike): improve this
339 format("_internal_set_$name$(from._internal_$name$());\n");
340 }
341
GenerateSwappingCode(io::Printer * printer) const342 void StringFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
343 Formatter format(printer, variables_);
344 format("$name$_.Swap(&other->$name$_, $init_value$, GetArena());\n");
345 }
346
GenerateConstructorCode(io::Printer * printer) const347 void StringFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
348 Formatter format(printer, variables_);
349 format("$name$_.UnsafeSetDefault($init_value$);\n");
350 }
351
GenerateCopyConstructorCode(io::Printer * printer) const352 void StringFieldGenerator::GenerateCopyConstructorCode(
353 io::Printer* printer) const {
354 Formatter format(printer, variables_);
355 GenerateConstructorCode(printer);
356
357 if (HasHasbit(descriptor_)) {
358 format("if (from._internal_has_$name$()) {\n");
359 } else {
360 format("if (!from._internal_$name$().empty()) {\n");
361 }
362
363 format.Indent();
364
365 // TODO(gpike): improve this
366 format(
367 "$name$_.Set($default_value_tag$, from._internal_$name$(), \n"
368 " GetArena());\n");
369
370 format.Outdent();
371 format("}\n");
372 }
373
GenerateDestructorCode(io::Printer * printer) const374 void StringFieldGenerator::GenerateDestructorCode(io::Printer* printer) const {
375 Formatter format(printer, variables_);
376 format("$name$_.DestroyNoArena($init_value$);\n");
377 }
378
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const379 void StringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
380 io::Printer* printer) const {
381 Formatter format(printer, variables_);
382 if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
383 GenerateUtf8CheckCodeForString(
384 descriptor_, options_, false,
385 "this->_internal_$name$().data(), "
386 "static_cast<int>(this->_internal_$name$().length()),\n",
387 format);
388 }
389 format(
390 "target = stream->Write$declared_type$MaybeAliased(\n"
391 " $number$, this->_internal_$name$(), target);\n");
392 }
393
GenerateByteSize(io::Printer * printer) const394 void StringFieldGenerator::GenerateByteSize(io::Printer* printer) const {
395 Formatter format(printer, variables_);
396 format(
397 "total_size += $tag_size$ +\n"
398 " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
399 " this->_internal_$name$());\n");
400 }
401
402 // ===================================================================
403
StringOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)404 StringOneofFieldGenerator::StringOneofFieldGenerator(
405 const FieldDescriptor* descriptor, const Options& options)
406 : StringFieldGenerator(descriptor, options) {
407 SetCommonOneofFieldVariables(descriptor, &variables_);
408 variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
409 variables_["oneof_index"] =
410 StrCat(descriptor->containing_oneof()->index());
411 }
412
~StringOneofFieldGenerator()413 StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
414
GenerateInlineAccessorDefinitions(io::Printer * printer) const415 void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
416 io::Printer* printer) const {
417 Formatter format(printer, variables_);
418 format(
419 "inline const std::string& $classname$::$name$() const {\n"
420 "$annotate_accessor$"
421 " // @@protoc_insertion_point(field_get:$full_name$)\n"
422 " return _internal_$name$();\n"
423 "}\n"
424 "inline void $classname$::set_$name$(const std::string& value) {\n"
425 "$annotate_accessor$"
426 " _internal_set_$name$(value);\n"
427 " // @@protoc_insertion_point(field_set:$full_name$)\n"
428 "}\n"
429 "inline std::string* $classname$::mutable_$name$() {\n"
430 "$annotate_accessor$"
431 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
432 " return _internal_mutable_$name$();\n"
433 "}\n"
434 "inline const std::string& $classname$::_internal_$name$() const {\n"
435 " if (_internal_has_$name$()) {\n"
436 " return $field_member$.Get();\n"
437 " }\n"
438 " return $default_string$;\n"
439 "}\n"
440 "inline void $classname$::_internal_set_$name$(const std::string& "
441 "value) {\n"
442 " if (!_internal_has_$name$()) {\n"
443 " clear_$oneof_name$();\n"
444 " set_has_$name$();\n"
445 " $field_member$.UnsafeSetDefault($init_value$);\n"
446 " }\n"
447 " $field_member$.Set($default_value_tag$, value, GetArena());\n"
448 "}\n"
449 "inline void $classname$::set_$name$(std::string&& value) {\n"
450 "$annotate_accessor$"
451 " // @@protoc_insertion_point(field_set:$full_name$)\n"
452 " if (!_internal_has_$name$()) {\n"
453 " clear_$oneof_name$();\n"
454 " set_has_$name$();\n"
455 " $field_member$.UnsafeSetDefault($init_value$);\n"
456 " }\n"
457 " $field_member$.Set(\n"
458 " $default_value_tag$, ::std::move(value), GetArena());\n"
459 " // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
460 "}\n"
461 "inline void $classname$::set_$name$(const char* value) {\n"
462 "$annotate_accessor$"
463 " $null_check$"
464 " if (!_internal_has_$name$()) {\n"
465 " clear_$oneof_name$();\n"
466 " set_has_$name$();\n"
467 " $field_member$.UnsafeSetDefault($init_value$);\n"
468 " }\n"
469 " $field_member$.Set($default_value_tag$,\n"
470 " $string_piece$(value), GetArena());\n"
471 " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
472 "}\n");
473 if (!options_.opensource_runtime) {
474 format(
475 "inline void $classname$::set_$name$(::StringPiece value) {\n"
476 "$annotate_accessor$"
477 " if (!_internal_has_$name$()) {\n"
478 " clear_$oneof_name$();\n"
479 " set_has_$name$();\n"
480 " $field_member$.UnsafeSetDefault($init_value$);\n"
481 " }\n"
482 " $field_member$.Set($default_value_tag$, value, GetArena());\n"
483 " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
484 "}\n");
485 }
486 format(
487 "inline "
488 "void $classname$::set_$name$(const $pointer_type$* value,\n"
489 " size_t size) {\n"
490 "$annotate_accessor$"
491 " if (!_internal_has_$name$()) {\n"
492 " clear_$oneof_name$();\n"
493 " set_has_$name$();\n"
494 " $field_member$.UnsafeSetDefault($init_value$);\n"
495 " }\n"
496 " $field_member$.Set(\n"
497 " $default_value_tag$, $string_piece$(\n"
498 " reinterpret_cast<const char*>(value), size),\n"
499 " GetArena());\n"
500 " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
501 "}\n"
502 "inline std::string* $classname$::_internal_mutable_$name$() {\n"
503 " if (!_internal_has_$name$()) {\n"
504 " clear_$oneof_name$();\n"
505 " set_has_$name$();\n"
506 " $field_member$.UnsafeSetDefault($init_value$);\n"
507 " }\n"
508 " return $field_member$.Mutable(\n"
509 " $default_variable_or_tag$, GetArena());\n"
510 "}\n"
511 "inline std::string* $classname$::$release_name$() {\n"
512 "$annotate_accessor$"
513 " // @@protoc_insertion_point(field_release:$full_name$)\n"
514 " if (_internal_has_$name$()) {\n"
515 " clear_has_$oneof_name$();\n"
516 " return $field_member$.ReleaseNonDefault($init_value$, GetArena());\n"
517 " } else {\n"
518 " return nullptr;\n"
519 " }\n"
520 "}\n"
521 "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
522 "$annotate_accessor$"
523 " if (has_$oneof_name$()) {\n"
524 " clear_$oneof_name$();\n"
525 " }\n"
526 " if ($name$ != nullptr) {\n"
527 " set_has_$name$();\n"
528 " $field_member$.UnsafeSetDefault($name$);\n"
529 " ::$proto_ns$::Arena* arena = GetArena();\n"
530 " if (arena != nullptr) {\n"
531 " arena->Own($name$);\n"
532 " }\n"
533 " }\n"
534 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
535 "}\n");
536 }
537
GenerateClearingCode(io::Printer * printer) const538 void StringOneofFieldGenerator::GenerateClearingCode(
539 io::Printer* printer) const {
540 Formatter format(printer, variables_);
541 format("$field_member$.Destroy($default_value_tag$, GetArena());\n");
542 }
543
GenerateMessageClearingCode(io::Printer * printer) const544 void StringOneofFieldGenerator::GenerateMessageClearingCode(
545 io::Printer* printer) const {
546 return GenerateClearingCode(printer);
547 }
548
GenerateSwappingCode(io::Printer * printer) const549 void StringOneofFieldGenerator::GenerateSwappingCode(
550 io::Printer* printer) const {
551 // Don't print any swapping code. Swapping the union will swap this field.
552 }
553
GenerateConstructorCode(io::Printer * printer) const554 void StringOneofFieldGenerator::GenerateConstructorCode(
555 io::Printer* printer) const {
556 // Nothing required here.
557 }
558
559 // ===================================================================
560
RepeatedStringFieldGenerator(const FieldDescriptor * descriptor,const Options & options)561 RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
562 const FieldDescriptor* descriptor, const Options& options)
563 : FieldGenerator(descriptor, options) {
564 SetStringVariables(descriptor, &variables_, options);
565 }
566
~RepeatedStringFieldGenerator()567 RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
568
GeneratePrivateMembers(io::Printer * printer) const569 void RepeatedStringFieldGenerator::GeneratePrivateMembers(
570 io::Printer* printer) const {
571 Formatter format(printer, variables_);
572 format("::$proto_ns$::RepeatedPtrField<std::string> $name$_;\n");
573 }
574
GenerateAccessorDeclarations(io::Printer * printer) const575 void RepeatedStringFieldGenerator::GenerateAccessorDeclarations(
576 io::Printer* printer) const {
577 Formatter format(printer, variables_);
578 // See comment above about unknown ctypes.
579 bool unknown_ctype = descriptor_->options().ctype() !=
580 EffectiveStringCType(descriptor_, options_);
581
582 if (unknown_ctype) {
583 format.Outdent();
584 format(
585 " private:\n"
586 " // Hidden due to unknown ctype option.\n");
587 format.Indent();
588 }
589
590 format(
591 "$deprecated_attr$const std::string& ${1$$name$$}$(int index) const;\n"
592 "$deprecated_attr$std::string* ${1$mutable_$name$$}$(int index);\n"
593 "$deprecated_attr$void ${1$set_$name$$}$(int index, const "
594 "std::string& value);\n"
595 "$deprecated_attr$void ${1$set_$name$$}$(int index, std::string&& "
596 "value);\n"
597 "$deprecated_attr$void ${1$set_$name$$}$(int index, const "
598 "char* value);\n",
599 descriptor_);
600 if (!options_.opensource_runtime) {
601 format(
602 "$deprecated_attr$void ${1$set_$name$$}$(int index, "
603 "StringPiece value);\n",
604 descriptor_);
605 }
606 format(
607 "$deprecated_attr$void ${1$set_$name$$}$("
608 "int index, const $pointer_type$* value, size_t size);\n"
609 "$deprecated_attr$std::string* ${1$add_$name$$}$();\n"
610 "$deprecated_attr$void ${1$add_$name$$}$(const std::string& value);\n"
611 "$deprecated_attr$void ${1$add_$name$$}$(std::string&& value);\n"
612 "$deprecated_attr$void ${1$add_$name$$}$(const char* value);\n",
613 descriptor_);
614 if (!options_.opensource_runtime) {
615 format(
616 "$deprecated_attr$void ${1$add_$name$$}$(StringPiece value);\n",
617 descriptor_);
618 }
619 format(
620 "$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* "
621 "value, size_t size)"
622 ";\n"
623 "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField<std::string>& "
624 "${1$$name$$}$() "
625 "const;\n"
626 "$deprecated_attr$::$proto_ns$::RepeatedPtrField<std::string>* "
627 "${1$mutable_$name$$}$()"
628 ";\n"
629 "private:\n"
630 "const std::string& ${1$_internal_$name$$}$(int index) const;\n"
631 "std::string* _internal_add_$name$();\n"
632 "public:\n",
633 descriptor_);
634
635 if (unknown_ctype) {
636 format.Outdent();
637 format(" public:\n");
638 format.Indent();
639 }
640 }
641
GenerateInlineAccessorDefinitions(io::Printer * printer) const642 void RepeatedStringFieldGenerator::GenerateInlineAccessorDefinitions(
643 io::Printer* printer) const {
644 Formatter format(printer, variables_);
645 format(
646 "inline std::string* $classname$::add_$name$() {\n"
647 "$annotate_accessor$"
648 " // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
649 " return _internal_add_$name$();\n"
650 "}\n");
651 if (options_.safe_boundary_check) {
652 format(
653 "inline const std::string& $classname$::_internal_$name$(int index) "
654 "const {\n"
655 " return $name$_.InternalCheckedGet(\n"
656 " index, ::$proto_ns$::internal::GetEmptyStringAlreadyInited());\n"
657 "}\n");
658 } else {
659 format(
660 "inline const std::string& $classname$::_internal_$name$(int index) "
661 "const {\n"
662 " return $name$_.Get(index);\n"
663 "}\n");
664 }
665 format(
666 "inline const std::string& $classname$::$name$(int index) const {\n"
667 "$annotate_accessor$"
668 " // @@protoc_insertion_point(field_get:$full_name$)\n"
669 " return _internal_$name$(index);\n"
670 "}\n"
671 "inline std::string* $classname$::mutable_$name$(int index) {\n"
672 "$annotate_accessor$"
673 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
674 " return $name$_.Mutable(index);\n"
675 "}\n"
676 "inline void $classname$::set_$name$(int index, const std::string& "
677 "value) "
678 "{\n"
679 "$annotate_accessor$"
680 " // @@protoc_insertion_point(field_set:$full_name$)\n"
681 " $name$_.Mutable(index)->assign(value);\n"
682 "}\n"
683 "inline void $classname$::set_$name$(int index, std::string&& value) {\n"
684 "$annotate_accessor$"
685 " // @@protoc_insertion_point(field_set:$full_name$)\n"
686 " $name$_.Mutable(index)->assign(std::move(value));\n"
687 "}\n"
688 "inline void $classname$::set_$name$(int index, const char* value) {\n"
689 "$annotate_accessor$"
690 " $null_check$"
691 " $name$_.Mutable(index)->assign(value);\n"
692 " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
693 "}\n");
694 if (!options_.opensource_runtime) {
695 format(
696 "inline void "
697 "$classname$::set_$name$(int index, StringPiece value) {\n"
698 "$annotate_accessor$"
699 " $name$_.Mutable(index)->assign(value.data(), value.size());\n"
700 " // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
701 "}\n");
702 }
703 format(
704 "inline void "
705 "$classname$::set_$name$"
706 "(int index, const $pointer_type$* value, size_t size) {\n"
707 "$annotate_accessor$"
708 " $name$_.Mutable(index)->assign(\n"
709 " reinterpret_cast<const char*>(value), size);\n"
710 " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
711 "}\n"
712 "inline std::string* $classname$::_internal_add_$name$() {\n"
713 " return $name$_.Add();\n"
714 "}\n"
715 "inline void $classname$::add_$name$(const std::string& value) {\n"
716 "$annotate_accessor$"
717 " $name$_.Add()->assign(value);\n"
718 " // @@protoc_insertion_point(field_add:$full_name$)\n"
719 "}\n"
720 "inline void $classname$::add_$name$(std::string&& value) {\n"
721 "$annotate_accessor$"
722 " $name$_.Add(std::move(value));\n"
723 " // @@protoc_insertion_point(field_add:$full_name$)\n"
724 "}\n"
725 "inline void $classname$::add_$name$(const char* value) {\n"
726 "$annotate_accessor$"
727 " $null_check$"
728 " $name$_.Add()->assign(value);\n"
729 " // @@protoc_insertion_point(field_add_char:$full_name$)\n"
730 "}\n");
731 if (!options_.opensource_runtime) {
732 format(
733 "inline void $classname$::add_$name$(StringPiece value) {\n"
734 "$annotate_accessor$"
735 " $name$_.Add()->assign(value.data(), value.size());\n"
736 " // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n"
737 "}\n");
738 }
739 format(
740 "inline void "
741 "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
742 "$annotate_accessor$"
743 " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
744 " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
745 "}\n"
746 "inline const ::$proto_ns$::RepeatedPtrField<std::string>&\n"
747 "$classname$::$name$() const {\n"
748 "$annotate_accessor$"
749 " // @@protoc_insertion_point(field_list:$full_name$)\n"
750 " return $name$_;\n"
751 "}\n"
752 "inline ::$proto_ns$::RepeatedPtrField<std::string>*\n"
753 "$classname$::mutable_$name$() {\n"
754 "$annotate_accessor$"
755 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
756 " return &$name$_;\n"
757 "}\n");
758 }
759
GenerateClearingCode(io::Printer * printer) const760 void RepeatedStringFieldGenerator::GenerateClearingCode(
761 io::Printer* printer) const {
762 Formatter format(printer, variables_);
763 format("$name$_.Clear();\n");
764 }
765
GenerateMergingCode(io::Printer * printer) const766 void RepeatedStringFieldGenerator::GenerateMergingCode(
767 io::Printer* printer) const {
768 Formatter format(printer, variables_);
769 format("$name$_.MergeFrom(from.$name$_);\n");
770 }
771
GenerateSwappingCode(io::Printer * printer) const772 void RepeatedStringFieldGenerator::GenerateSwappingCode(
773 io::Printer* printer) const {
774 Formatter format(printer, variables_);
775 format("$name$_.InternalSwap(&other->$name$_);\n");
776 }
777
GenerateConstructorCode(io::Printer * printer) const778 void RepeatedStringFieldGenerator::GenerateConstructorCode(
779 io::Printer* printer) const {
780 // Not needed for repeated fields.
781 }
782
GenerateCopyConstructorCode(io::Printer * printer) const783 void RepeatedStringFieldGenerator::GenerateCopyConstructorCode(
784 io::Printer* printer) const {
785 Formatter format(printer, variables_);
786 format("$name$_.CopyFrom(from.$name$_);");
787 }
788
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const789 void RepeatedStringFieldGenerator::GenerateSerializeWithCachedSizesToArray(
790 io::Printer* printer) const {
791 Formatter format(printer, variables_);
792 format(
793 "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
794 " const auto& s = this->_internal_$name$(i);\n");
795 // format("for (const std::string& s : this->$name$()) {\n");
796 format.Indent();
797 if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
798 GenerateUtf8CheckCodeForString(descriptor_, options_, false,
799 "s.data(), static_cast<int>(s.length()),\n",
800 format);
801 }
802 format.Outdent();
803 format(
804 " target = stream->Write$declared_type$($number$, s, target);\n"
805 "}\n");
806 }
807
GenerateByteSize(io::Printer * printer) const808 void RepeatedStringFieldGenerator::GenerateByteSize(
809 io::Printer* printer) const {
810 Formatter format(printer, variables_);
811 format(
812 "total_size += $tag_size$ *\n"
813 " ::$proto_ns$::internal::FromIntSize($name$_.size());\n"
814 "for (int i = 0, n = $name$_.size(); i < n; i++) {\n"
815 " total_size += "
816 "::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
817 " $name$_.Get(i));\n"
818 "}\n");
819 }
820
821 } // namespace cpp
822 } // namespace compiler
823 } // namespace protobuf
824 } // namespace google
825