blob: e2d2370beaf6e5046cef065bb120ca18daa4656b [file] [log] [blame]
temporal40ee5512008-07-10 02:12:20 +00001// Protocol Buffers - Google's data interchange format
kenton@google.com24bf56f2008-09-24 20:31:01 +00002// Copyright 2008 Google Inc. All rights reserved.
temporal40ee5512008-07-10 02:12:20 +00003// http://code.google.com/p/protobuf/
4//
kenton@google.com24bf56f2008-09-24 20:31:01 +00005// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
temporal40ee5512008-07-10 02:12:20 +00008//
kenton@google.com24bf56f2008-09-24 20:31:01 +00009// * 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.
temporal40ee5512008-07-10 02:12:20 +000018//
kenton@google.com24bf56f2008-09-24 20:31:01 +000019// 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.
temporal40ee5512008-07-10 02:12:20 +000030
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/wire_format_inl.h>
39#include <google/protobuf/stubs/strutil.h>
40
41namespace google {
42namespace protobuf {
43namespace compiler {
44namespace cpp {
45
46using internal::WireFormat;
47
48namespace {
49
50// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of
51// repeat code between this and the other field types.
52void SetMessageVariables(const FieldDescriptor* descriptor,
53 map<string, string>* variables) {
54 (*variables)["name"] = FieldName(descriptor);
55 (*variables)["type"] = ClassName(descriptor->message_type(), true);
56 (*variables)["index"] = SimpleItoa(descriptor->index());
57 (*variables)["number"] = SimpleItoa(descriptor->number());
58 (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
59 (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
60 (*variables)["tag_size"] = SimpleItoa(
61 WireFormat::TagSize(descriptor->number(), descriptor->type()));
62}
63
64} // namespace
65
66// ===================================================================
67
68MessageFieldGenerator::
69MessageFieldGenerator(const FieldDescriptor* descriptor)
70 : descriptor_(descriptor) {
71 SetMessageVariables(descriptor, &variables_);
72}
73
74MessageFieldGenerator::~MessageFieldGenerator() {}
75
76void MessageFieldGenerator::
77GeneratePrivateMembers(io::Printer* printer) const {
78 printer->Print(variables_, "$type$* $name$_;\n");
79}
80
81void MessageFieldGenerator::
82GenerateAccessorDeclarations(io::Printer* printer) const {
83 printer->Print(variables_,
84 "inline const $type$& $name$() const;\n"
85 "inline $type$* mutable_$name$();\n");
86}
87
88void MessageFieldGenerator::
89GenerateInlineAccessorDefinitions(io::Printer* printer) const {
90 printer->Print(variables_,
91 "inline const $type$& $classname$::$name$() const {\n"
kenton@google.com24bf56f2008-09-24 20:31:01 +000092 " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n"
temporal40ee5512008-07-10 02:12:20 +000093 "}\n"
94 "inline $type$* $classname$::mutable_$name$() {\n"
95 " _set_bit($index$);\n"
96 " if ($name$_ == NULL) $name$_ = new $type$;\n"
97 " return $name$_;\n"
98 "}\n");
99}
100
101void MessageFieldGenerator::
102GenerateClearingCode(io::Printer* printer) const {
103 printer->Print(variables_,
104 "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
105}
106
107void MessageFieldGenerator::
108GenerateMergingCode(io::Printer* printer) const {
109 printer->Print(variables_,
110 "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
111}
112
113void MessageFieldGenerator::
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000114GenerateSwappingCode(io::Printer* printer) const {
115 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
116}
117
118void MessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000119GenerateInitializer(io::Printer* printer) const {
120 printer->Print(variables_, ",\n$name$_(NULL)");
121}
122
123void MessageFieldGenerator::
124GenerateMergeFromCodedStream(io::Printer* printer) const {
125 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
126 printer->Print(variables_,
127 "DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n"
128 " input, mutable_$name$()));\n");
129 } else {
130 printer->Print(variables_,
131 "DO_(::google::protobuf::internal::WireFormat::ReadGroupNoVirtual("
132 "$number$, input, mutable_$name$()));\n");
133 }
134}
135
136void MessageFieldGenerator::
137GenerateSerializeWithCachedSizes(io::Printer* printer) const {
138 printer->Print(variables_,
139 "DO_(::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
140 "$number$, this->$name$(), output));\n");
141}
142
143void MessageFieldGenerator::
144GenerateByteSize(io::Printer* printer) const {
145 printer->Print(variables_,
146 "total_size += $tag_size$ +\n"
147 " ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n"
148 " this->$name$());\n");
149}
150
151// ===================================================================
152
153RepeatedMessageFieldGenerator::
154RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor)
155 : descriptor_(descriptor) {
156 SetMessageVariables(descriptor, &variables_);
157}
158
159RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
160
161void RepeatedMessageFieldGenerator::
162GeneratePrivateMembers(io::Printer* printer) const {
163 printer->Print(variables_,
164 "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
165}
166
167void RepeatedMessageFieldGenerator::
168GenerateAccessorDeclarations(io::Printer* printer) const {
169 printer->Print(variables_,
170 "inline const ::google::protobuf::RepeatedPtrField< $type$ >& $name$() const;\n"
171 "inline ::google::protobuf::RepeatedPtrField< $type$ >* mutable_$name$();\n"
172 "inline const $type$& $name$(int index) const;\n"
173 "inline $type$* mutable_$name$(int index);\n"
174 "inline $type$* add_$name$();\n");
175}
176
177void RepeatedMessageFieldGenerator::
178GenerateInlineAccessorDefinitions(io::Printer* printer) const {
179 printer->Print(variables_,
180 "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
181 "$classname$::$name$() const {\n"
182 " return $name$_;\n"
183 "}\n"
184 "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
185 "$classname$::mutable_$name$() {\n"
186 " return &$name$_;\n"
187 "}\n"
188 "inline const $type$& $classname$::$name$(int index) const {\n"
189 " return $name$_.Get(index);\n"
190 "}\n"
191 "inline $type$* $classname$::mutable_$name$(int index) {\n"
192 " return $name$_.Mutable(index);\n"
193 "}\n"
194 "inline $type$* $classname$::add_$name$() {\n"
195 " return $name$_.Add();\n"
196 "}\n");
197}
198
199void RepeatedMessageFieldGenerator::
200GenerateClearingCode(io::Printer* printer) const {
201 printer->Print(variables_, "$name$_.Clear();\n");
202}
203
204void RepeatedMessageFieldGenerator::
205GenerateMergingCode(io::Printer* printer) const {
206 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
207}
208
209void RepeatedMessageFieldGenerator::
kenton@google.com26bd9ee2008-11-21 00:06:27 +0000210GenerateSwappingCode(io::Printer* printer) const {
211 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
212}
213
214void RepeatedMessageFieldGenerator::
temporal40ee5512008-07-10 02:12:20 +0000215GenerateInitializer(io::Printer* printer) const {
kenton@google.comeb26a1e2009-04-16 22:43:40 +0000216 printer->Print(variables_, ",\n$name$_()");
temporal40ee5512008-07-10 02:12:20 +0000217}
218
219void RepeatedMessageFieldGenerator::
220GenerateMergeFromCodedStream(io::Printer* printer) const {
221 if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
222 printer->Print(variables_,
223 "DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n"
224 " input, add_$name$()));\n");
225 } else {
226 printer->Print(variables_,
227 "DO_(::google::protobuf::internal::WireFormat::ReadGroupNoVirtual("
228 "$number$, input, add_$name$()));\n");
229 }
230}
231
232void RepeatedMessageFieldGenerator::
233GenerateSerializeWithCachedSizes(io::Printer* printer) const {
234 printer->Print(variables_,
kenton@google.com2d6daa72009-01-22 01:27:00 +0000235 "for (int i = 0; i < this->$name$_size(); i++) {\n"
236 " DO_(::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual("
237 "$number$, this->$name$(i), output));\n"
238 "}\n");
temporal40ee5512008-07-10 02:12:20 +0000239}
240
241void RepeatedMessageFieldGenerator::
242GenerateByteSize(io::Printer* printer) const {
243 printer->Print(variables_,
kenton@google.com2d6daa72009-01-22 01:27:00 +0000244 "total_size += $tag_size$ * this->$name$_size();\n"
245 "for (int i = 0; i < this->$name$_size(); i++) {\n"
temporal40ee5512008-07-10 02:12:20 +0000246 " total_size +=\n"
247 " ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n"
248 " this->$name$(i));\n"
249 "}\n");
250}
251
252} // namespace cpp
253} // namespace compiler
254} // namespace protobuf
255} // namespace google