1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2008 Google Inc. All rights reserved.
3
// http://code.google.com/p/protobuf/
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
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
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.
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.
31
// Author: kenton@google.com (Kenton Varda)
32
// Based on original Protocol Buffers design by
33
// Sanjay Ghemawat, Jeff Dean, and others.
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>
46
using internal::WireFormatLite;
50
// For encodings with fixed sizes, returns that size in bytes. Otherwise
52
int FixedSize(FieldDescriptor::Type 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;
67
case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize;
68
case FieldDescriptor::TYPE_ENUM : return -1;
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;
75
// No default because we want the compiler to complain if any new
78
GOOGLE_LOG(FATAL) << "Can't get here.";
82
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
83
map<string, string>* variables) {
84
SetCommonFieldVariables(descriptor, variables);
85
(*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type());
86
(*variables)["default"] = DefaultValue(descriptor);
87
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
88
int fixed_size = FixedSize(descriptor->type());
89
if (fixed_size != -1) {
90
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
92
(*variables)["wire_format_field_type"] =
93
"::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name(
94
static_cast<FieldDescriptorProto_Type>(descriptor->type()));
99
// ===================================================================
101
PrimitiveFieldGenerator::
102
PrimitiveFieldGenerator(const FieldDescriptor* descriptor)
103
: descriptor_(descriptor) {
104
SetPrimitiveVariables(descriptor, &variables_);
107
PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
109
void PrimitiveFieldGenerator::
110
GeneratePrivateMembers(io::Printer* printer) const {
111
printer->Print(variables_, "$type$ $name$_;\n");
114
void PrimitiveFieldGenerator::
115
GenerateAccessorDeclarations(io::Printer* printer) const {
116
printer->Print(variables_,
117
"inline $type$ $name$() const$deprecation$;\n"
118
"inline void set_$name$($type$ value)$deprecation$;\n");
121
void PrimitiveFieldGenerator::
122
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
123
printer->Print(variables_,
124
"inline $type$ $classname$::$name$() const {\n"
127
"inline void $classname$::set_$name$($type$ value) {\n"
128
" _set_bit($index$);\n"
129
" $name$_ = value;\n"
133
void PrimitiveFieldGenerator::
134
GenerateClearingCode(io::Printer* printer) const {
135
printer->Print(variables_, "$name$_ = $default$;\n");
138
void PrimitiveFieldGenerator::
139
GenerateMergingCode(io::Printer* printer) const {
140
printer->Print(variables_, "set_$name$(from.$name$());\n");
143
void PrimitiveFieldGenerator::
144
GenerateSwappingCode(io::Printer* printer) const {
145
printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
148
void PrimitiveFieldGenerator::
149
GenerateConstructorCode(io::Printer* printer) const {
150
printer->Print(variables_, "$name$_ = $default$;\n");
153
void PrimitiveFieldGenerator::
154
GenerateMergeFromCodedStream(io::Printer* printer) const {
155
printer->Print(variables_,
156
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
157
" $type$, $wire_format_field_type$>(\n"
158
" input, &$name$_)));\n"
159
"_set_bit($index$);\n");
162
void PrimitiveFieldGenerator::
163
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
164
printer->Print(variables_,
165
"::google::protobuf::internal::WireFormatLite::Write$declared_type$("
166
"$number$, this->$name$(), output);\n");
169
void PrimitiveFieldGenerator::
170
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
171
printer->Print(variables_,
172
"target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray("
173
"$number$, this->$name$(), target);\n");
176
void PrimitiveFieldGenerator::
177
GenerateByteSize(io::Printer* printer) const {
178
int fixed_size = FixedSize(descriptor_->type());
179
if (fixed_size == -1) {
180
printer->Print(variables_,
181
"total_size += $tag_size$ +\n"
182
" ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
183
" this->$name$());\n");
185
printer->Print(variables_,
186
"total_size += $tag_size$ + $fixed_size$;\n");
190
// ===================================================================
192
RepeatedPrimitiveFieldGenerator::
193
RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor)
194
: descriptor_(descriptor) {
195
SetPrimitiveVariables(descriptor, &variables_);
197
if (descriptor->options().packed()) {
198
variables_["packed_reader"] = "ReadPackedPrimitive";
199
variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline";
201
variables_["packed_reader"] = "ReadPackedPrimitiveNoInline";
202
variables_["repeated_reader"] = "ReadRepeatedPrimitive";
206
RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
208
void RepeatedPrimitiveFieldGenerator::
209
GeneratePrivateMembers(io::Printer* printer) const {
210
printer->Print(variables_,
211
"::google::protobuf::RepeatedField< $type$ > $name$_;\n");
212
if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) {
213
printer->Print(variables_,
214
"mutable int _$name$_cached_byte_size_;\n");
218
void RepeatedPrimitiveFieldGenerator::
219
GenerateAccessorDeclarations(io::Printer* printer) const {
220
printer->Print(variables_,
221
"inline $type$ $name$(int index) const$deprecation$;\n"
222
"inline void set_$name$(int index, $type$ value)$deprecation$;\n"
223
"inline void add_$name$($type$ value)$deprecation$;\n");
224
printer->Print(variables_,
225
"inline const ::google::protobuf::RepeatedField< $type$ >&\n"
226
" $name$() const$deprecation$;\n"
227
"inline ::google::protobuf::RepeatedField< $type$ >*\n"
228
" mutable_$name$()$deprecation$;\n");
231
void RepeatedPrimitiveFieldGenerator::
232
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
233
printer->Print(variables_,
234
"inline $type$ $classname$::$name$(int index) const {\n"
235
" return $name$_.Get(index);\n"
237
"inline void $classname$::set_$name$(int index, $type$ value) {\n"
238
" $name$_.Set(index, value);\n"
240
"inline void $classname$::add_$name$($type$ value) {\n"
241
" $name$_.Add(value);\n"
243
printer->Print(variables_,
244
"inline const ::google::protobuf::RepeatedField< $type$ >&\n"
245
"$classname$::$name$() const {\n"
248
"inline ::google::protobuf::RepeatedField< $type$ >*\n"
249
"$classname$::mutable_$name$() {\n"
250
" return &$name$_;\n"
254
void RepeatedPrimitiveFieldGenerator::
255
GenerateClearingCode(io::Printer* printer) const {
256
printer->Print(variables_, "$name$_.Clear();\n");
259
void RepeatedPrimitiveFieldGenerator::
260
GenerateMergingCode(io::Printer* printer) const {
261
printer->Print(variables_, "$name$_.MergeFrom(from.$name$_);\n");
264
void RepeatedPrimitiveFieldGenerator::
265
GenerateSwappingCode(io::Printer* printer) const {
266
printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
269
void RepeatedPrimitiveFieldGenerator::
270
GenerateConstructorCode(io::Printer* printer) const {
271
// Not needed for repeated fields.
274
void RepeatedPrimitiveFieldGenerator::
275
GenerateMergeFromCodedStream(io::Printer* printer) const {
276
printer->Print(variables_,
277
"DO_((::google::protobuf::internal::WireFormatLite::$repeated_reader$<\n"
278
" $type$, $wire_format_field_type$>(\n"
279
" $tag_size$, $tag$, input, this->mutable_$name$())));\n");
282
void RepeatedPrimitiveFieldGenerator::
283
GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
284
printer->Print(variables_,
285
"DO_((::google::protobuf::internal::WireFormatLite::$packed_reader$<\n"
286
" $type$, $wire_format_field_type$>(\n"
287
" input, this->mutable_$name$())));\n");
290
void RepeatedPrimitiveFieldGenerator::
291
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
292
if (descriptor_->options().packed()) {
293
// Write the tag and the size.
294
printer->Print(variables_,
295
"if (this->$name$_size() > 0) {\n"
296
" ::google::protobuf::internal::WireFormatLite::WriteTag("
298
"::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
300
" output->WriteVarint32(_$name$_cached_byte_size_);\n"
303
printer->Print(variables_,
304
"for (int i = 0; i < this->$name$_size(); i++) {\n");
305
if (descriptor_->options().packed()) {
306
printer->Print(variables_,
307
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n"
308
" this->$name$(i), output);\n");
310
printer->Print(variables_,
311
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
312
" $number$, this->$name$(i), output);\n");
314
printer->Print("}\n");
317
void RepeatedPrimitiveFieldGenerator::
318
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
319
if (descriptor_->options().packed()) {
320
// Write the tag and the size.
321
printer->Print(variables_,
322
"if (this->$name$_size() > 0) {\n"
323
" target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n"
325
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
327
" target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
328
" _$name$_cached_byte_size_, target);\n"
331
printer->Print(variables_,
332
"for (int i = 0; i < this->$name$_size(); i++) {\n");
333
if (descriptor_->options().packed()) {
334
printer->Print(variables_,
335
" target = ::google::protobuf::internal::WireFormatLite::\n"
336
" Write$declared_type$NoTagToArray(this->$name$(i), target);\n");
338
printer->Print(variables_,
339
" target = ::google::protobuf::internal::WireFormatLite::\n"
340
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n");
342
printer->Print("}\n");
345
void RepeatedPrimitiveFieldGenerator::
346
GenerateByteSize(io::Printer* printer) const {
347
printer->Print(variables_,
349
" int data_size = 0;\n");
351
int fixed_size = FixedSize(descriptor_->type());
352
if (fixed_size == -1) {
353
printer->Print(variables_,
354
"for (int i = 0; i < this->$name$_size(); i++) {\n"
355
" data_size += ::google::protobuf::internal::WireFormatLite::\n"
356
" $declared_type$Size(this->$name$(i));\n"
359
printer->Print(variables_,
360
"data_size = $fixed_size$ * this->$name$_size();\n");
363
if (descriptor_->options().packed()) {
364
printer->Print(variables_,
365
"if (data_size > 0) {\n"
366
" total_size += $tag_size$ +\n"
367
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
369
"_$name$_cached_byte_size_ = data_size;\n"
370
"total_size += data_size;\n");
372
printer->Print(variables_,
373
"total_size += $tag_size$ * this->$name$_size() + data_size;\n");
376
printer->Print("}\n");
380
} // namespace compiler
381
} // namespace protobuf
382
} // namespace google