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  (*variables)["stream_writer"] = (*variables)["declared_type"] +
53      (HasFastArraySerialization(descriptor->message_type()->file()) ?
54       "MaybeToArray" :
55       "");
56  // NOTE: Escaped here to unblock proto1->proto2 migration.
57  // TODO(liujisi): Extend this to apply for other conflicting methods.
58  (*variables)["release_name"] =
59      SafeFunctionName(descriptor->containing_type(),
60                       descriptor, "release_");
61  (*variables)["full_name"] = descriptor->full_name();
62}
63
64}  // namespace
65
66// ===================================================================
67
68MessageFieldGenerator::
69MessageFieldGenerator(const FieldDescriptor* descriptor,
70                      const Options& options)
71  : descriptor_(descriptor) {
72  SetMessageVariables(descriptor, &variables_, options);
73}
74
75MessageFieldGenerator::~MessageFieldGenerator() {}
76
77void MessageFieldGenerator::
78GeneratePrivateMembers(io::Printer* printer) const {
79  printer->Print(variables_, "$type$* $name$_;\n");
80}
81
82void MessageFieldGenerator::
83GenerateAccessorDeclarations(io::Printer* printer) const {
84  printer->Print(variables_,
85    "inline const $type$& $name$() const$deprecation$;\n"
86    "inline $type$* mutable_$name$()$deprecation$;\n"
87    "inline $type$* $release_name$()$deprecation$;\n"
88    "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
89}
90
91void MessageFieldGenerator::
92GenerateInlineAccessorDefinitions(io::Printer* printer) const {
93  printer->Print(variables_,
94    "inline const $type$& $classname$::$name$() const {\n"
95    "  // @@protoc_insertion_point(field_get:$full_name$)\n");
96
97  PrintHandlingOptionalStaticInitializers(
98    variables_, descriptor_->file(), printer,
99    // With static initializers.
100    "  return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
101    // Without.
102    "  return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
103
104  printer->Print(variables_,
105    "}\n"
106    "inline $type$* $classname$::mutable_$name$() {\n"
107    "  set_has_$name$();\n"
108    "  if ($name$_ == NULL) $name$_ = new $type$;\n"
109    "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
110    "  return $name$_;\n"
111    "}\n"
112    "inline $type$* $classname$::$release_name$() {\n"
113    "  clear_has_$name$();\n"
114    "  $type$* temp = $name$_;\n"
115    "  $name$_ = NULL;\n"
116    "  return temp;\n"
117    "}\n"
118    "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
119    "  delete $name$_;\n"
120    "  $name$_ = $name$;\n"
121    "  if ($name$) {\n"
122    "    set_has_$name$();\n"
123    "  } else {\n"
124    "    clear_has_$name$();\n"
125    "  }\n"
126    "  // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
127    "}\n");
128}
129
130void MessageFieldGenerator::
131GenerateClearingCode(io::Printer* printer) const {
132  printer->Print(variables_,
133    "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
134}
135
136void MessageFieldGenerator::
137GenerateMergingCode(io::Printer* printer) const {
138  printer->Print(variables_,
139    "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
140}
141
142void MessageFieldGenerator::
143GenerateSwappingCode(io::Printer* printer) const {
144  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
145}
146
147void MessageFieldGenerator::
148GenerateConstructorCode(io::Printer* printer) const {
149  printer->Print(variables_, "$name$_ = NULL;\n");
150}
151
152void MessageFieldGenerator::
153GenerateMergeFromCodedStream(io::Printer* printer) const {
154  if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
155    printer->Print(variables_,
156      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
157      "     input, mutable_$name$()));\n");
158  } else {
159    printer->Print(variables_,
160      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
161      "      $number$, input, mutable_$name$()));\n");
162  }
163}
164
165void MessageFieldGenerator::
166GenerateSerializeWithCachedSizes(io::Printer* printer) const {
167  printer->Print(variables_,
168    "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
169    "  $number$, this->$name$(), output);\n");
170}
171
172void MessageFieldGenerator::
173GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
174  printer->Print(variables_,
175    "target = ::google::protobuf::internal::WireFormatLite::\n"
176    "  Write$declared_type$NoVirtualToArray(\n"
177    "    $number$, this->$name$(), target);\n");
178}
179
180void MessageFieldGenerator::
181GenerateByteSize(io::Printer* printer) const {
182  printer->Print(variables_,
183    "total_size += $tag_size$ +\n"
184    "  ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
185    "    this->$name$());\n");
186}
187
188// ===================================================================
189
190MessageOneofFieldGenerator::
191MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
192                           const Options& options)
193  : MessageFieldGenerator(descriptor, options) {
194  SetCommonOneofFieldVariables(descriptor, &variables_);
195}
196
197MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
198
199void MessageOneofFieldGenerator::
200GenerateInlineAccessorDefinitions(io::Printer* printer) const {
201  printer->Print(variables_,
202    "inline const $type$& $classname$::$name$() const {\n"
203    "  return has_$name$() ? *$oneof_prefix$$name$_\n"
204    "                      : $type$::default_instance();\n"
205    "}\n"
206    "inline $type$* $classname$::mutable_$name$() {\n"
207    "  if (!has_$name$()) {\n"
208    "    clear_$oneof_name$();\n"
209    "    set_has_$name$();\n"
210    "    $oneof_prefix$$name$_ = new $type$;\n"
211    "  }\n"
212    "  return $oneof_prefix$$name$_;\n"
213    "}\n"
214    "inline $type$* $classname$::$release_name$() {\n"
215    "  if (has_$name$()) {\n"
216    "    clear_has_$oneof_name$();\n"
217    "    $type$* temp = $oneof_prefix$$name$_;\n"
218    "    $oneof_prefix$$name$_ = NULL;\n"
219    "    return temp;\n"
220    "  } else {\n"
221    "    return NULL;\n"
222    "  }\n"
223    "}\n"
224    "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
225    "  clear_$oneof_name$();\n"
226    "  if ($name$) {\n"
227    "    set_has_$name$();\n"
228    "    $oneof_prefix$$name$_ = $name$;\n"
229    "  }\n"
230    "}\n");
231}
232
233void MessageOneofFieldGenerator::
234GenerateClearingCode(io::Printer* printer) const {
235  // if it is the active field, it cannot be NULL.
236  printer->Print(variables_,
237    "delete $oneof_prefix$$name$_;\n");
238}
239
240void MessageOneofFieldGenerator::
241GenerateSwappingCode(io::Printer* printer) const {
242  // Don't print any swapping code. Swapping the union will swap this field.
243}
244
245void MessageOneofFieldGenerator::
246GenerateConstructorCode(io::Printer* printer) const {
247  // Don't print any constructor code. The field is in a union. We allocate
248  // space only when this field is used.
249}
250
251// ===================================================================
252
253RepeatedMessageFieldGenerator::
254RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
255                              const Options& options)
256  : descriptor_(descriptor) {
257  SetMessageVariables(descriptor, &variables_, options);
258}
259
260RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
261
262void RepeatedMessageFieldGenerator::
263GeneratePrivateMembers(io::Printer* printer) const {
264  printer->Print(variables_,
265    "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
266}
267
268void RepeatedMessageFieldGenerator::
269GenerateAccessorDeclarations(io::Printer* printer) const {
270  printer->Print(variables_,
271    "inline const $type$& $name$(int index) const$deprecation$;\n"
272    "inline $type$* mutable_$name$(int index)$deprecation$;\n"
273    "inline $type$* add_$name$()$deprecation$;\n");
274  printer->Print(variables_,
275    "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
276    "    $name$() const$deprecation$;\n"
277    "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
278    "    mutable_$name$()$deprecation$;\n");
279}
280
281void RepeatedMessageFieldGenerator::
282GenerateInlineAccessorDefinitions(io::Printer* printer) const {
283  printer->Print(variables_,
284    "inline const $type$& $classname$::$name$(int index) const {\n"
285    "  // @@protoc_insertion_point(field_get:$full_name$)\n"
286    "  return $name$_.$cppget$(index);\n"
287    "}\n"
288    "inline $type$* $classname$::mutable_$name$(int index) {\n"
289    "  // @@protoc_insertion_point(field_mutable:$full_name$)\n"
290    "  return $name$_.Mutable(index);\n"
291    "}\n"
292    "inline $type$* $classname$::add_$name$() {\n"
293    "  // @@protoc_insertion_point(field_add:$full_name$)\n"
294    "  return $name$_.Add();\n"
295    "}\n");
296  printer->Print(variables_,
297    "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
298    "$classname$::$name$() const {\n"
299    "  // @@protoc_insertion_point(field_list:$full_name$)\n"
300    "  return $name$_;\n"
301    "}\n"
302    "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
303    "$classname$::mutable_$name$() {\n"
304    "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
305    "  return &$name$_;\n"
306    "}\n");
307}
308
309void RepeatedMessageFieldGenerator::
310GenerateClearingCode(io::Printer* printer) const {
311  printer->Print(variables_, "$name$_.Clear();\n");
312}
313
314void RepeatedMessageFieldGenerator::
315GenerateMergingCode(io::Printer* printer) const {
316  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
317}
318
319void RepeatedMessageFieldGenerator::
320GenerateSwappingCode(io::Printer* printer) const {
321  printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
322}
323
324void RepeatedMessageFieldGenerator::
325GenerateConstructorCode(io::Printer* printer) const {
326  // Not needed for repeated fields.
327}
328
329void RepeatedMessageFieldGenerator::
330GenerateMergeFromCodedStream(io::Printer* printer) const {
331  if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
332    printer->Print(variables_,
333      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
334      "      input, add_$name$()));\n");
335  } else {
336    printer->Print(variables_,
337      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
338      "      $number$, input, add_$name$()));\n");
339  }
340}
341
342void RepeatedMessageFieldGenerator::
343GenerateSerializeWithCachedSizes(io::Printer* printer) const {
344  printer->Print(variables_,
345    "for (int i = 0; i < this->$name$_size(); i++) {\n"
346    "  ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
347    "    $number$, this->$name$(i), output);\n"
348    "}\n");
349}
350
351void RepeatedMessageFieldGenerator::
352GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
353  printer->Print(variables_,
354    "for (int i = 0; i < this->$name$_size(); i++) {\n"
355    "  target = ::google::protobuf::internal::WireFormatLite::\n"
356    "    Write$declared_type$NoVirtualToArray(\n"
357    "      $number$, this->$name$(i), target);\n"
358    "}\n");
359}
360
361void RepeatedMessageFieldGenerator::
362GenerateByteSize(io::Printer* printer) const {
363  printer->Print(variables_,
364    "total_size += $tag_size$ * this->$name$_size();\n"
365    "for (int i = 0; i < this->$name$_size(); i++) {\n"
366    "  total_size +=\n"
367    "    ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
368    "      this->$name$(i));\n"
369    "}\n");
370}
371
372}  // namespace cpp
373}  // namespace compiler
374}  // namespace protobuf
375}  // namespace google
376