• 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 #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 
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)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
108   int fixed_size = FixedSize(descriptor->type());
109   if (fixed_size != -1) {
110     (*variables)["fixed_size"] = StrCat(fixed_size);
111   }
112   (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name(
113       static_cast<FieldDescriptorProto_Type>(descriptor->type()));
114   (*variables)["full_name"] = descriptor->full_name();
115 }
116 
117 }  // namespace
118 
119 // ===================================================================
120 
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)121 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
122     const FieldDescriptor* descriptor, const Options& options)
123     : FieldGenerator(descriptor, options) {
124   SetPrimitiveVariables(descriptor, &variables_, options);
125 }
126 
~PrimitiveFieldGenerator()127 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
128 
GeneratePrivateMembers(io::Printer * printer) const129 void PrimitiveFieldGenerator::GeneratePrivateMembers(
130     io::Printer* printer) const {
131   Formatter format(printer, variables_);
132   format("$type$ $name$_;\n");
133 }
134 
GenerateAccessorDeclarations(io::Printer * printer) const135 void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
136     io::Printer* printer) const {
137   Formatter format(printer, variables_);
138   format(
139       "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
140       "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n",
141       descriptor_);
142 }
143 
GenerateInlineAccessorDefinitions(io::Printer * printer) const144 void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
145     io::Printer* printer) const {
146   Formatter format(printer, variables_);
147   format(
148       "inline $type$ $classname$::$name$() const {\n"
149       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
150       "  return $name$_;\n"
151       "}\n"
152       "inline void $classname$::set_$name$($type$ value) {\n"
153       "  $set_hasbit$\n"
154       "  $name$_ = value;\n"
155       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
156       "}\n");
157 }
158 
GenerateClearingCode(io::Printer * printer) const159 void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
160   Formatter format(printer, variables_);
161   format("$name$_ = $default$;\n");
162 }
163 
GenerateMergingCode(io::Printer * printer) const164 void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
165   Formatter format(printer, variables_);
166   format("set_$name$(from.$name$());\n");
167 }
168 
GenerateSwappingCode(io::Printer * printer) const169 void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
170   Formatter format(printer, variables_);
171   format("swap($name$_, other->$name$_);\n");
172 }
173 
GenerateConstructorCode(io::Printer * printer) const174 void PrimitiveFieldGenerator::GenerateConstructorCode(
175     io::Printer* printer) const {
176   Formatter format(printer, variables_);
177   format("$name$_ = $default$;\n");
178 }
179 
GenerateCopyConstructorCode(io::Printer * printer) const180 void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
181     io::Printer* printer) const {
182   Formatter format(printer, variables_);
183   format("$name$_ = from.$name$_;\n");
184 }
185 
GenerateMergeFromCodedStream(io::Printer * printer) const186 void PrimitiveFieldGenerator::GenerateMergeFromCodedStream(
187     io::Printer* printer) const {
188   Formatter format(printer, variables_);
189   format(
190       "$set_hasbit_io$\n"
191       "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
192       "         $type$, "
193       "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
194       "       input, &$name$_)));\n");
195 }
196 
GenerateSerializeWithCachedSizes(io::Printer * printer) const197 void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizes(
198     io::Printer* printer) const {
199   Formatter format(printer, variables_);
200   format(
201       "::$proto_ns$::internal::WireFormatLite::Write$declared_type$("
202       "$number$, this->$name$(), output);\n");
203 }
204 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const205 void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
206     io::Printer* printer) const {
207   Formatter format(printer, variables_);
208   format(
209       "target = "
210       "::$proto_ns$::internal::WireFormatLite::Write$declared_type$ToArray("
211       "$number$, this->$name$(), target);\n");
212 }
213 
GenerateByteSize(io::Printer * printer) const214 void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
215   Formatter format(printer, variables_);
216   int fixed_size = FixedSize(descriptor_->type());
217   if (fixed_size == -1) {
218     format(
219         "total_size += $tag_size$ +\n"
220         "  ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
221         "    this->$name$());\n");
222   } else {
223     format("total_size += $tag_size$ + $fixed_size$;\n");
224   }
225 }
226 
227 // ===================================================================
228 
PrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)229 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
230     const FieldDescriptor* descriptor, const Options& options)
231     : PrimitiveFieldGenerator(descriptor, options) {
232   SetCommonOneofFieldVariables(descriptor, &variables_);
233 }
234 
~PrimitiveOneofFieldGenerator()235 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
236 
GenerateInlineAccessorDefinitions(io::Printer * printer) const237 void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions(
238     io::Printer* printer) const {
239   Formatter format(printer, variables_);
240   format(
241       "inline $type$ $classname$::$name$() const {\n"
242       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
243       "  if (has_$name$()) {\n"
244       "    return $field_member$;\n"
245       "  }\n"
246       "  return $default$;\n"
247       "}\n"
248       "inline void $classname$::set_$name$($type$ value) {\n"
249       "  if (!has_$name$()) {\n"
250       "    clear_$oneof_name$();\n"
251       "    set_has_$name$();\n"
252       "  }\n"
253       "  $field_member$ = value;\n"
254       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
255       "}\n");
256 }
257 
GenerateClearingCode(io::Printer * printer) const258 void PrimitiveOneofFieldGenerator::GenerateClearingCode(
259     io::Printer* printer) const {
260   Formatter format(printer, variables_);
261   format("$field_member$ = $default$;\n");
262 }
263 
GenerateSwappingCode(io::Printer * printer) const264 void PrimitiveOneofFieldGenerator::GenerateSwappingCode(
265     io::Printer* printer) const {
266   // Don't print any swapping code. Swapping the union will swap this field.
267 }
268 
GenerateConstructorCode(io::Printer * printer) const269 void PrimitiveOneofFieldGenerator::GenerateConstructorCode(
270     io::Printer* printer) const {
271   Formatter format(printer, variables_);
272   format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
273 }
274 
GenerateMergeFromCodedStream(io::Printer * printer) const275 void PrimitiveOneofFieldGenerator::GenerateMergeFromCodedStream(
276     io::Printer* printer) const {
277   Formatter format(printer, variables_);
278   format(
279       "clear_$oneof_name$();\n"
280       "DO_((::$proto_ns$::internal::WireFormatLite::ReadPrimitive<\n"
281       "         $type$, "
282       "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
283       "       input, &$field_member$)));\n"
284       "set_has_$name$();\n");
285 }
286 
287 // ===================================================================
288 
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)289 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
290     const FieldDescriptor* descriptor, const Options& options)
291     : FieldGenerator(descriptor, options) {
292   SetPrimitiveVariables(descriptor, &variables_, options);
293 
294   if (descriptor->is_packed()) {
295     variables_["packed_reader"] = "ReadPackedPrimitive";
296     variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
297   } else {
298     variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
299     variables_["repeated_reader"] = "ReadRepeatedPrimitive";
300   }
301 }
302 
~RepeatedPrimitiveFieldGenerator()303 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
304 
GeneratePrivateMembers(io::Printer * printer) const305 void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers(
306     io::Printer* printer) const {
307   Formatter format(printer, variables_);
308   format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
309   if (descriptor_->is_packed() &&
310       HasGeneratedMethods(descriptor_->file(), options_)) {
311     format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
312   }
313 }
314 
GenerateAccessorDeclarations(io::Printer * printer) const315 void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations(
316     io::Printer* printer) const {
317   Formatter format(printer, variables_);
318   format(
319       "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
320       "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
321       "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
322       "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n"
323       "    ${1$$name$$}$() const;\n"
324       "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n"
325       "    ${1$mutable_$name$$}$();\n",
326       descriptor_);
327 }
328 
GenerateInlineAccessorDefinitions(io::Printer * printer) const329 void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
330     io::Printer* printer) const {
331   Formatter format(printer, variables_);
332   format(
333       "inline $type$ $classname$::$name$(int index) const {\n"
334       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
335       "  return $name$_.Get(index);\n"
336       "}\n"
337       "inline void $classname$::set_$name$(int index, $type$ value) {\n"
338       "  $name$_.Set(index, value);\n"
339       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
340       "}\n"
341       "inline void $classname$::add_$name$($type$ value) {\n"
342       "  $name$_.Add(value);\n"
343       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
344       "}\n"
345       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
346       "$classname$::$name$() const {\n"
347       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
348       "  return $name$_;\n"
349       "}\n"
350       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
351       "$classname$::mutable_$name$() {\n"
352       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
353       "  return &$name$_;\n"
354       "}\n");
355 }
356 
GenerateClearingCode(io::Printer * printer) const357 void RepeatedPrimitiveFieldGenerator::GenerateClearingCode(
358     io::Printer* printer) const {
359   Formatter format(printer, variables_);
360   format("$name$_.Clear();\n");
361 }
362 
GenerateMergingCode(io::Printer * printer) const363 void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(
364     io::Printer* printer) const {
365   Formatter format(printer, variables_);
366   format("$name$_.MergeFrom(from.$name$_);\n");
367 }
368 
GenerateSwappingCode(io::Printer * printer) const369 void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
370     io::Printer* printer) const {
371   Formatter format(printer, variables_);
372   format("$name$_.InternalSwap(&other->$name$_);\n");
373 }
374 
GenerateConstructorCode(io::Printer * printer) const375 void RepeatedPrimitiveFieldGenerator::GenerateConstructorCode(
376     io::Printer* printer) const {
377   // Not needed for repeated fields.
378 }
379 
GenerateCopyConstructorCode(io::Printer * printer) const380 void RepeatedPrimitiveFieldGenerator::GenerateCopyConstructorCode(
381     io::Printer* printer) const {
382   Formatter format(printer, variables_);
383   format("$name$_.CopyFrom(from.$name$_);\n");
384 }
385 
GenerateMergeFromCodedStream(io::Printer * printer) const386 void RepeatedPrimitiveFieldGenerator::GenerateMergeFromCodedStream(
387     io::Printer* printer) const {
388   Formatter format(printer, variables_);
389   format(
390       "DO_((::$proto_ns$::internal::WireFormatLite::$repeated_reader$<\n"
391       "         $type$, "
392       "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
393       "       $tag_size$, $tag$u, input, this->mutable_$name$())));\n");
394 }
395 
GenerateMergeFromCodedStreamWithPacking(io::Printer * printer) const396 void RepeatedPrimitiveFieldGenerator::GenerateMergeFromCodedStreamWithPacking(
397     io::Printer* printer) const {
398   Formatter format(printer, variables_);
399   format(
400       "DO_((::$proto_ns$::internal::WireFormatLite::$packed_reader$<\n"
401       "         $type$, "
402       "::$proto_ns$::internal::WireFormatLite::$wire_format_field_type$>(\n"
403       "       input, this->mutable_$name$())));\n");
404 }
405 
GenerateSerializeWithCachedSizes(io::Printer * printer) const406 void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizes(
407     io::Printer* printer) const {
408   Formatter format(printer, variables_);
409   bool array_written = false;
410   if (descriptor_->is_packed()) {
411     // Write the tag and the size.
412     format(
413         "if (this->$name$_size() > 0) {\n"
414         "  ::$proto_ns$::internal::WireFormatLite::WriteTag("
415         "$number$, "
416         "::$proto_ns$::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
417         "output);\n"
418         "  output->WriteVarint32(_$name$_cached_byte_size_.load(\n"
419         "      std::memory_order_relaxed));\n");
420 
421     if (FixedSize(descriptor_->type()) > 0) {
422       // TODO(ckennelly): Use RepeatedField<T>::unsafe_data() via
423       // WireFormatLite to access the contents of this->$name$_ to save a branch
424       // here.
425       format(
426           "  "
427           "::$proto_ns$::internal::WireFormatLite::Write$declared_type$Array(\n"
428           "    this->$name$().data(), this->$name$_size(), output);\n");
429       array_written = true;  // Wrote array all at once
430     }
431     format("}\n");
432   }
433   if (!array_written) {
434     format("for (int i = 0, n = this->$name$_size(); i < n; i++) {\n");
435     if (descriptor_->is_packed()) {
436       format(
437           "  "
438           "::$proto_ns$::internal::WireFormatLite::Write$declared_type$NoTag(\n"
439           "    this->$name$(i), output);\n");
440     } else {
441       format(
442           "  ::$proto_ns$::internal::WireFormatLite::Write$declared_type$(\n"
443           "    $number$, this->$name$(i), output);\n");
444     }
445     format("}\n");
446   }
447 }
448 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const449 void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
450     io::Printer* printer) const {
451   Formatter format(printer, variables_);
452   if (descriptor_->is_packed()) {
453     // Write the tag and the size.
454     format(
455         "if (this->$name$_size() > 0) {\n"
456         "  target = ::$proto_ns$::internal::WireFormatLite::WriteTagToArray(\n"
457         "    $number$,\n"
458         "    "
459         "::$proto_ns$::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
460         "    target);\n"
461         "  target = "
462         "::$proto_ns$::io::CodedOutputStream::WriteVarint32ToArray(\n"
463         "      _$name$_cached_byte_size_.load(std::memory_order_relaxed),\n"
464         "       target);\n"
465         "  target = ::$proto_ns$::internal::WireFormatLite::\n"
466         "    Write$declared_type$NoTagToArray(this->$name$_, target);\n"
467         "}\n");
468   } else {
469     format(
470         "target = ::$proto_ns$::internal::WireFormatLite::\n"
471         "  Write$declared_type$ToArray($number$, this->$name$_, target);\n");
472   }
473 }
474 
GenerateByteSize(io::Printer * printer) const475 void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
476     io::Printer* printer) const {
477   Formatter format(printer, variables_);
478   format("{\n");
479   format.Indent();
480   int fixed_size = FixedSize(descriptor_->type());
481   if (fixed_size == -1) {
482     format(
483         "size_t data_size = ::$proto_ns$::internal::WireFormatLite::\n"
484         "  $declared_type$Size(this->$name$_);\n");
485   } else {
486     format(
487         "unsigned int count = static_cast<unsigned int>(this->$name$_size());\n"
488         "size_t data_size = $fixed_size$UL * count;\n");
489   }
490 
491   if (descriptor_->is_packed()) {
492     format(
493         "if (data_size > 0) {\n"
494         "  total_size += $tag_size$ +\n"
495         "    ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
496         "        static_cast<$int32$>(data_size));\n"
497         "}\n"
498         "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
499         "_$name$_cached_byte_size_.store(cached_size,\n"
500         "                                std::memory_order_relaxed);\n"
501         "total_size += data_size;\n");
502   } else {
503     format(
504         "total_size += $tag_size$ *\n"
505         "              "
506         "::$proto_ns$::internal::FromIntSize(this->$name$_size());\n"
507         "total_size += data_size;\n");
508   }
509   format.Outdent();
510   format("}\n");
511 }
512 
513 }  // namespace cpp
514 }  // namespace compiler
515 }  // namespace protobuf
516 }  // namespace google
517