1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// http://code.google.com/p/protobuf/
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  SetCommonFieldVariables(descriptor, variables);
50  (*variables)["type"] = FieldMessageTypeName(descriptor);
51  (*variables)["stream_writer"] = (*variables)["declared_type"] +
52      (HasFastArraySerialization(descriptor->message_type()->file()) ?
53       "MaybeToArray" :
54       "");
55}
56
57}  // namespace
58
59// ===================================================================
60
61MessageFieldGenerator::
62MessageFieldGenerator(const FieldDescriptor* descriptor)
63  : descriptor_(descriptor) {
64  SetMessageVariables(descriptor, &variables_);
65}
66
67MessageFieldGenerator::~MessageFieldGenerator() {}
68
69void MessageFieldGenerator::
70GeneratePrivateMembers(io::Printer* printer) const {
71  printer->Print(variables_, "$type$* $name$_;\n");
72}
73
74void MessageFieldGenerator::
75GenerateAccessorDeclarations(io::Printer* printer) const {
76  printer->Print(variables_,
77    "inline const $type$& $name$() const$deprecation$;\n"
78    "inline $type$* mutable_$name$()$deprecation$;\n");
79}
80
81void MessageFieldGenerator::
82GenerateInlineAccessorDefinitions(io::Printer* printer) const {
83  printer->Print(variables_,
84    "inline const $type$& $classname$::$name$() const {\n"
85    "  return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n"
86    "}\n"
87    "inline $type$* $classname$::mutable_$name$() {\n"
88    "  _set_bit($index$);\n"
89    "  if ($name$_ == NULL) $name$_ = new $type$;\n"
90    "  return $name$_;\n"
91    "}\n");
92}
93
94void MessageFieldGenerator::
95GenerateClearingCode(io::Printer* printer) const {
96  printer->Print(variables_,
97    "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
98}
99
100void MessageFieldGenerator::
101GenerateMergingCode(io::Printer* printer) const {
102  printer->Print(variables_,
103    "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
104}
105
106void MessageFieldGenerator::
107GenerateSwappingCode(io::Printer* printer) const {
108  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
109}
110
111void MessageFieldGenerator::
112GenerateConstructorCode(io::Printer* printer) const {
113  printer->Print(variables_, "$name$_ = NULL;\n");
114}
115
116void MessageFieldGenerator::
117GenerateMergeFromCodedStream(io::Printer* printer) const {
118  if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
119    printer->Print(variables_,
120      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
121      "     input, mutable_$name$()));\n");
122  } else {
123    printer->Print(variables_,
124      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
125      "      $number$, input, mutable_$name$()));\n");
126  }
127}
128
129void MessageFieldGenerator::
130GenerateSerializeWithCachedSizes(io::Printer* printer) const {
131  printer->Print(variables_,
132    "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
133    "  $number$, this->$name$(), output);\n");
134}
135
136void MessageFieldGenerator::
137GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
138  printer->Print(variables_,
139    "target = ::google::protobuf::internal::WireFormatLite::\n"
140    "  Write$declared_type$NoVirtualToArray(\n"
141    "    $number$, this->$name$(), target);\n");
142}
143
144void MessageFieldGenerator::
145GenerateByteSize(io::Printer* printer) const {
146  printer->Print(variables_,
147    "total_size += $tag_size$ +\n"
148    "  ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
149    "    this->$name$());\n");
150}
151
152// ===================================================================
153
154RepeatedMessageFieldGenerator::
155RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
156  : descriptor_(descriptor) {
157  SetMessageVariables(descriptor, &variables_);
158}
159
160RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
161
162void RepeatedMessageFieldGenerator::
163GeneratePrivateMembers(io::Printer* printer) const {
164  printer->Print(variables_,
165    "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
166}
167
168void RepeatedMessageFieldGenerator::
169GenerateAccessorDeclarations(io::Printer* printer) const {
170  printer->Print(variables_,
171    "inline const $type$& $name$(int index) const$deprecation$;\n"
172    "inline $type$* mutable_$name$(int index)$deprecation$;\n"
173    "inline $type$* add_$name$()$deprecation$;\n");
174  printer->Print(variables_,
175    "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
176    "    $name$() const$deprecation$;\n"
177    "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
178    "    mutable_$name$()$deprecation$;\n");
179}
180
181void RepeatedMessageFieldGenerator::
182GenerateInlineAccessorDefinitions(io::Printer* printer) const {
183  printer->Print(variables_,
184    "inline const $type$& $classname$::$name$(int index) const {\n"
185    "  return $name$_.Get(index);\n"
186    "}\n"
187    "inline $type$* $classname$::mutable_$name$(int index) {\n"
188    "  return $name$_.Mutable(index);\n"
189    "}\n"
190    "inline $type$* $classname$::add_$name$() {\n"
191    "  return $name$_.Add();\n"
192    "}\n");
193  printer->Print(variables_,
194    "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
195    "$classname$::$name$() const {\n"
196    "  return $name$_;\n"
197    "}\n"
198    "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
199    "$classname$::mutable_$name$() {\n"
200    "  return &$name$_;\n"
201    "}\n");
202}
203
204void RepeatedMessageFieldGenerator::
205GenerateClearingCode(io::Printer* printer) const {
206  printer->Print(variables_, "$name$_.Clear();\n");
207}
208
209void RepeatedMessageFieldGenerator::
210GenerateMergingCode(io::Printer* printer) const {
211  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
212}
213
214void RepeatedMessageFieldGenerator::
215GenerateSwappingCode(io::Printer* printer) const {
216  printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
217}
218
219void RepeatedMessageFieldGenerator::
220GenerateConstructorCode(io::Printer* printer) const {
221  // Not needed for repeated fields.
222}
223
224void RepeatedMessageFieldGenerator::
225GenerateMergeFromCodedStream(io::Printer* printer) const {
226  if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
227    printer->Print(variables_,
228      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
229      "      input, add_$name$()));\n");
230  } else {
231    printer->Print(variables_,
232      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
233      "      $number$, input, add_$name$()));\n");
234  }
235}
236
237void RepeatedMessageFieldGenerator::
238GenerateSerializeWithCachedSizes(io::Printer* printer) const {
239  printer->Print(variables_,
240    "for (int i = 0; i < this->$name$_size(); i++) {\n"
241    "  ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
242    "    $number$, this->$name$(i), output);\n"
243    "}\n");
244}
245
246void RepeatedMessageFieldGenerator::
247GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
248  printer->Print(variables_,
249    "for (int i = 0; i < this->$name$_size(); i++) {\n"
250    "  target = ::google::protobuf::internal::WireFormatLite::\n"
251    "    Write$declared_type$NoVirtualToArray(\n"
252    "      $number$, this->$name$(i), target);\n"
253    "}\n");
254}
255
256void RepeatedMessageFieldGenerator::
257GenerateByteSize(io::Printer* printer) const {
258  printer->Print(variables_,
259    "total_size += $tag_size$ * this->$name$_size();\n"
260    "for (int i = 0; i < this->$name$_size(); i++) {\n"
261    "  total_size +=\n"
262    "    ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
263    "      this->$name$(i));\n"
264    "}\n");
265}
266
267}  // namespace cpp
268}  // namespace compiler
269}  // namespace protobuf
270}  // namespace google
271