Line data Source code
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_primitive_field.h>
36 : #include <google/protobuf/compiler/cpp/cpp_helpers.h>
37 : #include <google/protobuf/io/printer.h>
38 : #include <google/protobuf/wire_format.h>
39 : #include <google/protobuf/stubs/strutil.h>
40 :
41 : namespace google {
42 : namespace protobuf {
43 : namespace compiler {
44 : namespace cpp {
45 :
46 : using internal::WireFormatLite;
47 :
48 : namespace {
49 :
50 : // For encodings with fixed sizes, returns that size in bytes. Otherwise
51 : // returns -1.
52 1285 : int FixedSize(FieldDescriptor::Type type) {
53 1285 : switch (type) {
54 : case FieldDescriptor::TYPE_INT32 : return -1;
55 : case FieldDescriptor::TYPE_INT64 : return -1;
56 : case FieldDescriptor::TYPE_UINT32 : return -1;
57 : case FieldDescriptor::TYPE_UINT64 : return -1;
58 : case FieldDescriptor::TYPE_SINT32 : return -1;
59 : case FieldDescriptor::TYPE_SINT64 : return -1;
60 54 : case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
61 52 : case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
62 50 : case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
63 50 : case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
64 77 : case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize;
65 122 : case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize;
66 :
67 84 : case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
68 : case FieldDescriptor::TYPE_ENUM : return -1;
69 :
70 : case FieldDescriptor::TYPE_STRING : return -1;
71 : case FieldDescriptor::TYPE_BYTES : return -1;
72 : case FieldDescriptor::TYPE_GROUP : return -1;
73 : case FieldDescriptor::TYPE_MESSAGE : return -1;
74 :
75 : // No default because we want the compiler to complain if any new
76 : // types are added.
77 : }
78 0 : GOOGLE_LOG(FATAL) << "Can't get here.";
79 0 : return -1;
80 : }
81 :
82 3635 : void SetPrimitiveVariables(const FieldDescriptor* descriptor,
83 : map<string, string>* variables,
84 : const Options& options) {
85 727 : SetCommonFieldVariables(descriptor, variables, options);
86 2181 : (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
87 2181 : (*variables)["default"] = DefaultValue(descriptor);
88 2181 : (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
89 727 : int fixed_size = FixedSize(descriptor->type());
90 727 : if (fixed_size != -1) {
91 810 : (*variables)["fixed_size"] = SimpleItoa(fixed_size);
92 : }
93 1454 : (*variables)["wire_format_field_type"] =
94 1454 : "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
95 727 : static_cast<FieldDescriptorProto_Type>(descriptor->type()));
96 1454 : (*variables)["full_name"] = descriptor->full_name();
97 727 : }
98 :
99 : } // namespace
100 :
101 : // ===================================================================
102 :
103 543 : PrimitiveFieldGenerator::
104 : PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
105 : const Options& options)
106 1086 : : descriptor_(descriptor) {
107 543 : SetPrimitiveVariables(descriptor, &variables_, options);
108 543 : }
109 :
110 1616 : PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
111 :
112 382 : void PrimitiveFieldGenerator::
113 : GeneratePrivateMembers(io::Printer* printer) const {
114 382 : printer->Print(variables_, "$type$ $name$_;\n");
115 382 : }
116 :
117 370 : void PrimitiveFieldGenerator::
118 : GenerateAccessorDeclarations(io::Printer* printer) const {
119 : printer->Print(variables_,
120 : "$type$ $name$() const$deprecation$;\n"
121 370 : "void set_$name$($type$ value)$deprecation$;\n");
122 370 : }
123 :
124 714 : void PrimitiveFieldGenerator::
125 : GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
126 714 : map<string, string> variables(variables_);
127 1428 : variables["inline"] = is_inline ? "inline" : "";
128 : printer->Print(variables,
129 : "$inline$ $type$ $classname$::$name$() const {\n"
130 : " // @@protoc_insertion_point(field_get:$full_name$)\n"
131 : " return $name$_;\n"
132 : "}\n"
133 : "$inline$ void $classname$::set_$name$($type$ value) {\n"
134 : " $set_hasbit$\n"
135 : " $name$_ = value;\n"
136 : " // @@protoc_insertion_point(field_set:$full_name$)\n"
137 714 : "}\n");
138 714 : }
139 :
140 872 : void PrimitiveFieldGenerator::
141 : GenerateClearingCode(io::Printer* printer) const {
142 872 : printer->Print(variables_, "$name$_ = $default$;\n");
143 872 : }
144 :
145 367 : void PrimitiveFieldGenerator::
146 : GenerateMergingCode(io::Printer* printer) const {
147 367 : printer->Print(variables_, "set_$name$(from.$name$());\n");
148 367 : }
149 :
150 355 : void PrimitiveFieldGenerator::
151 : GenerateSwappingCode(io::Printer* printer) const {
152 355 : printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
153 355 : }
154 :
155 357 : void PrimitiveFieldGenerator::
156 : GenerateConstructorCode(io::Printer* printer) const {
157 357 : printer->Print(variables_, "$name$_ = $default$;\n");
158 357 : }
159 :
160 355 : void PrimitiveFieldGenerator::
161 : GenerateMergeFromCodedStream(io::Printer* printer) const {
162 : printer->Print(variables_,
163 : "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
164 : " $type$, $wire_format_field_type$>(\n"
165 : " input, &$name$_)));\n"
166 355 : "$set_hasbit$\n");
167 355 : }
168 :
169 367 : void PrimitiveFieldGenerator::
170 : GenerateSerializeWithCachedSizes(io::Printer* printer) const {
171 : printer->Print(variables_,
172 : "::google::protobuf::internal::WireFormatLite::Write$declared_type$("
173 367 : "$number$, this->$name$(), output);\n");
174 367 : }
175 :
176 326 : void PrimitiveFieldGenerator::
177 : GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
178 : printer->Print(variables_,
179 : "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray("
180 326 : "$number$, this->$name$(), target);\n");
181 326 : }
182 :
183 374 : void PrimitiveFieldGenerator::
184 : GenerateByteSize(io::Printer* printer) const {
185 374 : int fixed_size = FixedSize(descriptor_->type());
186 374 : if (fixed_size == -1) {
187 : printer->Print(variables_,
188 : "total_size += $tag_size$ +\n"
189 : " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
190 248 : " this->$name$());\n");
191 : } else {
192 : printer->Print(variables_,
193 126 : "total_size += $tag_size$ + $fixed_size$;\n");
194 : }
195 374 : }
196 :
197 : // ===================================================================
198 :
199 13 : PrimitiveOneofFieldGenerator::
200 : PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
201 : const Options& options)
202 13 : : PrimitiveFieldGenerator(descriptor, options) {
203 13 : SetCommonOneofFieldVariables(descriptor, &variables_);
204 13 : }
205 :
206 26 : PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
207 :
208 26 : void PrimitiveOneofFieldGenerator::
209 : GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
210 26 : map<string, string> variables(variables_);
211 52 : variables["inline"] = is_inline ? "inline" : "";
212 : printer->Print(variables,
213 : "$inline$ $type$ $classname$::$name$() const {\n"
214 : " // @@protoc_insertion_point(field_get:$full_name$)\n"
215 : " if (has_$name$()) {\n"
216 : " return $oneof_prefix$$name$_;\n"
217 : " }\n"
218 : " return $default$;\n"
219 : "}\n"
220 : "$inline$ void $classname$::set_$name$($type$ value) {\n"
221 : " if (!has_$name$()) {\n"
222 : " clear_$oneof_name$();\n"
223 : " set_has_$name$();\n"
224 : " }\n"
225 : " $oneof_prefix$$name$_ = value;\n"
226 : " // @@protoc_insertion_point(field_set:$full_name$)\n"
227 26 : "}\n");
228 26 : }
229 :
230 26 : void PrimitiveOneofFieldGenerator::
231 : GenerateClearingCode(io::Printer* printer) const {
232 26 : printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
233 26 : }
234 :
235 12 : void PrimitiveOneofFieldGenerator::
236 : GenerateSwappingCode(io::Printer* printer) const {
237 : // Don't print any swapping code. Swapping the union will swap this field.
238 12 : }
239 :
240 12 : void PrimitiveOneofFieldGenerator::
241 : GenerateConstructorCode(io::Printer* printer) const {
242 : printer->Print(
243 : variables_,
244 12 : " $classname$_default_oneof_instance_->$name$_ = $default$;\n");
245 12 : }
246 :
247 12 : void PrimitiveOneofFieldGenerator::
248 : GenerateMergeFromCodedStream(io::Printer* printer) const {
249 : printer->Print(variables_,
250 : "clear_$oneof_name$();\n"
251 : "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
252 : " $type$, $wire_format_field_type$>(\n"
253 : " input, &$oneof_prefix$$name$_)));\n"
254 12 : "set_has_$name$();\n");
255 12 : }
256 :
257 : // ===================================================================
258 :
259 184 : RepeatedPrimitiveFieldGenerator::
260 : RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
261 : const Options& options)
262 368 : : descriptor_(descriptor) {
263 184 : SetPrimitiveVariables(descriptor, &variables_, options);
264 :
265 184 : if (descriptor->is_packed()) {
266 184 : variables_["packed_reader"] = "ReadPackedPrimitive";
267 184 : variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
268 : } else {
269 184 : variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
270 184 : variables_["repeated_reader"] = "ReadRepeatedPrimitive";
271 : }
272 184 : }
273 :
274 552 : RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
275 :
276 184 : void RepeatedPrimitiveFieldGenerator::
277 : GeneratePrivateMembers(io::Printer* printer) const {
278 : printer->Print(variables_,
279 184 : "::google::protobuf::RepeatedField< $type$ > $name$_;\n");
280 276 : if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file())) {
281 : printer->Print(variables_,
282 92 : "mutable int _$name$_cached_byte_size_;\n");
283 : }
284 184 : }
285 :
286 184 : void RepeatedPrimitiveFieldGenerator::
287 : GenerateAccessorDeclarations(io::Printer* printer) const {
288 : printer->Print(variables_,
289 : "$type$ $name$(int index) const$deprecation$;\n"
290 : "void set_$name$(int index, $type$ value)$deprecation$;\n"
291 184 : "void add_$name$($type$ value)$deprecation$;\n");
292 : printer->Print(variables_,
293 : "const ::google::protobuf::RepeatedField< $type$ >&\n"
294 : " $name$() const$deprecation$;\n"
295 : "::google::protobuf::RepeatedField< $type$ >*\n"
296 184 : " mutable_$name$()$deprecation$;\n");
297 184 : }
298 :
299 368 : void RepeatedPrimitiveFieldGenerator::
300 : GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
301 368 : map<string, string> variables(variables_);
302 736 : variables["inline"] = is_inline ? "inline" : "";
303 : printer->Print(variables,
304 : "$inline$ $type$ $classname$::$name$(int index) const {\n"
305 : " // @@protoc_insertion_point(field_get:$full_name$)\n"
306 : " return $name$_.Get(index);\n"
307 : "}\n"
308 : "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n"
309 : " $name$_.Set(index, value);\n"
310 : " // @@protoc_insertion_point(field_set:$full_name$)\n"
311 : "}\n"
312 : "$inline$ void $classname$::add_$name$($type$ value) {\n"
313 : " $name$_.Add(value);\n"
314 : " // @@protoc_insertion_point(field_add:$full_name$)\n"
315 368 : "}\n");
316 : printer->Print(variables,
317 : "$inline$ const ::google::protobuf::RepeatedField< $type$ >&\n"
318 : "$classname$::$name$() const {\n"
319 : " // @@protoc_insertion_point(field_list:$full_name$)\n"
320 : " return $name$_;\n"
321 : "}\n"
322 : "$inline$ ::google::protobuf::RepeatedField< $type$ >*\n"
323 : "$classname$::mutable_$name$() {\n"
324 : " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
325 : " return &$name$_;\n"
326 368 : "}\n");
327 368 : }
328 :
329 552 : void RepeatedPrimitiveFieldGenerator::
330 : GenerateClearingCode(io::Printer* printer) const {
331 552 : printer->Print(variables_, "$name$_.Clear();\n");
332 552 : }
333 :
334 184 : void RepeatedPrimitiveFieldGenerator::
335 : GenerateMergingCode(io::Printer* printer) const {
336 184 : printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
337 184 : }
338 :
339 184 : void RepeatedPrimitiveFieldGenerator::
340 : GenerateSwappingCode(io::Printer* printer) const {
341 184 : printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
342 184 : }
343 :
344 184 : void RepeatedPrimitiveFieldGenerator::
345 : GenerateConstructorCode(io::Printer* printer) const {
346 : // Not needed for repeated fields.
347 184 : }
348 :
349 184 : void RepeatedPrimitiveFieldGenerator::
350 : GenerateMergeFromCodedStream(io::Printer* printer) const {
351 : printer->Print(variables_,
352 : "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
353 : " $type$, $wire_format_field_type$>(\n"
354 184 : " $tag_size$, $tag$, input, this->mutable_$name$())));\n");
355 184 : }
356 :
357 184 : void RepeatedPrimitiveFieldGenerator::
358 : GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
359 : printer->Print(variables_,
360 : "DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n"
361 : " $type$, $wire_format_field_type$>(\n"
362 184 : " input, this->mutable_$name$())));\n");
363 184 : }
364 :
365 184 : void RepeatedPrimitiveFieldGenerator::
366 : GenerateSerializeWithCachedSizes(io::Printer* printer) const {
367 184 : if (descriptor_->is_packed()) {
368 : // Write the tag and the size.
369 : printer->Print(variables_,
370 : "if (this->$name$_size() > 0) {\n"
371 : " ::google::protobuf::internal::WireFormatLite::WriteTag("
372 : "$number$, "
373 : "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
374 : "output);\n"
375 : " output->WriteVarint32(_$name$_cached_byte_size_);\n"
376 92 : "}\n");
377 : }
378 : printer->Print(variables_,
379 184 : "for (int i = 0; i < this->$name$_size(); i++) {\n");
380 184 : if (descriptor_->is_packed()) {
381 : printer->Print(variables_,
382 : " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
383 92 : " this->$name$(i), output);\n");
384 : } else {
385 : printer->Print(variables_,
386 : " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
387 92 : " $number$, this->$name$(i), output);\n");
388 : }
389 184 : printer->Print("}\n");
390 184 : }
391 :
392 158 : void RepeatedPrimitiveFieldGenerator::
393 : GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
394 158 : if (descriptor_->is_packed()) {
395 : // Write the tag and the size.
396 : printer->Print(variables_,
397 : "if (this->$name$_size() > 0) {\n"
398 : " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
399 : " $number$,\n"
400 : " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
401 : " target);\n"
402 : " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
403 : " _$name$_cached_byte_size_, target);\n"
404 79 : "}\n");
405 : }
406 : printer->Print(variables_,
407 158 : "for (int i = 0; i < this->$name$_size(); i++) {\n");
408 158 : if (descriptor_->is_packed()) {
409 : printer->Print(variables_,
410 : " target = ::google::protobuf::internal::WireFormatLite::\n"
411 79 : " Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
412 : } else {
413 : printer->Print(variables_,
414 : " target = ::google::protobuf::internal::WireFormatLite::\n"
415 79 : " Write$declared_type$ToArray($number$, this->$name$(i), target);\n");
416 : }
417 158 : printer->Print("}\n");
418 158 : }
419 :
420 184 : void RepeatedPrimitiveFieldGenerator::
421 : GenerateByteSize(io::Printer* printer) const {
422 : printer->Print(variables_,
423 : "{\n"
424 184 : " int data_size = 0;\n");
425 184 : printer->Indent();
426 184 : int fixed_size = FixedSize(descriptor_->type());
427 184 : if (fixed_size == -1) {
428 : printer->Print(variables_,
429 : "for (int i = 0; i < this->$name$_size(); i++) {\n"
430 : " data_size += ::google::protobuf::internal::WireFormatLite::\n"
431 : " $declared_type$Size(this->$name$(i));\n"
432 91 : "}\n");
433 : } else {
434 : printer->Print(variables_,
435 93 : "data_size = $fixed_size$ * this->$name$_size();\n");
436 : }
437 :
438 184 : if (descriptor_->is_packed()) {
439 : printer->Print(variables_,
440 : "if (data_size > 0) {\n"
441 : " total_size += $tag_size$ +\n"
442 : " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
443 : "}\n"
444 : "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
445 : "_$name$_cached_byte_size_ = data_size;\n"
446 : "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
447 92 : "total_size += data_size;\n");
448 : } else {
449 : printer->Print(variables_,
450 92 : "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
451 : }
452 184 : printer->Outdent();
453 184 : printer->Print("}\n");
454 184 : }
455 :
456 : } // namespace cpp
457 : } // namespace compiler
458 : } // namespace protobuf
459 : } // namespace google
|