• 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 namespace google {
42 namespace protobuf {
43 namespace compiler {
44 namespace cpp {
45 
46 using internal::WireFormatLite;
47 
48 namespace {
49 
50 // For encodings with fixed sizes, returns that size in bytes.  Otherwise
51 // returns -1.
FixedSize(FieldDescriptor::Type type)52 int FixedSize(FieldDescriptor::Type type) {
53   switch (type) {
54     case FieldDescriptor::TYPE_INT32:
55       return -1;
56     case FieldDescriptor::TYPE_INT64:
57       return -1;
58     case FieldDescriptor::TYPE_UINT32:
59       return -1;
60     case FieldDescriptor::TYPE_UINT64:
61       return -1;
62     case FieldDescriptor::TYPE_SINT32:
63       return -1;
64     case FieldDescriptor::TYPE_SINT64:
65       return -1;
66     case FieldDescriptor::TYPE_FIXED32:
67       return WireFormatLite::kFixed32Size;
68     case FieldDescriptor::TYPE_FIXED64:
69       return WireFormatLite::kFixed64Size;
70     case FieldDescriptor::TYPE_SFIXED32:
71       return WireFormatLite::kSFixed32Size;
72     case FieldDescriptor::TYPE_SFIXED64:
73       return WireFormatLite::kSFixed64Size;
74     case FieldDescriptor::TYPE_FLOAT:
75       return WireFormatLite::kFloatSize;
76     case FieldDescriptor::TYPE_DOUBLE:
77       return WireFormatLite::kDoubleSize;
78 
79     case FieldDescriptor::TYPE_BOOL:
80       return WireFormatLite::kBoolSize;
81     case FieldDescriptor::TYPE_ENUM:
82       return -1;
83 
84     case FieldDescriptor::TYPE_STRING:
85       return -1;
86     case FieldDescriptor::TYPE_BYTES:
87       return -1;
88     case FieldDescriptor::TYPE_GROUP:
89       return -1;
90     case FieldDescriptor::TYPE_MESSAGE:
91       return -1;
92 
93       // No default because we want the compiler to complain if any new
94       // types are added.
95   }
96   GOOGLE_LOG(FATAL) << "Can't get here.";
97   return -1;
98 }
99 
SetPrimitiveVariables(const FieldDescriptor * descriptor,std::map<std::string,std::string> * variables,const Options & options)100 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
101                            std::map<std::string, std::string>* variables,
102                            const Options& options) {
103   SetCommonFieldVariables(descriptor, variables, options);
104   (*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type());
105   (*variables)["default"] = DefaultValue(options, descriptor);
106   (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
107   int fixed_size = FixedSize(descriptor->type());
108   if (fixed_size != -1) {
109     (*variables)["fixed_size"] = StrCat(fixed_size);
110   }
111   (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name(
112       static_cast<FieldDescriptorProto_Type>(descriptor->type()));
113   (*variables)["full_name"] = descriptor->full_name();
114 }
115 
116 }  // namespace
117 
118 // ===================================================================
119 
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)120 PrimitiveFieldGenerator::PrimitiveFieldGenerator(
121     const FieldDescriptor* descriptor, const Options& options)
122     : FieldGenerator(descriptor, options) {
123   SetPrimitiveVariables(descriptor, &variables_, options);
124 }
125 
~PrimitiveFieldGenerator()126 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
127 
GeneratePrivateMembers(io::Printer * printer) const128 void PrimitiveFieldGenerator::GeneratePrivateMembers(
129     io::Printer* printer) const {
130   Formatter format(printer, variables_);
131   format("$type$ $name$_;\n");
132 }
133 
GenerateAccessorDeclarations(io::Printer * printer) const134 void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
135     io::Printer* printer) const {
136   Formatter format(printer, variables_);
137   format(
138       "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
139       "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
140       "private:\n"
141       "$type$ ${1$_internal_$name$$}$() const;\n"
142       "void ${1$_internal_set_$name$$}$($type$ value);\n"
143       "public:\n",
144       descriptor_);
145 }
146 
GenerateInlineAccessorDefinitions(io::Printer * printer) const147 void PrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
148     io::Printer* printer) const {
149   Formatter format(printer, variables_);
150   format(
151       "inline $type$ $classname$::_internal_$name$() const {\n"
152       "  return $name$_;\n"
153       "}\n"
154       "inline $type$ $classname$::$name$() const {\n"
155       "$annotate_accessor$"
156       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
157       "  return _internal_$name$();\n"
158       "}\n"
159       "inline void $classname$::_internal_set_$name$($type$ value) {\n"
160       "  $set_hasbit$\n"
161       "  $name$_ = value;\n"
162       "}\n"
163       "inline void $classname$::set_$name$($type$ value) {\n"
164       "$annotate_accessor$"
165       "  _internal_set_$name$(value);\n"
166       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
167       "}\n");
168 }
169 
GenerateClearingCode(io::Printer * printer) const170 void PrimitiveFieldGenerator::GenerateClearingCode(io::Printer* printer) const {
171   Formatter format(printer, variables_);
172   format("$name$_ = $default$;\n");
173 }
174 
GenerateMergingCode(io::Printer * printer) const175 void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) const {
176   Formatter format(printer, variables_);
177   format("_internal_set_$name$(from._internal_$name$());\n");
178 }
179 
GenerateSwappingCode(io::Printer * printer) const180 void PrimitiveFieldGenerator::GenerateSwappingCode(io::Printer* printer) const {
181   Formatter format(printer, variables_);
182   format("swap($name$_, other->$name$_);\n");
183 }
184 
GenerateConstructorCode(io::Printer * printer) const185 void PrimitiveFieldGenerator::GenerateConstructorCode(
186     io::Printer* printer) const {
187   Formatter format(printer, variables_);
188   format("$name$_ = $default$;\n");
189 }
190 
GenerateCopyConstructorCode(io::Printer * printer) const191 void PrimitiveFieldGenerator::GenerateCopyConstructorCode(
192     io::Printer* printer) const {
193   Formatter format(printer, variables_);
194   format("$name$_ = from.$name$_;\n");
195 }
196 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const197 void PrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
198     io::Printer* printer) const {
199   Formatter format(printer, variables_);
200   format(
201       "target = stream->EnsureSpace(target);\n"
202       "target = "
203       "::$proto_ns$::internal::WireFormatLite::Write$declared_type$ToArray("
204       "$number$, this->_internal_$name$(), target);\n");
205 }
206 
GenerateByteSize(io::Printer * printer) const207 void PrimitiveFieldGenerator::GenerateByteSize(io::Printer* printer) const {
208   Formatter format(printer, variables_);
209   int fixed_size = FixedSize(descriptor_->type());
210   if (fixed_size == -1) {
211     format(
212         "total_size += $tag_size$ +\n"
213         "  ::$proto_ns$::internal::WireFormatLite::$declared_type$Size(\n"
214         "    this->_internal_$name$());\n");
215   } else {
216     format("total_size += $tag_size$ + $fixed_size$;\n");
217   }
218 }
219 
220 // ===================================================================
221 
PrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)222 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
223     const FieldDescriptor* descriptor, const Options& options)
224     : PrimitiveFieldGenerator(descriptor, options) {
225   SetCommonOneofFieldVariables(descriptor, &variables_);
226 }
227 
~PrimitiveOneofFieldGenerator()228 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
229 
GenerateInlineAccessorDefinitions(io::Printer * printer) const230 void PrimitiveOneofFieldGenerator::GenerateInlineAccessorDefinitions(
231     io::Printer* printer) const {
232   Formatter format(printer, variables_);
233   format(
234       "inline $type$ $classname$::_internal_$name$() const {\n"
235       "  if (_internal_has_$name$()) {\n"
236       "    return $field_member$;\n"
237       "  }\n"
238       "  return $default$;\n"
239       "}\n"
240       "inline void $classname$::_internal_set_$name$($type$ value) {\n"
241       "  if (!_internal_has_$name$()) {\n"
242       "    clear_$oneof_name$();\n"
243       "    set_has_$name$();\n"
244       "  }\n"
245       "  $field_member$ = value;\n"
246       "}\n"
247       "inline $type$ $classname$::$name$() const {\n"
248       "$annotate_accessor$"
249       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
250       "  return _internal_$name$();\n"
251       "}\n"
252       "inline void $classname$::set_$name$($type$ value) {\n"
253       "$annotate_accessor$"
254       "  _internal_set_$name$(value);\n"
255       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
256       "}\n");
257 }
258 
GenerateClearingCode(io::Printer * printer) const259 void PrimitiveOneofFieldGenerator::GenerateClearingCode(
260     io::Printer* printer) const {
261   Formatter format(printer, variables_);
262   format("$field_member$ = $default$;\n");
263 }
264 
GenerateSwappingCode(io::Printer * printer) const265 void PrimitiveOneofFieldGenerator::GenerateSwappingCode(
266     io::Printer* printer) const {
267   // Don't print any swapping code. Swapping the union will swap this field.
268 }
269 
GenerateConstructorCode(io::Printer * printer) const270 void PrimitiveOneofFieldGenerator::GenerateConstructorCode(
271     io::Printer* printer) const {
272   Formatter format(printer, variables_);
273   format("$ns$::_$classname$_default_instance_.$name$_ = $default$;\n");
274 }
275 
276 // ===================================================================
277 
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)278 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
279     const FieldDescriptor* descriptor, const Options& options)
280     : FieldGenerator(descriptor, options) {
281   SetPrimitiveVariables(descriptor, &variables_, options);
282 
283   if (descriptor->is_packed()) {
284     variables_["packed_reader"] = "ReadPackedPrimitive";
285     variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
286   } else {
287     variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
288     variables_["repeated_reader"] = "ReadRepeatedPrimitive";
289   }
290 }
291 
~RepeatedPrimitiveFieldGenerator()292 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
293 
GeneratePrivateMembers(io::Printer * printer) const294 void RepeatedPrimitiveFieldGenerator::GeneratePrivateMembers(
295     io::Printer* printer) const {
296   Formatter format(printer, variables_);
297   format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
298   if (descriptor_->is_packed() &&
299       HasGeneratedMethods(descriptor_->file(), options_)) {
300     format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
301   }
302 }
303 
GenerateAccessorDeclarations(io::Printer * printer) const304 void RepeatedPrimitiveFieldGenerator::GenerateAccessorDeclarations(
305     io::Printer* printer) const {
306   Formatter format(printer, variables_);
307   format(
308       "private:\n"
309       "$type$ ${1$_internal_$name$$}$(int index) const;\n"
310       "const ::$proto_ns$::RepeatedField< $type$ >&\n"
311       "    ${1$_internal_$name$$}$() const;\n"
312       "void ${1$_internal_add_$name$$}$($type$ value);\n"
313       "::$proto_ns$::RepeatedField< $type$ >*\n"
314       "    ${1$_internal_mutable_$name$$}$();\n"
315       "public:\n"
316       "$deprecated_attr$$type$ ${1$$name$$}$(int index) const;\n"
317       "$deprecated_attr$void ${1$set_$name$$}$(int index, $type$ value);\n"
318       "$deprecated_attr$void ${1$add_$name$$}$($type$ value);\n"
319       "$deprecated_attr$const ::$proto_ns$::RepeatedField< $type$ >&\n"
320       "    ${1$$name$$}$() const;\n"
321       "$deprecated_attr$::$proto_ns$::RepeatedField< $type$ >*\n"
322       "    ${1$mutable_$name$$}$();\n",
323       descriptor_);
324 }
325 
GenerateInlineAccessorDefinitions(io::Printer * printer) const326 void RepeatedPrimitiveFieldGenerator::GenerateInlineAccessorDefinitions(
327     io::Printer* printer) const {
328   Formatter format(printer, variables_);
329   format(
330       "inline $type$ $classname$::_internal_$name$(int index) const {\n"
331       "  return $name$_.Get(index);\n"
332       "}\n"
333       "inline $type$ $classname$::$name$(int index) const {\n"
334       "$annotate_accessor$"
335       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
336       "  return _internal_$name$(index);\n"
337       "}\n"
338       "inline void $classname$::set_$name$(int index, $type$ value) {\n"
339       "$annotate_accessor$"
340       "  $name$_.Set(index, value);\n"
341       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
342       "}\n"
343       "inline void $classname$::_internal_add_$name$($type$ value) {\n"
344       "  $name$_.Add(value);\n"
345       "}\n"
346       "inline void $classname$::add_$name$($type$ value) {\n"
347       "$annotate_accessor$"
348       "  _internal_add_$name$(value);\n"
349       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
350       "}\n"
351       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
352       "$classname$::_internal_$name$() const {\n"
353       "  return $name$_;\n"
354       "}\n"
355       "inline const ::$proto_ns$::RepeatedField< $type$ >&\n"
356       "$classname$::$name$() const {\n"
357       "$annotate_accessor$"
358       "  // @@protoc_insertion_point(field_list:$full_name$)\n"
359       "  return _internal_$name$();\n"
360       "}\n"
361       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
362       "$classname$::_internal_mutable_$name$() {\n"
363       "  return &$name$_;\n"
364       "}\n"
365       "inline ::$proto_ns$::RepeatedField< $type$ >*\n"
366       "$classname$::mutable_$name$() {\n"
367       "$annotate_accessor$"
368       "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
369       "  return _internal_mutable_$name$();\n"
370       "}\n");
371 }
372 
GenerateClearingCode(io::Printer * printer) const373 void RepeatedPrimitiveFieldGenerator::GenerateClearingCode(
374     io::Printer* printer) const {
375   Formatter format(printer, variables_);
376   format("$name$_.Clear();\n");
377 }
378 
GenerateMergingCode(io::Printer * printer) const379 void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(
380     io::Printer* printer) const {
381   Formatter format(printer, variables_);
382   format("$name$_.MergeFrom(from.$name$_);\n");
383 }
384 
GenerateSwappingCode(io::Printer * printer) const385 void RepeatedPrimitiveFieldGenerator::GenerateSwappingCode(
386     io::Printer* printer) const {
387   Formatter format(printer, variables_);
388   format("$name$_.InternalSwap(&other->$name$_);\n");
389 }
390 
GenerateConstructorCode(io::Printer * printer) const391 void RepeatedPrimitiveFieldGenerator::GenerateConstructorCode(
392     io::Printer* printer) const {
393   // Not needed for repeated fields.
394 }
395 
GenerateCopyConstructorCode(io::Printer * printer) const396 void RepeatedPrimitiveFieldGenerator::GenerateCopyConstructorCode(
397     io::Printer* printer) const {
398   Formatter format(printer, variables_);
399   format("$name$_.CopyFrom(from.$name$_);\n");
400 }
401 
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const402 void RepeatedPrimitiveFieldGenerator::GenerateSerializeWithCachedSizesToArray(
403     io::Printer* printer) const {
404   Formatter format(printer, variables_);
405   if (descriptor_->is_packed()) {
406     if (FixedSize(descriptor_->type()) > 0) {
407       format(
408           "if (this->_internal_$name$_size() > 0) {\n"
409           "  target = stream->WriteFixedPacked($number$, _internal_$name$(), "
410           "target);\n"
411           "}\n");
412     } else {
413       format(
414           "{\n"
415           "  int byte_size = "
416           "_$name$_cached_byte_size_.load(std::memory_order_relaxed);\n"
417           "  if (byte_size > 0) {\n"
418           "    target = stream->Write$declared_type$Packed(\n"
419           "        $number$, _internal_$name$(), byte_size, target);\n"
420           "  }\n"
421           "}\n");
422     }
423   } else {
424     format(
425         "for (int i = 0, n = this->_internal_$name$_size(); i < n; i++) {\n"
426         "  target = stream->EnsureSpace(target);\n"
427         "  target = ::$proto_ns$::internal::WireFormatLite::"
428         "Write$declared_type$ToArray($number$, this->_internal_$name$(i), "
429         "target);\n"
430         "}\n");
431   }
432 }
433 
GenerateByteSize(io::Printer * printer) const434 void RepeatedPrimitiveFieldGenerator::GenerateByteSize(
435     io::Printer* printer) const {
436   Formatter format(printer, variables_);
437   format("{\n");
438   format.Indent();
439   int fixed_size = FixedSize(descriptor_->type());
440   if (fixed_size == -1) {
441     format(
442         "size_t data_size = ::$proto_ns$::internal::WireFormatLite::\n"
443         "  $declared_type$Size(this->$name$_);\n");
444   } else {
445     format(
446         "unsigned int count = static_cast<unsigned "
447         "int>(this->_internal_$name$_size());\n"
448         "size_t data_size = $fixed_size$UL * count;\n");
449   }
450 
451   if (descriptor_->is_packed()) {
452     format(
453         "if (data_size > 0) {\n"
454         "  total_size += $tag_size$ +\n"
455         "    ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
456         "        static_cast<$int32$>(data_size));\n"
457         "}\n"
458         "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
459         "_$name$_cached_byte_size_.store(cached_size,\n"
460         "                                std::memory_order_relaxed);\n"
461         "total_size += data_size;\n");
462   } else {
463     format(
464         "total_size += $tag_size$ *\n"
465         "              "
466         "::$proto_ns$::internal::FromIntSize(this->_internal_$name$_size());\n"
467         "total_size += data_size;\n");
468   }
469   format.Outdent();
470   format("}\n");
471 }
472 
473 }  // namespace cpp
474 }  // namespace compiler
475 }  // namespace protobuf
476 }  // namespace google
477