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_message_field.h>
36 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
37 #include <google/protobuf/io/printer.h>
38 #include <google/protobuf/stubs/strutil.h>
39
40 namespace google {
41 namespace protobuf {
42 namespace compiler {
43 namespace cpp {
44
45 namespace {
46
SetMessageVariables(const FieldDescriptor * descriptor,map<string,string> * variables,const Options & options)47 void SetMessageVariables(const FieldDescriptor* descriptor,
48 map<string, string>* variables,
49 const Options& options) {
50 SetCommonFieldVariables(descriptor, variables, options);
51 (*variables)["type"] = FieldMessageTypeName(descriptor);
52 if (descriptor->options().weak() || !descriptor->containing_oneof()) {
53 (*variables)["non_null_ptr_to_name"] =
54 StrCat("this->", (*variables)["name"], "_");
55 }
56 (*variables)["stream_writer"] =
57 (*variables)["declared_type"] +
58 (HasFastArraySerialization(descriptor->message_type()->file(), options)
59 ? "MaybeToArray"
60 : "");
61 // NOTE: Escaped here to unblock proto1->proto2 migration.
62 // TODO(liujisi): Extend this to apply for other conflicting methods.
63 (*variables)["release_name"] =
64 SafeFunctionName(descriptor->containing_type(),
65 descriptor, "release_");
66 (*variables)["full_name"] = descriptor->full_name();
67 if (options.proto_h && IsFieldDependent(descriptor)) {
68 (*variables)["dependent_type"] = "T::" + DependentTypeName(descriptor);
69 (*variables)["dependent_typename"] =
70 "typename T::" + DependentTypeName(descriptor);
71 } else {
72 (*variables)["dependent_type"] = FieldMessageTypeName(descriptor);
73 (*variables)["dependent_typename"] = FieldMessageTypeName(descriptor);
74 }
75 }
76
77 } // namespace
78
79 // ===================================================================
80
MessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options)81 MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
82 const Options& options)
83 : FieldGenerator(options),
84 descriptor_(descriptor),
85 dependent_field_(options.proto_h && IsFieldDependent(descriptor)) {
86 SetMessageVariables(descriptor, &variables_, options);
87 }
88
~MessageFieldGenerator()89 MessageFieldGenerator::~MessageFieldGenerator() {}
90
91 void MessageFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const92 GeneratePrivateMembers(io::Printer* printer) const {
93 printer->Print(variables_, "$type$* $name$_;\n");
94 }
95
96 void MessageFieldGenerator::
GenerateGetterDeclaration(io::Printer * printer) const97 GenerateGetterDeclaration(io::Printer* printer) const {
98 printer->Print(variables_,
99 "$deprecated_attr$const $type$& $name$() const;\n");
100 }
101
102 void MessageFieldGenerator::
GenerateDependentAccessorDeclarations(io::Printer * printer) const103 GenerateDependentAccessorDeclarations(io::Printer* printer) const {
104 if (!dependent_field_) {
105 return;
106 }
107 // Arena manipulation code is out-of-line in the derived message class.
108 printer->Print(variables_,
109 "$deprecated_attr$$type$* mutable_$name$();\n"
110 "$deprecated_attr$$type$* $release_name$();\n"
111 "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n");
112 }
113
114 void MessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const115 GenerateAccessorDeclarations(io::Printer* printer) const {
116 if (SupportsArenas(descriptor_)) {
117 printer->Print(variables_,
118 "private:\n"
119 "void _slow_mutable_$name$();\n");
120 if (SupportsArenas(descriptor_->message_type())) {
121 printer->Print(variables_,
122 "void _slow_set_allocated_$name$(\n"
123 " ::google::protobuf::Arena* message_arena, $type$** $name$);\n");
124 }
125 printer->Print(variables_,
126 "$type$* _slow_$release_name$();\n"
127 "public:\n");
128 }
129 GenerateGetterDeclaration(printer);
130 if (!dependent_field_) {
131 printer->Print(variables_,
132 "$deprecated_attr$$type$* mutable_$name$();\n"
133 "$deprecated_attr$$type$* $release_name$();\n"
134 "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n");
135 }
136 if (SupportsArenas(descriptor_)) {
137 printer->Print(variables_,
138 "$deprecated_attr$$type$* unsafe_arena_release_$name$();\n"
139 "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n"
140 " $type$* $name$);\n");
141 }
142 }
143
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const144 void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
145 io::Printer* printer) const {
146 if (SupportsArenas(descriptor_)) {
147 printer->Print(variables_,
148 "void $classname$::_slow_mutable_$name$() {\n");
149 if (SupportsArenas(descriptor_->message_type())) {
150 printer->Print(variables_,
151 " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
152 " GetArenaNoVirtual());\n");
153 } else {
154 printer->Print(variables_,
155 " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
156 " GetArenaNoVirtual());\n");
157 }
158 printer->Print(variables_,
159 "}\n"
160 "$type$* $classname$::_slow_$release_name$() {\n"
161 " if ($name$_ == NULL) {\n"
162 " return NULL;\n"
163 " } else {\n"
164 " $type$* temp = new $type$;\n"
165 " temp->MergeFrom(*$name$_);\n"
166 " $name$_ = NULL;\n"
167 " return temp;\n"
168 " }\n"
169 "}\n"
170 "$type$* $classname$::unsafe_arena_release_$name$() {\n"
171 " // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
172 " $clear_hasbit$\n"
173 " $type$* temp = $name$_;\n"
174 " $name$_ = NULL;\n"
175 " return temp;\n"
176 "}\n");
177 if (SupportsArenas(descriptor_->message_type())) {
178 // NOTE: the same logic is mirrored in weak_message_field.cc. Any
179 // arena-related semantics changes should be made in both places.
180 printer->Print(variables_,
181 "void $classname$::_slow_set_allocated_$name$(\n"
182 " ::google::protobuf::Arena* message_arena, $type$** $name$) {\n"
183 " if (message_arena != NULL && \n"
184 " ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n"
185 " message_arena->Own(*$name$);\n"
186 " } else if (message_arena !=\n"
187 " ::google::protobuf::Arena::GetArena(*$name$)) {\n"
188 " $type$* new_$name$ = \n"
189 " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
190 " message_arena);\n"
191 " new_$name$->CopyFrom(**$name$);\n"
192 " *$name$ = new_$name$;\n"
193 " }\n"
194 "}\n");
195 }
196 printer->Print(variables_,
197 "void $classname$::unsafe_arena_set_allocated_$name$(\n"
198 " $type$* $name$) {\n"
199 // If we're not on an arena, free whatever we were holding before.
200 // (If we are on arena, we can just forget the earlier pointer.)
201 " if (GetArenaNoVirtual() == NULL) {\n"
202 " delete $name$_;\n"
203 " }\n"
204 " $name$_ = $name$;\n"
205 " if ($name$) {\n"
206 " $set_hasbit$\n"
207 " } else {\n"
208 " $clear_hasbit$\n"
209 " }\n"
210 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
211 ":$full_name$)\n"
212 "}\n");
213 }
214 }
215
216 void MessageFieldGenerator::
GenerateDependentInlineAccessorDefinitions(io::Printer * printer) const217 GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
218 if (!dependent_field_) {
219 return;
220 }
221
222 map<string, string> variables(variables_);
223 // For the CRTP base class, all mutation methods are dependent, and so
224 // they must be in the header.
225 variables["dependent_classname"] =
226 DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
227 variables["this_message"] = DependentBaseDownCast();
228 if (!variables["set_hasbit"].empty()) {
229 variables["set_hasbit"] =
230 variables["this_message"] + variables["set_hasbit"];
231 }
232 if (!variables["clear_hasbit"].empty()) {
233 variables["clear_hasbit"] =
234 variables["this_message"] + variables["clear_hasbit"];
235 }
236
237 if (SupportsArenas(descriptor_)) {
238 printer->Print(variables,
239 "template <class T>\n"
240 "inline $type$* $dependent_classname$::mutable_$name$() {\n"
241 " $set_hasbit$\n"
242 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
243 " if ($name$_ == NULL) {\n"
244 " $this_message$_slow_mutable_$name$();\n"
245 " }\n"
246 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
247 " return $name$_;\n"
248 "}\n"
249 "template <class T>\n"
250 "inline $type$* $dependent_classname$::$release_name$() {\n"
251 " // @@protoc_insertion_point(field_release:$full_name$)\n"
252 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
253 " $clear_hasbit$\n"
254 " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
255 " return $this_message$_slow_$release_name$();\n"
256 " } else {\n"
257 " $dependent_typename$* temp = $name$_;\n"
258 " $name$_ = NULL;\n"
259 " return temp;\n"
260 " }\n"
261 "}\n"
262 "template <class T>\n"
263 "inline void $dependent_classname$::"
264 "set_allocated_$name$($type$* $name$) {\n"
265 " ::google::protobuf::Arena* message_arena = $this_message$GetArenaNoVirtual();\n"
266 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
267 " if (message_arena == NULL) {\n"
268 " delete $name$_;\n"
269 " }\n"
270 " if ($name$ != NULL) {\n");
271 if (SupportsArenas(descriptor_->message_type())) {
272 // If we're on an arena and the incoming message is not, simply Own() it
273 // rather than copy to the arena -- either way we need a heap dealloc,
274 // so we might as well defer it. Otherwise, if incoming message is on a
275 // different ownership domain (specific arena, or the heap) than we are,
276 // copy to our arena (or heap, as the case may be).
277 printer->Print(variables,
278 " $this_message$_slow_set_allocated_$name$(message_arena, "
279 "&$name$);\n");
280 } else {
281 printer->Print(variables,
282 " if (message_arena != NULL) {\n"
283 " message_arena->Own($name$);\n"
284 " }\n");
285 }
286 printer->Print(variables,
287 " }\n"
288 " $name$_ = $name$;\n"
289 " if ($name$) {\n"
290 " $set_hasbit$\n"
291 " } else {\n"
292 " $clear_hasbit$\n"
293 " }\n"
294 // TODO(dlj): move insertion points to message class.
295 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
296 "}\n");
297 } else {
298 printer->Print(variables,
299 "template <class T>\n"
300 "inline $type$* $dependent_classname$::mutable_$name$() {\n"
301 " $set_hasbit$\n"
302 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
303 " if ($name$_ == NULL) {\n"
304 " $name$_ = new $dependent_typename$;\n"
305 " }\n"
306 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
307 " return $name$_;\n"
308 "}\n"
309 "template <class T>\n"
310 "inline $type$* $dependent_classname$::$release_name$() {\n"
311 " // @@protoc_insertion_point(field_release:$full_name$)\n"
312 " $clear_hasbit$\n"
313 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
314 " $dependent_typename$* temp = $name$_;\n"
315 " $name$_ = NULL;\n"
316 " return temp;\n"
317 "}\n"
318 "template <class T>\n"
319 "inline void $dependent_classname$::"
320 "set_allocated_$name$($type$* $name$) {\n"
321 " $dependent_typename$*& $name$_ = $this_message$$name$_;\n"
322 " delete $name$_;\n");
323
324 if (SupportsArenas(descriptor_->message_type())) {
325 printer->Print(variables,
326 " if ($name$ != NULL && static_cast< $dependent_typename$* >($name$)"
327 "->GetArena() != NULL) {\n"
328 " $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
329 " new_$name$->CopyFrom(*$name$);\n"
330 " $name$ = new_$name$;\n"
331 " }\n");
332 }
333
334 printer->Print(variables,
335 " $name$_ = $name$;\n"
336 " if ($name$) {\n"
337 " $set_hasbit$\n"
338 " } else {\n"
339 " $clear_hasbit$\n"
340 " }\n"
341 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
342 "}\n");
343 }
344 }
345
346 void MessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer,bool is_inline) const347 GenerateInlineAccessorDefinitions(io::Printer* printer,
348 bool is_inline) const {
349 map<string, string> variables(variables_);
350 variables["inline"] = is_inline ? "inline " : "";
351 printer->Print(variables,
352 "$inline$const $type$& $classname$::$name$() const {\n"
353 " // @@protoc_insertion_point(field_get:$full_name$)\n");
354
355 PrintHandlingOptionalStaticInitializers(
356 variables, descriptor_->file(), options_, printer,
357 // With static initializers.
358 " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
359 // Without.
360 " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
361 printer->Print(variables, "}\n");
362
363 if (dependent_field_) {
364 return;
365 }
366
367 if (SupportsArenas(descriptor_)) {
368 printer->Print(variables,
369 "$inline$"
370 "$type$* $classname$::mutable_$name$() {\n"
371 " $set_hasbit$\n"
372 " if ($name$_ == NULL) {\n"
373 " _slow_mutable_$name$();\n"
374 " }\n"
375 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
376 " return $name$_;\n"
377 "}\n"
378 "$inline$"
379 "$type$* $classname$::$release_name$() {\n"
380 " // @@protoc_insertion_point(field_release:$full_name$)\n"
381 " $clear_hasbit$\n"
382 " if (GetArenaNoVirtual() != NULL) {\n"
383 " return _slow_$release_name$();\n"
384 " } else {\n"
385 " $type$* temp = $name$_;\n"
386 " $name$_ = NULL;\n"
387 " return temp;\n"
388 " }\n"
389 "}\n"
390 "$inline$ "
391 "void $classname$::set_allocated_$name$($type$* $name$) {\n"
392 " ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n"
393 " if (message_arena == NULL) {\n"
394 " delete $name$_;\n"
395 " }\n"
396 " if ($name$ != NULL) {\n");
397 if (SupportsArenas(descriptor_->message_type())) {
398 // If we're on an arena and the incoming message is not, simply Own() it
399 // rather than copy to the arena -- either way we need a heap dealloc,
400 // so we might as well defer it. Otherwise, if incoming message is on a
401 // different ownership domain (specific arena, or the heap) than we are,
402 // copy to our arena (or heap, as the case may be).
403 printer->Print(variables,
404 " _slow_set_allocated_$name$(message_arena, &$name$);\n");
405 } else {
406 printer->Print(variables,
407 " if (message_arena != NULL) {\n"
408 " message_arena->Own($name$);\n"
409 " }\n");
410 }
411 printer->Print(variables,
412 " }\n"
413 " $name$_ = $name$;\n"
414 " if ($name$) {\n"
415 " $set_hasbit$\n"
416 " } else {\n"
417 " $clear_hasbit$\n"
418 " }\n"
419 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
420 "}\n");
421 } else {
422 printer->Print(variables,
423 "$inline$"
424 "$type$* $classname$::mutable_$name$() {\n"
425 " $set_hasbit$\n"
426 " if ($name$_ == NULL) {\n"
427 " $name$_ = new $type$;\n"
428 " }\n"
429 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
430 " return $name$_;\n"
431 "}\n"
432 "$inline$"
433 "$type$* $classname$::$release_name$() {\n"
434 " // @@protoc_insertion_point(field_release:$full_name$)\n"
435 " $clear_hasbit$\n"
436 " $type$* temp = $name$_;\n"
437 " $name$_ = NULL;\n"
438 " return temp;\n"
439 "}\n"
440 "$inline$"
441 "void $classname$::set_allocated_$name$($type$* $name$) {\n"
442 " delete $name$_;\n");
443
444 if (SupportsArenas(descriptor_->message_type())) {
445 printer->Print(variables,
446 " if ($name$ != NULL && $name$->GetArena() != NULL) {\n"
447 " $type$* new_$name$ = new $type$;\n"
448 " new_$name$->CopyFrom(*$name$);\n"
449 " $name$ = new_$name$;\n"
450 " }\n");
451 }
452
453 printer->Print(variables,
454 " $name$_ = $name$;\n"
455 " if ($name$) {\n"
456 " $set_hasbit$\n"
457 " } else {\n"
458 " $clear_hasbit$\n"
459 " }\n"
460 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
461 "}\n");
462 }
463 }
464
465 void MessageFieldGenerator::
GenerateClearingCode(io::Printer * printer) const466 GenerateClearingCode(io::Printer* printer) const {
467 map<string, string> variables(variables_);
468 variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
469 if (!HasFieldPresence(descriptor_->file())) {
470 // If we don't have has-bits, message presence is indicated only by ptr !=
471 // NULL. Thus on clear, we need to delete the object.
472 printer->Print(variables,
473 "if ($this_message$GetArenaNoVirtual() == NULL && "
474 "$this_message$$name$_ != NULL) delete $this_message$$name$_;\n"
475 "$this_message$$name$_ = NULL;\n");
476 } else {
477 printer->Print(variables,
478 "if ($this_message$$name$_ != NULL) $this_message$$name$_->"
479 "$dependent_type$::Clear();\n");
480 }
481 }
482
483 void MessageFieldGenerator::
GenerateMergingCode(io::Printer * printer) const484 GenerateMergingCode(io::Printer* printer) const {
485 printer->Print(variables_,
486 "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
487 }
488
489 void MessageFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const490 GenerateSwappingCode(io::Printer* printer) const {
491 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
492 }
493
494 void MessageFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const495 GenerateConstructorCode(io::Printer* printer) const {
496 printer->Print(variables_, "$name$_ = NULL;\n");
497 }
498
499 void MessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const500 GenerateMergeFromCodedStream(io::Printer* printer) const {
501 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
502 printer->Print(variables_,
503 "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
504 " input, mutable_$name$()));\n");
505 } else {
506 printer->Print(variables_,
507 "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
508 " $number$, input, mutable_$name$()));\n");
509 }
510 }
511
512 void MessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const513 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
514 printer->Print(variables_,
515 "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
516 " $number$, *$non_null_ptr_to_name$, output);\n");
517 }
518
519 void MessageFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const520 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
521 printer->Print(variables_,
522 "target = ::google::protobuf::internal::WireFormatLite::\n"
523 " Write$declared_type$NoVirtualToArray(\n"
524 " $number$, *$non_null_ptr_to_name$, target);\n");
525 }
526
527 void MessageFieldGenerator::
GenerateByteSize(io::Printer * printer) const528 GenerateByteSize(io::Printer* printer) const {
529 printer->Print(variables_,
530 "total_size += $tag_size$ +\n"
531 " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
532 " *$non_null_ptr_to_name$);\n");
533 }
534
535 // ===================================================================
536
537 MessageOneofFieldGenerator::
MessageOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)538 MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
539 const Options& options)
540 : MessageFieldGenerator(descriptor, options),
541 dependent_base_(options.proto_h) {
542 SetCommonOneofFieldVariables(descriptor, &variables_);
543 }
544
~MessageOneofFieldGenerator()545 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
546
547
548 void MessageOneofFieldGenerator::
GenerateDependentAccessorDeclarations(io::Printer * printer) const549 GenerateDependentAccessorDeclarations(io::Printer* printer) const {
550 // Oneof field getters must be dependent as they call default_instance().
551 // Otherwise, the logic is the same as MessageFields.
552 if (!dependent_field_) {
553 return;
554 }
555 printer->Print(variables_,
556 "$deprecated_attr$const $type$& $name$() const;\n");
557 MessageFieldGenerator::GenerateDependentAccessorDeclarations(printer);
558 }
559
560 void MessageOneofFieldGenerator::
GenerateGetterDeclaration(io::Printer * printer) const561 GenerateGetterDeclaration(io::Printer* printer) const {
562 // Oneof field getters must be dependent as they call default_instance().
563 // Unlike MessageField, this means there is no (non-dependent) getter to
564 // generate.
565 if (dependent_field_) {
566 return;
567 }
568 printer->Print(variables_,
569 "$deprecated_attr$const $type$& $name$() const;\n");
570 }
571
572 void MessageOneofFieldGenerator::
GenerateDependentInlineAccessorDefinitions(io::Printer * printer) const573 GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
574 // For the CRTP base class, all mutation methods are dependent, and so
575 // they must be in the header.
576 if (!dependent_base_) {
577 return;
578 }
579 map<string, string> variables(variables_);
580 variables["inline"] = "inline ";
581 variables["dependent_classname"] =
582 DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
583 variables["this_message"] = "reinterpret_cast<T*>(this)->";
584 // Const message access is needed for the dependent getter.
585 variables["this_const_message"] = "reinterpret_cast<const T*>(this)->";
586 variables["tmpl"] = "template <class T>\n";
587 variables["field_member"] = variables["this_message"] +
588 variables["oneof_prefix"] + variables["name"] +
589 "_";
590 InternalGenerateInlineAccessorDefinitions(variables, printer);
591 }
592
593 void MessageOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer,bool is_inline) const594 GenerateInlineAccessorDefinitions(io::Printer* printer,
595 bool is_inline) const {
596 if (dependent_base_) {
597 return;
598 }
599 map<string, string> variables(variables_);
600 variables["inline"] = is_inline ? "inline " : "";
601 variables["dependent_classname"] = variables["classname"];
602 variables["this_message"] = "";
603 variables["this_const_message"] = "";
604 variables["tmpl"] = "";
605 variables["field_member"] =
606 variables["oneof_prefix"] + variables["name"] + "_";
607 variables["dependent_type"] = variables["type"];
608 InternalGenerateInlineAccessorDefinitions(variables, printer);
609 }
610
611 void MessageOneofFieldGenerator::
GenerateNonInlineAccessorDefinitions(io::Printer * printer) const612 GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
613 map<string, string> variables(variables_);
614 variables["field_member"] =
615 variables["oneof_prefix"] + variables["name"] + "_";
616
617 //printer->Print(variables,
618 }
619
620 void MessageOneofFieldGenerator::
InternalGenerateInlineAccessorDefinitions(const map<string,string> & variables,io::Printer * printer) const621 InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
622 io::Printer* printer) const {
623 printer->Print(variables,
624 "$tmpl$"
625 "$inline$ "
626 "const $type$& $dependent_classname$::$name$() const {\n"
627 " // @@protoc_insertion_point(field_get:$full_name$)\n"
628 " return $this_const_message$has_$name$()\n"
629 " ? *$this_const_message$$oneof_prefix$$name$_\n"
630 " : $dependent_type$::default_instance();\n"
631 "}\n");
632
633 if (SupportsArenas(descriptor_)) {
634 printer->Print(variables,
635 "$tmpl$"
636 "$inline$"
637 "$type$* $dependent_classname$::mutable_$name$() {\n"
638 " if (!$this_message$has_$name$()) {\n"
639 " $this_message$clear_$oneof_name$();\n"
640 " $this_message$set_has_$name$();\n");
641 if (SupportsArenas(descriptor_->message_type())) {
642 printer->Print(variables,
643 " $field_member$ = \n"
644 " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
645 " $this_message$GetArenaNoVirtual());\n");
646 } else {
647 printer->Print(variables,
648 " $this_message$$oneof_prefix$$name$_ = \n"
649 " ::google::protobuf::Arena::Create< $dependent_typename$ >(\n"
650 " $this_message$GetArenaNoVirtual());\n");
651 }
652 printer->Print(variables,
653 " }\n"
654 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
655 " return $field_member$;\n"
656 "}\n"
657 "$tmpl$"
658 "$inline$"
659 "$type$* $dependent_classname$::$release_name$() {\n"
660 " // @@protoc_insertion_point(field_release:$full_name$)\n"
661 " if ($this_message$has_$name$()) {\n"
662 " $this_message$clear_has_$oneof_name$();\n"
663 " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
664 // N.B.: safe to use the underlying field pointer here because we are sure
665 // that it is non-NULL (because has_$name$() returned true).
666 " $dependent_typename$* temp = new $dependent_typename$;\n"
667 " temp->MergeFrom(*$field_member$);\n"
668 " $field_member$ = NULL;\n"
669 " return temp;\n"
670 " } else {\n"
671 " $dependent_typename$* temp = $field_member$;\n"
672 " $field_member$ = NULL;\n"
673 " return temp;\n"
674 " }\n"
675 " } else {\n"
676 " return NULL;\n"
677 " }\n"
678 "}\n"
679 "$tmpl$"
680 "$inline$"
681 "void $dependent_classname$::"
682 "set_allocated_$name$($type$* $name$) {\n"
683 " $this_message$clear_$oneof_name$();\n"
684 " if ($name$) {\n");
685
686 if (SupportsArenas(descriptor_->message_type())) {
687 printer->Print(variables,
688 // If incoming message is on the heap and we are on an arena, just Own()
689 // it (see above). If it's on a different arena than we are or one of us
690 // is on the heap, we make a copy to our arena/heap.
691 " if ($this_message$GetArenaNoVirtual() != NULL &&\n"
692 " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
693 " $this_message$GetArenaNoVirtual()->Own($name$);\n"
694 " } else if ($this_message$GetArenaNoVirtual() !=\n"
695 " ::google::protobuf::Arena::GetArena($name$)) {\n"
696 " $dependent_typename$* new_$name$ = \n"
697 " ::google::protobuf::Arena::CreateMessage< $dependent_typename$ >(\n"
698 " $this_message$GetArenaNoVirtual());\n"
699 " new_$name$->CopyFrom(*$name$);\n"
700 " $name$ = new_$name$;\n"
701 " }\n");
702 } else {
703 printer->Print(variables,
704 " if ($this_message$GetArenaNoVirtual() != NULL) {\n"
705 " $this_message$GetArenaNoVirtual()->Own($name$);\n"
706 " }\n");
707 }
708
709 printer->Print(variables,
710 " $this_message$set_has_$name$();\n"
711 " $field_member$ = $name$;\n"
712 " }\n"
713 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
714 "}\n"
715 "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n"
716 " // @@protoc_insertion_point(field_unsafe_arena_release"
717 ":$full_name$)\n"
718 " if (has_$name$()) {\n"
719 " clear_has_$oneof_name$();\n"
720 " $type$* temp = $oneof_prefix$$name$_;\n"
721 " $oneof_prefix$$name$_ = NULL;\n"
722 " return temp;\n"
723 " } else {\n"
724 " return NULL;\n"
725 " }\n"
726 "}\n"
727 "$inline$ void $classname$::unsafe_arena_set_allocated_$name$"
728 "($type$* $name$) {\n"
729 // We rely on the oneof clear method to free the earlier contents of this
730 // oneof. We can directly use the pointer we're given to set the new
731 // value.
732 " clear_$oneof_name$();\n"
733 " if ($name$) {\n"
734 " set_has_$name$();\n"
735 " $oneof_prefix$$name$_ = $name$;\n"
736 " }\n"
737 " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
738 "$full_name$)\n"
739 "}\n");
740 } else {
741 printer->Print(variables,
742 "$tmpl$"
743 "$inline$"
744 "$type$* $dependent_classname$::mutable_$name$() {\n"
745 " if (!$this_message$has_$name$()) {\n"
746 " $this_message$clear_$oneof_name$();\n"
747 " $this_message$set_has_$name$();\n"
748 " $field_member$ = new $dependent_typename$;\n"
749 " }\n"
750 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
751 " return $field_member$;\n"
752 "}\n"
753 "$tmpl$"
754 "$inline$"
755 "$type$* $dependent_classname$::$release_name$() {\n"
756 " // @@protoc_insertion_point(field_release:$full_name$)\n"
757 " if ($this_message$has_$name$()) {\n"
758 " $this_message$clear_has_$oneof_name$();\n"
759 " $dependent_typename$* temp = $field_member$;\n"
760 " $field_member$ = NULL;\n"
761 " return temp;\n"
762 " } else {\n"
763 " return NULL;\n"
764 " }\n"
765 "}\n"
766 "$tmpl$"
767 "$inline$"
768 "void $dependent_classname$::"
769 "set_allocated_$name$($type$* $name$) {\n"
770 " $this_message$clear_$oneof_name$();\n"
771 " if ($name$) {\n");
772 if (SupportsArenas(descriptor_->message_type())) {
773 printer->Print(variables,
774 " if (static_cast< $dependent_typename$*>($name$)->"
775 "GetArena() != NULL) {\n"
776 " $dependent_typename$* new_$name$ = new $dependent_typename$;\n"
777 " new_$name$->CopyFrom(*$name$);\n"
778 " $name$ = new_$name$;\n"
779 " }\n");
780 }
781 printer->Print(variables,
782 " $this_message$set_has_$name$();\n"
783 " $field_member$ = $name$;\n"
784 " }\n"
785 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
786 "}\n");
787 }
788 }
789
790 void MessageOneofFieldGenerator::
GenerateClearingCode(io::Printer * printer) const791 GenerateClearingCode(io::Printer* printer) const {
792 map<string, string> variables(variables_);
793 variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
794 if (SupportsArenas(descriptor_)) {
795 printer->Print(variables,
796 "if ($this_message$GetArenaNoVirtual() == NULL) {\n"
797 " delete $this_message$$oneof_prefix$$name$_;\n"
798 "}\n");
799 } else {
800 printer->Print(variables,
801 "delete $this_message$$oneof_prefix$$name$_;\n");
802 }
803 }
804
805 void MessageOneofFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const806 GenerateSwappingCode(io::Printer* printer) const {
807 // Don't print any swapping code. Swapping the union will swap this field.
808 }
809
810 void MessageOneofFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const811 GenerateConstructorCode(io::Printer* printer) const {
812 // Don't print any constructor code. The field is in a union. We allocate
813 // space only when this field is used.
814 }
815
816 // ===================================================================
817
RepeatedMessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options)818 RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
819 const FieldDescriptor* descriptor, const Options& options)
820 : FieldGenerator(options),
821 descriptor_(descriptor),
822 dependent_field_(options.proto_h && IsFieldDependent(descriptor)),
823 dependent_getter_(dependent_field_ && options.safe_boundary_check) {
824 SetMessageVariables(descriptor, &variables_, options);
825 }
826
~RepeatedMessageFieldGenerator()827 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
828
829 void RepeatedMessageFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const830 GeneratePrivateMembers(io::Printer* printer) const {
831 printer->Print(variables_,
832 "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
833 }
834
835 void RepeatedMessageFieldGenerator::
InternalGenerateTypeDependentAccessorDeclarations(io::Printer * printer) const836 InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const {
837 printer->Print(variables_,
838 "$deprecated_attr$$type$* mutable_$name$(int index);\n"
839 "$deprecated_attr$$type$* add_$name$();\n");
840 if (dependent_getter_) {
841 printer->Print(variables_,
842 "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
843 " $name$() const;\n");
844 }
845 printer->Print(variables_,
846 "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n"
847 " mutable_$name$();\n");
848 }
849
850 void RepeatedMessageFieldGenerator::
GenerateDependentAccessorDeclarations(io::Printer * printer) const851 GenerateDependentAccessorDeclarations(io::Printer* printer) const {
852 if (dependent_getter_) {
853 printer->Print(variables_,
854 "$deprecated_attr$const $type$& $name$(int index) const;\n");
855 }
856 if (dependent_field_) {
857 InternalGenerateTypeDependentAccessorDeclarations(printer);
858 }
859 }
860
861 void RepeatedMessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const862 GenerateAccessorDeclarations(io::Printer* printer) const {
863 if (!dependent_getter_) {
864 printer->Print(variables_,
865 "$deprecated_attr$const $type$& $name$(int index) const;\n");
866 }
867 if (!dependent_field_) {
868 InternalGenerateTypeDependentAccessorDeclarations(printer);
869 }
870 if (!dependent_getter_) {
871 printer->Print(variables_,
872 "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
873 " $name$() const;\n");
874 }
875 }
876
877 void RepeatedMessageFieldGenerator::
GenerateDependentInlineAccessorDefinitions(io::Printer * printer) const878 GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
879 if (!dependent_field_) {
880 return;
881 }
882 map<string, string> variables(variables_);
883 // For the CRTP base class, all mutation methods are dependent, and so
884 // they must be in the header.
885 variables["dependent_classname"] =
886 DependentBaseClassTemplateName(descriptor_->containing_type()) + "<T>";
887 variables["this_message"] = DependentBaseDownCast();
888 variables["this_const_message"] = DependentBaseConstDownCast();
889
890 if (dependent_getter_) {
891 printer->Print(variables,
892 "template <class T>\n"
893 "inline const $type$& $dependent_classname$::$name$(int index) const {\n"
894 " // @@protoc_insertion_point(field_get:$full_name$)\n"
895 " return $this_const_message$$name$_.$cppget$(index);\n"
896 "}\n");
897 }
898
899 // Generate per-element accessors:
900 printer->Print(variables,
901 "template <class T>\n"
902 "inline $type$* $dependent_classname$::mutable_$name$(int index) {\n"
903 // TODO(dlj): move insertion points
904 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
905 " return $this_message$$name$_.Mutable(index);\n"
906 "}\n"
907 "template <class T>\n"
908 "inline $type$* $dependent_classname$::add_$name$() {\n"
909 " // @@protoc_insertion_point(field_add:$full_name$)\n"
910 " return $this_message$$name$_.Add();\n"
911 "}\n");
912
913
914 if (dependent_getter_) {
915 printer->Print(variables,
916 "template <class T>\n"
917 "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
918 "$dependent_classname$::$name$() const {\n"
919 " // @@protoc_insertion_point(field_list:$full_name$)\n"
920 " return $this_const_message$$name$_;\n"
921 "}\n");
922 }
923
924 // Generate mutable access to the entire list:
925 printer->Print(variables,
926 "template <class T>\n"
927 "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
928 "$dependent_classname$::mutable_$name$() {\n"
929 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
930 " return &$this_message$$name$_;\n"
931 "}\n");
932 }
933
934 void RepeatedMessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer,bool is_inline) const935 GenerateInlineAccessorDefinitions(io::Printer* printer,
936 bool is_inline) const {
937 map<string, string> variables(variables_);
938 variables["inline"] = is_inline ? "inline " : "";
939
940 if (!dependent_getter_) {
941 printer->Print(variables,
942 "$inline$"
943 "const $type$& $classname$::$name$(int index) const {\n"
944 " // @@protoc_insertion_point(field_get:$full_name$)\n"
945 " return $name$_.$cppget$(index);\n"
946 "}\n");
947 }
948
949 if (!dependent_field_) {
950 printer->Print(variables,
951 "$inline$"
952 "$type$* $classname$::mutable_$name$(int index) {\n"
953 // TODO(dlj): move insertion points
954 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
955 " return $name$_.Mutable(index);\n"
956 "}\n"
957 "$inline$"
958 "$type$* $classname$::add_$name$() {\n"
959 " // @@protoc_insertion_point(field_add:$full_name$)\n"
960 " return $name$_.Add();\n"
961 "}\n");
962 }
963
964
965 if (!dependent_field_) {
966 printer->Print(variables,
967 "$inline$"
968 "::google::protobuf::RepeatedPtrField< $type$ >*\n"
969 "$classname$::mutable_$name$() {\n"
970 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
971 " return &$name$_;\n"
972 "}\n");
973 }
974 if (!dependent_getter_) {
975 printer->Print(variables,
976 "$inline$"
977 "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
978 "$classname$::$name$() const {\n"
979 " // @@protoc_insertion_point(field_list:$full_name$)\n"
980 " return $name$_;\n"
981 "}\n");
982 }
983 }
984
985 void RepeatedMessageFieldGenerator::
GenerateClearingCode(io::Printer * printer) const986 GenerateClearingCode(io::Printer* printer) const {
987 map<string, string> variables(variables_);
988 variables["this_message"] = dependent_field_ ? DependentBaseDownCast() : "";
989 printer->Print(variables, "$this_message$$name$_.Clear();\n");
990 }
991
992 void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer * printer) const993 GenerateMergingCode(io::Printer* printer) const {
994 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
995 }
996
997 void RepeatedMessageFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const998 GenerateSwappingCode(io::Printer* printer) const {
999 printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
1000 }
1001
1002 void RepeatedMessageFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const1003 GenerateConstructorCode(io::Printer* printer) const {
1004 // Not needed for repeated fields.
1005 }
1006
1007 void RepeatedMessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const1008 GenerateMergeFromCodedStream(io::Printer* printer) const {
1009 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
1010 printer->Print(variables_,
1011 "DO_(::google::protobuf::internal::WireFormatLite::"
1012 "ReadMessageNoVirtualNoRecursionDepth(\n"
1013 " input, add_$name$()));\n");
1014 } else {
1015 printer->Print(variables_,
1016 "DO_(::google::protobuf::internal::WireFormatLite::"
1017 "ReadGroupNoVirtualNoRecursionDepth(\n"
1018 " $number$, input, add_$name$()));\n");
1019 }
1020 }
1021
1022 void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const1023 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
1024 printer->Print(variables_,
1025 "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
1026 " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
1027 " $number$, this->$name$(i), output);\n"
1028 "}\n");
1029 }
1030
1031 void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const1032 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
1033 printer->Print(variables_,
1034 "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
1035 " target = ::google::protobuf::internal::WireFormatLite::\n"
1036 " Write$declared_type$NoVirtualToArray(\n"
1037 " $number$, this->$name$(i), target);\n"
1038 "}\n");
1039 }
1040
1041 void RepeatedMessageFieldGenerator::
GenerateByteSize(io::Printer * printer) const1042 GenerateByteSize(io::Printer* printer) const {
1043 printer->Print(variables_,
1044 "total_size += $tag_size$ * this->$name$_size();\n"
1045 "for (int i = 0; i < this->$name$_size(); i++) {\n"
1046 " total_size +=\n"
1047 " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
1048 " this->$name$(i));\n"
1049 "}\n");
1050 }
1051
1052 } // namespace cpp
1053 } // namespace compiler
1054 } // namespace protobuf
1055 } // namespace google
1056