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_enum_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 namespace {
47
SetEnumVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables,const Options & options)48 void SetEnumVariables(const FieldDescriptor* descriptor,
49 std::map<std::string, std::string>* variables,
50 const Options& options) {
51 SetCommonFieldVariables(descriptor, variables, options);
52 const EnumValueDescriptor* default_value = descriptor->default_value_enum();
53 (*variables)["type"] = QualifiedClassName(descriptor->enum_type(), options);
54 (*variables)["default"] = Int32ToString(default_value->number());
55 (*variables)["full_name"] = descriptor->full_name();
56 }
57
58 } // namespace
59
60 // ===================================================================
61
EnumFieldGenerator(const FieldDescriptor * descriptor,const Options & options)62 EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
63 const Options& options)
64 : FieldGenerator(descriptor, options) {
65 SetEnumVariables(descriptor, &variables_, options);
66 }
67
~EnumFieldGenerator()68 EnumFieldGenerator::~EnumFieldGenerator() {}
69
GeneratePrivateMembers(io::Printer * printer) const70 void EnumFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
71 Formatter format(printer, variables_);
72 format("int $name$_;\n");
73 }
74
GenerateAccessorDeclarations(io::Printer * printer) const75 void EnumFieldGenerator::GenerateAccessorDeclarations(
76 io::Printer* printer) const {
77 Formatter format(printer, variables_);
78 format(
79 "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
80 "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
81 "private:\n"
82 "$type$ ${1$_internal_$name$$}$() const;\n"
83 "void ${1$_internal_set_$name$$}$($type$ value);\n"
84 "public:\n",
85 descriptor_);
86 }
87
GenerateInlineAccessorDefinitions(io::Printer * printer) const88 void EnumFieldGenerator::GenerateInlineAccessorDefinitions(
89 io::Printer* printer) const {
90 Formatter format(printer, variables_);
91 format(
92 "inline $type$ $classname$::_internal_$name$() const {\n"
93 " return static_cast< $type$ >($name$_);\n"
94 "}\n"
95 "inline $type$ $classname$::$name$() const {\n"
96 "$annotate_accessor$"
97 " // @@protoc_insertion_point(field_get:$full_name$)\n"
98 " return _internal_$name$();\n"
99 "}\n"
100 "inline void $classname$::_internal_set_$name$($type$ value) {\n");
101 if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
102 format(" assert($type$_IsValid(value));\n");
103 }
104 format(
105 " $set_hasbit$\n"
106 " $name$_ = value;\n"
107 "}\n"
108 "inline void $classname$::set_$name$($type$ value) {\n"
109 "$annotate_accessor$"
110 " _internal_set_$name$(value);\n"
111 " // @@protoc_insertion_point(field_set:$full_name$)\n"
112 "}\n");
113 }
114
GenerateClearingCode(io::Printer * printer) const115 void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
116 Formatter format(printer, variables_);
117 format("$name$_ = $default$;\n");
118 }
119
GenerateMergingCode(io::Printer * printer) const120 void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
121 Formatter format(printer, variables_);
122 format("_internal_set_$name$(from._internal_$name$());\n");
123 }
124
GenerateSwappingCode(io::Printer * printer) const125 void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
126 Formatter format(printer, variables_);
127 format("swap($name$_, other->$name$_);\n");
128 }
129
GenerateConstructorCode(io::Printer * printer) const130 void EnumFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
131 Formatter format(printer, variables_);
132 format("$name$_ = $default$;\n");
133 }
134
GenerateCopyConstructorCode(io::Printer * printer) const135 void EnumFieldGenerator::GenerateCopyConstructorCode(
136 io::Printer* printer) const {
137 Formatter format(printer, variables_);
138 format("$name$_ = from.$name$_;\n");
139 }
140
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const141 void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
142 io::Printer* printer) const {
143 Formatter format(printer, variables_);
144 format(
145 "target = stream->EnsureSpace(target);\n"
146 "target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n"
147 " $number$, this->_internal_$name$(), target);\n");
148 }
149
GenerateByteSize(io::Printer * printer) const150 void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
151 Formatter format(printer, variables_);
152 format(
153 "total_size += $tag_size$ +\n"
154 " "
155 "::$proto_ns$::internal::WireFormatLite::EnumSize(this->_internal_$name$("
156 "));\n");
157 }
158
159 // ===================================================================
160
EnumOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)161 EnumOneofFieldGenerator::EnumOneofFieldGenerator(
162 const FieldDescriptor* descriptor, const Options& options)
163 : EnumFieldGenerator(descriptor, options) {
164 SetCommonOneofFieldVariables(descriptor, &variables_);
165 }
166
~EnumOneofFieldGenerator()167 EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
168
GenerateInlineAccessorDefinitions(io::Printer * printer) const169 void EnumOneofFieldGenerator::GenerateInlineAccessorDefinitions(
170 io::Printer* printer) const {
171 Formatter format(printer, variables_);
172 format(
173 "inline $type$ $classname$::_internal_$name$() const {\n"
174 " if (_internal_has_$name$()) {\n"
175 " return static_cast< $type$ >($field_member$);\n"
176 " }\n"
177 " return static_cast< $type$ >($default$);\n"
178 "}\n"
179 "inline $type$ $classname$::$name$() const {\n"
180 "$annotate_accessor$"
181 " // @@protoc_insertion_point(field_get:$full_name$)\n"
182 " return _internal_$name$();\n"
183 "}\n"
184 "inline void $classname$::_internal_set_$name$($type$ value) {\n");
185 if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
186 format(" assert($type$_IsValid(value));\n");
187 }
188 format(
189 " if (!_internal_has_$name$()) {\n"
190 " clear_$oneof_name$();\n"
191 " set_has_$name$();\n"
192 " }\n"
193 " $field_member$ = value;\n"
194 "}\n"
195 "inline void $classname$::set_$name$($type$ value) {\n"
196 "$annotate_accessor$"
197 " // @@protoc_insertion_point(field_set:$full_name$)\n"
198 " _internal_set_$name$(value);\n"
199 "}\n");
200 }
201
GenerateClearingCode(io::Printer * printer) const202 void EnumOneofFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
203 Formatter format(printer, variables_);
204 format("$field_member$ = $default$;\n");
205 }
206
GenerateSwappingCode(io::Printer * printer) const207 void EnumOneofFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
208 // Don't print any swapping code. Swapping the union will swap this field.
209 }
210
GenerateConstructorCode(io::Printer * printer) const211 void EnumOneofFieldGenerator::GenerateConstructorCode(
212 io::Printer* printer) const {
213 Formatter format(printer, variables_);
214 format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
215 }
216
217 // ===================================================================
218
RepeatedEnumFieldGenerator(const FieldDescriptor * descriptor,const Options & options)219 RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
220 const FieldDescriptor* descriptor, const Options& options)
221 : FieldGenerator(descriptor, options) {
222 SetEnumVariables(descriptor, &variables_, options);
223 }
224
~RepeatedEnumFieldGenerator()225 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
226
GeneratePrivateMembers(io::Printer * printer) const227 void RepeatedEnumFieldGenerator::GeneratePrivateMembers(
228 io::Printer* printer) const {
229 Formatter format(printer, variables_);
230 format("::$proto_ns$::RepeatedField<int> $name$_;\n");
231 if (descriptor_->is_packed() &&
232 HasGeneratedMethods(descriptor_->file(), options_)) {
233 format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
234 }
235 }
236
GenerateAccessorDeclarations(io::Printer * printer) const237 void RepeatedEnumFieldGenerator::GenerateAccessorDeclarations(
238 io::Printer* printer) const {
239 Formatter format(printer, variables_);
240 format(
241 "private:\n"
242 "$type$ ${1$_internal_$name$$}$(int index) const;\n"
243 "void ${1$_internal_add_$name$$}$($type$ value);\n"
244 "::$proto_ns$::RepeatedField<int>* "
245 "${1$_internal_mutable_$name$$}$();\n"
246 "public:\n"
247 "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
248 "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
249 "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
250 "$deprecated_attr$const ::$proto_ns$::RepeatedField<int>& "
251 "${1$$name$$}$() const;\n"
252 "$deprecated_attr$::$proto_ns$::RepeatedField<int>* "
253 "${1$mutable_$name$$}$();\n",
254 descriptor_);
255 }
256
GenerateInlineAccessorDefinitions(io::Printer * printer) const257 void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions(
258 io::Printer* printer) const {
259 Formatter format(printer, variables_);
260 format(
261 "inline $type$ $classname$::_internal_$name$(int index) const {\n"
262 " return static_cast< $type$ >($name$_.Get(index));\n"
263 "}\n"
264 "inline $type$ $classname$::$name$(int index) const {\n"
265 "$annotate_accessor$"
266 " // @@protoc_insertion_point(field_get:$full_name$)\n"
267 " return _internal_$name$(index);\n"
268 "}\n"
269 "inline void $classname$::set_$name$(int index, $type$ value) {\n"
270 "$annotate_accessor$");
271 if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
272 format(" assert($type$_IsValid(value));\n");
273 }
274 format(
275 " $name$_.Set(index, value);\n"
276 " // @@protoc_insertion_point(field_set:$full_name$)\n"
277 "}\n"
278 "inline void $classname$::_internal_add_$name$($type$ value) {\n");
279 if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
280 format(" assert($type$_IsValid(value));\n");
281 }
282 format(
283 " $name$_.Add(value);\n"
284 "}\n"
285 "inline void $classname$::add_$name$($type$ value) {\n"
286 "$annotate_accessor$"
287 " // @@protoc_insertion_point(field_add:$full_name$)\n"
288 " _internal_add_$name$(value);\n"
289 "}\n"
290 "inline const ::$proto_ns$::RepeatedField<int>&\n"
291 "$classname$::$name$() const {\n"
292 "$annotate_accessor$"
293 " // @@protoc_insertion_point(field_list:$full_name$)\n"
294 " return $name$_;\n"
295 "}\n"
296 "inline ::$proto_ns$::RepeatedField<int>*\n"
297 "$classname$::_internal_mutable_$name$() {\n"
298 " return &$name$_;\n"
299 "}\n"
300 "inline ::$proto_ns$::RepeatedField<int>*\n"
301 "$classname$::mutable_$name$() {\n"
302 "$annotate_accessor$"
303 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
304 " return _internal_mutable_$name$();\n"
305 "}\n");
306 }
307
GenerateClearingCode(io::Printer * printer) const308 void RepeatedEnumFieldGenerator::GenerateClearingCode(
309 io::Printer* printer) const {
310 Formatter format(printer, variables_);
311 format("$name$_.Clear();\n");
312 }
313
GenerateMergingCode(io::Printer * printer) const314 void RepeatedEnumFieldGenerator::GenerateMergingCode(
315 io::Printer* printer) const {
316 Formatter format(printer, variables_);
317 format("$name$_.MergeFrom(from.$name$_);\n");
318 }
319
GenerateSwappingCode(io::Printer * printer) const320 void RepeatedEnumFieldGenerator::GenerateSwappingCode(
321 io::Printer* printer) const {
322 Formatter format(printer, variables_);
323 format("$name$_.InternalSwap(&other->$name$_);\n");
324 }
325
GenerateConstructorCode(io::Printer * printer) const326 void RepeatedEnumFieldGenerator::GenerateConstructorCode(
327 io::Printer* printer) const {
328 // Not needed for repeated fields.
329 }
330
GenerateMergeFromCodedStream(io::Printer * printer) const331 void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStream(
332 io::Printer* printer) const {
333 Formatter format(printer, variables_);
334 // Don't use ReadRepeatedPrimitive here so that the enum can be validated.
335 format(
336 "int value = 0;\n"
337 "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
338 " int, ::$proto_ns$::internal::WireFormatLite::TYPE_ENUM>(\n"
339 " input, &value)));\n");
340 if (HasPreservingUnknownEnumSemantics(descriptor_)) {
341 format("add_$name$(static_cast< $type$ >(value));\n");
342 } else {
343 format(
344 "if ($type$_IsValid(value)) {\n"
345 " add_$name$(static_cast< $type$ >(value));\n");
346 if (UseUnknownFieldSet(descriptor_->file(), options_)) {
347 format(
348 "} else {\n"
349 " mutable_unknown_fields()->AddVarint(\n"
350 " $number$, static_cast<$uint64$>(value));\n");
351 } else {
352 format(
353 "} else {\n"
354 " unknown_fields_stream.WriteVarint32(tag);\n"
355 " unknown_fields_stream.WriteVarint32(\n"
356 " static_cast<$uint32$>(value));\n");
357 }
358 format("}\n");
359 }
360 }
361
GenerateMergeFromCodedStreamWithPacking(io::Printer * printer) const362 void RepeatedEnumFieldGenerator::GenerateMergeFromCodedStreamWithPacking(
363 io::Printer* printer) const {
364 Formatter format(printer, variables_);
365 if (!descriptor_->is_packed()) {
366 // This path is rarely executed, so we use a non-inlined implementation.
367 if (HasPreservingUnknownEnumSemantics(descriptor_)) {
368 format(
369 "DO_((::$proto_ns$::internal::"
370 "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
371 " input,\n"
372 " $number$,\n"
373 " nullptr,\n"
374 " nullptr,\n"
375 " this->_internal_mutable_$name$())));\n");
376 } else if (UseUnknownFieldSet(descriptor_->file(), options_)) {
377 format(
378 "DO_((::$proto_ns$::internal::WireFormat::"
379 "ReadPackedEnumPreserveUnknowns(\n"
380 " input,\n"
381 " $number$,\n"
382 " $type$_IsValid,\n"
383 " mutable_unknown_fields(),\n"
384 " this->_internal_mutable_$name$())));\n");
385 } else {
386 format(
387 "DO_((::$proto_ns$::internal::"
388 "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n"
389 " input,\n"
390 " $number$,\n"
391 " $type$_IsValid,\n"
392 " &unknown_fields_stream,\n"
393 " this->_internal_mutable_$name$())));\n");
394 }
395 } else {
396 format(
397 "$uint32$ length;\n"
398 "DO_(input->ReadVarint32(&length));\n"
399 "::$proto_ns$::io::CodedInputStream::Limit limit = "
400 "input->PushLimit(static_cast<int>(length));\n"
401 "while (input->BytesUntilLimit() > 0) {\n"
402 " int value = 0;\n"
403 " DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
404 " int, ::$proto_ns$::internal::WireFormatLite::TYPE_ENUM>(\n"
405 " input, &value)));\n");
406 if (HasPreservingUnknownEnumSemantics(descriptor_)) {
407 format(" add_$name$(static_cast< $type$ >(value));\n");
408 } else {
409 format(
410 " if ($type$_IsValid(value)) {\n"
411 " _internal_add_$name$(static_cast< $type$ >(value));\n"
412 " } else {\n");
413 if (UseUnknownFieldSet(descriptor_->file(), options_)) {
414 format(
415 " mutable_unknown_fields()->AddVarint(\n"
416 " $number$, static_cast<$uint64$>(value));\n");
417 } else {
418 format(
419 " unknown_fields_stream.WriteVarint32(tag);\n"
420 " unknown_fields_stream.WriteVarint32(\n"
421 " static_cast<$uint32$>(value));\n");
422 }
423 format(" }\n");
424 }
425 format(
426 "}\n"
427 "input->PopLimit(limit);\n");
428 }
429 }
430
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const431 void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
432 io::Printer* printer) const {
433 Formatter format(printer, variables_);
434 if (descriptor_->is_packed()) {
435 // Write the tag and the size.
436 format(
437 "{\n"
438 " int byte_size = "
439 "_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n"
440 " if (byte_size > 0) {\n"
441 " target = stream->WriteEnumPacked(\n"
442 " $number$, $name$_, byte_size, target);\n"
443 " }\n"
444 "}\n");
445 } else {
446 format(
447 "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
448 " target = stream->EnsureSpace(target);\n"
449 " target = ::$proto_ns$::internal::WireFormatLite::WriteEnumToArray(\n"
450 " $number$, this->_internal_$name$(i), target);\n"
451 "}\n");
452 }
453 }
454
GenerateByteSize(io::Printer * printer) const455 void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
456 Formatter format(printer, variables_);
457 format(
458 "{\n"
459 " size_t data_size = 0;\n"
460 " unsigned int count = static_cast<unsigned "
461 "int>(this->_internal_$name$_size());");
462 format.Indent();
463 format(
464 "for (unsigned int i = 0; i < count; i++) {\n"
465 " data_size += ::$proto_ns$::internal::WireFormatLite::EnumSize(\n"
466 " this->_internal_$name$(static_cast<int>(i)));\n"
467 "}\n");
468
469 if (descriptor_->is_packed()) {
470 format(
471 "if (data_size > 0) {\n"
472 " total_size += $tag_size$ +\n"
473 " ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
474 " static_cast<$int32$>(data_size));\n"
475 "}\n"
476 "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
477 "_$name$_cached_byte_size_.store(cached_size,\n"
478 " std::memory_order_relaxed);\n"
479 "total_size += data_size;\n");
480 } else {
481 format("total_size += ($tag_size$UL * count) + data_size;\n");
482 }
483 format.Outdent();
484 format("}\n");
485 }
486
487 } // namespace cpp
488 } // namespace compiler
489 } // namespace protobuf
490 } // namespace google
491