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/enum_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/field.h>
41 #include <google/protobuf/compiler/cpp/helpers.h>
42
43 namespace google {
44 namespace protobuf {
45 namespace compiler {
46 namespace cpp {
47
48 namespace {
49
SetEnumVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables,const Options & options)50 void SetEnumVariables(const FieldDescriptor* descriptor,
51 std::map<std::string, std::string>* variables,
52 const Options& options) {
53 SetCommonFieldVariables(descriptor, variables, options);
54 const EnumValueDescriptor* default_value = descriptor->default_value_enum();
55 (*variables)["type"] = QualifiedClassName(descriptor->enum_type(), options);
56 (*variables)["default"] = Int32ToString(default_value->number());
57 (*variables)["full_name"] = descriptor->full_name();
58 (*variables)["cached_byte_size_name"] = MakeVarintCachedSizeName(descriptor);
59 bool cold = ShouldSplit(descriptor, options);
60 (*variables)["cached_byte_size_field"] =
61 MakeVarintCachedSizeFieldName(descriptor, cold);
62 }
63
64 } // namespace
65
66 // ===================================================================
67
EnumFieldGenerator(const FieldDescriptor * descriptor,const Options & options)68 EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
69 const Options& options)
70 : FieldGenerator(descriptor, options) {
71 SetEnumVariables(descriptor, &variables_, options);
72 }
73
~EnumFieldGenerator()74 EnumFieldGenerator::~EnumFieldGenerator() {}
75
GeneratePrivateMembers(io::Printer * printer) const76 void EnumFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
77 Formatter format(printer, variables_);
78 format("int $name$_;\n");
79 }
80
GenerateAccessorDeclarations(io::Printer * printer) const81 void EnumFieldGenerator::GenerateAccessorDeclarations(
82 io::Printer* printer) const {
83 Formatter format(printer, variables_);
84 format(
85 "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
86 "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
87 "private:\n"
88 "$type$ ${1$_internal_$name$$}$() const;\n"
89 "void ${1$_internal_set_$name$$}$($type$ value);\n"
90 "public:\n",
91 descriptor_);
92 }
93
GenerateInlineAccessorDefinitions(io::Printer * printer) const94 void EnumFieldGenerator::GenerateInlineAccessorDefinitions(
95 io::Printer* printer) const {
96 Formatter format(printer, variables_);
97 format(
98 "inline $type$ $classname$::_internal_$name$() const {\n"
99 " return static_cast< $type$ >($field$);\n"
100 "}\n"
101 "inline $type$ $classname$::$name$() const {\n"
102 "$annotate_get$"
103 " // @@protoc_insertion_point(field_get:$full_name$)\n"
104 " return _internal_$name$();\n"
105 "}\n"
106 "inline void $classname$::_internal_set_$name$($type$ value) {\n");
107 if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
108 format(" assert($type$_IsValid(value));\n");
109 }
110 format(
111 " $set_hasbit$\n"
112 " $field$ = value;\n"
113 "}\n"
114 "inline void $classname$::set_$name$($type$ value) {\n"
115 "$maybe_prepare_split_message$"
116 " _internal_set_$name$(value);\n"
117 "$annotate_set$"
118 " // @@protoc_insertion_point(field_set:$full_name$)\n"
119 "}\n");
120 }
121
GenerateClearingCode(io::Printer * printer) const122 void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
123 Formatter format(printer, variables_);
124 format("$field$ = $default$;\n");
125 }
126
GenerateMergingCode(io::Printer * printer) const127 void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
128 Formatter format(printer, variables_);
129 format("_this->_internal_set_$name$(from._internal_$name$());\n");
130 }
131
GenerateSwappingCode(io::Printer * printer) const132 void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
133 Formatter format(printer, variables_);
134 format("swap($field$, other->$field$);\n");
135 }
136
GenerateCopyConstructorCode(io::Printer * printer) const137 void EnumFieldGenerator::GenerateCopyConstructorCode(
138 io::Printer* printer) const {
139 Formatter format(printer, variables_);
140 format("_this->$field$ = from.$field$;\n");
141 }
142
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const143 void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
144 io::Printer* printer) const {
145 Formatter format(printer, variables_);
146 format(
147 "target = stream->EnsureSpace(target);\n"
148 "target = ::_pbi::WireFormatLite::WriteEnumToArray(\n"
149 " $number$, this->_internal_$name$(), target);\n");
150 }
151
GenerateByteSize(io::Printer * printer) const152 void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
153 Formatter format(printer, variables_);
154 format(
155 "total_size += $tag_size$ +\n"
156 " ::_pbi::WireFormatLite::EnumSize(this->_internal_$name$());\n");
157 }
158
GenerateConstexprAggregateInitializer(io::Printer * printer) const159 void EnumFieldGenerator::GenerateConstexprAggregateInitializer(
160 io::Printer* printer) const {
161 Formatter format(printer, variables_);
162 format("/*decltype($field$)*/$default$");
163 }
164
GenerateAggregateInitializer(io::Printer * printer) const165 void EnumFieldGenerator::GenerateAggregateInitializer(
166 io::Printer* printer) const {
167 Formatter format(printer, variables_);
168 if (ShouldSplit(descriptor_, options_)) {
169 format("decltype(Impl_::Split::$name$_){$default$}");
170 return;
171 }
172 format("decltype($field$){$default$}");
173 }
174
GenerateCopyAggregateInitializer(io::Printer * printer) const175 void EnumFieldGenerator::GenerateCopyAggregateInitializer(
176 io::Printer* printer) const {
177 Formatter format(printer, variables_);
178 format("decltype($field$){}");
179 }
180
181 // ===================================================================
182
EnumOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)183 EnumOneofFieldGenerator::EnumOneofFieldGenerator(
184 const FieldDescriptor* descriptor, const Options& options)
185 : EnumFieldGenerator(descriptor, options) {
186 SetCommonOneofFieldVariables(descriptor, &variables_);
187 }
188
~EnumOneofFieldGenerator()189 EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
190
GenerateInlineAccessorDefinitions(io::Printer * printer) const191 void EnumOneofFieldGenerator::GenerateInlineAccessorDefinitions(
192 io::Printer* printer) const {
193 Formatter format(printer, variables_);
194 format(
195 "inline $type$ $classname$::_internal_$name$() const {\n"
196 " if (_internal_has_$name$()) {\n"
197 " return static_cast< $type$ >($field$);\n"
198 " }\n"
199 " return static_cast< $type$ >($default$);\n"
200 "}\n"
201 "inline $type$ $classname$::$name$() const {\n"
202 "$annotate_get$"
203 " // @@protoc_insertion_point(field_get:$full_name$)\n"
204 " return _internal_$name$();\n"
205 "}\n"
206 "inline void $classname$::_internal_set_$name$($type$ value) {\n");
207 if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
208 format(" assert($type$_IsValid(value));\n");
209 }
210 format(
211 " if (!_internal_has_$name$()) {\n"
212 " clear_$oneof_name$();\n"
213 " set_has_$name$();\n"
214 " }\n"
215 " $field$ = value;\n"
216 "}\n"
217 "inline void $classname$::set_$name$($type$ value) {\n"
218 " _internal_set_$name$(value);\n"
219 "$annotate_set$"
220 " // @@protoc_insertion_point(field_set:$full_name$)\n"
221 "}\n");
222 }
223
GenerateClearingCode(io::Printer * printer) const224 void EnumOneofFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
225 Formatter format(printer, variables_);
226 format("$field$ = $default$;\n");
227 }
228
GenerateSwappingCode(io::Printer * printer) const229 void EnumOneofFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
230 // Don't print any swapping code. Swapping the union will swap this field.
231 }
232
GenerateConstructorCode(io::Printer * printer) const233 void EnumOneofFieldGenerator::GenerateConstructorCode(
234 io::Printer* printer) const {
235 Formatter format(printer, variables_);
236 format("$ns$::_$classname$_default_instance_.$field$ = $default$;\n");
237 }
238
239 // ===================================================================
240
RepeatedEnumFieldGenerator(const FieldDescriptor * descriptor,const Options & options)241 RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
242 const FieldDescriptor* descriptor, const Options& options)
243 : FieldGenerator(descriptor, options) {
244 SetEnumVariables(descriptor, &variables_, options);
245 }
246
~RepeatedEnumFieldGenerator()247 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
248
GeneratePrivateMembers(io::Printer * printer) const249 void RepeatedEnumFieldGenerator::GeneratePrivateMembers(
250 io::Printer* printer) const {
251 Formatter format(printer, variables_);
252 format("::$proto_ns$::RepeatedField<int> $name$_;\n");
253 if (descriptor_->is_packed() &&
254 HasGeneratedMethods(descriptor_->file(), options_)) {
255 format("mutable std::atomic<int> $cached_byte_size_name$;\n");
256 }
257 }
258
GenerateAccessorDeclarations(io::Printer * printer) const259 void RepeatedEnumFieldGenerator::GenerateAccessorDeclarations(
260 io::Printer* printer) const {
261 Formatter format(printer, variables_);
262 format(
263 "private:\n"
264 "$type$ ${1$_internal_$name$$}$(int index) const;\n"
265 "void ${1$_internal_add_$name$$}$($type$ value);\n"
266 "::$proto_ns$::RepeatedField<int>* "
267 "${1$_internal_mutable_$name$$}$();\n"
268 "public:\n"
269 "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
270 "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
271 "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
272 "$deprecated_attr$const ::$proto_ns$::RepeatedField<int>& "
273 "${1$$name$$}$() const;\n"
274 "$deprecated_attr$::$proto_ns$::RepeatedField<int>* "
275 "${1$mutable_$name$$}$();\n",
276 descriptor_);
277 }
278
GenerateInlineAccessorDefinitions(io::Printer * printer) const279 void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions(
280 io::Printer* printer) const {
281 Formatter format(printer, variables_);
282 format(
283 "inline $type$ $classname$::_internal_$name$(int index) const {\n"
284 " return static_cast< $type$ >($field$.Get(index));\n"
285 "}\n"
286 "inline $type$ $classname$::$name$(int index) const {\n"
287 "$annotate_get$"
288 " // @@protoc_insertion_point(field_get:$full_name$)\n"
289 " return _internal_$name$(index);\n"
290 "}\n"
291 "inline void $classname$::set_$name$(int index, $type$ value) {\n");
292 if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
293 format(" assert($type$_IsValid(value));\n");
294 }
295 format(
296 " $field$.Set(index, value);\n"
297 "$annotate_set$"
298 " // @@protoc_insertion_point(field_set:$full_name$)\n"
299 "}\n"
300 "inline void $classname$::_internal_add_$name$($type$ value) {\n");
301 if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
302 format(" assert($type$_IsValid(value));\n");
303 }
304 format(
305 " $field$.Add(value);\n"
306 "}\n"
307 "inline void $classname$::add_$name$($type$ value) {\n"
308 " _internal_add_$name$(value);\n"
309 "$annotate_add$"
310 " // @@protoc_insertion_point(field_add:$full_name$)\n"
311 "}\n"
312 "inline const ::$proto_ns$::RepeatedField<int>&\n"
313 "$classname$::$name$() const {\n"
314 "$annotate_list$"
315 " // @@protoc_insertion_point(field_list:$full_name$)\n"
316 " return $field$;\n"
317 "}\n"
318 "inline ::$proto_ns$::RepeatedField<int>*\n"
319 "$classname$::_internal_mutable_$name$() {\n"
320 " return &$field$;\n"
321 "}\n"
322 "inline ::$proto_ns$::RepeatedField<int>*\n"
323 "$classname$::mutable_$name$() {\n"
324 "$annotate_mutable_list$"
325 " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
326 " return _internal_mutable_$name$();\n"
327 "}\n");
328 }
329
GenerateClearingCode(io::Printer * printer) const330 void RepeatedEnumFieldGenerator::GenerateClearingCode(
331 io::Printer* printer) const {
332 Formatter format(printer, variables_);
333 format("$field$.Clear();\n");
334 }
335
GenerateMergingCode(io::Printer * printer) const336 void RepeatedEnumFieldGenerator::GenerateMergingCode(
337 io::Printer* printer) const {
338 Formatter format(printer, variables_);
339 format("_this->$field$.MergeFrom(from.$field$);\n");
340 }
341
GenerateSwappingCode(io::Printer * printer) const342 void RepeatedEnumFieldGenerator::GenerateSwappingCode(
343 io::Printer* printer) const {
344 Formatter format(printer, variables_);
345 format("$field$.InternalSwap(&other->$field$);\n");
346 }
347
GenerateConstructorCode(io::Printer * printer) const348 void RepeatedEnumFieldGenerator::GenerateConstructorCode(
349 io::Printer* printer) const {
350 // Not needed for repeated fields.
351 }
352
GenerateDestructorCode(io::Printer * printer) const353 void RepeatedEnumFieldGenerator::GenerateDestructorCode(
354 io::Printer* printer) const {
355 Formatter format(printer, variables_);
356 format("$field$.~RepeatedField();\n");
357 }
358
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const359 void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
360 io::Printer* printer) const {
361 Formatter format(printer, variables_);
362 if (descriptor_->is_packed()) {
363 // Write the tag and the size.
364 format(
365 "{\n"
366 " int byte_size = "
367 "$cached_byte_size_field$.load(std::memory_order_relaxed);\n"
368 " if (byte_size > 0) {\n"
369 " target = stream->WriteEnumPacked(\n"
370 " $number$, $field$, byte_size, target);\n"
371 " }\n"
372 "}\n");
373 } else {
374 format(
375 "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
376 " target = stream->EnsureSpace(target);\n"
377 " target = ::_pbi::WireFormatLite::WriteEnumToArray(\n"
378 " $number$, this->_internal_$name$(i), target);\n"
379 "}\n");
380 }
381 }
382
GenerateByteSize(io::Printer * printer) const383 void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
384 Formatter format(printer, variables_);
385 format(
386 "{\n"
387 " size_t data_size = 0;\n"
388 " unsigned int count = static_cast<unsigned "
389 "int>(this->_internal_$name$_size());");
390 format.Indent();
391 format(
392 "for (unsigned int i = 0; i < count; i++) {\n"
393 " data_size += ::_pbi::WireFormatLite::EnumSize(\n"
394 " this->_internal_$name$(static_cast<int>(i)));\n"
395 "}\n");
396
397 if (descriptor_->is_packed()) {
398 format(
399 "if (data_size > 0) {\n"
400 " total_size += $tag_size$ +\n"
401 " "
402 "::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n"
403 "}\n"
404 "int cached_size = ::_pbi::ToCachedSize(data_size);\n"
405 "$cached_byte_size_field$.store(cached_size,\n"
406 " std::memory_order_relaxed);\n"
407 "total_size += data_size;\n");
408 } else {
409 format("total_size += ($tag_size$UL * count) + data_size;\n");
410 }
411 format.Outdent();
412 format("}\n");
413 }
414
GenerateConstexprAggregateInitializer(io::Printer * printer) const415 void RepeatedEnumFieldGenerator::GenerateConstexprAggregateInitializer(
416 io::Printer* printer) const {
417 Formatter format(printer, variables_);
418 format("/*decltype($field$)*/{}");
419 if (descriptor_->is_packed() &&
420 HasGeneratedMethods(descriptor_->file(), options_)) {
421 format("\n, /*decltype($cached_byte_size_field$)*/{0}");
422 }
423 }
424
GenerateAggregateInitializer(io::Printer * printer) const425 void RepeatedEnumFieldGenerator::GenerateAggregateInitializer(
426 io::Printer* printer) const {
427 Formatter format(printer, variables_);
428 format("decltype($field$){arena}");
429 if (descriptor_->is_packed() &&
430 HasGeneratedMethods(descriptor_->file(), options_)) {
431 // std::atomic has no copy constructor, which prevents explicit aggregate
432 // initialization pre-C++17.
433 format("\n, /*decltype($cached_byte_size_field$)*/{0}");
434 }
435 }
436
GenerateCopyAggregateInitializer(io::Printer * printer) const437 void RepeatedEnumFieldGenerator::GenerateCopyAggregateInitializer(
438 io::Printer* printer) const {
439 Formatter format(printer, variables_);
440 format("decltype($field$){from.$field$}");
441 if (descriptor_->is_packed() &&
442 HasGeneratedMethods(descriptor_->file(), options_)) {
443 // std::atomic has no copy constructor.
444 format("\n, /*decltype($cached_byte_size_field$)*/{0}");
445 }
446 }
447
448 } // namespace cpp
449 } // namespace compiler
450 } // namespace protobuf
451 } // namespace google
452