• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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