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
37 #include <google/protobuf/io/printer.h>
38 #include <google/protobuf/wire_format.h>
39 #include <google/protobuf/stubs/strutil.h>
40 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
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)["cached_byte_size_name"] = MakeVarintCachedSizeName(descriptor);
108 (*variables)["cached_byte_size_field"] =
109 MakeVarintCachedSizeFieldName(descriptor);
110 (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
111 int fixed_size = FixedSize(descriptor->type());
112 if (fixed_size != -1) {
113 (*variables)["fixed_size"] = StrCat(fixed_size);
114 }
115 (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name(
116 static_cast<FieldDescriptorProto_Type>(descriptor->type()));
117 (*variables)["full_name"] = descriptor->full_name();
118 }
119
120 } // namespace
121
122 // ===================================================================
123
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)124 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
125 const FieldDescriptor* descriptor, const Options& options)
126 : FieldGenerator(descriptor, options) {
127 SetPrimitiveVariables(descriptor, &variables_, options);
128 }
129
~PrimitiveFieldGenerator()130 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
131
GeneratePrivateMembers(io::Printer * printer) const132 void PrimitiveFieldGenerator::GeneratePrivateMembers(
133 io::Printer* printer) const {
134 Formatter format(printer, variables_);
135 format("$type$ $name$_;\n");
136 }
137
GenerateAccessorDeclarations(io::Printer * printer) const138 void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
139 io::Printer* printer) const {
140 Formatter format(printer, variables_);
141 format(
142 "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
143 "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
144 "private:\n"
145 "$type$ ${1$_internal_$name$$}$() const;\n"
146 "void ${1$_internal_set_$name$$}$($type$ value);\n"
147 "public:\n",
148 descriptor_);
149 }
150
GenerateInlineAccessorDefinitions(io::Printer * printer) const151 void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
152 io::Printer* printer) const {
153 Formatter format(printer, variables_);
154 format(
155 "inline $type$ $classname$::_internal_$name$() const {\n"
156 " return $field$;\n"
157 "}\n"
158 "inline $type$ $classname$::$name$() const {\n"
159 "$annotate_get$"
160 " // @@protoc_insertion_point(field_get:$full_name$)\n"
161 " return _internal_$name$();\n"
162 "}\n"
163 "inline void $classname$::_internal_set_$name$($type$ value) {\n"
164 " $set_hasbit$\n"
165 " $field$ = value;\n"
166 "}\n"
167 "inline void $classname$::set_$name$($type$ value) {\n"
168 " _internal_set_$name$(value);\n"
169 "$annotate_set$"
170 " // @@protoc_insertion_point(field_set:$full_name$)\n"
171 "}\n");
172 }
173
GenerateClearingCode(io::Printer * printer) const174 void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
175 Formatter format(printer, variables_);
176 format("$field$ = $default$;\n");
177 }
178
GenerateMergingCode(io::Printer * printer) const179 void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
180 Formatter format(printer, variables_);
181 format("_internal_set_$name$(from._internal_$name$());\n");
182 }
183
GenerateSwappingCode(io::Printer * printer) const184 void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
185 Formatter format(printer, variables_);
186 format("swap($field$, other->$field$);\n");
187 }
188
GenerateConstructorCode(io::Printer * printer) const189 void PrimitiveFieldGenerator::GenerateConstructorCode(
190 io::Printer* printer) const {
191 Formatter format(printer, variables_);
192 format("$field$ = $default$;\n");
193 }
194
GenerateCopyConstructorCode(io::Printer * printer) const195 void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
196 io::Printer* printer) const {
197 Formatter format(printer, variables_);
198 format("$field$ = from.$field$;\n");
199 }
200
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const201 void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
202 io::Printer* printer) const {
203 Formatter format(printer, variables_);
204 format(
205 "target = stream->EnsureSpace(target);\n"
206 "target = "
207 "::_pbi::WireFormatLite::Write$declared_type$ToArray("
208 "$number$, this->_internal_$name$(), target);\n");
209 }
210
GenerateByteSize(io::Printer * printer) const211 void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
212 Formatter format(printer, variables_);
213 int fixed_size = FixedSize(descriptor_->type());
214 if (fixed_size == -1) {
215 if (internal::WireFormat::TagSize(descriptor_->number(),
216 descriptor_->type()) == 1) {
217 // Adding one is very common and it turns out it can be done for
218 // free inside of WireFormatLite, so we can save an instruction here.
219 format(
220 "total_size += ::_pbi::WireFormatLite::"
221 "$declared_type$SizePlusOne(this->_internal_$name$());\n");
222 } else {
223 format(
224 "total_size += $tag_size$ +\n"
225 " ::_pbi::WireFormatLite::$declared_type$Size(\n"
226 " this->_internal_$name$());\n");
227 }
228 } else {
229 format("total_size += $tag_size$ + $fixed_size$;\n");
230 }
231 }
232
GenerateConstinitInitializer(io::Printer * printer) const233 void PrimitiveFieldGenerator::GenerateConstinitInitializer(
234 io::Printer* printer) const {
235 Formatter format(printer, variables_);
236 format("$name$_($default$)");
237 }
238
239 // ===================================================================
240
PrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)241 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
242 const FieldDescriptor* descriptor, const Options& options)
243 : PrimitiveFieldGenerator(descriptor, options) {
244 SetCommonOneofFieldVariables(descriptor, &variables_);
245 }
246
~PrimitiveOneofFieldGenerator()247 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
248
GenerateInlineAccessorDefinitions(io::Printer * printer) const249 void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions(
250 io::Printer* printer) const {
251 Formatter format(printer, variables_);
252 format(
253 "inline $type$ $classname$::_internal_$name$() const {\n"
254 " if (_internal_has_$name$()) {\n"
255 " return $field$;\n"
256 " }\n"
257 " return $default$;\n"
258 "}\n"
259 "inline void $classname$::_internal_set_$name$($type$ value) {\n"
260 " if (!_internal_has_$name$()) {\n"
261 " clear_$oneof_name$();\n"
262 " set_has_$name$();\n"
263 " }\n"
264 " $field$ = value;\n"
265 "}\n"
266 "inline $type$ $classname$::$name$() const {\n"
267 "$annotate_get$"
268 " // @@protoc_insertion_point(field_get:$full_name$)\n"
269 " return _internal_$name$();\n"
270 "}\n"
271 "inline void $classname$::set_$name$($type$ value) {\n"
272 " _internal_set_$name$(value);\n"
273 "$annotate_set$"
274 " // @@protoc_insertion_point(field_set:$full_name$)\n"
275 "}\n");
276 }
277
GenerateClearingCode(io::Printer * printer) const278 void PrimitiveOneofFieldGenerator::GenerateClearingCode(
279 io::Printer* printer) const {
280 Formatter format(printer, variables_);
281 format("$field$ = $default$;\n");
282 }
283
GenerateSwappingCode(io::Printer * printer) const284 void PrimitiveOneofFieldGenerator::GenerateSwappingCode(
285 io::Printer* printer) const {
286 // Don't print any swapping code. Swapping the union will swap this field.
287 }
288
GenerateConstructorCode(io::Printer * printer) const289 void PrimitiveOneofFieldGenerator::GenerateConstructorCode(
290 io::Printer* printer) const {
291 Formatter format(printer, variables_);
292 format("$ns$::_$classname$_default_instance_.$field$ = $default$;\n");
293 }
294
295 // ===================================================================
296
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)297 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
298 const FieldDescriptor* descriptor, const Options& options)
299 : FieldGenerator(descriptor, options) {
300 SetPrimitiveVariables(descriptor, &variables_, options);
301
302 if (descriptor->is_packed()) {
303 variables_["packed_reader"] = "ReadPackedPrimitive";
304 variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
305 } else {
306 variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
307 variables_["repeated_reader"] = "ReadRepeatedPrimitive";
308 }
309 }
310
~RepeatedPrimitiveFieldGenerator()311 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
312
GeneratePrivateMembers(io::Printer * printer) const313 void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers(
314 io::Printer* printer) const {
315 Formatter format(printer, variables_);
316 format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
317 if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
318 HasGeneratedMethods(descriptor_->file(), options_)) {
319 format("mutable std::atomic<int> $cached_byte_size_name$;\n");
320 }
321 }
322
GenerateAccessorDeclarations(io::Printer * printer) const323 void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations(
324 io::Printer* printer) const {
325 Formatter format(printer, variables_);
326 format(
327 "private:\n"
328 "$type$ ${1$_internal_$name$$}$(int index) const;\n"
329 "const ::$proto_ns$::RepeatedField< $type$ >&\n"
330 " ${1$_internal_$name$$}$() const;\n"
331 "void ${1$_internal_add_$name$$}$($type$ value);\n"
332 "::$proto_ns$::RepeatedField< $type$ >*\n"
333 " ${1$_internal_mutable_$name$$}$();\n"
334 "public:\n"
335 "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
336 "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
337 "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
338 "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n"
339 " ${1$$name$$}$() const;\n"
340 "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n"
341 " ${1$mutable_$name$$}$();\n",
342 descriptor_);
343 }
344
GenerateInlineAccessorDefinitions(io::Printer * printer) const345 void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
346 io::Printer* printer) const {
347 Formatter format(printer, variables_);
348 format(
349 "inline $type$ $classname$::_internal_$name$(int index) const {\n"
350 " return $field$.Get(index);\n"
351 "}\n"
352 "inline $type$ $classname$::$name$(int index) const {\n"
353 "$annotate_get$"
354 " // @@protoc_insertion_point(field_get:$full_name$)\n"
355 " return _internal_$name$(index);\n"
356 "}\n"
357 "inline void $classname$::set_$name$(int index, $type$ value) {\n"
358 "$annotate_set$"
359 " $field$.Set(index, value);\n"
360 " // @@protoc_insertion_point(field_set:$full_name$)\n"
361 "}\n"
362 "inline void $classname$::_internal_add_$name$($type$ value) {\n"
363 " $field$.Add(value);\n"
364 "}\n"
365 "inline void $classname$::add_$name$($type$ value) {\n"
366 " _internal_add_$name$(value);\n"
367 "$annotate_add$"
368 " // @@protoc_insertion_point(field_add:$full_name$)\n"
369 "}\n"
370 "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
371 "$classname$::_internal_$name$() const {\n"
372 " return $field$;\n"
373 "}\n"
374 "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
375 "$classname$::$name$() const {\n"
376 "$annotate_list$"
377 " // @@protoc_insertion_point(field_list:$full_name$)\n"
378 " return _internal_$name$();\n"
379 "}\n"
380 "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
381 "$classname$::_internal_mutable_$name$() {\n"
382 " return &$field$;\n"
383 "}\n"
384 "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
385 "$classname$::mutable_$name$() {\n"
386 "$annotate_mutable_list$"
387 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
388 " return _internal_mutable_$name$();\n"
389 "}\n");
390 }
391
GenerateClearingCode(io::Printer * printer) const392 void RepeatedPrimitiveFieldGenerator::GenerateClearingCode(
393 io::Printer* printer) const {
394 Formatter format(printer, variables_);
395 format("$field$.Clear();\n");
396 }
397
GenerateMergingCode(io::Printer * printer) const398 void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(
399 io::Printer* printer) const {
400 Formatter format(printer, variables_);
401 format("$field$.MergeFrom(from.$field$);\n");
402 }
403
GenerateSwappingCode(io::Printer * printer) const404 void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
405 io::Printer* printer) const {
406 Formatter format(printer, variables_);
407 format("$field$.InternalSwap(&other->$field$);\n");
408 }
409
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const410 void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
411 io::Printer* printer) const {
412 Formatter format(printer, variables_);
413 if (descriptor_->is_packed()) {
414 if (FixedSize(descriptor_->type()) == -1) {
415 format(
416 "{\n"
417 " int byte_size = "
418 "$cached_byte_size_field$.load(std::memory_order_relaxed);\n"
419 " if (byte_size > 0) {\n"
420 " target = stream->Write$declared_type$Packed(\n"
421 " $number$, _internal_$name$(), byte_size, target);\n"
422 " }\n"
423 "}\n");
424 } else {
425 format(
426 "if (this->_internal_$name$_size() > 0) {\n"
427 " target = stream->WriteFixedPacked($number$, _internal_$name$(), "
428 "target);\n"
429 "}\n");
430 }
431 } else {
432 format(
433 "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
434 " target = stream->EnsureSpace(target);\n"
435 " target = ::_pbi::WireFormatLite::"
436 "Write$declared_type$ToArray($number$, this->_internal_$name$(i), "
437 "target);\n"
438 "}\n");
439 }
440 }
441
GenerateByteSize(io::Printer * printer) const442 void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
443 io::Printer* printer) const {
444 Formatter format(printer, variables_);
445 format("{\n");
446 format.Indent();
447 int fixed_size = FixedSize(descriptor_->type());
448 if (fixed_size == -1) {
449 format(
450 "size_t data_size = ::_pbi::WireFormatLite::\n"
451 " $declared_type$Size(this->$field$);\n");
452 } else {
453 format(
454 "unsigned int count = static_cast<unsigned "
455 "int>(this->_internal_$name$_size());\n"
456 "size_t data_size = $fixed_size$UL * count;\n");
457 }
458
459 if (descriptor_->is_packed()) {
460 format(
461 "if (data_size > 0) {\n"
462 " total_size += $tag_size$ +\n"
463 " ::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n"
464 "}\n");
465 if (FixedSize(descriptor_->type()) == -1) {
466 format(
467 "int cached_size = ::_pbi::ToCachedSize(data_size);\n"
468 "$cached_byte_size_field$.store(cached_size,\n"
469 " std::memory_order_relaxed);\n");
470 }
471 format("total_size += data_size;\n");
472 } else {
473 format(
474 "total_size += $tag_size$ *\n"
475 " "
476 "::_pbi::FromIntSize(this->_internal_$name$_size());\n"
477 "total_size += data_size;\n");
478 }
479 format.Outdent();
480 format("}\n");
481 }
482
GenerateConstinitInitializer(io::Printer * printer) const483 void RepeatedPrimitiveFieldGenerator::GenerateConstinitInitializer(
484 io::Printer* printer) const {
485 Formatter format(printer, variables_);
486 format("$name$_()");
487 if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
488 HasGeneratedMethods(descriptor_->file(), options_)) {
489 format("\n, $cached_byte_size_name$(0)");
490 }
491 }
492
493 } // namespace cpp
494 } // namespace compiler
495 } // namespace protobuf
496 } // namespace google
497