• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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