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
40 namespace google {
41 namespace protobuf {
42 namespace compiler {
43 namespace cpp {
44
45 namespace {
46
SetMessageVariables(const FieldDescriptor * descriptor,map<string,string> * variables,const Options & options)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()) ?
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
68 MessageFieldGenerator::
MessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options)69 MessageFieldGenerator(const FieldDescriptor* descriptor,
70 const Options& options)
71 : descriptor_(descriptor) {
72 SetMessageVariables(descriptor, &variables_, options);
73 }
74
~MessageFieldGenerator()75 MessageFieldGenerator::~MessageFieldGenerator() {}
76
77 void MessageFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const78 GeneratePrivateMembers(io::Printer* printer) const {
79 printer->Print(variables_, "$type$* $name$_;\n");
80 }
81
82 void MessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const83 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");
89 }
90
91 void MessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const92 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");
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
130 void MessageFieldGenerator::
GenerateClearingCode(io::Printer * printer) const131 GenerateClearingCode(io::Printer* printer) const {
132 printer->Print(variables_,
133 "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
134 }
135
136 void MessageFieldGenerator::
GenerateMergingCode(io::Printer * printer) const137 GenerateMergingCode(io::Printer* printer) const {
138 printer->Print(variables_,
139 "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
140 }
141
142 void MessageFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const143 GenerateSwappingCode(io::Printer* printer) const {
144 printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
145 }
146
147 void MessageFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const148 GenerateConstructorCode(io::Printer* printer) const {
149 printer->Print(variables_, "$name$_ = NULL;\n");
150 }
151
152 void MessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const153 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");
158 } else {
159 printer->Print(variables_,
160 "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
161 " $number$, input, mutable_$name$()));\n");
162 }
163 }
164
165 void MessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const166 GenerateSerializeWithCachedSizes(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
172 void MessageFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const173 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");
178 }
179
180 void MessageFieldGenerator::
GenerateByteSize(io::Printer * printer) const181 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");
186 }
187
188 // ===================================================================
189
190 MessageOneofFieldGenerator::
MessageOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)191 MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
192 const Options& options)
193 : MessageFieldGenerator(descriptor, options) {
194 SetCommonOneofFieldVariables(descriptor, &variables_);
195 }
196
~MessageOneofFieldGenerator()197 MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
198
199 void MessageOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const200 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"
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
233 void MessageOneofFieldGenerator::
GenerateClearingCode(io::Printer * printer) const234 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");
238 }
239
240 void MessageOneofFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const241 GenerateSwappingCode(io::Printer* printer) const {
242 // Don't print any swapping code. Swapping the union will swap this field.
243 }
244
245 void MessageOneofFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const246 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.
249 }
250
251 // ===================================================================
252
253 RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options)254 RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
255 const Options& options)
256 : descriptor_(descriptor) {
257 SetMessageVariables(descriptor, &variables_, options);
258 }
259
~RepeatedMessageFieldGenerator()260 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
261
262 void RepeatedMessageFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const263 GeneratePrivateMembers(io::Printer* printer) const {
264 printer->Print(variables_,
265 "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
266 }
267
268 void RepeatedMessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const269 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");
279 }
280
281 void RepeatedMessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const282 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"
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
309 void RepeatedMessageFieldGenerator::
GenerateClearingCode(io::Printer * printer) const310 GenerateClearingCode(io::Printer* printer) const {
311 printer->Print(variables_, "$name$_.Clear();\n");
312 }
313
314 void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer * printer) const315 GenerateMergingCode(io::Printer* printer) const {
316 printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
317 }
318
319 void RepeatedMessageFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const320 GenerateSwappingCode(io::Printer* printer) const {
321 printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
322 }
323
324 void RepeatedMessageFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const325 GenerateConstructorCode(io::Printer* printer) const {
326 // Not needed for repeated fields.
327 }
328
329 void RepeatedMessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const330 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");
335 } else {
336 printer->Print(variables_,
337 "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
338 " $number$, input, add_$name$()));\n");
339 }
340 }
341
342 void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const343 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"
348 "}\n");
349 }
350
351 void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const352 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"
358 "}\n");
359 }
360
361 void RepeatedMessageFieldGenerator::
GenerateByteSize(io::Printer * printer) const362 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"
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