1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
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
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.
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.
31 // Author: kenton@google.com (Kenton Varda)
32 // Based on original Protocol Buffers design by
33 // Sanjay Ghemawat, Jeff Dean, and others.
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>
47 void 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()) ?
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();
66 // ===================================================================
68 MessageFieldGenerator::
69 MessageFieldGenerator(const FieldDescriptor* descriptor,
70 const Options& options)
71 : descriptor_(descriptor) {
72 SetMessageVariables(descriptor, &variables_, options);
75 MessageFieldGenerator::~MessageFieldGenerator() {}
77 void MessageFieldGenerator::
78 GeneratePrivateMembers(io::Printer* printer) const {
79 printer->Print(variables_, "$type$* $name$_;\n");
82 void MessageFieldGenerator::
83 GenerateAccessorDeclarations(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");
91 void MessageFieldGenerator::
92 GenerateInlineAccessorDefinitions(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");
97 PrintHandlingOptionalStaticInitializers(
98 variables_, descriptor_->file(), printer,
99 // With static initializers.
100 " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
102 " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
104 printer->Print(variables_,
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"
112 "inline $type$* $classname$::$release_name$() {\n"
113 " clear_has_$name$();\n"
114 " $type$* temp = $name$_;\n"
118 "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
120 " $name$_ = $name$;\n"
122 " set_has_$name$();\n"
124 " clear_has_$name$();\n"
126 " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
130 void MessageFieldGenerator::
131 GenerateClearingCode(io::Printer* printer) const {
132 printer->Print(variables_,
133 "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
136 void MessageFieldGenerator::
137 GenerateMergingCode(io::Printer* printer) const {
138 printer->Print(variables_,
139 "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
142 void MessageFieldGenerator::
143 GenerateSwappingCode(io::Printer* printer) const {
144 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
147 void MessageFieldGenerator::
148 GenerateConstructorCode(io::Printer* printer) const {
149 printer->Print(variables_, "$name$_ = NULL;\n");
152 void MessageFieldGenerator::
153 GenerateMergeFromCodedStream(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");
159 printer->Print(variables_,
160 "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
161 " $number$, input, mutable_$name$()));\n");
165 void MessageFieldGenerator::
166 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
167 printer->Print(variables_,
168 "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
169 " $number$, this->$name$(), output);\n");
172 void MessageFieldGenerator::
173 GenerateSerializeWithCachedSizesToArray(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");
180 void MessageFieldGenerator::
181 GenerateByteSize(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");
188 // ===================================================================
190 MessageOneofFieldGenerator::
191 MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
192 const Options& options)
193 : MessageFieldGenerator(descriptor, options) {
194 SetCommonOneofFieldVariables(descriptor, &variables_);
197 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
199 void MessageOneofFieldGenerator::
200 GenerateInlineAccessorDefinitions(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"
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"
212 " return $oneof_prefix$$name$_;\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"
224 "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
225 " clear_$oneof_name$();\n"
227 " set_has_$name$();\n"
228 " $oneof_prefix$$name$_ = $name$;\n"
233 void MessageOneofFieldGenerator::
234 GenerateClearingCode(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");
240 void MessageOneofFieldGenerator::
241 GenerateSwappingCode(io::Printer* printer) const {
242 // Don't print any swapping code. Swapping the union will swap this field.
245 void MessageOneofFieldGenerator::
246 GenerateConstructorCode(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.
251 // ===================================================================
253 RepeatedMessageFieldGenerator::
254 RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
255 const Options& options)
256 : descriptor_(descriptor) {
257 SetMessageVariables(descriptor, &variables_, options);
260 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
262 void RepeatedMessageFieldGenerator::
263 GeneratePrivateMembers(io::Printer* printer) const {
264 printer->Print(variables_,
265 "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
268 void RepeatedMessageFieldGenerator::
269 GenerateAccessorDeclarations(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");
281 void RepeatedMessageFieldGenerator::
282 GenerateInlineAccessorDefinitions(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"
288 "inline $type$* $classname$::mutable_$name$(int index) {\n"
289 " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
290 " return $name$_.Mutable(index);\n"
292 "inline $type$* $classname$::add_$name$() {\n"
293 " // @@protoc_insertion_point(field_add:$full_name$)\n"
294 " return $name$_.Add();\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"
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"
309 void RepeatedMessageFieldGenerator::
310 GenerateClearingCode(io::Printer* printer) const {
311 printer->Print(variables_, "$name$_.Clear();\n");
314 void RepeatedMessageFieldGenerator::
315 GenerateMergingCode(io::Printer* printer) const {
316 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
319 void RepeatedMessageFieldGenerator::
320 GenerateSwappingCode(io::Printer* printer) const {
321 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
324 void RepeatedMessageFieldGenerator::
325 GenerateConstructorCode(io::Printer* printer) const {
326 // Not needed for repeated fields.
329 void RepeatedMessageFieldGenerator::
330 GenerateMergeFromCodedStream(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");
336 printer->Print(variables_,
337 "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
338 " $number$, input, add_$name$()));\n");
342 void RepeatedMessageFieldGenerator::
343 GenerateSerializeWithCachedSizes(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"
351 void RepeatedMessageFieldGenerator::
352 GenerateSerializeWithCachedSizesToArray(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"
361 void RepeatedMessageFieldGenerator::
362 GenerateByteSize(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"
367 " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
368 " this->$name$(i));\n"
373 } // namespace compiler
374 } // namespace protobuf
375 } // namespace google