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.
36
#include <google/protobuf/stubs/hash.h>
39
#include <google/protobuf/compiler/cpp/cpp_message.h>
40
#include <google/protobuf/compiler/cpp/cpp_field.h>
41
#include <google/protobuf/compiler/cpp/cpp_enum.h>
42
#include <google/protobuf/compiler/cpp/cpp_extension.h>
43
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
44
#include <google/protobuf/stubs/strutil.h>
45
#include <google/protobuf/io/printer.h>
46
#include <google/protobuf/io/coded_stream.h>
47
#include <google/protobuf/wire_format.h>
48
#include <google/protobuf/descriptor.pb.h>
55
using internal::WireFormat;
56
using internal::WireFormatLite;
60
void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) {
61
// Print the field's proto-syntax definition as a comment. We don't want to
62
// print group bodies so we cut off after the first line.
63
string def = field->DebugString();
64
printer->Print("// $def$\n",
65
"def", def.substr(0, def.find_first_of('\n')));
68
struct FieldOrderingByNumber {
69
inline bool operator()(const FieldDescriptor* a,
70
const FieldDescriptor* b) const {
71
return a->number() < b->number();
75
const char* kWireTypeNames[] = {
84
// Sort the fields of the given Descriptor by number into a new[]'d array
86
const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
87
const FieldDescriptor** fields =
88
new const FieldDescriptor*[descriptor->field_count()];
89
for (int i = 0; i < descriptor->field_count(); i++) {
90
fields[i] = descriptor->field(i);
92
sort(fields, fields + descriptor->field_count(),
93
FieldOrderingByNumber());
97
// Functor for sorting extension ranges by their "start" field number.
98
struct ExtensionRangeSorter {
99
bool operator()(const Descriptor::ExtensionRange* left,
100
const Descriptor::ExtensionRange* right) const {
101
return left->start < right->start;
105
// Returns true if the message type has any required fields. If it doesn't,
106
// we can optimize out calls to its IsInitialized() method.
108
// already_seen is used to avoid checking the same type multiple times
109
// (and also to protect against recursion).
110
static bool HasRequiredFields(
111
const Descriptor* type,
112
hash_set<const Descriptor*>* already_seen) {
113
if (already_seen->count(type) > 0) {
114
// Since the first occurrence of a required field causes the whole
115
// function to return true, we can assume that if the type is already
116
// in the cache it didn't have any required fields.
119
already_seen->insert(type);
121
// If the type has extensions, an extension with message type could contain
122
// required fields, so we have to be conservative and assume such an
124
if (type->extension_range_count() > 0) return true;
126
for (int i = 0; i < type->field_count(); i++) {
127
const FieldDescriptor* field = type->field(i);
128
if (field->is_required()) {
131
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
132
if (HasRequiredFields(field->message_type(), already_seen)) {
141
static bool HasRequiredFields(const Descriptor* type) {
142
hash_set<const Descriptor*> already_seen;
143
return HasRequiredFields(type, &already_seen);
148
// ===================================================================
150
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
151
const string& dllexport_decl)
152
: descriptor_(descriptor),
153
classname_(ClassName(descriptor, false)),
154
dllexport_decl_(dllexport_decl),
155
field_generators_(descriptor),
156
nested_generators_(new scoped_ptr<MessageGenerator>[
157
descriptor->nested_type_count()]),
158
enum_generators_(new scoped_ptr<EnumGenerator>[
159
descriptor->enum_type_count()]),
160
extension_generators_(new scoped_ptr<ExtensionGenerator>[
161
descriptor->extension_count()]) {
163
for (int i = 0; i < descriptor->nested_type_count(); i++) {
164
nested_generators_[i].reset(
165
new MessageGenerator(descriptor->nested_type(i), dllexport_decl));
168
for (int i = 0; i < descriptor->enum_type_count(); i++) {
169
enum_generators_[i].reset(
170
new EnumGenerator(descriptor->enum_type(i), dllexport_decl));
173
for (int i = 0; i < descriptor->extension_count(); i++) {
174
extension_generators_[i].reset(
175
new ExtensionGenerator(descriptor->extension(i), dllexport_decl));
179
MessageGenerator::~MessageGenerator() {}
181
void MessageGenerator::
182
GenerateForwardDeclaration(io::Printer* printer) {
183
printer->Print("class $classname$;\n",
184
"classname", classname_);
186
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
187
nested_generators_[i]->GenerateForwardDeclaration(printer);
191
void MessageGenerator::
192
GenerateEnumDefinitions(io::Printer* printer) {
193
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
194
nested_generators_[i]->GenerateEnumDefinitions(printer);
197
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
198
enum_generators_[i]->GenerateDefinition(printer);
202
void MessageGenerator::
203
GenerateGetEnumDescriptorSpecializations(io::Printer* printer) {
204
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
205
nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
207
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
208
enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
212
void MessageGenerator::
213
GenerateFieldAccessorDeclarations(io::Printer* printer) {
214
for (int i = 0; i < descriptor_->field_count(); i++) {
215
const FieldDescriptor* field = descriptor_->field(i);
217
PrintFieldComment(printer, field);
219
map<string, string> vars;
220
SetCommonFieldVariables(field, &vars);
221
vars["constant_name"] = FieldConstantName(field);
223
if (field->is_repeated()) {
224
printer->Print(vars, "inline int $name$_size() const$deprecation$;\n");
226
printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n");
229
printer->Print(vars, "inline void clear_$name$()$deprecation$;\n");
230
printer->Print(vars, "static const int $constant_name$ = $number$;\n");
232
// Generate type-specific accessor declarations.
233
field_generators_.get(field).GenerateAccessorDeclarations(printer);
235
printer->Print("\n");
238
if (descriptor_->extension_range_count() > 0) {
239
// Generate accessors for extensions. We just call a macro located in
240
// extension_set.h since the accessors about 80 lines of static code.
242
"GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n",
243
"classname", classname_);
247
void MessageGenerator::
248
GenerateFieldAccessorDefinitions(io::Printer* printer) {
249
printer->Print("// $classname$\n\n", "classname", classname_);
251
for (int i = 0; i < descriptor_->field_count(); i++) {
252
const FieldDescriptor* field = descriptor_->field(i);
254
PrintFieldComment(printer, field);
256
map<string, string> vars;
257
SetCommonFieldVariables(field, &vars);
259
// Generate has_$name$() or $name$_size().
260
if (field->is_repeated()) {
262
"inline int $classname$::$name$_size() const {\n"
263
" return $name$_.size();\n"
268
"inline bool $classname$::has_$name$() const {\n"
269
" return _has_bit($index$);\n"
273
// Generate clear_$name$()
275
"inline void $classname$::clear_$name$() {\n");
278
field_generators_.get(field).GenerateClearingCode(printer);
281
if (!field->is_repeated()) {
282
printer->Print(vars, " _clear_bit($index$);\n");
285
printer->Print("}\n");
287
// Generate type-specific accessors.
288
field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
290
printer->Print("\n");
294
void MessageGenerator::
295
GenerateClassDefinition(io::Printer* printer) {
296
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
297
nested_generators_[i]->GenerateClassDefinition(printer);
298
printer->Print("\n");
299
printer->Print(kThinSeparator);
300
printer->Print("\n");
303
map<string, string> vars;
304
vars["classname"] = classname_;
305
vars["field_count"] = SimpleItoa(descriptor_->field_count());
306
if (dllexport_decl_.empty()) {
307
vars["dllexport"] = "";
309
vars["dllexport"] = dllexport_decl_ + " ";
311
vars["superclass"] = SuperClassName(descriptor_);
314
"class $dllexport$$classname$ : public $superclass$ {\n"
320
"virtual ~$classname$();\n"
322
"$classname$(const $classname$& from);\n"
324
"inline $classname$& operator=(const $classname$& from) {\n"
330
if (HasUnknownFields(descriptor_->file())) {
332
"inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
333
" return _unknown_fields_;\n"
336
"inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
337
" return &_unknown_fields_;\n"
342
// Only generate this member if it's not disabled.
343
if (HasDescriptorMethods(descriptor_->file()) &&
344
!descriptor_->options().no_standard_descriptor_accessor()) {
346
"static const ::google::protobuf::Descriptor* descriptor();\n");
350
"static const $classname$& default_instance();\n"
355
"void Swap($classname$* other);\n"
357
"// implements Message ----------------------------------------------\n"
359
"$classname$* New() const;\n");
361
if (HasGeneratedMethods(descriptor_->file())) {
362
if (HasDescriptorMethods(descriptor_->file())) {
364
"void CopyFrom(const ::google::protobuf::Message& from);\n"
365
"void MergeFrom(const ::google::protobuf::Message& from);\n");
368
"void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n");
372
"void CopyFrom(const $classname$& from);\n"
373
"void MergeFrom(const $classname$& from);\n"
375
"bool IsInitialized() const;\n"
377
"int ByteSize() const;\n"
378
"bool MergePartialFromCodedStream(\n"
379
" ::google::protobuf::io::CodedInputStream* input);\n"
380
"void SerializeWithCachedSizes(\n"
381
" ::google::protobuf::io::CodedOutputStream* output) const;\n");
382
if (HasFastArraySerialization(descriptor_->file())) {
384
"::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n");
389
"int GetCachedSize() const { return _cached_size_; }\n"
391
"void SharedCtor();\n"
392
"void SharedDtor();\n"
393
"void SetCachedSize(int size) const;\n"
397
if (HasDescriptorMethods(descriptor_->file())) {
399
"::google::protobuf::Metadata GetMetadata() const;\n"
403
"::std::string GetTypeName() const;\n"
408
"// nested types ----------------------------------------------------\n"
411
// Import all nested message classes into this class's scope with typedefs.
412
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
413
const Descriptor* nested_type = descriptor_->nested_type(i);
414
printer->Print("typedef $nested_full_name$ $nested_name$;\n",
415
"nested_name", nested_type->name(),
416
"nested_full_name", ClassName(nested_type, false));
419
if (descriptor_->nested_type_count() > 0) {
420
printer->Print("\n");
423
// Import all nested enums and their values into this class's scope with
424
// typedefs and constants.
425
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
426
enum_generators_[i]->GenerateSymbolImports(printer);
427
printer->Print("\n");
431
"// accessors -------------------------------------------------------\n"
434
// Generate accessor methods for all fields.
435
GenerateFieldAccessorDeclarations(printer);
437
// Declare extension identifiers.
438
for (int i = 0; i < descriptor_->extension_count(); i++) {
439
extension_generators_[i]->GenerateDeclaration(printer);
444
"// @@protoc_insertion_point(class_scope:$full_name$)\n",
445
"full_name", descriptor_->full_name());
447
// Generate private members for fields.
449
printer->Print(" private:\n");
452
if (descriptor_->extension_range_count() > 0) {
454
"::google::protobuf::internal::ExtensionSet _extensions_;\n");
457
if (HasUnknownFields(descriptor_->file())) {
459
"::google::protobuf::UnknownFieldSet _unknown_fields_;\n");
462
// TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it.
464
"mutable int _cached_size_;\n"
466
for (int i = 0; i < descriptor_->field_count(); i++) {
467
field_generators_.get(descriptor_->field(i))
468
.GeneratePrivateMembers(printer);
471
// Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as
472
// friends so that they can access private static variables like
473
// default_instance_ and reflection_.
475
"friend void $dllexport_decl$ $adddescriptorsname$();\n",
476
"dllexport_decl", dllexport_decl_,
477
"adddescriptorsname",
478
GlobalAddDescriptorsName(descriptor_->file()->name()));
480
"friend void $assigndescriptorsname$();\n"
481
"friend void $shutdownfilename$();\n"
483
"assigndescriptorsname",
484
GlobalAssignDescriptorsName(descriptor_->file()->name()),
485
"shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
487
// Generate offsets and _has_bits_ boilerplate.
488
if (descriptor_->field_count() > 0) {
490
"::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n");
492
// Zero-size arrays aren't technically allowed, and MSVC in particular
493
// doesn't like them. We still need to declare these arrays to make
494
// other code compile. Since this is an uncommon case, we'll just declare
495
// them with size 1 and waste some space. Oh well.
497
"::google::protobuf::uint32 _has_bits_[1];\n");
502
"// WHY DOES & HAVE LOWER PRECEDENCE THAN != !?\n"
503
"inline bool _has_bit(int index) const {\n"
504
" return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;\n"
506
"inline void _set_bit(int index) {\n"
507
" _has_bits_[index / 32] |= (1u << (index % 32));\n"
509
"inline void _clear_bit(int index) {\n"
510
" _has_bits_[index / 32] &= ~(1u << (index % 32));\n"
513
"void InitAsDefaultInstance();\n"
514
"static $classname$* default_instance_;\n",
515
"classname", classname_);
518
printer->Print(vars, "};");
521
void MessageGenerator::
522
GenerateInlineMethods(io::Printer* printer) {
523
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
524
nested_generators_[i]->GenerateInlineMethods(printer);
525
printer->Print(kThinSeparator);
526
printer->Print("\n");
529
GenerateFieldAccessorDefinitions(printer);
532
void MessageGenerator::
533
GenerateDescriptorDeclarations(io::Printer* printer) {
535
"const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n"
536
"const ::google::protobuf::internal::GeneratedMessageReflection*\n"
537
" $name$_reflection_ = NULL;\n",
540
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
541
nested_generators_[i]->GenerateDescriptorDeclarations(printer);
544
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
546
"const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n",
547
"name", ClassName(descriptor_->enum_type(i), false));
551
void MessageGenerator::
552
GenerateDescriptorInitializer(io::Printer* printer, int index) {
553
// TODO(kenton): Passing the index to this method is redundant; just use
554
// descriptor_->index() instead.
555
map<string, string> vars;
556
vars["classname"] = classname_;
557
vars["index"] = SimpleItoa(index);
559
// Obtain the descriptor from the parent's descriptor.
560
if (descriptor_->containing_type() == NULL) {
562
"$classname$_descriptor_ = file->message_type($index$);\n");
564
vars["parent"] = ClassName(descriptor_->containing_type(), false);
566
"$classname$_descriptor_ = "
567
"$parent$_descriptor_->nested_type($index$);\n");
570
// Generate the offsets.
571
GenerateOffsets(printer);
573
// Construct the reflection object.
575
"$classname$_reflection_ =\n"
576
" new ::google::protobuf::internal::GeneratedMessageReflection(\n"
577
" $classname$_descriptor_,\n"
578
" $classname$::default_instance_,\n"
579
" $classname$_offsets_,\n"
580
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n"
581
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
582
"$classname$, _unknown_fields_),\n");
583
if (descriptor_->extension_range_count() > 0) {
585
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
586
"$classname$, _extensions_),\n");
593
" ::google::protobuf::DescriptorPool::generated_pool(),\n"
594
" ::google::protobuf::MessageFactory::generated_factory(),\n"
595
" sizeof($classname$));\n");
597
// Handle nested types.
598
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
599
nested_generators_[i]->GenerateDescriptorInitializer(printer, i);
602
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
603
enum_generators_[i]->GenerateDescriptorInitializer(printer, i);
607
void MessageGenerator::
608
GenerateTypeRegistrations(io::Printer* printer) {
609
// Register this message type with the message factory.
611
"::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
612
" $classname$_descriptor_, &$classname$::default_instance());\n",
613
"classname", classname_);
615
// Handle nested types.
616
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
617
nested_generators_[i]->GenerateTypeRegistrations(printer);
621
void MessageGenerator::
622
GenerateDefaultInstanceAllocator(io::Printer* printer) {
623
// Construct the default instance. We can't call InitAsDefaultInstance() yet
624
// because we need to make sure all default instances that this one might
625
// depend on are constructed first.
627
"$classname$::default_instance_ = new $classname$();\n",
628
"classname", classname_);
630
// Handle nested types.
631
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
632
nested_generators_[i]->GenerateDefaultInstanceAllocator(printer);
637
void MessageGenerator::
638
GenerateDefaultInstanceInitializer(io::Printer* printer) {
640
"$classname$::default_instance_->InitAsDefaultInstance();\n",
641
"classname", classname_);
643
// Register extensions.
644
for (int i = 0; i < descriptor_->extension_count(); i++) {
645
extension_generators_[i]->GenerateRegistration(printer);
648
// Handle nested types.
649
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
650
nested_generators_[i]->GenerateDefaultInstanceInitializer(printer);
654
void MessageGenerator::
655
GenerateShutdownCode(io::Printer* printer) {
657
"delete $classname$::default_instance_;\n",
658
"classname", classname_);
660
if (HasDescriptorMethods(descriptor_->file())) {
662
"delete $classname$_reflection_;\n",
663
"classname", classname_);
666
// Handle nested types.
667
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
668
nested_generators_[i]->GenerateShutdownCode(printer);
672
void MessageGenerator::
673
GenerateClassMethods(io::Printer* printer) {
674
for (int i = 0; i < descriptor_->enum_type_count(); i++) {
675
enum_generators_[i]->GenerateMethods(printer);
678
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
679
nested_generators_[i]->GenerateClassMethods(printer);
680
printer->Print("\n");
681
printer->Print(kThinSeparator);
682
printer->Print("\n");
685
// Generate non-inline field definitions.
686
for (int i = 0; i < descriptor_->field_count(); i++) {
687
field_generators_.get(descriptor_->field(i))
688
.GenerateNonInlineAccessorDefinitions(printer);
691
// Generate field number constants.
692
printer->Print("#ifndef _MSC_VER\n");
693
for (int i = 0; i < descriptor_->field_count(); i++) {
694
const FieldDescriptor *field = descriptor_->field(i);
696
"const int $classname$::$constant_name$;\n",
697
"classname", ClassName(FieldScope(field), false),
698
"constant_name", FieldConstantName(field));
701
"#endif // !_MSC_VER\n"
704
// Define extension identifiers.
705
for (int i = 0; i < descriptor_->extension_count(); i++) {
706
extension_generators_[i]->GenerateDefinition(printer);
709
GenerateStructors(printer);
710
printer->Print("\n");
712
if (HasGeneratedMethods(descriptor_->file())) {
713
GenerateClear(printer);
714
printer->Print("\n");
716
GenerateMergeFromCodedStream(printer);
717
printer->Print("\n");
719
GenerateSerializeWithCachedSizes(printer);
720
printer->Print("\n");
722
if (HasFastArraySerialization(descriptor_->file())) {
723
GenerateSerializeWithCachedSizesToArray(printer);
724
printer->Print("\n");
727
GenerateByteSize(printer);
728
printer->Print("\n");
730
GenerateMergeFrom(printer);
731
printer->Print("\n");
733
GenerateCopyFrom(printer);
734
printer->Print("\n");
736
GenerateIsInitialized(printer);
737
printer->Print("\n");
740
GenerateSwap(printer);
741
printer->Print("\n");
743
if (HasDescriptorMethods(descriptor_->file())) {
745
"::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
746
" protobuf_AssignDescriptorsOnce();\n"
747
" ::google::protobuf::Metadata metadata;\n"
748
" metadata.descriptor = $classname$_descriptor_;\n"
749
" metadata.reflection = $classname$_reflection_;\n"
750
" return metadata;\n"
753
"classname", classname_);
756
"::std::string $classname$::GetTypeName() const {\n"
757
" return \"$type_name$\";\n"
760
"classname", classname_,
761
"type_name", descriptor_->full_name());
766
void MessageGenerator::
767
GenerateOffsets(io::Printer* printer) {
769
"static const int $classname$_offsets_[$field_count$] = {\n",
770
"classname", classname_,
771
"field_count", SimpleItoa(max(1, descriptor_->field_count())));
774
for (int i = 0; i < descriptor_->field_count(); i++) {
775
const FieldDescriptor* field = descriptor_->field(i);
777
"GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n",
778
"classname", classname_,
779
"name", FieldName(field));
783
printer->Print("};\n");
786
void MessageGenerator::
787
GenerateSharedConstructorCode(io::Printer* printer) {
789
"void $classname$::SharedCtor() {\n",
790
"classname", classname_);
794
"_cached_size_ = 0;\n");
796
for (int i = 0; i < descriptor_->field_count(); i++) {
797
field_generators_.get(descriptor_->field(i))
798
.GenerateConstructorCode(printer);
802
"::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
805
printer->Print("}\n\n");
808
void MessageGenerator::
809
GenerateSharedDestructorCode(io::Printer* printer) {
811
"void $classname$::SharedDtor() {\n",
812
"classname", classname_);
814
// Write the destructors for each field.
815
for (int i = 0; i < descriptor_->field_count(); i++) {
816
field_generators_.get(descriptor_->field(i))
817
.GenerateDestructorCode(printer);
821
"if (this != default_instance_) {\n");
823
// We need to delete all embedded messages.
824
// TODO(kenton): If we make unset messages point at default instances
825
// instead of NULL, then it would make sense to move this code into
826
// MessageFieldGenerator::GenerateDestructorCode().
827
for (int i = 0; i < descriptor_->field_count(); i++) {
828
const FieldDescriptor* field = descriptor_->field(i);
830
if (!field->is_repeated() &&
831
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
832
printer->Print(" delete $name$_;\n",
833
"name", FieldName(field));
844
void MessageGenerator::
845
GenerateStructors(io::Printer* printer) {
846
string superclass = SuperClassName(descriptor_);
848
// Generate the default constructor.
850
"$classname$::$classname$()\n"
851
" : $superclass$() {\n"
854
"classname", classname_,
855
"superclass", superclass);
859
"void $classname$::InitAsDefaultInstance() {\n",
860
"classname", classname_);
862
// The default instance needs all of its embedded message pointers
863
// cross-linked to other default instances. We can't do this initialization
864
// in the constructor because some other default instances may not have been
865
// constructed yet at that time.
866
// TODO(kenton): Maybe all message fields (even for non-default messages)
867
// should be initialized to point at default instances rather than NULL?
868
for (int i = 0; i < descriptor_->field_count(); i++) {
869
const FieldDescriptor* field = descriptor_->field(i);
871
if (!field->is_repeated() &&
872
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
874
" $name$_ = const_cast< $type$*>(&$type$::default_instance());\n",
875
"name", FieldName(field),
876
"type", FieldMessageTypeName(field));
883
// Generate the copy constructor.
885
"$classname$::$classname$(const $classname$& from)\n"
886
" : $superclass$() {\n"
888
" MergeFrom(from);\n"
891
"classname", classname_,
892
"superclass", superclass);
894
// Generate the shared constructor code.
895
GenerateSharedConstructorCode(printer);
897
// Generate the destructor.
899
"$classname$::~$classname$() {\n"
903
"classname", classname_);
905
// Generate the shared destructor code.
906
GenerateSharedDestructorCode(printer);
908
// Generate SetCachedSize.
910
"void $classname$::SetCachedSize(int size) const {\n"
911
" GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
912
" _cached_size_ = size;\n"
913
" GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
915
"classname", classname_);
917
// Only generate this member if it's not disabled.
918
if (HasDescriptorMethods(descriptor_->file()) &&
919
!descriptor_->options().no_standard_descriptor_accessor()) {
921
"const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
922
" protobuf_AssignDescriptorsOnce();\n"
923
" return $classname$_descriptor_;\n"
926
"classname", classname_,
927
"adddescriptorsname",
928
GlobalAddDescriptorsName(descriptor_->file()->name()));
932
"const $classname$& $classname$::default_instance() {\n"
933
" if (default_instance_ == NULL) $adddescriptorsname$();"
934
" return *default_instance_;\n"
937
"$classname$* $classname$::default_instance_ = NULL;\n"
939
"$classname$* $classname$::New() const {\n"
940
" return new $classname$;\n"
942
"classname", classname_,
943
"adddescriptorsname",
944
GlobalAddDescriptorsName(descriptor_->file()->name()));
948
void MessageGenerator::
949
GenerateClear(io::Printer* printer) {
950
printer->Print("void $classname$::Clear() {\n",
951
"classname", classname_);
956
if (descriptor_->extension_range_count() > 0) {
957
printer->Print("_extensions_.Clear();\n");
960
for (int i = 0; i < descriptor_->field_count(); i++) {
961
const FieldDescriptor* field = descriptor_->field(i);
963
if (!field->is_repeated()) {
964
map<string, string> vars;
965
vars["index"] = SimpleItoa(field->index());
967
// We can use the fact that _has_bits_ is a giant bitfield to our
968
// advantage: We can check up to 32 bits at a time for equality to
969
// zero, and skip the whole range if so. This can improve the speed
970
// of Clear() for messages which contain a very large number of
971
// optional fields of which only a few are used at a time. Here,
972
// we've chosen to check 8 bits at a time rather than 32.
973
if (i / 8 != last_index / 8 || last_index < 0) {
974
if (last_index >= 0) {
976
printer->Print("}\n");
979
"if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n");
984
// It's faster to just overwrite primitive types, but we should
985
// only clear strings and messages if they were set.
986
// TODO(kenton): Let the CppFieldGenerator decide this somehow.
987
bool should_check_bit =
988
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
989
field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
991
if (should_check_bit) {
992
printer->Print(vars, "if (_has_bit($index$)) {\n");
996
field_generators_.get(field).GenerateClearingCode(printer);
998
if (should_check_bit) {
1000
printer->Print("}\n");
1005
if (last_index >= 0) {
1007
printer->Print("}\n");
1010
// Repeated fields don't use _has_bits_ so we clear them in a separate
1012
for (int i = 0; i < descriptor_->field_count(); i++) {
1013
const FieldDescriptor* field = descriptor_->field(i);
1015
if (field->is_repeated()) {
1016
field_generators_.get(field).GenerateClearingCode(printer);
1021
"::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
1023
if (HasUnknownFields(descriptor_->file())) {
1025
"mutable_unknown_fields()->Clear();\n");
1029
printer->Print("}\n");
1032
void MessageGenerator::
1033
GenerateSwap(io::Printer* printer) {
1034
// Generate the Swap member function.
1035
printer->Print("void $classname$::Swap($classname$* other) {\n",
1036
"classname", classname_);
1038
printer->Print("if (other != this) {\n");
1041
if (HasGeneratedMethods(descriptor_->file())) {
1042
for (int i = 0; i < descriptor_->field_count(); i++) {
1043
const FieldDescriptor* field = descriptor_->field(i);
1044
field_generators_.get(field).GenerateSwappingCode(printer);
1047
for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) {
1048
printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
1049
"i", SimpleItoa(i));
1052
if (HasUnknownFields(descriptor_->file())) {
1053
printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
1055
printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
1056
if (descriptor_->extension_range_count() > 0) {
1057
printer->Print("_extensions_.Swap(&other->_extensions_);\n");
1060
printer->Print("GetReflection()->Swap(this, other);");
1064
printer->Print("}\n");
1066
printer->Print("}\n");
1069
void MessageGenerator::
1070
GenerateMergeFrom(io::Printer* printer) {
1071
if (HasDescriptorMethods(descriptor_->file())) {
1072
// Generate the generalized MergeFrom (aka that which takes in the Message
1073
// base class as a parameter).
1075
"void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n"
1076
" GOOGLE_CHECK_NE(&from, this);\n",
1077
"classname", classname_);
1080
// Cast the message to the proper type. If we find that the message is
1081
// *not* of the proper type, we can still call Merge via the reflection
1082
// system, as the GOOGLE_CHECK above ensured that we have the same descriptor
1083
// for each message.
1085
"const $classname$* source =\n"
1086
" ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n"
1088
"if (source == NULL) {\n"
1089
" ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
1091
" MergeFrom(*source);\n"
1093
"classname", classname_);
1096
printer->Print("}\n\n");
1098
// Generate CheckTypeAndMergeFrom().
1100
"void $classname$::CheckTypeAndMergeFrom(\n"
1101
" const ::google::protobuf::MessageLite& from) {\n"
1102
" MergeFrom(*::google::protobuf::down_cast<const $classname$*>(&from));\n"
1105
"classname", classname_);
1108
// Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
1110
"void $classname$::MergeFrom(const $classname$& from) {\n"
1111
" GOOGLE_CHECK_NE(&from, this);\n",
1112
"classname", classname_);
1115
// Merge Repeated fields. These fields do not require a
1116
// check as we can simply iterate over them.
1117
for (int i = 0; i < descriptor_->field_count(); ++i) {
1118
const FieldDescriptor* field = descriptor_->field(i);
1120
if (field->is_repeated()) {
1121
field_generators_.get(field).GenerateMergingCode(printer);
1125
// Merge Optional and Required fields (after a _has_bit check).
1126
int last_index = -1;
1128
for (int i = 0; i < descriptor_->field_count(); ++i) {
1129
const FieldDescriptor* field = descriptor_->field(i);
1131
if (!field->is_repeated()) {
1132
map<string, string> vars;
1133
vars["index"] = SimpleItoa(field->index());
1135
// See above in GenerateClear for an explanation of this.
1136
if (i / 8 != last_index / 8 || last_index < 0) {
1137
if (last_index >= 0) {
1139
printer->Print("}\n");
1141
printer->Print(vars,
1142
"if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n");
1148
printer->Print(vars,
1149
"if (from._has_bit($index$)) {\n");
1152
field_generators_.get(field).GenerateMergingCode(printer);
1155
printer->Print("}\n");
1159
if (last_index >= 0) {
1161
printer->Print("}\n");
1164
if (descriptor_->extension_range_count() > 0) {
1165
printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
1168
if (HasUnknownFields(descriptor_->file())) {
1170
"mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n");
1174
printer->Print("}\n");
1177
void MessageGenerator::
1178
GenerateCopyFrom(io::Printer* printer) {
1179
if (HasDescriptorMethods(descriptor_->file())) {
1180
// Generate the generalized CopyFrom (aka that which takes in the Message
1181
// base class as a parameter).
1183
"void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n",
1184
"classname", classname_);
1188
"if (&from == this) return;\n"
1190
"MergeFrom(from);\n");
1193
printer->Print("}\n\n");
1196
// Generate the class-specific CopyFrom.
1198
"void $classname$::CopyFrom(const $classname$& from) {\n",
1199
"classname", classname_);
1203
"if (&from == this) return;\n"
1205
"MergeFrom(from);\n");
1208
printer->Print("}\n");
1211
void MessageGenerator::
1212
GenerateMergeFromCodedStream(io::Printer* printer) {
1213
if (descriptor_->options().message_set_wire_format()) {
1214
// Special-case MessageSet.
1216
"bool $classname$::MergePartialFromCodedStream(\n"
1217
" ::google::protobuf::io::CodedInputStream* input) {\n"
1218
" return _extensions_.ParseMessageSet(input, default_instance_,\n"
1219
" mutable_unknown_fields());\n"
1221
"classname", classname_);
1226
"bool $classname$::MergePartialFromCodedStream(\n"
1227
" ::google::protobuf::io::CodedInputStream* input) {\n"
1228
"#define DO_(EXPRESSION) if (!(EXPRESSION)) return false\n"
1229
" ::google::protobuf::uint32 tag;\n"
1230
" while ((tag = input->ReadTag()) != 0) {\n",
1231
"classname", classname_);
1236
if (descriptor_->field_count() > 0) {
1237
// We don't even want to print the switch() if we have no fields because
1238
// MSVC dislikes switch() statements that contain only a default value.
1240
// Note: If we just switched on the tag rather than the field number, we
1241
// could avoid the need for the if() to check the wire type at the beginning
1242
// of each case. However, this is actually a bit slower in practice as it
1243
// creates a jump table that is 8x larger and sparser, and meanwhile the
1244
// if()s are highly predictable.
1246
"switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n");
1250
scoped_array<const FieldDescriptor*> ordered_fields(
1251
SortFieldsByNumber(descriptor_));
1253
for (int i = 0; i < descriptor_->field_count(); i++) {
1254
const FieldDescriptor* field = ordered_fields[i];
1256
PrintFieldComment(printer, field);
1259
"case $number$: {\n",
1260
"number", SimpleItoa(field->number()));
1262
const FieldGenerator& field_generator = field_generators_.get(field);
1264
// Emit code to parse the common, expected case.
1266
"if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
1267
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n",
1268
"wiretype", kWireTypeNames[WireFormat::WireTypeForField(field)]);
1270
if (i > 0 || (field->is_repeated() && !field->options().packed())) {
1273
"name", field->name());
1277
if (field->options().packed()) {
1278
field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
1280
field_generator.GenerateMergeFromCodedStream(printer);
1284
// Emit code to parse unexpectedly packed or unpacked values.
1285
if (field->is_packable() && field->options().packed()) {
1287
"} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n"
1288
" == ::google::protobuf::internal::WireFormatLite::\n"
1289
" WIRETYPE_$wiretype$) {\n",
1291
kWireTypeNames[WireFormat::WireTypeForFieldType(field->type())]);
1293
field_generator.GenerateMergeFromCodedStream(printer);
1295
} else if (field->is_packable() && !field->options().packed()) {
1297
"} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n"
1298
" == ::google::protobuf::internal::WireFormatLite::\n"
1299
" WIRETYPE_LENGTH_DELIMITED) {\n");
1301
field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
1307
" goto handle_uninterpreted;\n"
1310
// switch() is slow since it can't be predicted well. Insert some if()s
1311
// here that attempt to predict the next tag.
1312
if (field->is_repeated() && !field->options().packed()) {
1313
// Expect repeats of this field.
1315
"if (input->ExpectTag($tag$)) goto parse_$name$;\n",
1316
"tag", SimpleItoa(WireFormat::MakeTag(field)),
1317
"name", field->name());
1320
if (i + 1 < descriptor_->field_count()) {
1321
// Expect the next field in order.
1322
const FieldDescriptor* next_field = ordered_fields[i + 1];
1324
"if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n",
1325
"next_tag", SimpleItoa(WireFormat::MakeTag(next_field)),
1326
"next_name", next_field->name());
1329
// TODO(kenton): Expect group end-tag?
1331
"if (input->ExpectAtEnd()) return true;\n");
1338
printer->Print("}\n\n");
1343
"handle_uninterpreted:\n");
1347
// Is this an end-group tag? If so, this must be the end of the message.
1349
"if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
1350
" ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
1354
// Handle extension ranges.
1355
if (descriptor_->extension_range_count() > 0) {
1358
for (int i = 0; i < descriptor_->extension_range_count(); i++) {
1359
const Descriptor::ExtensionRange* range =
1360
descriptor_->extension_range(i);
1361
if (i > 0) printer->Print(" ||\n ");
1363
uint32 start_tag = WireFormatLite::MakeTag(
1364
range->start, static_cast<WireFormatLite::WireType>(0));
1365
uint32 end_tag = WireFormatLite::MakeTag(
1366
range->end, static_cast<WireFormatLite::WireType>(0));
1368
if (range->end > FieldDescriptor::kMaxNumber) {
1370
"($start$u <= tag)",
1371
"start", SimpleItoa(start_tag));
1374
"($start$u <= tag && tag < $end$u)",
1375
"start", SimpleItoa(start_tag),
1376
"end", SimpleItoa(end_tag));
1379
printer->Print(") {\n");
1380
if (HasUnknownFields(descriptor_->file())) {
1382
" DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
1383
" mutable_unknown_fields()));\n");
1386
" DO_(_extensions_.ParseField(tag, input, default_instance_));\n");
1393
// We really don't recognize this tag. Skip it.
1394
if (HasUnknownFields(descriptor_->file())) {
1396
"DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
1397
" input, tag, mutable_unknown_fields()));\n");
1400
"DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n");
1403
if (descriptor_->field_count() > 0) {
1404
printer->Print("break;\n");
1406
printer->Print("}\n"); // default:
1408
printer->Print("}\n"); // switch
1420
void MessageGenerator::GenerateSerializeOneField(
1421
io::Printer* printer, const FieldDescriptor* field, bool to_array) {
1422
PrintFieldComment(printer, field);
1424
if (!field->is_repeated()) {
1426
"if (_has_bit($index$)) {\n",
1427
"index", SimpleItoa(field->index()));
1432
field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
1435
field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
1438
if (!field->is_repeated()) {
1440
printer->Print("}\n");
1442
printer->Print("\n");
1445
void MessageGenerator::GenerateSerializeOneExtensionRange(
1446
io::Printer* printer, const Descriptor::ExtensionRange* range,
1448
map<string, string> vars;
1449
vars["start"] = SimpleItoa(range->start);
1450
vars["end"] = SimpleItoa(range->end);
1451
printer->Print(vars,
1452
"// Extension range [$start$, $end$)\n");
1454
printer->Print(vars,
1455
"target = _extensions_.SerializeWithCachedSizesToArray(\n"
1456
" $start$, $end$, target);\n\n");
1458
printer->Print(vars,
1459
"_extensions_.SerializeWithCachedSizes(\n"
1460
" $start$, $end$, output);\n\n");
1464
void MessageGenerator::
1465
GenerateSerializeWithCachedSizes(io::Printer* printer) {
1466
if (descriptor_->options().message_set_wire_format()) {
1467
// Special-case MessageSet.
1469
"void $classname$::SerializeWithCachedSizes(\n"
1470
" ::google::protobuf::io::CodedOutputStream* output) const {\n"
1471
" _extensions_.SerializeMessageSetWithCachedSizes(output);\n",
1472
"classname", classname_);
1473
if (HasUnknownFields(descriptor_->file())) {
1475
" ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n"
1476
" unknown_fields(), output);\n");
1484
"void $classname$::SerializeWithCachedSizes(\n"
1485
" ::google::protobuf::io::CodedOutputStream* output) const {\n",
1486
"classname", classname_);
1489
GenerateSerializeWithCachedSizesBody(printer, false);
1496
void MessageGenerator::
1497
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
1498
if (descriptor_->options().message_set_wire_format()) {
1499
// Special-case MessageSet.
1501
"::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
1502
" ::google::protobuf::uint8* target) const {\n"
1504
" _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n",
1505
"classname", classname_);
1506
if (HasUnknownFields(descriptor_->file())) {
1508
" target = ::google::protobuf::internal::WireFormat::\n"
1509
" SerializeUnknownMessageSetItemsToArray(\n"
1510
" unknown_fields(), target);\n");
1519
"::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n"
1520
" ::google::protobuf::uint8* target) const {\n",
1521
"classname", classname_);
1524
GenerateSerializeWithCachedSizesBody(printer, true);
1532
void MessageGenerator::
1533
GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
1534
scoped_array<const FieldDescriptor*> ordered_fields(
1535
SortFieldsByNumber(descriptor_));
1537
vector<const Descriptor::ExtensionRange*> sorted_extensions;
1538
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
1539
sorted_extensions.push_back(descriptor_->extension_range(i));
1541
sort(sorted_extensions.begin(), sorted_extensions.end(),
1542
ExtensionRangeSorter());
1544
// Merge the fields and the extension ranges, both sorted by field number.
1547
i < descriptor_->field_count() || j < sorted_extensions.size();
1549
if (i == descriptor_->field_count()) {
1550
GenerateSerializeOneExtensionRange(printer,
1551
sorted_extensions[j++],
1553
} else if (j == sorted_extensions.size()) {
1554
GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
1555
} else if (ordered_fields[i]->number() < sorted_extensions[j]->start) {
1556
GenerateSerializeOneField(printer, ordered_fields[i++], to_array);
1558
GenerateSerializeOneExtensionRange(printer,
1559
sorted_extensions[j++],
1564
if (HasUnknownFields(descriptor_->file())) {
1565
printer->Print("if (!unknown_fields().empty()) {\n");
1570
"::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
1571
" unknown_fields(), target);\n");
1574
"::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
1575
" unknown_fields(), output);\n");
1584
void MessageGenerator::
1585
GenerateByteSize(io::Printer* printer) {
1586
if (descriptor_->options().message_set_wire_format()) {
1587
// Special-case MessageSet.
1589
"int $classname$::ByteSize() const {\n"
1590
" int total_size = _extensions_.MessageSetByteSize();\n",
1591
"classname", classname_);
1592
if (HasUnknownFields(descriptor_->file())) {
1594
" total_size += ::google::protobuf::internal::WireFormat::\n"
1595
" ComputeUnknownMessageSetItemsSize(unknown_fields());\n");
1598
" GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
1599
" _cached_size_ = total_size;\n"
1600
" GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
1601
" return total_size;\n"
1607
"int $classname$::ByteSize() const {\n",
1608
"classname", classname_);
1611
"int total_size = 0;\n"
1614
int last_index = -1;
1616
for (int i = 0; i < descriptor_->field_count(); i++) {
1617
const FieldDescriptor* field = descriptor_->field(i);
1619
if (!field->is_repeated()) {
1620
// See above in GenerateClear for an explanation of this.
1621
// TODO(kenton): Share code? Unclear how to do so without
1622
// over-engineering.
1623
if ((i / 8) != (last_index / 8) ||
1625
if (last_index >= 0) {
1627
printer->Print("}\n");
1630
"if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
1631
"index", SimpleItoa(field->index()));
1636
PrintFieldComment(printer, field);
1639
"if (has_$name$()) {\n",
1640
"name", FieldName(field));
1643
field_generators_.get(field).GenerateByteSize(printer);
1652
if (last_index >= 0) {
1654
printer->Print("}\n");
1657
// Repeated fields don't use _has_bits_ so we count them in a separate
1659
for (int i = 0; i < descriptor_->field_count(); i++) {
1660
const FieldDescriptor* field = descriptor_->field(i);
1662
if (field->is_repeated()) {
1663
PrintFieldComment(printer, field);
1664
field_generators_.get(field).GenerateByteSize(printer);
1665
printer->Print("\n");
1669
if (descriptor_->extension_range_count() > 0) {
1671
"total_size += _extensions_.ByteSize();\n"
1675
if (HasUnknownFields(descriptor_->file())) {
1676
printer->Print("if (!unknown_fields().empty()) {\n");
1680
" ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
1681
" unknown_fields());\n");
1683
printer->Print("}\n");
1686
// We update _cached_size_ even though this is a const method. In theory,
1687
// this is not thread-compatible, because concurrent writes have undefined
1688
// results. In practice, since any concurrent writes will be writing the
1689
// exact same value, it works on all common processors. In a future version
1690
// of C++, _cached_size_ should be made into an atomic<int>.
1692
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
1693
"_cached_size_ = total_size;\n"
1694
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
1695
"return total_size;\n");
1698
printer->Print("}\n");
1701
void MessageGenerator::
1702
GenerateIsInitialized(io::Printer* printer) {
1704
"bool $classname$::IsInitialized() const {\n",
1705
"classname", classname_);
1708
// Check that all required fields in this message are set. We can do this
1709
// most efficiently by checking 32 "has bits" at a time.
1710
int has_bits_array_size = (descriptor_->field_count() + 31) / 32;
1711
for (int i = 0; i < has_bits_array_size; i++) {
1713
for (int bit = 0; bit < 32; bit++) {
1714
int index = i * 32 + bit;
1715
if (index >= descriptor_->field_count()) break;
1716
const FieldDescriptor* field = descriptor_->field(index);
1718
if (field->is_required()) {
1724
char buffer[kFastToBufferSize];
1726
"if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
1728
"mask", FastHex32ToBuffer(mask, buffer));
1732
// Now check that all embedded messages are initialized.
1733
printer->Print("\n");
1734
for (int i = 0; i < descriptor_->field_count(); i++) {
1735
const FieldDescriptor* field = descriptor_->field(i);
1736
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
1737
HasRequiredFields(field->message_type())) {
1738
if (field->is_repeated()) {
1740
"for (int i = 0; i < $name$_size(); i++) {\n"
1741
" if (!this->$name$(i).IsInitialized()) return false;\n"
1743
"name", FieldName(field));
1746
"if (has_$name$()) {\n"
1747
" if (!this->$name$().IsInitialized()) return false;\n"
1749
"name", FieldName(field));
1754
if (descriptor_->extension_range_count() > 0) {
1757
"if (!_extensions_.IsInitialized()) return false;");
1768
} // namespace compiler
1769
} // namespace protobuf
1770
} // namespace google