cpp_message_field.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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    "inline $type$* release_$name$()$deprecation$;\n");
80}
81
82void MessageFieldGenerator::
83GenerateInlineAccessorDefinitions(io::Printer* printer) const {
84  printer->Print(variables_,
85    "inline const $type$& $classname$::$name$() const {\n");
86
87  PrintHandlingOptionalStaticInitializers(
88    variables_, descriptor_->file(), printer,
89    // With static initializers.
90    "  return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
91    // Without.
92    "  return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
93
94  printer->Print(variables_,
95    "}\n"
96    "inline $type$* $classname$::mutable_$name$() {\n"
97    "  set_has_$name$();\n"
98    "  if ($name$_ == NULL) $name$_ = new $type$;\n"
99    "  return $name$_;\n"
100    "}\n"
101    "inline $type$* $classname$::release_$name$() {\n"
102    "  clear_has_$name$();\n"
103    "  $type$* temp = $name$_;\n"
104    "  $name$_ = NULL;\n"
105    "  return temp;\n"
106    "}\n");
107}
108
109void MessageFieldGenerator::
110GenerateClearingCode(io::Printer* printer) const {
111  printer->Print(variables_,
112    "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
113}
114
115void MessageFieldGenerator::
116GenerateMergingCode(io::Printer* printer) const {
117  printer->Print(variables_,
118    "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
119}
120
121void MessageFieldGenerator::
122GenerateSwappingCode(io::Printer* printer) const {
123  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
124}
125
126void MessageFieldGenerator::
127GenerateConstructorCode(io::Printer* printer) const {
128  printer->Print(variables_, "$name$_ = NULL;\n");
129}
130
131void MessageFieldGenerator::
132GenerateMergeFromCodedStream(io::Printer* printer) const {
133  if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
134    printer->Print(variables_,
135      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
136      "     input, mutable_$name$()));\n");
137  } else {
138    printer->Print(variables_,
139      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
140      "      $number$, input, mutable_$name$()));\n");
141  }
142}
143
144void MessageFieldGenerator::
145GenerateSerializeWithCachedSizes(io::Printer* printer) const {
146  printer->Print(variables_,
147    "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
148    "  $number$, this->$name$(), output);\n");
149}
150
151void MessageFieldGenerator::
152GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
153  printer->Print(variables_,
154    "target = ::google::protobuf::internal::WireFormatLite::\n"
155    "  Write$declared_type$NoVirtualToArray(\n"
156    "    $number$, this->$name$(), target);\n");
157}
158
159void MessageFieldGenerator::
160GenerateByteSize(io::Printer* printer) const {
161  printer->Print(variables_,
162    "total_size += $tag_size$ +\n"
163    "  ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
164    "    this->$name$());\n");
165}
166
167// ===================================================================
168
169RepeatedMessageFieldGenerator::
170RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
171  : descriptor_(descriptor) {
172  SetMessageVariables(descriptor, &variables_);
173}
174
175RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
176
177void RepeatedMessageFieldGenerator::
178GeneratePrivateMembers(io::Printer* printer) const {
179  printer->Print(variables_,
180    "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
181}
182
183void RepeatedMessageFieldGenerator::
184GenerateAccessorDeclarations(io::Printer* printer) const {
185  printer->Print(variables_,
186    "inline const $type$& $name$(int index) const$deprecation$;\n"
187    "inline $type$* mutable_$name$(int index)$deprecation$;\n"
188    "inline $type$* add_$name$()$deprecation$;\n");
189  printer->Print(variables_,
190    "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
191    "    $name$() const$deprecation$;\n"
192    "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
193    "    mutable_$name$()$deprecation$;\n");
194}
195
196void RepeatedMessageFieldGenerator::
197GenerateInlineAccessorDefinitions(io::Printer* printer) const {
198  printer->Print(variables_,
199    "inline const $type$& $classname$::$name$(int index) const {\n"
200    "  return $name$_.Get(index);\n"
201    "}\n"
202    "inline $type$* $classname$::mutable_$name$(int index) {\n"
203    "  return $name$_.Mutable(index);\n"
204    "}\n"
205    "inline $type$* $classname$::add_$name$() {\n"
206    "  return $name$_.Add();\n"
207    "}\n");
208  printer->Print(variables_,
209    "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
210    "$classname$::$name$() const {\n"
211    "  return $name$_;\n"
212    "}\n"
213    "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
214    "$classname$::mutable_$name$() {\n"
215    "  return &$name$_;\n"
216    "}\n");
217}
218
219void RepeatedMessageFieldGenerator::
220GenerateClearingCode(io::Printer* printer) const {
221  printer->Print(variables_, "$name$_.Clear();\n");
222}
223
224void RepeatedMessageFieldGenerator::
225GenerateMergingCode(io::Printer* printer) const {
226  printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
227}
228
229void RepeatedMessageFieldGenerator::
230GenerateSwappingCode(io::Printer* printer) const {
231  printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
232}
233
234void RepeatedMessageFieldGenerator::
235GenerateConstructorCode(io::Printer* printer) const {
236  // Not needed for repeated fields.
237}
238
239void RepeatedMessageFieldGenerator::
240GenerateMergeFromCodedStream(io::Printer* printer) const {
241  if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
242    printer->Print(variables_,
243      "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
244      "      input, add_$name$()));\n");
245  } else {
246    printer->Print(variables_,
247      "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
248      "      $number$, input, add_$name$()));\n");
249  }
250}
251
252void RepeatedMessageFieldGenerator::
253GenerateSerializeWithCachedSizes(io::Printer* printer) const {
254  printer->Print(variables_,
255    "for (int i = 0; i < this->$name$_size(); i++) {\n"
256    "  ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
257    "    $number$, this->$name$(i), output);\n"
258    "}\n");
259}
260
261void RepeatedMessageFieldGenerator::
262GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
263  printer->Print(variables_,
264    "for (int i = 0; i < this->$name$_size(); i++) {\n"
265    "  target = ::google::protobuf::internal::WireFormatLite::\n"
266    "    Write$declared_type$NoVirtualToArray(\n"
267    "      $number$, this->$name$(i), target);\n"
268    "}\n");
269}
270
271void RepeatedMessageFieldGenerator::
272GenerateByteSize(io::Printer* printer) const {
273  printer->Print(variables_,
274    "total_size += $tag_size$ * this->$name$_size();\n"
275    "for (int i = 0; i < this->$name$_size(); i++) {\n"
276    "  total_size +=\n"
277    "    ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
278    "      this->$name$(i));\n"
279    "}\n");
280}
281
282}  // namespace cpp
283}  // namespace compiler
284}  // namespace protobuf
285}  // namespace google
286