• 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   : return -1;
55     case FieldDescriptor::TYPE_INT64   : return -1;
56     case FieldDescriptor::TYPE_UINT32  : return -1;
57     case FieldDescriptor::TYPE_UINT64  : return -1;
58     case FieldDescriptor::TYPE_SINT32  : return -1;
59     case FieldDescriptor::TYPE_SINT64  : return -1;
60     case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size;
61     case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size;
62     case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size;
63     case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size;
64     case FieldDescriptor::TYPE_FLOAT   : return WireFormatLite::kFloatSize;
65     case FieldDescriptor::TYPE_DOUBLE  : return WireFormatLite::kDoubleSize;
66 
67     case FieldDescriptor::TYPE_BOOL    : return WireFormatLite::kBoolSize;
68     case FieldDescriptor::TYPE_ENUM    : return -1;
69 
70     case FieldDescriptor::TYPE_STRING  : return -1;
71     case FieldDescriptor::TYPE_BYTES   : return -1;
72     case FieldDescriptor::TYPE_GROUP   : return -1;
73     case FieldDescriptor::TYPE_MESSAGE : return -1;
74 
75     // No default because we want the compiler to complain if any new
76     // types are added.
77   }
78   GOOGLE_LOG(FATAL) << "Can't get here.";
79   return -1;
80 }
81 
SetPrimitiveVariables(const FieldDescriptor * descriptor,map<string,string> * variables,const Options & options)82 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
83                            map<string, string>* variables,
84                            const Options& options) {
85   SetCommonFieldVariables(descriptor, variables, options);
86   (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
87   (*variables)["default"] = DefaultValue(descriptor);
88   (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
89   int fixed_size = FixedSize(descriptor->type());
90   if (fixed_size != -1) {
91     (*variables)["fixed_size"] = SimpleItoa(fixed_size);
92   }
93   (*variables)["wire_format_field_type"] =
94       "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
95           static_cast<FieldDescriptorProto_Type>(descriptor->type()));
96   (*variables)["full_name"] = descriptor->full_name();
97 }
98 
99 }  // namespace
100 
101 // ===================================================================
102 
103 PrimitiveFieldGenerator::
PrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)104 PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
105                         const Options& options)
106   : descriptor_(descriptor) {
107   SetPrimitiveVariables(descriptor, &variables_, options);
108 }
109 
~PrimitiveFieldGenerator()110 PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
111 
112 void PrimitiveFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const113 GeneratePrivateMembers(io::Printer* printer) const {
114   printer->Print(variables_, "$type$ $name$_;\n");
115 }
116 
117 void PrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const118 GenerateAccessorDeclarations(io::Printer* printer) const {
119   printer->Print(variables_,
120     "inline $type$ $name$() const$deprecation$;\n"
121     "inline void set_$name$($type$ value)$deprecation$;\n");
122 }
123 
124 void PrimitiveFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const125 GenerateInlineAccessorDefinitions(io::Printer* printer) const {
126   printer->Print(variables_,
127     "inline $type$ $classname$::$name$() const {\n"
128     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
129     "  return $name$_;\n"
130     "}\n"
131     "inline void $classname$::set_$name$($type$ value) {\n"
132     "  set_has_$name$();\n"
133     "  $name$_ = value;\n"
134     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
135     "}\n");
136 }
137 
138 void PrimitiveFieldGenerator::
GenerateClearingCode(io::Printer * printer) const139 GenerateClearingCode(io::Printer* printer) const {
140   printer->Print(variables_, "$name$_ = $default$;\n");
141 }
142 
143 void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer * printer) const144 GenerateMergingCode(io::Printer* printer) const {
145   printer->Print(variables_, "set_$name$(from.$name$());\n");
146 }
147 
148 void PrimitiveFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const149 GenerateSwappingCode(io::Printer* printer) const {
150   printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
151 }
152 
153 void PrimitiveFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const154 GenerateConstructorCode(io::Printer* printer) const {
155   printer->Print(variables_, "$name$_ = $default$;\n");
156 }
157 
158 void PrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const159 GenerateMergeFromCodedStream(io::Printer* printer) const {
160   printer->Print(variables_,
161     "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
162     "         $type$, $wire_format_field_type$>(\n"
163     "       input, &$name$_)));\n"
164     "set_has_$name$();\n");
165 }
166 
167 void PrimitiveFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const168 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
169   printer->Print(variables_,
170     "::google::protobuf::internal::WireFormatLite::Write$declared_type$("
171       "$number$, this->$name$(), output);\n");
172 }
173 
174 void PrimitiveFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const175 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
176   printer->Print(variables_,
177     "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray("
178       "$number$, this->$name$(), target);\n");
179 }
180 
181 void PrimitiveFieldGenerator::
GenerateByteSize(io::Printer * printer) const182 GenerateByteSize(io::Printer* printer) const {
183   int fixed_size = FixedSize(descriptor_->type());
184   if (fixed_size == -1) {
185     printer->Print(variables_,
186       "total_size += $tag_size$ +\n"
187       "  ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
188       "    this->$name$());\n");
189   } else {
190     printer->Print(variables_,
191       "total_size += $tag_size$ + $fixed_size$;\n");
192   }
193 }
194 
195 // ===================================================================
196 
197 PrimitiveOneofFieldGenerator::
PrimitiveOneofFieldGenerator(const FieldDescriptor * descriptor,const Options & options)198 PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
199                              const Options& options)
200   : PrimitiveFieldGenerator(descriptor, options) {
201   SetCommonOneofFieldVariables(descriptor, &variables_);
202 }
203 
~PrimitiveOneofFieldGenerator()204 PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
205 
206 void PrimitiveOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const207 GenerateInlineAccessorDefinitions(io::Printer* printer) const {
208   printer->Print(variables_,
209     "inline $type$ $classname$::$name$() const {\n"
210     "  if (has_$name$()) {\n"
211     "    return $oneof_prefix$$name$_;\n"
212     "  }\n"
213     "  return $default$;\n"
214     "}\n"
215     "inline void $classname$::set_$name$($type$ value) {\n"
216     "  if (!has_$name$()) {\n"
217     "    clear_$oneof_name$();\n"
218     "    set_has_$name$();\n"
219     "  }\n"
220     "  $oneof_prefix$$name$_ = value;\n"
221     "}\n");
222 }
223 
224 void PrimitiveOneofFieldGenerator::
GenerateClearingCode(io::Printer * printer) const225 GenerateClearingCode(io::Printer* printer) const {
226   printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n");
227 }
228 
229 void PrimitiveOneofFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const230 GenerateSwappingCode(io::Printer* printer) const {
231   // Don't print any swapping code. Swapping the union will swap this field.
232 }
233 
234 void PrimitiveOneofFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const235 GenerateConstructorCode(io::Printer* printer) const {
236   printer->Print(
237       variables_,
238       "  $classname$_default_oneof_instance_->$name$_ = $default$;\n");
239 }
240 
241 void PrimitiveOneofFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const242 GenerateMergeFromCodedStream(io::Printer* printer) const {
243   printer->Print(variables_,
244     "clear_$oneof_name$();\n"
245     "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
246     "         $type$, $wire_format_field_type$>(\n"
247     "       input, &$oneof_prefix$$name$_)));\n"
248     "set_has_$name$();\n");
249 }
250 
251 // ===================================================================
252 
253 RepeatedPrimitiveFieldGenerator::
RepeatedPrimitiveFieldGenerator(const FieldDescriptor * descriptor,const Options & options)254 RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
255                                 const Options& options)
256   : descriptor_(descriptor) {
257   SetPrimitiveVariables(descriptor, &variables_, options);
258 
259   if (descriptor->options().packed()) {
260     variables_["packed_reader"] = "ReadPackedPrimitive";
261     variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
262   } else {
263     variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
264     variables_["repeated_reader"] = "ReadRepeatedPrimitive";
265   }
266 }
267 
~RepeatedPrimitiveFieldGenerator()268 RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
269 
270 void RepeatedPrimitiveFieldGenerator::
GeneratePrivateMembers(io::Printer * printer) const271 GeneratePrivateMembers(io::Printer* printer) const {
272   printer->Print(variables_,
273     "::google::protobuf::RepeatedField< $type$ > $name$_;\n");
274   if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
275     printer->Print(variables_,
276       "mutable int _$name$_cached_byte_size_;\n");
277   }
278 }
279 
280 void RepeatedPrimitiveFieldGenerator::
GenerateAccessorDeclarations(io::Printer * printer) const281 GenerateAccessorDeclarations(io::Printer* printer) const {
282   printer->Print(variables_,
283     "inline $type$ $name$(int index) const$deprecation$;\n"
284     "inline void set_$name$(int index, $type$ value)$deprecation$;\n"
285     "inline void add_$name$($type$ value)$deprecation$;\n");
286   printer->Print(variables_,
287     "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
288     "    $name$() const$deprecation$;\n"
289     "inline ::google::protobuf::RepeatedField< $type$ >*\n"
290     "    mutable_$name$()$deprecation$;\n");
291 }
292 
293 void RepeatedPrimitiveFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer * printer) const294 GenerateInlineAccessorDefinitions(io::Printer* printer) const {
295   printer->Print(variables_,
296     "inline $type$ $classname$::$name$(int index) const {\n"
297     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
298     "  return $name$_.Get(index);\n"
299     "}\n"
300     "inline void $classname$::set_$name$(int index, $type$ value) {\n"
301     "  $name$_.Set(index, value);\n"
302     "  // @@protoc_insertion_point(field_set:$full_name$)\n"
303     "}\n"
304     "inline void $classname$::add_$name$($type$ value) {\n"
305     "  $name$_.Add(value);\n"
306     "  // @@protoc_insertion_point(field_add:$full_name$)\n"
307     "}\n");
308   printer->Print(variables_,
309     "inline const ::google::protobuf::RepeatedField< $type$ >&\n"
310     "$classname$::$name$() const {\n"
311     "  // @@protoc_insertion_point(field_list:$full_name$)\n"
312     "  return $name$_;\n"
313     "}\n"
314     "inline ::google::protobuf::RepeatedField< $type$ >*\n"
315     "$classname$::mutable_$name$() {\n"
316     "  // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
317     "  return &$name$_;\n"
318     "}\n");
319 }
320 
321 void RepeatedPrimitiveFieldGenerator::
GenerateClearingCode(io::Printer * printer) const322 GenerateClearingCode(io::Printer* printer) const {
323   printer->Print(variables_, "$name$_.Clear();\n");
324 }
325 
326 void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer * printer) const327 GenerateMergingCode(io::Printer* printer) const {
328   printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
329 }
330 
331 void RepeatedPrimitiveFieldGenerator::
GenerateSwappingCode(io::Printer * printer) const332 GenerateSwappingCode(io::Printer* printer) const {
333   printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
334 }
335 
336 void RepeatedPrimitiveFieldGenerator::
GenerateConstructorCode(io::Printer * printer) const337 GenerateConstructorCode(io::Printer* printer) const {
338   // Not needed for repeated fields.
339 }
340 
341 void RepeatedPrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer * printer) const342 GenerateMergeFromCodedStream(io::Printer* printer) const {
343   printer->Print(variables_,
344     "DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
345     "         $type$, $wire_format_field_type$>(\n"
346     "       $tag_size$, $tag$, input, this->mutable_$name$())));\n");
347 }
348 
349 void RepeatedPrimitiveFieldGenerator::
GenerateMergeFromCodedStreamWithPacking(io::Printer * printer) const350 GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
351   printer->Print(variables_,
352     "DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n"
353     "         $type$, $wire_format_field_type$>(\n"
354     "       input, this->mutable_$name$())));\n");
355 }
356 
357 void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer * printer) const358 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
359   if (descriptor_->options().packed()) {
360     // Write the tag and the size.
361     printer->Print(variables_,
362       "if (this->$name$_size() > 0) {\n"
363       "  ::google::protobuf::internal::WireFormatLite::WriteTag("
364           "$number$, "
365           "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
366           "output);\n"
367       "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
368       "}\n");
369   }
370   printer->Print(variables_,
371       "for (int i = 0; i < this->$name$_size(); i++) {\n");
372   if (descriptor_->options().packed()) {
373     printer->Print(variables_,
374       "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
375       "    this->$name$(i), output);\n");
376   } else {
377     printer->Print(variables_,
378       "  ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
379       "    $number$, this->$name$(i), output);\n");
380   }
381   printer->Print("}\n");
382 }
383 
384 void RepeatedPrimitiveFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer * printer) const385 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
386   if (descriptor_->options().packed()) {
387     // Write the tag and the size.
388     printer->Print(variables_,
389       "if (this->$name$_size() > 0) {\n"
390       "  target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
391       "    $number$,\n"
392       "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
393       "    target);\n"
394       "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
395       "    _$name$_cached_byte_size_, target);\n"
396       "}\n");
397   }
398   printer->Print(variables_,
399       "for (int i = 0; i < this->$name$_size(); i++) {\n");
400   if (descriptor_->options().packed()) {
401     printer->Print(variables_,
402       "  target = ::google::protobuf::internal::WireFormatLite::\n"
403       "    Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
404   } else {
405     printer->Print(variables_,
406       "  target = ::google::protobuf::internal::WireFormatLite::\n"
407       "    Write$declared_type$ToArray($number$, this->$name$(i), target);\n");
408   }
409   printer->Print("}\n");
410 }
411 
412 void RepeatedPrimitiveFieldGenerator::
GenerateByteSize(io::Printer * printer) const413 GenerateByteSize(io::Printer* printer) const {
414   printer->Print(variables_,
415     "{\n"
416     "  int data_size = 0;\n");
417   printer->Indent();
418   int fixed_size = FixedSize(descriptor_->type());
419   if (fixed_size == -1) {
420     printer->Print(variables_,
421       "for (int i = 0; i < this->$name$_size(); i++) {\n"
422       "  data_size += ::google::protobuf::internal::WireFormatLite::\n"
423       "    $declared_type$Size(this->$name$(i));\n"
424       "}\n");
425   } else {
426     printer->Print(variables_,
427       "data_size = $fixed_size$ * this->$name$_size();\n");
428   }
429 
430   if (descriptor_->options().packed()) {
431     printer->Print(variables_,
432       "if (data_size > 0) {\n"
433       "  total_size += $tag_size$ +\n"
434       "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
435       "}\n"
436       "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
437       "_$name$_cached_byte_size_ = data_size;\n"
438       "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
439       "total_size += data_size;\n");
440   } else {
441     printer->Print(variables_,
442       "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
443   }
444   printer->Outdent();
445   printer->Print("}\n");
446 }
447 
448 }  // namespace cpp
449 }  // namespace compiler
450 }  // namespace protobuf
451 }  // namespace google
452