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.
FixedSize(FieldDescriptor::Type type)52 int FixedSize(FieldDescriptor::Type type) {
53 switch (type) {
54 case FieldDescriptor::TYPE_INT32:
55 return -1;
56 case FieldDescriptor::TYPE_INT64:
57 return -1;
58 case FieldDescriptor::TYPE_UINT32:
59 return -1;
60 case FieldDescriptor::TYPE_UINT64:
61 return -1;
62 case FieldDescriptor::TYPE_SINT32:
63 return -1;
64 case FieldDescriptor::TYPE_SINT64:
65 return -1;
66 case FieldDescriptor::TYPE_FIXED32:
67 return WireFormatLite::kFixed32Size;
68 case FieldDescriptor::TYPE_FIXED64:
69 return WireFormatLite::kFixed64Size;
70 case FieldDescriptor::TYPE_SFIXED32:
71 return WireFormatLite::kSFixed32Size;
72 case FieldDescriptor::TYPE_SFIXED64:
73 return WireFormatLite::kSFixed64Size;
74 case FieldDescriptor::TYPE_FLOAT:
75 return WireFormatLite::kFloatSize;
76 case FieldDescriptor::TYPE_DOUBLE:
77 return WireFormatLite::kDoubleSize;
78
79 case FieldDescriptor::TYPE_BOOL:
80 return WireFormatLite::kBoolSize;
81 case FieldDescriptor::TYPE_ENUM:
82 return -1;
83
84 case FieldDescriptor::TYPE_STRING:
85 return -1;
86 case FieldDescriptor::TYPE_BYTES:
87 return -1;
88 case FieldDescriptor::TYPE_GROUP:
89 return -1;
90 case FieldDescriptor::TYPE_MESSAGE:
91 return -1;
92
93 // No default because we want the compiler to complain if any new
94 // types are added.
95 }
96 GOOGLE_LOG(FATAL) << "Can't get here.";
97 return -1;
98 }
99
SetPrimitiveVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables,const Options & options)100 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
101 std::map<std::string, std::string>* variables,
102 const Options& options) {
103 SetCommonFieldVariables(descriptor, variables, options);
104 (*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type());
105 (*variables)["default"] = DefaultValue(options, descriptor);
106 (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
107 int fixed_size = FixedSize(descriptor->type());
108 if (fixed_size != -1) {
109 (*variables)["fixed_size"] = StrCat(fixed_size);
110 }
111 (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name(
112 static_cast<FieldDescriptorProto_Type>(descriptor->type()));
113 (*variables)["full_name"] = descriptor->full_name();
114 }
115
116 } // namespace
117
118 // ===================================================================
119
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)120 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
121 const FieldDescriptor* descriptor, const Options& options)
122 : FieldGenerator(descriptor, options) {
123 SetPrimitiveVariables(descriptor, &variables_, options);
124 }
125
~PrimitiveFieldGenerator()126 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
127
GeneratePrivateMembers(io::Printer * printer) const128 void PrimitiveFieldGenerator::GeneratePrivateMembers(
129 io::Printer* printer) const {
130 Formatter format(printer, variables_);
131 format("$type$ $name$_;\n");
132 }
133
GenerateAccessorDeclarations(io::Printer * printer) const134 void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
135 io::Printer* printer) const {
136 Formatter format(printer, variables_);
137 format(
138 "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
139 "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
140 "private:\n"
141 "$type$ ${1$_internal_$name$$}$() const;\n"
142 "void ${1$_internal_set_$name$$}$($type$ value);\n"
143 "public:\n",
144 descriptor_);
145 }
146
GenerateInlineAccessorDefinitions(io::Printer * printer) const147 void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
148 io::Printer* printer) const {
149 Formatter format(printer, variables_);
150 format(
151 "inline $type$ $classname$::_internal_$name$() const {\n"
152 " return $name$_;\n"
153 "}\n"
154 "inline $type$ $classname$::$name$() const {\n"
155 "$annotate_accessor$"
156 " // @@protoc_insertion_point(field_get:$full_name$)\n"
157 " return _internal_$name$();\n"
158 "}\n"
159 "inline void $classname$::_internal_set_$name$($type$ value) {\n"
160 " $set_hasbit$\n"
161 " $name$_ = value;\n"
162 "}\n"
163 "inline void $classname$::set_$name$($type$ value) {\n"
164 "$annotate_accessor$"
165 " _internal_set_$name$(value);\n"
166 " // @@protoc_insertion_point(field_set:$full_name$)\n"
167 "}\n");
168 }
169
GenerateClearingCode(io::Printer * printer) const170 void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
171 Formatter format(printer, variables_);
172 format("$name$_ = $default$;\n");
173 }
174
GenerateMergingCode(io::Printer * printer) const175 void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
176 Formatter format(printer, variables_);
177 format("_internal_set_$name$(from._internal_$name$());\n");
178 }
179
GenerateSwappingCode(io::Printer * printer) const180 void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
181 Formatter format(printer, variables_);
182 format("swap($name$_, other->$name$_);\n");
183 }
184
GenerateConstructorCode(io::Printer * printer) const185 void PrimitiveFieldGenerator::GenerateConstructorCode(
186 io::Printer* printer) const {
187 Formatter format(printer, variables_);
188 format("$name$_ = $default$;\n");
189 }
190
GenerateCopyConstructorCode(io::Printer * printer) const191 void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
192 io::Printer* printer) const {
193 Formatter format(printer, variables_);
194 format("$name$_ = from.$name$_;\n");
195 }
196
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const197 void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
198 io::Printer* printer) const {
199 Formatter format(printer, variables_);
200 format(
201 "target = stream->EnsureSpace(target);\n"
202 "target = "
203 "::$proto_ns$::internal::WireFormatLite::Write$declared_type$ToArray("
204 "$number$, this->_internal_$name$(), target);\n");
205 }
206
GenerateByteSize(io::Printer * printer) const207 void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
208 Formatter format(printer, variables_);
209 int fixed_size = FixedSize(descriptor_->type());
210 if (fixed_size == -1) {
211 format(
212 "total_size += $tag_size$ +\n"
213 " ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
214 " this->_internal_$name$());\n");
215 } else {
216 format("total_size += $tag_size$ + $fixed_size$;\n");
217 }
218 }
219
220 // ===================================================================
221
PrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)222 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
223 const FieldDescriptor* descriptor, const Options& options)
224 : PrimitiveFieldGenerator(descriptor, options) {
225 SetCommonOneofFieldVariables(descriptor, &variables_);
226 }
227
~PrimitiveOneofFieldGenerator()228 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
229
GenerateInlineAccessorDefinitions(io::Printer * printer) const230 void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions(
231 io::Printer* printer) const {
232 Formatter format(printer, variables_);
233 format(
234 "inline $type$ $classname$::_internal_$name$() const {\n"
235 " if (_internal_has_$name$()) {\n"
236 " return $field_member$;\n"
237 " }\n"
238 " return $default$;\n"
239 "}\n"
240 "inline void $classname$::_internal_set_$name$($type$ value) {\n"
241 " if (!_internal_has_$name$()) {\n"
242 " clear_$oneof_name$();\n"
243 " set_has_$name$();\n"
244 " }\n"
245 " $field_member$ = value;\n"
246 "}\n"
247 "inline $type$ $classname$::$name$() const {\n"
248 "$annotate_accessor$"
249 " // @@protoc_insertion_point(field_get:$full_name$)\n"
250 " return _internal_$name$();\n"
251 "}\n"
252 "inline void $classname$::set_$name$($type$ value) {\n"
253 "$annotate_accessor$"
254 " _internal_set_$name$(value);\n"
255 " // @@protoc_insertion_point(field_set:$full_name$)\n"
256 "}\n");
257 }
258
GenerateClearingCode(io::Printer * printer) const259 void PrimitiveOneofFieldGenerator::GenerateClearingCode(
260 io::Printer* printer) const {
261 Formatter format(printer, variables_);
262 format("$field_member$ = $default$;\n");
263 }
264
GenerateSwappingCode(io::Printer * printer) const265 void PrimitiveOneofFieldGenerator::GenerateSwappingCode(
266 io::Printer* printer) const {
267 // Don't print any swapping code. Swapping the union will swap this field.
268 }
269
GenerateConstructorCode(io::Printer * printer) const270 void PrimitiveOneofFieldGenerator::GenerateConstructorCode(
271 io::Printer* printer) const {
272 Formatter format(printer, variables_);
273 format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
274 }
275
276 // ===================================================================
277
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)278 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
279 const FieldDescriptor* descriptor, const Options& options)
280 : FieldGenerator(descriptor, options) {
281 SetPrimitiveVariables(descriptor, &variables_, options);
282
283 if (descriptor->is_packed()) {
284 variables_["packed_reader"] = "ReadPackedPrimitive";
285 variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
286 } else {
287 variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
288 variables_["repeated_reader"] = "ReadRepeatedPrimitive";
289 }
290 }
291
~RepeatedPrimitiveFieldGenerator()292 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
293
GeneratePrivateMembers(io::Printer * printer) const294 void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers(
295 io::Printer* printer) const {
296 Formatter format(printer, variables_);
297 format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
298 if (descriptor_->is_packed() &&
299 HasGeneratedMethods(descriptor_->file(), options_)) {
300 format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
301 }
302 }
303
GenerateAccessorDeclarations(io::Printer * printer) const304 void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations(
305 io::Printer* printer) const {
306 Formatter format(printer, variables_);
307 format(
308 "private:\n"
309 "$type$ ${1$_internal_$name$$}$(int index) const;\n"
310 "const ::$proto_ns$::RepeatedField< $type$ >&\n"
311 " ${1$_internal_$name$$}$() const;\n"
312 "void ${1$_internal_add_$name$$}$($type$ value);\n"
313 "::$proto_ns$::RepeatedField< $type$ >*\n"
314 " ${1$_internal_mutable_$name$$}$();\n"
315 "public:\n"
316 "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
317 "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
318 "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
319 "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n"
320 " ${1$$name$$}$() const;\n"
321 "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n"
322 " ${1$mutable_$name$$}$();\n",
323 descriptor_);
324 }
325
GenerateInlineAccessorDefinitions(io::Printer * printer) const326 void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
327 io::Printer* printer) const {
328 Formatter format(printer, variables_);
329 format(
330 "inline $type$ $classname$::_internal_$name$(int index) const {\n"
331 " return $name$_.Get(index);\n"
332 "}\n"
333 "inline $type$ $classname$::$name$(int index) const {\n"
334 "$annotate_accessor$"
335 " // @@protoc_insertion_point(field_get:$full_name$)\n"
336 " return _internal_$name$(index);\n"
337 "}\n"
338 "inline void $classname$::set_$name$(int index, $type$ value) {\n"
339 "$annotate_accessor$"
340 " $name$_.Set(index, value);\n"
341 " // @@protoc_insertion_point(field_set:$full_name$)\n"
342 "}\n"
343 "inline void $classname$::_internal_add_$name$($type$ value) {\n"
344 " $name$_.Add(value);\n"
345 "}\n"
346 "inline void $classname$::add_$name$($type$ value) {\n"
347 "$annotate_accessor$"
348 " _internal_add_$name$(value);\n"
349 " // @@protoc_insertion_point(field_add:$full_name$)\n"
350 "}\n"
351 "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
352 "$classname$::_internal_$name$() const {\n"
353 " return $name$_;\n"
354 "}\n"
355 "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
356 "$classname$::$name$() const {\n"
357 "$annotate_accessor$"
358 " // @@protoc_insertion_point(field_list:$full_name$)\n"
359 " return _internal_$name$();\n"
360 "}\n"
361 "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
362 "$classname$::_internal_mutable_$name$() {\n"
363 " return &$name$_;\n"
364 "}\n"
365 "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
366 "$classname$::mutable_$name$() {\n"
367 "$annotate_accessor$"
368 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
369 " return _internal_mutable_$name$();\n"
370 "}\n");
371 }
372
GenerateClearingCode(io::Printer * printer) const373 void RepeatedPrimitiveFieldGenerator::GenerateClearingCode(
374 io::Printer* printer) const {
375 Formatter format(printer, variables_);
376 format("$name$_.Clear();\n");
377 }
378
GenerateMergingCode(io::Printer * printer) const379 void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(
380 io::Printer* printer) const {
381 Formatter format(printer, variables_);
382 format("$name$_.MergeFrom(from.$name$_);\n");
383 }
384
GenerateSwappingCode(io::Printer * printer) const385 void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
386 io::Printer* printer) const {
387 Formatter format(printer, variables_);
388 format("$name$_.InternalSwap(&other->$name$_);\n");
389 }
390
GenerateConstructorCode(io::Printer * printer) const391 void RepeatedPrimitiveFieldGenerator::GenerateConstructorCode(
392 io::Printer* printer) const {
393 // Not needed for repeated fields.
394 }
395
GenerateCopyConstructorCode(io::Printer * printer) const396 void RepeatedPrimitiveFieldGenerator::GenerateCopyConstructorCode(
397 io::Printer* printer) const {
398 Formatter format(printer, variables_);
399 format("$name$_.CopyFrom(from.$name$_);\n");
400 }
401
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const402 void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
403 io::Printer* printer) const {
404 Formatter format(printer, variables_);
405 if (descriptor_->is_packed()) {
406 if (FixedSize(descriptor_->type()) > 0) {
407 format(
408 "if (this->_internal_$name$_size() > 0) {\n"
409 " target = stream->WriteFixedPacked($number$, _internal_$name$(), "
410 "target);\n"
411 "}\n");
412 } else {
413 format(
414 "{\n"
415 " int byte_size = "
416 "_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n"
417 " if (byte_size > 0) {\n"
418 " target = stream->Write$declared_type$Packed(\n"
419 " $number$, _internal_$name$(), byte_size, target);\n"
420 " }\n"
421 "}\n");
422 }
423 } else {
424 format(
425 "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
426 " target = stream->EnsureSpace(target);\n"
427 " target = ::$proto_ns$::internal::WireFormatLite::"
428 "Write$declared_type$ToArray($number$, this->_internal_$name$(i), "
429 "target);\n"
430 "}\n");
431 }
432 }
433
GenerateByteSize(io::Printer * printer) const434 void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
435 io::Printer* printer) const {
436 Formatter format(printer, variables_);
437 format("{\n");
438 format.Indent();
439 int fixed_size = FixedSize(descriptor_->type());
440 if (fixed_size == -1) {
441 format(
442 "size_t data_size = ::$proto_ns$::internal::WireFormatLite::\n"
443 " $declared_type$Size(this->$name$_);\n");
444 } else {
445 format(
446 "unsigned int count = static_cast<unsigned "
447 "int>(this->_internal_$name$_size());\n"
448 "size_t data_size = $fixed_size$UL * count;\n");
449 }
450
451 if (descriptor_->is_packed()) {
452 format(
453 "if (data_size > 0) {\n"
454 " total_size += $tag_size$ +\n"
455 " ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
456 " static_cast<$int32$>(data_size));\n"
457 "}\n"
458 "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
459 "_$name$_cached_byte_size_.store(cached_size,\n"
460 " std::memory_order_relaxed);\n"
461 "total_size += data_size;\n");
462 } else {
463 format(
464 "total_size += $tag_size$ *\n"
465 " "
466 "::$proto_ns$::internal::FromIntSize(this->_internal_$name$_size());\n"
467 "total_size += data_size;\n");
468 }
469 format.Outdent();
470 format("}\n");
471 }
472
473 } // namespace cpp
474 } // namespace compiler
475 } // namespace protobuf
476 } // namespace google
477