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