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
40namespace google {
41namespace protobuf {
42namespace compiler {
43namespace cpp {
44
45namespace {
46
47void 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
81MessageFieldGenerator::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
89MessageFieldGenerator::~MessageFieldGenerator() {}
90
91void MessageFieldGenerator::
92GeneratePrivateMembers(io::Printer* printer) const {
93  printer->Print(variables_, "$type$* $name$_;\n");
94}
95
96void MessageFieldGenerator::
97GenerateGetterDeclaration(io::Printer* printer) const {
98  printer->Print(variables_,
99      "$deprecated_attr$const $type$& $name$() const;\n");
100}
101
102void MessageFieldGenerator::
103GenerateDependentAccessorDeclarations(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
114void MessageFieldGenerator::
115GenerateAccessorDeclarations(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
144void 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
216void MessageFieldGenerator::
217GenerateDependentInlineAccessorDefinitions(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
346void MessageFieldGenerator::
347GenerateInlineAccessorDefinitions(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
465void MessageFieldGenerator::
466GenerateClearingCode(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
483void MessageFieldGenerator::
484GenerateMergingCode(io::Printer* printer) const {
485  printer->Print(variables_,
486    "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
487}
488
489void MessageFieldGenerator::
490GenerateSwappingCode(io::Printer* printer) const {
491  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
492}
493
494void MessageFieldGenerator::
495GenerateConstructorCode(io::Printer* printer) const {
496  printer->Print(variables_, "$name$_ = NULL;\n");
497}
498
499void MessageFieldGenerator::
500GenerateMergeFromCodedStream(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
512void MessageFieldGenerator::
513GenerateSerializeWithCachedSizes(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
519void MessageFieldGenerator::
520GenerateSerializeWithCachedSizesToArray(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
527void MessageFieldGenerator::
528GenerateByteSize(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
537MessageOneofFieldGenerator::
538MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
539                           const Options& options)
540  : MessageFieldGenerator(descriptor, options),
541    dependent_base_(options.proto_h) {
542  SetCommonOneofFieldVariables(descriptor, &variables_);
543}
544
545MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
546
547
548void MessageOneofFieldGenerator::
549GenerateDependentAccessorDeclarations(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
560void MessageOneofFieldGenerator::
561GenerateGetterDeclaration(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
572void MessageOneofFieldGenerator::
573GenerateDependentInlineAccessorDefinitions(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
593void MessageOneofFieldGenerator::
594GenerateInlineAccessorDefinitions(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
611void MessageOneofFieldGenerator::
612GenerateNonInlineAccessorDefinitions(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
620void MessageOneofFieldGenerator::
621InternalGenerateInlineAccessorDefinitions(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
790void MessageOneofFieldGenerator::
791GenerateClearingCode(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
805void MessageOneofFieldGenerator::
806GenerateSwappingCode(io::Printer* printer) const {
807  // Don't print any swapping code. Swapping the union will swap this field.
808}
809
810void MessageOneofFieldGenerator::
811GenerateConstructorCode(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
818RepeatedMessageFieldGenerator::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
827RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
828
829void RepeatedMessageFieldGenerator::
830GeneratePrivateMembers(io::Printer* printer) const {
831  printer->Print(variables_,
832    "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
833}
834
835void RepeatedMessageFieldGenerator::
836InternalGenerateTypeDependentAccessorDeclarations(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
850void RepeatedMessageFieldGenerator::
851GenerateDependentAccessorDeclarations(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
861void RepeatedMessageFieldGenerator::
862GenerateAccessorDeclarations(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
877void RepeatedMessageFieldGenerator::
878GenerateDependentInlineAccessorDefinitions(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
934void RepeatedMessageFieldGenerator::
935GenerateInlineAccessorDefinitions(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
985void RepeatedMessageFieldGenerator::
986GenerateClearingCode(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
992void RepeatedMessageFieldGenerator::
993GenerateMergingCode(io::Printer* printer) const {
994  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
995}
996
997void RepeatedMessageFieldGenerator::
998GenerateSwappingCode(io::Printer* printer) const {
999  printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
1000}
1001
1002void RepeatedMessageFieldGenerator::
1003GenerateConstructorCode(io::Printer* printer) const {
1004  // Not needed for repeated fields.
1005}
1006
1007void RepeatedMessageFieldGenerator::
1008GenerateMergeFromCodedStream(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
1022void RepeatedMessageFieldGenerator::
1023GenerateSerializeWithCachedSizes(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
1031void RepeatedMessageFieldGenerator::
1032GenerateSerializeWithCachedSizesToArray(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
1041void RepeatedMessageFieldGenerator::
1042GenerateByteSize(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