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 
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 namespace {
48 
SetEnumVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables,const Options & options)49 void SetEnumVariables(const FieldDescriptor* descriptor,
50                       std::map<std::string, std::string>* variables,
51                       const Options& options) {
52   SetCommonFieldVariables(descriptor, variables, options);
53   const EnumValueDescriptor* default_value = descriptor->default_value_enum();
54   (*variables)["type"] = QualifiedClassName(descriptor->enum_type(), options);
55   (*variables)["default"] = Int32ToString(default_value->number());
56   (*variables)["full_name"] = descriptor->full_name();
57   (*variables)["cached_byte_size_name"] = MakeVarintCachedSizeName(descriptor);
58   (*variables)["cached_byte_size_field"] =
59       MakeVarintCachedSizeFieldName(descriptor);
60 }
61 
62 }  // namespace
63 
64 // ===================================================================
65 
EnumFieldGenerator(const FieldDescriptor * descriptor,const Options & options)66 EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
67                                        const Options& options)
68     : FieldGenerator(descriptor, options) {
69   SetEnumVariables(descriptor, &variables_, options);
70 }
71 
~EnumFieldGenerator()72 EnumFieldGenerator::~EnumFieldGenerator() {}
73 
GeneratePrivateMembers(io::Printer * printer) const74 void EnumFieldGenerator::GeneratePrivateMembers(io::Printer* printer) const {
75   Formatter format(printer, variables_);
76   format("int $name$_;\n");
77 }
78 
GenerateAccessorDeclarations(io::Printer * printer) const79 void EnumFieldGenerator::GenerateAccessorDeclarations(
80     io::Printer* printer) const {
81   Formatter format(printer, variables_);
82   format(
83       "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
84       "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
85       "private:\n"
86       "$type$ ${1$_internal_$name$$}$() const;\n"
87       "void ${1$_internal_set_$name$$}$($type$ value);\n"
88       "public:\n",
89       descriptor_);
90 }
91 
GenerateInlineAccessorDefinitions(io::Printer * printer) const92 void EnumFieldGenerator::GenerateInlineAccessorDefinitions(
93     io::Printer* printer) const {
94   Formatter format(printer, variables_);
95   format(
96       "inline $type$ $classname$::_internal_$name$() const {\n"
97       "  return static_cast< $type$ >($field$);\n"
98       "}\n"
99       "inline $type$ $classname$::$name$() const {\n"
100       "$annotate_get$"
101       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
102       "  return _internal_$name$();\n"
103       "}\n"
104       "inline void $classname$::_internal_set_$name$($type$ value) {\n");
105   if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
106     format("  assert($type$_IsValid(value));\n");
107   }
108   format(
109       "  $set_hasbit$\n"
110       "  $field$ = value;\n"
111       "}\n"
112       "inline void $classname$::set_$name$($type$ value) {\n"
113       "  _internal_set_$name$(value);\n"
114       "$annotate_set$"
115       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
116       "}\n");
117 }
118 
GenerateClearingCode(io::Printer * printer) const119 void EnumFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
120   Formatter format(printer, variables_);
121   format("$field$ = $default$;\n");
122 }
123 
GenerateMergingCode(io::Printer * printer) const124 void EnumFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
125   Formatter format(printer, variables_);
126   format("_internal_set_$name$(from._internal_$name$());\n");
127 }
128 
GenerateSwappingCode(io::Printer * printer) const129 void EnumFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
130   Formatter format(printer, variables_);
131   format("swap($field$, other->$field$);\n");
132 }
133 
GenerateConstructorCode(io::Printer * printer) const134 void EnumFieldGenerator::GenerateConstructorCode(io::Printer* printer) const {
135   Formatter format(printer, variables_);
136   format("$field$ = $default$;\n");
137 }
138 
GenerateCopyConstructorCode(io::Printer * printer) const139 void EnumFieldGenerator::GenerateCopyConstructorCode(
140     io::Printer* printer) const {
141   Formatter format(printer, variables_);
142   format("$field$ = from.$field$;\n");
143 }
144 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const145 void EnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
146     io::Printer* printer) const {
147   Formatter format(printer, variables_);
148   format(
149       "target = stream->EnsureSpace(target);\n"
150       "target = ::_pbi::WireFormatLite::WriteEnumToArray(\n"
151       "  $number$, this->_internal_$name$(), target);\n");
152 }
153 
GenerateByteSize(io::Printer * printer) const154 void EnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
155   Formatter format(printer, variables_);
156   format(
157       "total_size += $tag_size$ +\n"
158       "  ::_pbi::WireFormatLite::EnumSize(this->_internal_$name$());\n");
159 }
160 
GenerateConstinitInitializer(io::Printer * printer) const161 void EnumFieldGenerator::GenerateConstinitInitializer(
162     io::Printer* printer) const {
163   Formatter format(printer, variables_);
164   format("$name$_($default$)\n");
165 }
166 
167 // ===================================================================
168 
EnumOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)169 EnumOneofFieldGenerator::EnumOneofFieldGenerator(
170     const FieldDescriptor* descriptor, const Options& options)
171     : EnumFieldGenerator(descriptor, options) {
172   SetCommonOneofFieldVariables(descriptor, &variables_);
173 }
174 
~EnumOneofFieldGenerator()175 EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {}
176 
GenerateInlineAccessorDefinitions(io::Printer * printer) const177 void EnumOneofFieldGenerator::GenerateInlineAccessorDefinitions(
178     io::Printer* printer) const {
179   Formatter format(printer, variables_);
180   format(
181       "inline $type$ $classname$::_internal_$name$() const {\n"
182       "  if (_internal_has_$name$()) {\n"
183       "    return static_cast< $type$ >($field$);\n"
184       "  }\n"
185       "  return static_cast< $type$ >($default$);\n"
186       "}\n"
187       "inline $type$ $classname$::$name$() const {\n"
188       "$annotate_get$"
189       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
190       "  return _internal_$name$();\n"
191       "}\n"
192       "inline void $classname$::_internal_set_$name$($type$ value) {\n");
193   if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
194     format("  assert($type$_IsValid(value));\n");
195   }
196   format(
197       "  if (!_internal_has_$name$()) {\n"
198       "    clear_$oneof_name$();\n"
199       "    set_has_$name$();\n"
200       "  }\n"
201       "  $field$ = value;\n"
202       "}\n"
203       "inline void $classname$::set_$name$($type$ value) {\n"
204       "  _internal_set_$name$(value);\n"
205       "$annotate_set$"
206       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
207       "}\n");
208 }
209 
GenerateClearingCode(io::Printer * printer) const210 void EnumOneofFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
211   Formatter format(printer, variables_);
212   format("$field$ = $default$;\n");
213 }
214 
GenerateSwappingCode(io::Printer * printer) const215 void EnumOneofFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
216   // Don't print any swapping code. Swapping the union will swap this field.
217 }
218 
GenerateConstructorCode(io::Printer * printer) const219 void EnumOneofFieldGenerator::GenerateConstructorCode(
220     io::Printer* printer) const {
221   Formatter format(printer, variables_);
222   format("$ns$::_$classname$_default_instance_.$field$ = $default$;\n");
223 }
224 
225 // ===================================================================
226 
RepeatedEnumFieldGenerator(const FieldDescriptor * descriptor,const Options & options)227 RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
228     const FieldDescriptor* descriptor, const Options& options)
229     : FieldGenerator(descriptor, options) {
230   SetEnumVariables(descriptor, &variables_, options);
231 }
232 
~RepeatedEnumFieldGenerator()233 RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
234 
GeneratePrivateMembers(io::Printer * printer) const235 void RepeatedEnumFieldGenerator::GeneratePrivateMembers(
236     io::Printer* printer) const {
237   Formatter format(printer, variables_);
238   format("::$proto_ns$::RepeatedField<int> $name$_;\n");
239   if (descriptor_->is_packed() &&
240       HasGeneratedMethods(descriptor_->file(), options_)) {
241     format("mutable std::atomic<int> $cached_byte_size_name$;\n");
242   }
243 }
244 
GenerateAccessorDeclarations(io::Printer * printer) const245 void RepeatedEnumFieldGenerator::GenerateAccessorDeclarations(
246     io::Printer* printer) const {
247   Formatter format(printer, variables_);
248   format(
249       "private:\n"
250       "$type$ ${1$_internal_$name$$}$(int index) const;\n"
251       "void ${1$_internal_add_$name$$}$($type$ value);\n"
252       "::$proto_ns$::RepeatedField<int>* "
253       "${1$_internal_mutable_$name$$}$();\n"
254       "public:\n"
255       "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
256       "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
257       "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
258       "$deprecated_attr$const ::$proto_ns$::RepeatedField<int>& "
259       "${1$$name$$}$() const;\n"
260       "$deprecated_attr$::$proto_ns$::RepeatedField<int>* "
261       "${1$mutable_$name$$}$();\n",
262       descriptor_);
263 }
264 
GenerateInlineAccessorDefinitions(io::Printer * printer) const265 void RepeatedEnumFieldGenerator::GenerateInlineAccessorDefinitions(
266     io::Printer* printer) const {
267   Formatter format(printer, variables_);
268   format(
269       "inline $type$ $classname$::_internal_$name$(int index) const {\n"
270       "  return static_cast< $type$ >($field$.Get(index));\n"
271       "}\n"
272       "inline $type$ $classname$::$name$(int index) const {\n"
273       "$annotate_get$"
274       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
275       "  return _internal_$name$(index);\n"
276       "}\n"
277       "inline void $classname$::set_$name$(int index, $type$ value) {\n");
278   if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
279     format("  assert($type$_IsValid(value));\n");
280   }
281   format(
282       "  $field$.Set(index, value);\n"
283       "$annotate_set$"
284       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
285       "}\n"
286       "inline void $classname$::_internal_add_$name$($type$ value) {\n");
287   if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
288     format("  assert($type$_IsValid(value));\n");
289   }
290   format(
291       "  $field$.Add(value);\n"
292       "}\n"
293       "inline void $classname$::add_$name$($type$ value) {\n"
294       "  _internal_add_$name$(value);\n"
295       "$annotate_add$"
296       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
297       "}\n"
298       "inline const ::$proto_ns$::RepeatedField<int>&\n"
299       "$classname$::$name$() const {\n"
300       "$annotate_list$"
301       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
302       "  return $field$;\n"
303       "}\n"
304       "inline ::$proto_ns$::RepeatedField<int>*\n"
305       "$classname$::_internal_mutable_$name$() {\n"
306       "  return &$field$;\n"
307       "}\n"
308       "inline ::$proto_ns$::RepeatedField<int>*\n"
309       "$classname$::mutable_$name$() {\n"
310       "$annotate_mutable_list$"
311       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
312       "  return _internal_mutable_$name$();\n"
313       "}\n");
314 }
315 
GenerateClearingCode(io::Printer * printer) const316 void RepeatedEnumFieldGenerator::GenerateClearingCode(
317     io::Printer* printer) const {
318   Formatter format(printer, variables_);
319   format("$field$.Clear();\n");
320 }
321 
GenerateMergingCode(io::Printer * printer) const322 void RepeatedEnumFieldGenerator::GenerateMergingCode(
323     io::Printer* printer) const {
324   Formatter format(printer, variables_);
325   format("$field$.MergeFrom(from.$field$);\n");
326 }
327 
GenerateSwappingCode(io::Printer * printer) const328 void RepeatedEnumFieldGenerator::GenerateSwappingCode(
329     io::Printer* printer) const {
330   Formatter format(printer, variables_);
331   format("$field$.InternalSwap(&other->$field$);\n");
332 }
333 
GenerateConstructorCode(io::Printer * printer) const334 void RepeatedEnumFieldGenerator::GenerateConstructorCode(
335     io::Printer* printer) const {
336   // Not needed for repeated fields.
337 }
338 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const339 void RepeatedEnumFieldGenerator::GenerateSerializeWithCachedSizesToArray(
340     io::Printer* printer) const {
341   Formatter format(printer, variables_);
342   if (descriptor_->is_packed()) {
343     // Write the tag and the size.
344     format(
345         "{\n"
346         "  int byte_size = "
347         "$cached_byte_size_field$.load(std::memory_order_relaxed);\n"
348         "  if (byte_size > 0) {\n"
349         "    target = stream->WriteEnumPacked(\n"
350         "        $number$, $field$, byte_size, target);\n"
351         "  }\n"
352         "}\n");
353   } else {
354     format(
355         "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
356         "  target = stream->EnsureSpace(target);\n"
357         "  target = ::_pbi::WireFormatLite::WriteEnumToArray(\n"
358         "      $number$, this->_internal_$name$(i), target);\n"
359         "}\n");
360   }
361 }
362 
GenerateByteSize(io::Printer * printer) const363 void RepeatedEnumFieldGenerator::GenerateByteSize(io::Printer* printer) const {
364   Formatter format(printer, variables_);
365   format(
366       "{\n"
367       "  size_t data_size = 0;\n"
368       "  unsigned int count = static_cast<unsigned "
369       "int>(this->_internal_$name$_size());");
370   format.Indent();
371   format(
372       "for (unsigned int i = 0; i < count; i++) {\n"
373       "  data_size += ::_pbi::WireFormatLite::EnumSize(\n"
374       "    this->_internal_$name$(static_cast<int>(i)));\n"
375       "}\n");
376 
377   if (descriptor_->is_packed()) {
378     format(
379         "if (data_size > 0) {\n"
380         "  total_size += $tag_size$ +\n"
381         "    "
382         "::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n"
383         "}\n"
384         "int cached_size = ::_pbi::ToCachedSize(data_size);\n"
385         "$cached_byte_size_field$.store(cached_size,\n"
386         "                                std::memory_order_relaxed);\n"
387         "total_size += data_size;\n");
388   } else {
389     format("total_size += ($tag_size$UL * count) + data_size;\n");
390   }
391   format.Outdent();
392   format("}\n");
393 }
394 
GenerateConstinitInitializer(io::Printer * printer) const395 void RepeatedEnumFieldGenerator::GenerateConstinitInitializer(
396     io::Printer* printer) const {
397   Formatter format(printer, variables_);
398   format("$name$_()");
399   if (descriptor_->is_packed() &&
400       HasGeneratedMethods(descriptor_->file(), options_)) {
401     format("\n, $cached_byte_size_name$(0)");
402   }
403 }
404 
405 }  // namespace cpp
406 }  // namespace compiler
407 }  // namespace protobuf
408 }  // namespace google
409