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