• 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_primitive_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 using internal::WireFormatLite;
48 
49 namespace {
50 
51 // For encodings with fixed sizes, returns that size in bytes.  Otherwise
52 // returns -1.
FixedSize(FieldDescriptor::Type type)53 int FixedSize(FieldDescriptor::Type type) {
54   switch (type) {
55     case FieldDescriptor::TYPE_INT32:
56       return -1;
57     case FieldDescriptor::TYPE_INT64:
58       return -1;
59     case FieldDescriptor::TYPE_UINT32:
60       return -1;
61     case FieldDescriptor::TYPE_UINT64:
62       return -1;
63     case FieldDescriptor::TYPE_SINT32:
64       return -1;
65     case FieldDescriptor::TYPE_SINT64:
66       return -1;
67     case FieldDescriptor::TYPE_FIXED32:
68       return WireFormatLite::kFixed32Size;
69     case FieldDescriptor::TYPE_FIXED64:
70       return WireFormatLite::kFixed64Size;
71     case FieldDescriptor::TYPE_SFIXED32:
72       return WireFormatLite::kSFixed32Size;
73     case FieldDescriptor::TYPE_SFIXED64:
74       return WireFormatLite::kSFixed64Size;
75     case FieldDescriptor::TYPE_FLOAT:
76       return WireFormatLite::kFloatSize;
77     case FieldDescriptor::TYPE_DOUBLE:
78       return WireFormatLite::kDoubleSize;
79 
80     case FieldDescriptor::TYPE_BOOL:
81       return WireFormatLite::kBoolSize;
82     case FieldDescriptor::TYPE_ENUM:
83       return -1;
84 
85     case FieldDescriptor::TYPE_STRING:
86       return -1;
87     case FieldDescriptor::TYPE_BYTES:
88       return -1;
89     case FieldDescriptor::TYPE_GROUP:
90       return -1;
91     case FieldDescriptor::TYPE_MESSAGE:
92       return -1;
93 
94       // No default because we want the compiler to complain if any new
95       // types are added.
96   }
97   GOOGLE_LOG(FATAL) << "Can't get here.";
98   return -1;
99 }
100 
SetPrimitiveVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables,const Options & options)101 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
102                            std::map<std::string, std::string>* variables,
103                            const Options& options) {
104   SetCommonFieldVariables(descriptor, variables, options);
105   (*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type());
106   (*variables)["default"] = DefaultValue(options, descriptor);
107   (*variables)["cached_byte_size_name"] = MakeVarintCachedSizeName(descriptor);
108   (*variables)["cached_byte_size_field"] =
109       MakeVarintCachedSizeFieldName(descriptor);
110   (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
111   int fixed_size = FixedSize(descriptor->type());
112   if (fixed_size != -1) {
113     (*variables)["fixed_size"] = StrCat(fixed_size);
114   }
115   (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name(
116       static_cast<FieldDescriptorProto_Type>(descriptor->type()));
117   (*variables)["full_name"] = descriptor->full_name();
118 }
119 
120 }  // namespace
121 
122 // ===================================================================
123 
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)124 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
125     const FieldDescriptor* descriptor, const Options& options)
126     : FieldGenerator(descriptor, options) {
127   SetPrimitiveVariables(descriptor, &variables_, options);
128 }
129 
~PrimitiveFieldGenerator()130 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
131 
GeneratePrivateMembers(io::Printer * printer) const132 void PrimitiveFieldGenerator::GeneratePrivateMembers(
133     io::Printer* printer) const {
134   Formatter format(printer, variables_);
135   format("$type$ $name$_;\n");
136 }
137 
GenerateAccessorDeclarations(io::Printer * printer) const138 void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
139     io::Printer* printer) const {
140   Formatter format(printer, variables_);
141   format(
142       "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
143       "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
144       "private:\n"
145       "$type$ ${1$_internal_$name$$}$() const;\n"
146       "void ${1$_internal_set_$name$$}$($type$ value);\n"
147       "public:\n",
148       descriptor_);
149 }
150 
GenerateInlineAccessorDefinitions(io::Printer * printer) const151 void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
152     io::Printer* printer) const {
153   Formatter format(printer, variables_);
154   format(
155       "inline $type$ $classname$::_internal_$name$() const {\n"
156       "  return $field$;\n"
157       "}\n"
158       "inline $type$ $classname$::$name$() const {\n"
159       "$annotate_get$"
160       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
161       "  return _internal_$name$();\n"
162       "}\n"
163       "inline void $classname$::_internal_set_$name$($type$ value) {\n"
164       "  $set_hasbit$\n"
165       "  $field$ = value;\n"
166       "}\n"
167       "inline void $classname$::set_$name$($type$ value) {\n"
168       "  _internal_set_$name$(value);\n"
169       "$annotate_set$"
170       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
171       "}\n");
172 }
173 
GenerateClearingCode(io::Printer * printer) const174 void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
175   Formatter format(printer, variables_);
176   format("$field$ = $default$;\n");
177 }
178 
GenerateMergingCode(io::Printer * printer) const179 void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
180   Formatter format(printer, variables_);
181   format("_internal_set_$name$(from._internal_$name$());\n");
182 }
183 
GenerateSwappingCode(io::Printer * printer) const184 void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
185   Formatter format(printer, variables_);
186   format("swap($field$, other->$field$);\n");
187 }
188 
GenerateConstructorCode(io::Printer * printer) const189 void PrimitiveFieldGenerator::GenerateConstructorCode(
190     io::Printer* printer) const {
191   Formatter format(printer, variables_);
192   format("$field$ = $default$;\n");
193 }
194 
GenerateCopyConstructorCode(io::Printer * printer) const195 void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
196     io::Printer* printer) const {
197   Formatter format(printer, variables_);
198   format("$field$ = from.$field$;\n");
199 }
200 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const201 void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
202     io::Printer* printer) const {
203   Formatter format(printer, variables_);
204   format(
205       "target = stream->EnsureSpace(target);\n"
206       "target = "
207       "::_pbi::WireFormatLite::Write$declared_type$ToArray("
208       "$number$, this->_internal_$name$(), target);\n");
209 }
210 
GenerateByteSize(io::Printer * printer) const211 void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
212   Formatter format(printer, variables_);
213   int fixed_size = FixedSize(descriptor_->type());
214   if (fixed_size == -1) {
215     if (internal::WireFormat::TagSize(descriptor_->number(),
216                                       descriptor_->type()) == 1) {
217       // Adding one is very common and it turns out it can be done for
218       // free inside of WireFormatLite, so we can save an instruction here.
219       format(
220           "total_size += ::_pbi::WireFormatLite::"
221           "$declared_type$SizePlusOne(this->_internal_$name$());\n");
222     } else {
223       format(
224           "total_size += $tag_size$ +\n"
225           "  ::_pbi::WireFormatLite::$declared_type$Size(\n"
226           "    this->_internal_$name$());\n");
227     }
228   } else {
229     format("total_size += $tag_size$ + $fixed_size$;\n");
230   }
231 }
232 
GenerateConstinitInitializer(io::Printer * printer) const233 void PrimitiveFieldGenerator::GenerateConstinitInitializer(
234     io::Printer* printer) const {
235   Formatter format(printer, variables_);
236   format("$name$_($default$)");
237 }
238 
239 // ===================================================================
240 
PrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)241 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
242     const FieldDescriptor* descriptor, const Options& options)
243     : PrimitiveFieldGenerator(descriptor, options) {
244   SetCommonOneofFieldVariables(descriptor, &variables_);
245 }
246 
~PrimitiveOneofFieldGenerator()247 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
248 
GenerateInlineAccessorDefinitions(io::Printer * printer) const249 void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions(
250     io::Printer* printer) const {
251   Formatter format(printer, variables_);
252   format(
253       "inline $type$ $classname$::_internal_$name$() const {\n"
254       "  if (_internal_has_$name$()) {\n"
255       "    return $field$;\n"
256       "  }\n"
257       "  return $default$;\n"
258       "}\n"
259       "inline void $classname$::_internal_set_$name$($type$ value) {\n"
260       "  if (!_internal_has_$name$()) {\n"
261       "    clear_$oneof_name$();\n"
262       "    set_has_$name$();\n"
263       "  }\n"
264       "  $field$ = value;\n"
265       "}\n"
266       "inline $type$ $classname$::$name$() const {\n"
267       "$annotate_get$"
268       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
269       "  return _internal_$name$();\n"
270       "}\n"
271       "inline void $classname$::set_$name$($type$ value) {\n"
272       "  _internal_set_$name$(value);\n"
273       "$annotate_set$"
274       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
275       "}\n");
276 }
277 
GenerateClearingCode(io::Printer * printer) const278 void PrimitiveOneofFieldGenerator::GenerateClearingCode(
279     io::Printer* printer) const {
280   Formatter format(printer, variables_);
281   format("$field$ = $default$;\n");
282 }
283 
GenerateSwappingCode(io::Printer * printer) const284 void PrimitiveOneofFieldGenerator::GenerateSwappingCode(
285     io::Printer* printer) const {
286   // Don't print any swapping code. Swapping the union will swap this field.
287 }
288 
GenerateConstructorCode(io::Printer * printer) const289 void PrimitiveOneofFieldGenerator::GenerateConstructorCode(
290     io::Printer* printer) const {
291   Formatter format(printer, variables_);
292   format("$ns$::_$classname$_default_instance_.$field$ = $default$;\n");
293 }
294 
295 // ===================================================================
296 
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)297 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
298     const FieldDescriptor* descriptor, const Options& options)
299     : FieldGenerator(descriptor, options) {
300   SetPrimitiveVariables(descriptor, &variables_, options);
301 
302   if (descriptor->is_packed()) {
303     variables_["packed_reader"] = "ReadPackedPrimitive";
304     variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
305   } else {
306     variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
307     variables_["repeated_reader"] = "ReadRepeatedPrimitive";
308   }
309 }
310 
~RepeatedPrimitiveFieldGenerator()311 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
312 
GeneratePrivateMembers(io::Printer * printer) const313 void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers(
314     io::Printer* printer) const {
315   Formatter format(printer, variables_);
316   format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
317   if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
318       HasGeneratedMethods(descriptor_->file(), options_)) {
319     format("mutable std::atomic<int> $cached_byte_size_name$;\n");
320   }
321 }
322 
GenerateAccessorDeclarations(io::Printer * printer) const323 void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations(
324     io::Printer* printer) const {
325   Formatter format(printer, variables_);
326   format(
327       "private:\n"
328       "$type$ ${1$_internal_$name$$}$(int index) const;\n"
329       "const ::$proto_ns$::RepeatedField< $type$ >&\n"
330       "    ${1$_internal_$name$$}$() const;\n"
331       "void ${1$_internal_add_$name$$}$($type$ value);\n"
332       "::$proto_ns$::RepeatedField< $type$ >*\n"
333       "    ${1$_internal_mutable_$name$$}$();\n"
334       "public:\n"
335       "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
336       "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
337       "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
338       "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n"
339       "    ${1$$name$$}$() const;\n"
340       "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n"
341       "    ${1$mutable_$name$$}$();\n",
342       descriptor_);
343 }
344 
GenerateInlineAccessorDefinitions(io::Printer * printer) const345 void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
346     io::Printer* printer) const {
347   Formatter format(printer, variables_);
348   format(
349       "inline $type$ $classname$::_internal_$name$(int index) const {\n"
350       "  return $field$.Get(index);\n"
351       "}\n"
352       "inline $type$ $classname$::$name$(int index) const {\n"
353       "$annotate_get$"
354       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
355       "  return _internal_$name$(index);\n"
356       "}\n"
357       "inline void $classname$::set_$name$(int index, $type$ value) {\n"
358       "$annotate_set$"
359       "  $field$.Set(index, value);\n"
360       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
361       "}\n"
362       "inline void $classname$::_internal_add_$name$($type$ value) {\n"
363       "  $field$.Add(value);\n"
364       "}\n"
365       "inline void $classname$::add_$name$($type$ value) {\n"
366       "  _internal_add_$name$(value);\n"
367       "$annotate_add$"
368       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
369       "}\n"
370       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
371       "$classname$::_internal_$name$() const {\n"
372       "  return $field$;\n"
373       "}\n"
374       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
375       "$classname$::$name$() const {\n"
376       "$annotate_list$"
377       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
378       "  return _internal_$name$();\n"
379       "}\n"
380       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
381       "$classname$::_internal_mutable_$name$() {\n"
382       "  return &$field$;\n"
383       "}\n"
384       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
385       "$classname$::mutable_$name$() {\n"
386       "$annotate_mutable_list$"
387       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
388       "  return _internal_mutable_$name$();\n"
389       "}\n");
390 }
391 
GenerateClearingCode(io::Printer * printer) const392 void RepeatedPrimitiveFieldGenerator::GenerateClearingCode(
393     io::Printer* printer) const {
394   Formatter format(printer, variables_);
395   format("$field$.Clear();\n");
396 }
397 
GenerateMergingCode(io::Printer * printer) const398 void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(
399     io::Printer* printer) const {
400   Formatter format(printer, variables_);
401   format("$field$.MergeFrom(from.$field$);\n");
402 }
403 
GenerateSwappingCode(io::Printer * printer) const404 void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
405     io::Printer* printer) const {
406   Formatter format(printer, variables_);
407   format("$field$.InternalSwap(&other->$field$);\n");
408 }
409 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const410 void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
411     io::Printer* printer) const {
412   Formatter format(printer, variables_);
413   if (descriptor_->is_packed()) {
414     if (FixedSize(descriptor_->type()) == -1) {
415       format(
416           "{\n"
417           "  int byte_size = "
418           "$cached_byte_size_field$.load(std::memory_order_relaxed);\n"
419           "  if (byte_size > 0) {\n"
420           "    target = stream->Write$declared_type$Packed(\n"
421           "        $number$, _internal_$name$(), byte_size, target);\n"
422           "  }\n"
423           "}\n");
424     } else {
425       format(
426           "if (this->_internal_$name$_size() > 0) {\n"
427           "  target = stream->WriteFixedPacked($number$, _internal_$name$(), "
428           "target);\n"
429           "}\n");
430     }
431   } else {
432     format(
433         "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
434         "  target = stream->EnsureSpace(target);\n"
435         "  target = ::_pbi::WireFormatLite::"
436         "Write$declared_type$ToArray($number$, this->_internal_$name$(i), "
437         "target);\n"
438         "}\n");
439   }
440 }
441 
GenerateByteSize(io::Printer * printer) const442 void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
443     io::Printer* printer) const {
444   Formatter format(printer, variables_);
445   format("{\n");
446   format.Indent();
447   int fixed_size = FixedSize(descriptor_->type());
448   if (fixed_size == -1) {
449     format(
450         "size_t data_size = ::_pbi::WireFormatLite::\n"
451         "  $declared_type$Size(this->$field$);\n");
452   } else {
453     format(
454         "unsigned int count = static_cast<unsigned "
455         "int>(this->_internal_$name$_size());\n"
456         "size_t data_size = $fixed_size$UL * count;\n");
457   }
458 
459   if (descriptor_->is_packed()) {
460     format(
461         "if (data_size > 0) {\n"
462         "  total_size += $tag_size$ +\n"
463         "    ::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n"
464         "}\n");
465     if (FixedSize(descriptor_->type()) == -1) {
466       format(
467           "int cached_size = ::_pbi::ToCachedSize(data_size);\n"
468           "$cached_byte_size_field$.store(cached_size,\n"
469           "                                std::memory_order_relaxed);\n");
470     }
471     format("total_size += data_size;\n");
472   } else {
473     format(
474         "total_size += $tag_size$ *\n"
475         "              "
476         "::_pbi::FromIntSize(this->_internal_$name$_size());\n"
477         "total_size += data_size;\n");
478   }
479   format.Outdent();
480   format("}\n");
481 }
482 
GenerateConstinitInitializer(io::Printer * printer) const483 void RepeatedPrimitiveFieldGenerator::GenerateConstinitInitializer(
484     io::Printer* printer) const {
485   Formatter format(printer, variables_);
486   format("$name$_()");
487   if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
488       HasGeneratedMethods(descriptor_->file(), options_)) {
489     format("\n, $cached_byte_size_name$(0)");
490   }
491 }
492 
493 }  // namespace cpp
494 }  // namespace compiler
495 }  // namespace protobuf
496 }  // namespace google
497