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
42 namespace google {
43 namespace protobuf {
44 namespace compiler {
45 namespace cpp {
46
47 using internal::WireFormatLite;
48
49 namespace {
50
51 // For encodings with fixed sizes, returns that size in bytes. Otherwise
52 // returns -1.
FixedSize(FieldDescriptor::Type type)53 int FixedSize(FieldDescriptor::Type type) {
54 switch (type) {
55 case FieldDescriptor::TYPE_INT32:
56 return -1;
57 case FieldDescriptor::TYPE_INT64:
58 return -1;
59 case FieldDescriptor::TYPE_UINT32:
60 return -1;
61 case FieldDescriptor::TYPE_UINT64:
62 return -1;
63 case FieldDescriptor::TYPE_SINT32:
64 return -1;
65 case FieldDescriptor::TYPE_SINT64:
66 return -1;
67 case FieldDescriptor::TYPE_FIXED32:
68 return WireFormatLite::kFixed32Size;
69 case FieldDescriptor::TYPE_FIXED64:
70 return WireFormatLite::kFixed64Size;
71 case FieldDescriptor::TYPE_SFIXED32:
72 return WireFormatLite::kSFixed32Size;
73 case FieldDescriptor::TYPE_SFIXED64:
74 return WireFormatLite::kSFixed64Size;
75 case FieldDescriptor::TYPE_FLOAT:
76 return WireFormatLite::kFloatSize;
77 case FieldDescriptor::TYPE_DOUBLE:
78 return WireFormatLite::kDoubleSize;
79
80 case FieldDescriptor::TYPE_BOOL:
81 return WireFormatLite::kBoolSize;
82 case FieldDescriptor::TYPE_ENUM:
83 return -1;
84
85 case FieldDescriptor::TYPE_STRING:
86 return -1;
87 case FieldDescriptor::TYPE_BYTES:
88 return -1;
89 case FieldDescriptor::TYPE_GROUP:
90 return -1;
91 case FieldDescriptor::TYPE_MESSAGE:
92 return -1;
93
94 // No default because we want the compiler to complain if any new
95 // types are added.
96 }
97 GOOGLE_LOG(FATAL) << "Can't get here.";
98 return -1;
99 }
100
SetPrimitiveVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables,const Options & options)101 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
102 std::map<std::string, std::string>* variables,
103 const Options& options) {
104 SetCommonFieldVariables(descriptor, variables, options);
105 (*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type());
106 (*variables)["default"] = DefaultValue(options, descriptor);
107 (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
108 int fixed_size = FixedSize(descriptor->type());
109 if (fixed_size != -1) {
110 (*variables)["fixed_size"] = StrCat(fixed_size);
111 }
112 (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name(
113 static_cast<FieldDescriptorProto_Type>(descriptor->type()));
114 (*variables)["full_name"] = descriptor->full_name();
115 }
116
117 } // namespace
118
119 // ===================================================================
120
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)121 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
122 const FieldDescriptor* descriptor, const Options& options)
123 : FieldGenerator(descriptor, options) {
124 SetPrimitiveVariables(descriptor, &variables_, options);
125 }
126
~PrimitiveFieldGenerator()127 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
128
GeneratePrivateMembers(io::Printer * printer) const129 void PrimitiveFieldGenerator::GeneratePrivateMembers(
130 io::Printer* printer) const {
131 Formatter format(printer, variables_);
132 format("$type$ $name$_;\n");
133 }
134
GenerateAccessorDeclarations(io::Printer * printer) const135 void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
136 io::Printer* printer) const {
137 Formatter format(printer, variables_);
138 format(
139 "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
140 "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n",
141 descriptor_);
142 }
143
GenerateInlineAccessorDefinitions(io::Printer * printer) const144 void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
145 io::Printer* printer) const {
146 Formatter format(printer, variables_);
147 format(
148 "inline $type$ $classname$::$name$() const {\n"
149 " // @@protoc_insertion_point(field_get:$full_name$)\n"
150 " return $name$_;\n"
151 "}\n"
152 "inline void $classname$::set_$name$($type$ value) {\n"
153 " $set_hasbit$\n"
154 " $name$_ = value;\n"
155 " // @@protoc_insertion_point(field_set:$full_name$)\n"
156 "}\n");
157 }
158
GenerateClearingCode(io::Printer * printer) const159 void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
160 Formatter format(printer, variables_);
161 format("$name$_ = $default$;\n");
162 }
163
GenerateMergingCode(io::Printer * printer) const164 void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
165 Formatter format(printer, variables_);
166 format("set_$name$(from.$name$());\n");
167 }
168
GenerateSwappingCode(io::Printer * printer) const169 void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
170 Formatter format(printer, variables_);
171 format("swap($name$_, other->$name$_);\n");
172 }
173
GenerateConstructorCode(io::Printer * printer) const174 void PrimitiveFieldGenerator::GenerateConstructorCode(
175 io::Printer* printer) const {
176 Formatter format(printer, variables_);
177 format("$name$_ = $default$;\n");
178 }
179
GenerateCopyConstructorCode(io::Printer * printer) const180 void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
181 io::Printer* printer) const {
182 Formatter format(printer, variables_);
183 format("$name$_ = from.$name$_;\n");
184 }
185
GenerateMergeFromCodedStream(io::Printer * printer) const186 void PrimitiveFieldGenerator::GenerateMergeFromCodedStream(
187 io::Printer* printer) const {
188 Formatter format(printer, variables_);
189 format(
190 "$set_hasbit_io$\n"
191 "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
192 " $type$, "
193 "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
194 " input, &$name$_)));\n");
195 }
196
GenerateSerializeWithCachedSizes(io::Printer * printer) const197 void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizes(
198 io::Printer* printer) const {
199 Formatter format(printer, variables_);
200 format(
201 "::$proto_ns$::internal::WireFormatLite::Write$declared_type$("
202 "$number$, this->$name$(), output);\n");
203 }
204
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const205 void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
206 io::Printer* printer) const {
207 Formatter format(printer, variables_);
208 format(
209 "target = "
210 "::$proto_ns$::internal::WireFormatLite::Write$declared_type$ToArray("
211 "$number$, this->$name$(), target);\n");
212 }
213
GenerateByteSize(io::Printer * printer) const214 void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
215 Formatter format(printer, variables_);
216 int fixed_size = FixedSize(descriptor_->type());
217 if (fixed_size == -1) {
218 format(
219 "total_size += $tag_size$ +\n"
220 " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
221 " this->$name$());\n");
222 } else {
223 format("total_size += $tag_size$ + $fixed_size$;\n");
224 }
225 }
226
227 // ===================================================================
228
PrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)229 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
230 const FieldDescriptor* descriptor, const Options& options)
231 : PrimitiveFieldGenerator(descriptor, options) {
232 SetCommonOneofFieldVariables(descriptor, &variables_);
233 }
234
~PrimitiveOneofFieldGenerator()235 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
236
GenerateInlineAccessorDefinitions(io::Printer * printer) const237 void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions(
238 io::Printer* printer) const {
239 Formatter format(printer, variables_);
240 format(
241 "inline $type$ $classname$::$name$() const {\n"
242 " // @@protoc_insertion_point(field_get:$full_name$)\n"
243 " if (has_$name$()) {\n"
244 " return $field_member$;\n"
245 " }\n"
246 " return $default$;\n"
247 "}\n"
248 "inline void $classname$::set_$name$($type$ value) {\n"
249 " if (!has_$name$()) {\n"
250 " clear_$oneof_name$();\n"
251 " set_has_$name$();\n"
252 " }\n"
253 " $field_member$ = value;\n"
254 " // @@protoc_insertion_point(field_set:$full_name$)\n"
255 "}\n");
256 }
257
GenerateClearingCode(io::Printer * printer) const258 void PrimitiveOneofFieldGenerator::GenerateClearingCode(
259 io::Printer* printer) const {
260 Formatter format(printer, variables_);
261 format("$field_member$ = $default$;\n");
262 }
263
GenerateSwappingCode(io::Printer * printer) const264 void PrimitiveOneofFieldGenerator::GenerateSwappingCode(
265 io::Printer* printer) const {
266 // Don't print any swapping code. Swapping the union will swap this field.
267 }
268
GenerateConstructorCode(io::Printer * printer) const269 void PrimitiveOneofFieldGenerator::GenerateConstructorCode(
270 io::Printer* printer) const {
271 Formatter format(printer, variables_);
272 format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
273 }
274
GenerateMergeFromCodedStream(io::Printer * printer) const275 void PrimitiveOneofFieldGenerator::GenerateMergeFromCodedStream(
276 io::Printer* printer) const {
277 Formatter format(printer, variables_);
278 format(
279 "clear_$oneof_name$();\n"
280 "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
281 " $type$, "
282 "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
283 " input, &$field_member$)));\n"
284 "set_has_$name$();\n");
285 }
286
287 // ===================================================================
288
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)289 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
290 const FieldDescriptor* descriptor, const Options& options)
291 : FieldGenerator(descriptor, options) {
292 SetPrimitiveVariables(descriptor, &variables_, options);
293
294 if (descriptor->is_packed()) {
295 variables_["packed_reader"] = "ReadPackedPrimitive";
296 variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
297 } else {
298 variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
299 variables_["repeated_reader"] = "ReadRepeatedPrimitive";
300 }
301 }
302
~RepeatedPrimitiveFieldGenerator()303 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
304
GeneratePrivateMembers(io::Printer * printer) const305 void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers(
306 io::Printer* printer) const {
307 Formatter format(printer, variables_);
308 format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
309 if (descriptor_->is_packed() &&
310 HasGeneratedMethods(descriptor_->file(), options_)) {
311 format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
312 }
313 }
314
GenerateAccessorDeclarations(io::Printer * printer) const315 void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations(
316 io::Printer* printer) const {
317 Formatter format(printer, variables_);
318 format(
319 "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
320 "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
321 "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
322 "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n"
323 " ${1$$name$$}$() const;\n"
324 "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n"
325 " ${1$mutable_$name$$}$();\n",
326 descriptor_);
327 }
328
GenerateInlineAccessorDefinitions(io::Printer * printer) const329 void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
330 io::Printer* printer) const {
331 Formatter format(printer, variables_);
332 format(
333 "inline $type$ $classname$::$name$(int index) const {\n"
334 " // @@protoc_insertion_point(field_get:$full_name$)\n"
335 " return $name$_.Get(index);\n"
336 "}\n"
337 "inline void $classname$::set_$name$(int index, $type$ value) {\n"
338 " $name$_.Set(index, value);\n"
339 " // @@protoc_insertion_point(field_set:$full_name$)\n"
340 "}\n"
341 "inline void $classname$::add_$name$($type$ value) {\n"
342 " $name$_.Add(value);\n"
343 " // @@protoc_insertion_point(field_add:$full_name$)\n"
344 "}\n"
345 "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
346 "$classname$::$name$() const {\n"
347 " // @@protoc_insertion_point(field_list:$full_name$)\n"
348 " return $name$_;\n"
349 "}\n"
350 "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
351 "$classname$::mutable_$name$() {\n"
352 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
353 " return &$name$_;\n"
354 "}\n");
355 }
356
GenerateClearingCode(io::Printer * printer) const357 void RepeatedPrimitiveFieldGenerator::GenerateClearingCode(
358 io::Printer* printer) const {
359 Formatter format(printer, variables_);
360 format("$name$_.Clear();\n");
361 }
362
GenerateMergingCode(io::Printer * printer) const363 void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(
364 io::Printer* printer) const {
365 Formatter format(printer, variables_);
366 format("$name$_.MergeFrom(from.$name$_);\n");
367 }
368
GenerateSwappingCode(io::Printer * printer) const369 void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
370 io::Printer* printer) const {
371 Formatter format(printer, variables_);
372 format("$name$_.InternalSwap(&other->$name$_);\n");
373 }
374
GenerateConstructorCode(io::Printer * printer) const375 void RepeatedPrimitiveFieldGenerator::GenerateConstructorCode(
376 io::Printer* printer) const {
377 // Not needed for repeated fields.
378 }
379
GenerateCopyConstructorCode(io::Printer * printer) const380 void RepeatedPrimitiveFieldGenerator::GenerateCopyConstructorCode(
381 io::Printer* printer) const {
382 Formatter format(printer, variables_);
383 format("$name$_.CopyFrom(from.$name$_);\n");
384 }
385
GenerateMergeFromCodedStream(io::Printer * printer) const386 void RepeatedPrimitiveFieldGenerator::GenerateMergeFromCodedStream(
387 io::Printer* printer) const {
388 Formatter format(printer, variables_);
389 format(
390 "DO_((::$proto_ns$::internal::WireFormatLite::$repeated_reader$<\n"
391 " $type$, "
392 "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
393 " $tag_size$, $tag$u, input, this->mutable_$name$())));\n");
394 }
395
GenerateMergeFromCodedStreamWithPacking(io::Printer * printer) const396 void RepeatedPrimitiveFieldGenerator::GenerateMergeFromCodedStreamWithPacking(
397 io::Printer* printer) const {
398 Formatter format(printer, variables_);
399 format(
400 "DO_((::$proto_ns$::internal::WireFormatLite::$packed_reader$<\n"
401 " $type$, "
402 "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
403 " input, this->mutable_$name$())));\n");
404 }
405
GenerateSerializeWithCachedSizes(io::Printer * printer) const406 void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizes(
407 io::Printer* printer) const {
408 Formatter format(printer, variables_);
409 bool array_written = false;
410 if (descriptor_->is_packed()) {
411 // Write the tag and the size.
412 format(
413 "if (this->$name$_size() > 0) {\n"
414 " ::$proto_ns$::internal::WireFormatLite::WriteTag("
415 "$number$, "
416 "::$proto_ns$::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
417 "output);\n"
418 " output->WriteVarint32(_$name$_cached_byte_size_.load(\n"
419 " std::memory_order_relaxed));\n");
420
421 if (FixedSize(descriptor_->type()) > 0) {
422 // TODO(ckennelly): Use RepeatedField<T>::unsafe_data() via
423 // WireFormatLite to access the contents of this->$name$_ to save a branch
424 // here.
425 format(
426 " "
427 "::$proto_ns$::internal::WireFormatLite::Write$declared_type$Array(\n"
428 " this->$name$().data(), this->$name$_size(), output);\n");
429 array_written = true; // Wrote array all at once
430 }
431 format("}\n");
432 }
433 if (!array_written) {
434 format("for (int i = 0, n = this->$name$_size(); i < n; i++) {\n");
435 if (descriptor_->is_packed()) {
436 format(
437 " "
438 "::$proto_ns$::internal::WireFormatLite::Write$declared_type$NoTag(\n"
439 " this->$name$(i), output);\n");
440 } else {
441 format(
442 " ::$proto_ns$::internal::WireFormatLite::Write$declared_type$(\n"
443 " $number$, this->$name$(i), output);\n");
444 }
445 format("}\n");
446 }
447 }
448
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const449 void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
450 io::Printer* printer) const {
451 Formatter format(printer, variables_);
452 if (descriptor_->is_packed()) {
453 // Write the tag and the size.
454 format(
455 "if (this->$name$_size() > 0) {\n"
456 " target = ::$proto_ns$::internal::WireFormatLite::WriteTagToArray(\n"
457 " $number$,\n"
458 " "
459 "::$proto_ns$::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
460 " target);\n"
461 " target = "
462 "::$proto_ns$::io::CodedOutputStream::WriteVarint32ToArray(\n"
463 " _$name$_cached_byte_size_.load(std::memory_order_relaxed),\n"
464 " target);\n"
465 " target = ::$proto_ns$::internal::WireFormatLite::\n"
466 " Write$declared_type$NoTagToArray(this->$name$_, target);\n"
467 "}\n");
468 } else {
469 format(
470 "target = ::$proto_ns$::internal::WireFormatLite::\n"
471 " Write$declared_type$ToArray($number$, this->$name$_, target);\n");
472 }
473 }
474
GenerateByteSize(io::Printer * printer) const475 void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
476 io::Printer* printer) const {
477 Formatter format(printer, variables_);
478 format("{\n");
479 format.Indent();
480 int fixed_size = FixedSize(descriptor_->type());
481 if (fixed_size == -1) {
482 format(
483 "size_t data_size = ::$proto_ns$::internal::WireFormatLite::\n"
484 " $declared_type$Size(this->$name$_);\n");
485 } else {
486 format(
487 "unsigned int count = static_cast<unsigned int>(this->$name$_size());\n"
488 "size_t data_size = $fixed_size$UL * count;\n");
489 }
490
491 if (descriptor_->is_packed()) {
492 format(
493 "if (data_size > 0) {\n"
494 " total_size += $tag_size$ +\n"
495 " ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
496 " static_cast<$int32$>(data_size));\n"
497 "}\n"
498 "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
499 "_$name$_cached_byte_size_.store(cached_size,\n"
500 " std::memory_order_relaxed);\n"
501 "total_size += data_size;\n");
502 } else {
503 format(
504 "total_size += $tag_size$ *\n"
505 " "
506 "::$proto_ns$::internal::FromIntSize(this->$name$_size());\n"
507 "total_size += data_size;\n");
508 }
509 format.Outdent();
510 format("}\n");
511 }
512
513 } // namespace cpp
514 } // namespace compiler
515 } // namespace protobuf
516 } // namespace google
517