• 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/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