• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 }
57 
58 }  // namespace
59 
60 // ===================================================================
61 
62 MessageFieldGenerator::
MessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options)63 MessageFieldGenerator(const FieldDescriptor* descriptor,
64                       const Options& options)
65   : descriptor_(descriptor) {
66   SetMessageVariables(descriptor, &variables_, options);
67 }
68 
~MessageFieldGenerator()69 MessageFieldGenerator::~MessageFieldGenerator() {}
70 
71 void MessageFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const72 GeneratePrivateMembers(io::Printer* printer) const {
73   printer->Print(variables_, "$type$* $name$_;\n");
74 }
75 
76 void MessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const77 GenerateAccessorDeclarations(io::Printer* printer) const {
78   printer->Print(variables_,
79     "inline const $type$& $name$() const$deprecation$;\n"
80     "inline $type$* mutable_$name$()$deprecation$;\n"
81     "inline $type$* release_$name$()$deprecation$;\n"
82     "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
83 }
84 
85 void MessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const86 GenerateInlineAccessorDefinitions(io::Printer* printer) const {
87   printer->Print(variables_,
88     "inline const $type$& $classname$::$name$() const {\n");
89 
90   PrintHandlingOptionalStaticInitializers(
91     variables_, descriptor_->file(), printer,
92     // With static initializers.
93     "  return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
94     // Without.
95     "  return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
96 
97   printer->Print(variables_,
98     "}\n"
99     "inline $type$* $classname$::mutable_$name$() {\n"
100     "  set_has_$name$();\n"
101     "  if ($name$_ == NULL) $name$_ = new $type$;\n"
102     "  return $name$_;\n"
103     "}\n"
104     "inline $type$* $classname$::release_$name$() {\n"
105     "  clear_has_$name$();\n"
106     "  $type$* temp = $name$_;\n"
107     "  $name$_ = NULL;\n"
108     "  return temp;\n"
109     "}\n"
110     "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
111     "  delete $name$_;\n"
112     "  $name$_ = $name$;\n"
113     "  if ($name$) {\n"
114     "    set_has_$name$();\n"
115     "  } else {\n"
116     "    clear_has_$name$();\n"
117     "  }\n"
118     "}\n");
119 }
120 
121 void MessageFieldGenerator::
GenerateClearingCode(io::Printer * printer) const122 GenerateClearingCode(io::Printer* printer) const {
123   printer->Print(variables_,
124     "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
125 }
126 
127 void MessageFieldGenerator::
GenerateMergingCode(io::Printer * printer) const128 GenerateMergingCode(io::Printer* printer) const {
129   printer->Print(variables_,
130     "mutable_$name$()->$type$::MergeFrom(from.$name$());\n");
131 }
132 
133 void MessageFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const134 GenerateSwappingCode(io::Printer* printer) const {
135   printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
136 }
137 
138 void MessageFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const139 GenerateConstructorCode(io::Printer* printer) const {
140   printer->Print(variables_, "$name$_ = NULL;\n");
141 }
142 
143 void MessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const144 GenerateMergeFromCodedStream(io::Printer* printer) const {
145   if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
146     printer->Print(variables_,
147       "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
148       "     input, mutable_$name$()));\n");
149   } else {
150     printer->Print(variables_,
151       "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
152       "      $number$, input, mutable_$name$()));\n");
153   }
154 }
155 
156 void MessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const157 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
158   printer->Print(variables_,
159     "::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
160     "  $number$, this->$name$(), output);\n");
161 }
162 
163 void MessageFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const164 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
165   printer->Print(variables_,
166     "target = ::google::protobuf::internal::WireFormatLite::\n"
167     "  Write$declared_type$NoVirtualToArray(\n"
168     "    $number$, this->$name$(), target);\n");
169 }
170 
171 void MessageFieldGenerator::
GenerateByteSize(io::Printer * printer) const172 GenerateByteSize(io::Printer* printer) const {
173   printer->Print(variables_,
174     "total_size += $tag_size$ +\n"
175     "  ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
176     "    this->$name$());\n");
177 }
178 
179 // ===================================================================
180 
181 RepeatedMessageFieldGenerator::
RepeatedMessageFieldGenerator(const FieldDescriptor * descriptor,const Options & options)182 RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
183                               const Options& options)
184   : descriptor_(descriptor) {
185   SetMessageVariables(descriptor, &variables_, options);
186 }
187 
~RepeatedMessageFieldGenerator()188 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
189 
190 void RepeatedMessageFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const191 GeneratePrivateMembers(io::Printer* printer) const {
192   printer->Print(variables_,
193     "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n");
194 }
195 
196 void RepeatedMessageFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const197 GenerateAccessorDeclarations(io::Printer* printer) const {
198   printer->Print(variables_,
199     "inline const $type$& $name$(int index) const$deprecation$;\n"
200     "inline $type$* mutable_$name$(int index)$deprecation$;\n"
201     "inline $type$* add_$name$()$deprecation$;\n");
202   printer->Print(variables_,
203     "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
204     "    $name$() const$deprecation$;\n"
205     "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
206     "    mutable_$name$()$deprecation$;\n");
207 }
208 
209 void RepeatedMessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const210 GenerateInlineAccessorDefinitions(io::Printer* printer) const {
211   printer->Print(variables_,
212     "inline const $type$& $classname$::$name$(int index) const {\n"
213     "  return $name$_.$cppget$(index);\n"
214     "}\n"
215     "inline $type$* $classname$::mutable_$name$(int index) {\n"
216     "  return $name$_.Mutable(index);\n"
217     "}\n"
218     "inline $type$* $classname$::add_$name$() {\n"
219     "  return $name$_.Add();\n"
220     "}\n");
221   printer->Print(variables_,
222     "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
223     "$classname$::$name$() const {\n"
224     "  return $name$_;\n"
225     "}\n"
226     "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n"
227     "$classname$::mutable_$name$() {\n"
228     "  return &$name$_;\n"
229     "}\n");
230 }
231 
232 void RepeatedMessageFieldGenerator::
GenerateClearingCode(io::Printer * printer) const233 GenerateClearingCode(io::Printer* printer) const {
234   printer->Print(variables_, "$name$_.Clear();\n");
235 }
236 
237 void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer * printer) const238 GenerateMergingCode(io::Printer* printer) const {
239   printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
240 }
241 
242 void RepeatedMessageFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const243 GenerateSwappingCode(io::Printer* printer) const {
244   printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
245 }
246 
247 void RepeatedMessageFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const248 GenerateConstructorCode(io::Printer* printer) const {
249   // Not needed for repeated fields.
250 }
251 
252 void RepeatedMessageFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const253 GenerateMergeFromCodedStream(io::Printer* printer) const {
254   if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) {
255     printer->Print(variables_,
256       "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n"
257       "      input, add_$name$()));\n");
258   } else {
259     printer->Print(variables_,
260       "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n"
261       "      $number$, input, add_$name$()));\n");
262   }
263 }
264 
265 void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const266 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
267   printer->Print(variables_,
268     "for (int i = 0; i < this->$name$_size(); i++) {\n"
269     "  ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
270     "    $number$, this->$name$(i), output);\n"
271     "}\n");
272 }
273 
274 void RepeatedMessageFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const275 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
276   printer->Print(variables_,
277     "for (int i = 0; i < this->$name$_size(); i++) {\n"
278     "  target = ::google::protobuf::internal::WireFormatLite::\n"
279     "    Write$declared_type$NoVirtualToArray(\n"
280     "      $number$, this->$name$(i), target);\n"
281     "}\n");
282 }
283 
284 void RepeatedMessageFieldGenerator::
GenerateByteSize(io::Printer * printer) const285 GenerateByteSize(io::Printer* printer) const {
286   printer->Print(variables_,
287     "total_size += $tag_size$ * this->$name$_size();\n"
288     "for (int i = 0; i < this->$name$_size(); i++) {\n"
289     "  total_size +=\n"
290     "    ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
291     "      this->$name$(i));\n"
292     "}\n");
293 }
294 
295 }  // namespace cpp
296 }  // namespace compiler
297 }  // namespace protobuf
298 }  // namespace google
299