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/io/printer.h>
38 #include <google/protobuf/descriptor.pb.h>
39 #include <google/protobuf/stubs/strutil.h>
40
41 namespace google {
42 namespace protobuf {
43 namespace compiler {
44 namespace cpp {
45
46 namespace {
47
SetStringVariables(const FieldDescriptor * descriptor,map<string,string> * variables,const Options & options)48 void SetStringVariables(const FieldDescriptor* descriptor,
49 map<string, string>* variables,
50 const Options& options) {
51 SetCommonFieldVariables(descriptor, variables, options);
52 (*variables)["default"] = DefaultValue(descriptor);
53 (*variables)["default_length"] =
54 SimpleItoa(descriptor->default_value_string().length());
55 string default_variable_string =
56 descriptor->default_value_string().empty()
57 ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()"
58 : "_default_" + FieldName(descriptor) + "_";
59 (*variables)["default_variable"] = default_variable_string;
60 (*variables)["default_value_init"] =
61 descriptor->default_value_string().empty()
62 ? "" : "*" + default_variable_string;
63 (*variables)["pointer_type"] =
64 descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
65 // NOTE: Escaped here to unblock proto1->proto2 migration.
66 // TODO(liujisi): Extend this to apply for other conflicting methods.
67 (*variables)["release_name"] =
68 SafeFunctionName(descriptor->containing_type(),
69 descriptor, "release_");
70 (*variables)["full_name"] = descriptor->full_name();
71
72 (*variables)["string_piece"] = "::std::string";
73 }
74
75 } // namespace
76
77 // ===================================================================
78
StringFieldGenerator(const FieldDescriptor * descriptor,const Options & options)79 StringFieldGenerator::StringFieldGenerator(const FieldDescriptor* descriptor,
80 const Options& options)
81 : FieldGenerator(options), descriptor_(descriptor) {
82 SetStringVariables(descriptor, &variables_, options);
83 }
84
~StringFieldGenerator()85 StringFieldGenerator::~StringFieldGenerator() {}
86
87 void StringFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const88 GeneratePrivateMembers(io::Printer* printer) const {
89 // N.B. that we continue to use |ArenaStringPtr| instead of |string*| for
90 // string fields, even when SupportArenas(descriptor_) == false. Why?
91 // The simple answer is to avoid unmaintainable complexity. The reflection
92 // code assumes ArenaStringPtrs. These are *almost* in-memory-compatible with
93 // string*, except for the pointer tags and related ownership semantics. We
94 // could modify the runtime code to use string* for the not-supporting-arenas
95 // case, but this would require a way to detect which type of class was
96 // generated (adding overhead and complexity to GeneratedMessageReflection)
97 // and littering the runtime code paths with conditionals. It's simpler to
98 // stick with this but use lightweight accessors that assume arena == NULL.
99 // There should be very little overhead anyway because it's just a tagged
100 // pointer in-memory.
101 printer->Print(variables_, "::google::protobuf::internal::ArenaStringPtr $name$_;\n");
102 }
103
104 void StringFieldGenerator::
GenerateStaticMembers(io::Printer * printer) const105 GenerateStaticMembers(io::Printer* printer) const {
106 if (!descriptor_->default_value_string().empty()) {
107 printer->Print(variables_, "static ::std::string* $default_variable$;\n");
108 }
109 }
110
111 void StringFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const112 GenerateAccessorDeclarations(io::Printer* printer) const {
113 // If we're using StringFieldGenerator for a field with a ctype, it's
114 // because that ctype isn't actually implemented. In particular, this is
115 // true of ctype=CORD and ctype=STRING_PIECE in the open source release.
116 // We aren't releasing Cord because it has too many Google-specific
117 // dependencies and we aren't releasing StringPiece because it's hardly
118 // useful outside of Google and because it would get confusing to have
119 // multiple instances of the StringPiece class in different libraries (PCRE
120 // already includes it for their C++ bindings, which came from Google).
121 //
122 // In any case, we make all the accessors private while still actually
123 // using a string to represent the field internally. This way, we can
124 // guarantee that if we do ever implement the ctype, it won't break any
125 // existing users who might be -- for whatever reason -- already using .proto
126 // files that applied the ctype. The field can still be accessed via the
127 // reflection interface since the reflection interface is independent of
128 // the string's underlying representation.
129
130 bool unknown_ctype =
131 descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
132
133 if (unknown_ctype) {
134 printer->Outdent();
135 printer->Print(
136 " private:\n"
137 " // Hidden due to unknown ctype option.\n");
138 printer->Indent();
139 }
140
141 printer->Print(variables_,
142 "$deprecated_attr$const ::std::string& $name$() const;\n"
143 "$deprecated_attr$void set_$name$(const ::std::string& value);\n"
144 "$deprecated_attr$void set_$name$(const char* value);\n"
145 "$deprecated_attr$void set_$name$(const $pointer_type$* value, size_t size)"
146 ";\n"
147 "$deprecated_attr$::std::string* mutable_$name$();\n"
148 "$deprecated_attr$::std::string* $release_name$();\n"
149 "$deprecated_attr$void set_allocated_$name$(::std::string* $name$);\n");
150 if (SupportsArenas(descriptor_)) {
151 printer->Print(variables_,
152 "$deprecated_attr$::std::string* unsafe_arena_release_$name$();\n"
153 "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n"
154 " ::std::string* $name$);\n");
155 }
156
157
158 if (unknown_ctype) {
159 printer->Outdent();
160 printer->Print(" public:\n");
161 printer->Indent();
162 }
163 }
164
165 void StringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer,bool is_inline) const166 GenerateInlineAccessorDefinitions(io::Printer* printer,
167 bool is_inline) const {
168 map<string, string> variables(variables_);
169 variables["inline"] = is_inline ? "inline" : "";
170 if (SupportsArenas(descriptor_)) {
171 printer->Print(variables,
172 "$inline$ const ::std::string& $classname$::$name$() const {\n"
173 " // @@protoc_insertion_point(field_get:$full_name$)\n"
174 " return $name$_.Get($default_variable$);\n"
175 "}\n"
176 "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
177 " $set_hasbit$\n"
178 " $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n"
179 " // @@protoc_insertion_point(field_set:$full_name$)\n"
180 "}\n"
181 "$inline$ void $classname$::set_$name$(const char* value) {\n"
182 " $set_hasbit$\n"
183 " $name$_.Set($default_variable$, $string_piece$(value),\n"
184 " GetArenaNoVirtual());\n"
185 " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
186 "}\n"
187 "$inline$ "
188 "void $classname$::set_$name$(const $pointer_type$* value,\n"
189 " size_t size) {\n"
190 " $set_hasbit$\n"
191 " $name$_.Set($default_variable$, $string_piece$(\n"
192 " reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());\n"
193 " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
194 "}\n"
195 "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
196 " $set_hasbit$\n"
197 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
198 " return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
199 "}\n"
200 "$inline$ ::std::string* $classname$::$release_name$() {\n"
201 " // @@protoc_insertion_point(field_release:$full_name$)\n"
202 " $clear_hasbit$\n"
203 " return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
204 "}\n"
205 "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
206 " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
207 " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
208 " $clear_hasbit$\n"
209 " return $name$_.UnsafeArenaRelease($default_variable$,\n"
210 " GetArenaNoVirtual());\n"
211 "}\n"
212 "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
213 " if ($name$ != NULL) {\n"
214 " $set_hasbit$\n"
215 " } else {\n"
216 " $clear_hasbit$\n"
217 " }\n"
218 " $name$_.SetAllocated($default_variable$, $name$,\n"
219 " GetArenaNoVirtual());\n"
220 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
221 "}\n"
222 "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(\n"
223 " ::std::string* $name$) {\n"
224 " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
225 " if ($name$ != NULL) {\n"
226 " $set_hasbit$\n"
227 " } else {\n"
228 " $clear_hasbit$\n"
229 " }\n"
230 " $name$_.UnsafeArenaSetAllocated($default_variable$,\n"
231 " $name$, GetArenaNoVirtual());\n"
232 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
233 "$full_name$)\n"
234 "}\n");
235 } else {
236 // No-arena case.
237 printer->Print(variables,
238 "$inline$ const ::std::string& $classname$::$name$() const {\n"
239 " // @@protoc_insertion_point(field_get:$full_name$)\n"
240 " return $name$_.GetNoArena($default_variable$);\n"
241 "}\n"
242 "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
243 " $set_hasbit$\n"
244 " $name$_.SetNoArena($default_variable$, value);\n"
245 " // @@protoc_insertion_point(field_set:$full_name$)\n"
246 "}\n"
247 "$inline$ void $classname$::set_$name$(const char* value) {\n"
248 " $set_hasbit$\n"
249 " $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
250 " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
251 "}\n"
252 "$inline$ "
253 "void $classname$::set_$name$(const $pointer_type$* value, "
254 "size_t size) {\n"
255 " $set_hasbit$\n"
256 " $name$_.SetNoArena($default_variable$,\n"
257 " $string_piece$(reinterpret_cast<const char*>(value), size));\n"
258 " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
259 "}\n"
260 "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
261 " $set_hasbit$\n"
262 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
263 " return $name$_.MutableNoArena($default_variable$);\n"
264 "}\n"
265 "$inline$ ::std::string* $classname$::$release_name$() {\n"
266 " // @@protoc_insertion_point(field_release:$full_name$)\n"
267 " $clear_hasbit$\n"
268 " return $name$_.ReleaseNoArena($default_variable$);\n"
269 "}\n"
270 "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
271 " if ($name$ != NULL) {\n"
272 " $set_hasbit$\n"
273 " } else {\n"
274 " $clear_hasbit$\n"
275 " }\n"
276 " $name$_.SetAllocatedNoArena($default_variable$, $name$);\n"
277 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
278 "}\n");
279 }
280 }
281
282 void StringFieldGenerator::
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const283 GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
284 if (!descriptor_->default_value_string().empty()) {
285 // Initialized in GenerateDefaultInstanceAllocator.
286 printer->Print(variables_,
287 "::std::string* $classname$::$default_variable$ = NULL;\n");
288 }
289 }
290
291 void StringFieldGenerator::
GenerateClearingCode(io::Printer * printer) const292 GenerateClearingCode(io::Printer* printer) const {
293 // Two-dimension specialization here: supporting arenas or not, and default
294 // value is the empty string or not. Complexity here ensures the minimal
295 // number of branches / amount of extraneous code at runtime (given that the
296 // below methods are inlined one-liners)!
297 if (SupportsArenas(descriptor_)) {
298 if (descriptor_->default_value_string().empty()) {
299 printer->Print(variables_,
300 "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n");
301 } else {
302 printer->Print(variables_,
303 "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n");
304 }
305 } else {
306 if (descriptor_->default_value_string().empty()) {
307 printer->Print(variables_,
308 "$name$_.ClearToEmptyNoArena($default_variable$);\n");
309 } else {
310 printer->Print(variables_,
311 "$name$_.ClearToDefaultNoArena($default_variable$);\n");
312 }
313 }
314 }
315
316 void StringFieldGenerator::
GenerateMergingCode(io::Printer * printer) const317 GenerateMergingCode(io::Printer* printer) const {
318 if (SupportsArenas(descriptor_) || descriptor_->containing_oneof() != NULL) {
319 // TODO(gpike): improve this
320 printer->Print(variables_, "set_$name$(from.$name$());\n");
321 } else {
322 printer->Print(variables_,
323 "$set_hasbit$\n"
324 "$name$_.AssignWithDefault($default_variable$, from.$name$_);\n");
325 }
326 }
327
328 void StringFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const329 GenerateSwappingCode(io::Printer* printer) const {
330 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
331 }
332
333 void StringFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const334 GenerateConstructorCode(io::Printer* printer) const {
335 printer->Print(variables_,
336 "$name$_.UnsafeSetDefault($default_variable$);\n");
337 }
338
339 void StringFieldGenerator::
GenerateDestructorCode(io::Printer * printer) const340 GenerateDestructorCode(io::Printer* printer) const {
341 if (SupportsArenas(descriptor_)) {
342 printer->Print(variables_,
343 "$name$_.Destroy($default_variable$, GetArenaNoVirtual());\n");
344 } else {
345 printer->Print(variables_,
346 "$name$_.DestroyNoArena($default_variable$);\n");
347 }
348 }
349
350 void StringFieldGenerator::
GenerateDefaultInstanceAllocator(io::Printer * printer) const351 GenerateDefaultInstanceAllocator(io::Printer* printer) const {
352 if (!descriptor_->default_value_string().empty()) {
353 printer->Print(variables_,
354 "$classname$::$default_variable$ =\n"
355 " new ::std::string($default$, $default_length$);\n");
356 }
357 }
358
359 void StringFieldGenerator::
GenerateShutdownCode(io::Printer * printer) const360 GenerateShutdownCode(io::Printer* printer) const {
361 if (!descriptor_->default_value_string().empty()) {
362 printer->Print(variables_,
363 "delete $classname$::$default_variable$;\n");
364 }
365 }
366
367 void StringFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const368 GenerateMergeFromCodedStream(io::Printer* printer) const {
369 printer->Print(variables_,
370 "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
371 " input, this->mutable_$name$()));\n");
372
373 if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
374 GenerateUtf8CheckCodeForString(
375 descriptor_, options_, true, variables_,
376 "this->$name$().data(), this->$name$().length(),\n", printer);
377 }
378 }
379
380 void StringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const381 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
382 if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
383 GenerateUtf8CheckCodeForString(
384 descriptor_, options_, false, variables_,
385 "this->$name$().data(), this->$name$().length(),\n", printer);
386 }
387 printer->Print(variables_,
388 "::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n"
389 " $number$, this->$name$(), output);\n");
390 }
391
392 void StringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const393 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
394 if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
395 GenerateUtf8CheckCodeForString(
396 descriptor_, options_, false, variables_,
397 "this->$name$().data(), this->$name$().length(),\n", printer);
398 }
399 printer->Print(variables_,
400 "target =\n"
401 " ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n"
402 " $number$, this->$name$(), target);\n");
403 }
404
405 void StringFieldGenerator::
GenerateByteSize(io::Printer * printer) const406 GenerateByteSize(io::Printer* printer) const {
407 printer->Print(variables_,
408 "total_size += $tag_size$ +\n"
409 " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
410 " this->$name$());\n");
411 }
412
413 // ===================================================================
414
415 StringOneofFieldGenerator::
StringOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)416 StringOneofFieldGenerator(const FieldDescriptor* descriptor,
417 const Options& options)
418 : StringFieldGenerator(descriptor, options),
419 dependent_field_(options.proto_h) {
420 SetCommonOneofFieldVariables(descriptor, &variables_);
421 }
422
~StringOneofFieldGenerator()423 StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
424
425 void StringOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer,bool is_inline) const426 GenerateInlineAccessorDefinitions(io::Printer* printer,
427 bool is_inline) const {
428 map<string, string> variables(variables_);
429 variables["inline"] = is_inline ? "inline" : "";
430 if (SupportsArenas(descriptor_)) {
431 printer->Print(variables,
432 "$inline$ const ::std::string& $classname$::$name$() const {\n"
433 " // @@protoc_insertion_point(field_get:$full_name$)\n"
434 " if (has_$name$()) {\n"
435 " return $oneof_prefix$$name$_.Get($default_variable$);\n"
436 " }\n"
437 " return *$default_variable$;\n"
438 "}\n"
439 "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
440 " if (!has_$name$()) {\n"
441 " clear_$oneof_name$();\n"
442 " set_has_$name$();\n"
443 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
444 " }\n"
445 " $oneof_prefix$$name$_.Set($default_variable$, value,\n"
446 " GetArenaNoVirtual());\n"
447 " // @@protoc_insertion_point(field_set:$full_name$)\n"
448 "}\n"
449 "$inline$ void $classname$::set_$name$(const char* value) {\n"
450 " if (!has_$name$()) {\n"
451 " clear_$oneof_name$();\n"
452 " set_has_$name$();\n"
453 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
454 " }\n"
455 " $oneof_prefix$$name$_.Set($default_variable$,\n"
456 " $string_piece$(value), GetArenaNoVirtual());\n"
457 " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
458 "}\n"
459 "$inline$ "
460 "void $classname$::set_$name$(const $pointer_type$* value,\n"
461 " size_t size) {\n"
462 " if (!has_$name$()) {\n"
463 " clear_$oneof_name$();\n"
464 " set_has_$name$();\n"
465 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
466 " }\n"
467 " $oneof_prefix$$name$_.Set($default_variable$, $string_piece$(\n"
468 " reinterpret_cast<const char*>(value), size),\n"
469 " GetArenaNoVirtual());\n"
470 " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
471 "}\n"
472 "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
473 " if (!has_$name$()) {\n"
474 " clear_$oneof_name$();\n"
475 " set_has_$name$();\n"
476 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
477 " }\n"
478 " return $oneof_prefix$$name$_.Mutable($default_variable$,\n"
479 " GetArenaNoVirtual());\n"
480 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
481 "}\n"
482 "$inline$ ::std::string* $classname$::$release_name$() {\n"
483 " // @@protoc_insertion_point(field_release:$full_name$)\n"
484 " if (has_$name$()) {\n"
485 " clear_has_$oneof_name$();\n"
486 " return $oneof_prefix$$name$_.Release($default_variable$,\n"
487 " GetArenaNoVirtual());\n"
488 " } else {\n"
489 " return NULL;\n"
490 " }\n"
491 "}\n"
492 "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
493 " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
494 " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
495 " if (has_$name$()) {\n"
496 " clear_has_$oneof_name$();\n"
497 " return $oneof_prefix$$name$_.UnsafeArenaRelease(\n"
498 " $default_variable$, GetArenaNoVirtual());\n"
499 " } else {\n"
500 " return NULL;\n"
501 " }\n"
502 "}\n"
503 "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
504 " if (!has_$name$()) {\n"
505 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
506 " }\n"
507 " clear_$oneof_name$();\n"
508 " if ($name$ != NULL) {\n"
509 " set_has_$name$();\n"
510 " $oneof_prefix$$name$_.SetAllocated($default_variable$, $name$,\n"
511 " GetArenaNoVirtual());\n"
512 " }\n"
513 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
514 "}\n"
515 "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
516 "::std::string* $name$) {\n"
517 " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
518 " if (!has_$name$()) {\n"
519 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
520 " }\n"
521 " clear_$oneof_name$();\n"
522 " if ($name$) {\n"
523 " set_has_$name$();\n"
524 " $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, "
525 "$name$, GetArenaNoVirtual());\n"
526 " }\n"
527 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
528 "$full_name$)\n"
529 "}\n");
530 } else {
531 // No-arena case.
532 printer->Print(variables,
533 "$inline$ const ::std::string& $classname$::$name$() const {\n"
534 " // @@protoc_insertion_point(field_get:$full_name$)\n"
535 " if (has_$name$()) {\n"
536 " return $oneof_prefix$$name$_.GetNoArena($default_variable$);\n"
537 " }\n"
538 " return *$default_variable$;\n"
539 "}\n"
540 "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
541 " // @@protoc_insertion_point(field_set:$full_name$)\n"
542 " if (!has_$name$()) {\n"
543 " clear_$oneof_name$();\n"
544 " set_has_$name$();\n"
545 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
546 " }\n"
547 " $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
548 " // @@protoc_insertion_point(field_set:$full_name$)\n"
549 "}\n"
550 "$inline$ void $classname$::set_$name$(const char* value) {\n"
551 " if (!has_$name$()) {\n"
552 " clear_$oneof_name$();\n"
553 " set_has_$name$();\n"
554 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
555 " }\n"
556 " $oneof_prefix$$name$_.SetNoArena($default_variable$,\n"
557 " $string_piece$(value));\n"
558 " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
559 "}\n"
560 "$inline$ "
561 "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
562 " if (!has_$name$()) {\n"
563 " clear_$oneof_name$();\n"
564 " set_has_$name$();\n"
565 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
566 " }\n"
567 " $oneof_prefix$$name$_.SetNoArena($default_variable$, $string_piece$(\n"
568 " reinterpret_cast<const char*>(value), size));\n"
569 " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
570 "}\n"
571 "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
572 " if (!has_$name$()) {\n"
573 " clear_$oneof_name$();\n"
574 " set_has_$name$();\n"
575 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
576 " }\n"
577 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
578 " return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
579 "}\n"
580 "$inline$ ::std::string* $classname$::$release_name$() {\n"
581 " // @@protoc_insertion_point(field_release:$full_name$)\n"
582 " if (has_$name$()) {\n"
583 " clear_has_$oneof_name$();\n"
584 " return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
585 " } else {\n"
586 " return NULL;\n"
587 " }\n"
588 "}\n"
589 "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
590 " if (!has_$name$()) {\n"
591 " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
592 " }\n"
593 " clear_$oneof_name$();\n"
594 " if ($name$ != NULL) {\n"
595 " set_has_$name$();\n"
596 " $oneof_prefix$$name$_.SetAllocatedNoArena($default_variable$,\n"
597 " $name$);\n"
598 " }\n"
599 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
600 "}\n");
601 }
602 }
603
604 void StringOneofFieldGenerator::
GenerateClearingCode(io::Printer * printer) const605 GenerateClearingCode(io::Printer* printer) const {
606 map<string, string> variables(variables_);
607 if (dependent_field_) {
608 variables["this_message"] = DependentBaseDownCast();
609 // This clearing code may be in the dependent base class. If the default
610 // value is an empty string, then the $default_variable$ is a global
611 // singleton. If the default is not empty, we need to down-cast to get the
612 // default value's global singleton instance. See SetStringVariables() for
613 // possible values of default_variable.
614 if (!descriptor_->default_value_string().empty()) {
615 variables["default_variable"] =
616 DependentBaseDownCast() + variables["default_variable"];
617 }
618 } else {
619 variables["this_message"] = "";
620 }
621 if (SupportsArenas(descriptor_)) {
622 printer->Print(variables,
623 "$this_message$$oneof_prefix$$name$_.Destroy($default_variable$,\n"
624 " $this_message$GetArenaNoVirtual());\n");
625 } else {
626 printer->Print(variables,
627 "$this_message$$oneof_prefix$$name$_."
628 "DestroyNoArena($default_variable$);\n");
629 }
630 }
631
632 void StringOneofFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const633 GenerateSwappingCode(io::Printer* printer) const {
634 // Don't print any swapping code. Swapping the union will swap this field.
635 }
636
637 void StringOneofFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const638 GenerateConstructorCode(io::Printer* printer) const {
639 printer->Print(variables_,
640 " $classname$_default_oneof_instance_->$name$_.UnsafeSetDefault("
641 "$default_variable$);\n");
642 }
643
644 void StringOneofFieldGenerator::
GenerateDestructorCode(io::Printer * printer) const645 GenerateDestructorCode(io::Printer* printer) const {
646 if (SupportsArenas(descriptor_)) {
647 printer->Print(variables_,
648 "if (has_$name$()) {\n"
649 " $oneof_prefix$$name$_.Destroy($default_variable$,\n"
650 " GetArenaNoVirtual());\n"
651 "}\n");
652 } else {
653 printer->Print(variables_,
654 "if (has_$name$()) {\n"
655 " $oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n"
656 "}\n");
657 }
658 }
659
660 void StringOneofFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const661 GenerateMergeFromCodedStream(io::Printer* printer) const {
662 printer->Print(variables_,
663 "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
664 " input, this->mutable_$name$()));\n");
665
666 if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
667 GenerateUtf8CheckCodeForString(
668 descriptor_, options_, true, variables_,
669 "this->$name$().data(), this->$name$().length(),\n", printer);
670 }
671 }
672
673
674 // ===================================================================
675
RepeatedStringFieldGenerator(const FieldDescriptor * descriptor,const Options & options)676 RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(
677 const FieldDescriptor* descriptor, const Options& options)
678 : FieldGenerator(options), descriptor_(descriptor) {
679 SetStringVariables(descriptor, &variables_, options);
680 }
681
~RepeatedStringFieldGenerator()682 RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {}
683
684 void RepeatedStringFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const685 GeneratePrivateMembers(io::Printer* printer) const {
686 printer->Print(variables_,
687 "::google::protobuf::RepeatedPtrField< ::std::string> $name$_;\n");
688 }
689
690 void RepeatedStringFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const691 GenerateAccessorDeclarations(io::Printer* printer) const {
692 // See comment above about unknown ctypes.
693 bool unknown_ctype =
694 descriptor_->options().ctype() != EffectiveStringCType(descriptor_);
695
696 if (unknown_ctype) {
697 printer->Outdent();
698 printer->Print(
699 " private:\n"
700 " // Hidden due to unknown ctype option.\n");
701 printer->Indent();
702 }
703
704 printer->Print(variables_,
705 "$deprecated_attr$const ::std::string& $name$(int index) const;\n"
706 "$deprecated_attr$::std::string* mutable_$name$(int index);\n"
707 "$deprecated_attr$void set_$name$(int index, const ::std::string& value);\n"
708 "$deprecated_attr$void set_$name$(int index, const char* value);\n"
709 ""
710 "$deprecated_attr$void set_$name$("
711 "int index, const $pointer_type$* value, size_t size);\n"
712 "$deprecated_attr$::std::string* add_$name$();\n"
713 "$deprecated_attr$void add_$name$(const ::std::string& value);\n"
714 "$deprecated_attr$void add_$name$(const char* value);\n"
715 "$deprecated_attr$void add_$name$(const $pointer_type$* value, size_t size)"
716 ";\n");
717
718 printer->Print(variables_,
719 "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() "
720 "const;\n"
721 "$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
722 ";\n");
723
724 if (unknown_ctype) {
725 printer->Outdent();
726 printer->Print(" public:\n");
727 printer->Indent();
728 }
729 }
730
731 void RepeatedStringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer,bool is_inline) const732 GenerateInlineAccessorDefinitions(io::Printer* printer,
733 bool is_inline) const {
734 map<string, string> variables(variables_);
735 variables["inline"] = is_inline ? "inline" : "";
736 printer->Print(variables,
737 "$inline$ const ::std::string& $classname$::$name$(int index) const {\n"
738 " // @@protoc_insertion_point(field_get:$full_name$)\n"
739 " return $name$_.$cppget$(index);\n"
740 "}\n"
741 "$inline$ ::std::string* $classname$::mutable_$name$(int index) {\n"
742 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
743 " return $name$_.Mutable(index);\n"
744 "}\n"
745 "$inline$ void $classname$::set_$name$(int index, const ::std::string& value) {\n"
746 " // @@protoc_insertion_point(field_set:$full_name$)\n"
747 " $name$_.Mutable(index)->assign(value);\n"
748 "}\n"
749 "$inline$ void $classname$::set_$name$(int index, const char* value) {\n"
750 " $name$_.Mutable(index)->assign(value);\n"
751 " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
752 "}\n"
753 "$inline$ void "
754 "$classname$::set_$name$"
755 "(int index, const $pointer_type$* value, size_t size) {\n"
756 " $name$_.Mutable(index)->assign(\n"
757 " reinterpret_cast<const char*>(value), size);\n"
758 " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
759 "}\n"
760 "$inline$ ::std::string* $classname$::add_$name$() {\n"
761 " // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
762 " return $name$_.Add();\n"
763 "}\n"
764 "$inline$ void $classname$::add_$name$(const ::std::string& value) {\n"
765 " $name$_.Add()->assign(value);\n"
766 " // @@protoc_insertion_point(field_add:$full_name$)\n"
767 "}\n"
768 "$inline$ void $classname$::add_$name$(const char* value) {\n"
769 " $name$_.Add()->assign(value);\n"
770 " // @@protoc_insertion_point(field_add_char:$full_name$)\n"
771 "}\n"
772 "$inline$ void "
773 "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
774 " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
775 " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
776 "}\n");
777 printer->Print(variables,
778 "$inline$ const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
779 "$classname$::$name$() const {\n"
780 " // @@protoc_insertion_point(field_list:$full_name$)\n"
781 " return $name$_;\n"
782 "}\n"
783 "$inline$ ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
784 "$classname$::mutable_$name$() {\n"
785 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
786 " return &$name$_;\n"
787 "}\n");
788 }
789
790 void RepeatedStringFieldGenerator::
GenerateClearingCode(io::Printer * printer) const791 GenerateClearingCode(io::Printer* printer) const {
792 printer->Print(variables_, "$name$_.Clear();\n");
793 }
794
795 void RepeatedStringFieldGenerator::
GenerateMergingCode(io::Printer * printer) const796 GenerateMergingCode(io::Printer* printer) const {
797 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
798 }
799
800 void RepeatedStringFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const801 GenerateSwappingCode(io::Printer* printer) const {
802 printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
803 }
804
805 void RepeatedStringFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const806 GenerateConstructorCode(io::Printer* printer) const {
807 // Not needed for repeated fields.
808 }
809
810 void RepeatedStringFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const811 GenerateMergeFromCodedStream(io::Printer* printer) const {
812 printer->Print(variables_,
813 "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
814 " input, this->add_$name$()));\n");
815 if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
816 GenerateUtf8CheckCodeForString(
817 descriptor_, options_, true, variables_,
818 "this->$name$(this->$name$_size() - 1).data(),\n"
819 "this->$name$(this->$name$_size() - 1).length(),\n",
820 printer);
821 }
822 }
823
824 void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const825 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
826 printer->Print(variables_,
827 "for (int i = 0; i < this->$name$_size(); i++) {\n");
828 printer->Indent();
829 if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
830 GenerateUtf8CheckCodeForString(
831 descriptor_, options_, false, variables_,
832 "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
833 }
834 printer->Outdent();
835 printer->Print(variables_,
836 " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
837 " $number$, this->$name$(i), output);\n"
838 "}\n");
839 }
840
841 void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const842 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
843 printer->Print(variables_,
844 "for (int i = 0; i < this->$name$_size(); i++) {\n");
845 printer->Indent();
846 if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
847 GenerateUtf8CheckCodeForString(
848 descriptor_, options_, false, variables_,
849 "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
850 }
851 printer->Outdent();
852 printer->Print(variables_,
853 " target = ::google::protobuf::internal::WireFormatLite::\n"
854 " Write$declared_type$ToArray($number$, this->$name$(i), target);\n"
855 "}\n");
856 }
857
858 void RepeatedStringFieldGenerator::
GenerateByteSize(io::Printer * printer) const859 GenerateByteSize(io::Printer* printer) const {
860 printer->Print(variables_,
861 "total_size += $tag_size$ * this->$name$_size();\n"
862 "for (int i = 0; i < this->$name$_size(); i++) {\n"
863 " total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
864 " this->$name$(i));\n"
865 "}\n");
866 }
867
868 } // namespace cpp
869 } // namespace compiler
870 } // namespace protobuf
871 } // namespace google
872