diff options
Diffstat (limited to 'third_party/protobuf/3.0.0/src/google/protobuf/compiler/cpp/cpp_message.cc')
-rw-r--r-- | third_party/protobuf/3.0.0/src/google/protobuf/compiler/cpp/cpp_message.cc | 3819 |
1 files changed, 3819 insertions, 0 deletions
diff --git a/third_party/protobuf/3.0.0/src/google/protobuf/compiler/cpp/cpp_message.cc b/third_party/protobuf/3.0.0/src/google/protobuf/compiler/cpp/cpp_message.cc new file mode 100644 index 0000000000..405a5fed55 --- /dev/null +++ b/third_party/protobuf/3.0.0/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -0,0 +1,3819 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include <algorithm> +#include <google/protobuf/stubs/hash.h> +#include <map> +#include <memory> +#ifndef _SHARED_PTR_H +#include <google/protobuf/stubs/shared_ptr.h> +#endif +#include <utility> +#include <vector> +#include <google/protobuf/compiler/cpp/cpp_message.h> +#include <google/protobuf/compiler/cpp/cpp_field.h> +#include <google/protobuf/compiler/cpp/cpp_enum.h> +#include <google/protobuf/compiler/cpp/cpp_extension.h> +#include <google/protobuf/compiler/cpp/cpp_helpers.h> +#include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/io/printer.h> +#include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/wire_format.h> +#include <google/protobuf/descriptor.pb.h> + + +namespace google { +namespace protobuf { +namespace compiler { +namespace cpp { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +template <class T> +void PrintFieldComment(io::Printer* printer, const T* field) { + // Print the field's (or oneof's) proto-syntax definition as a comment. + // We don't want to print group bodies so we cut off after the first + // line. + DebugStringOptions options; + options.elide_group_body = true; + options.elide_oneof_body = true; + string def = field->DebugStringWithOptions(options); + printer->Print("// $def$\n", + "def", def.substr(0, def.find_first_of('\n'))); +} + +struct FieldOrderingByNumber { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + return a->number() < b->number(); + } +}; + +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor*[descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + std::sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); + return fields; +} + +// Functor for sorting extension ranges by their "start" field number. +struct ExtensionRangeSorter { + bool operator()(const Descriptor::ExtensionRange* left, + const Descriptor::ExtensionRange* right) const { + return left->start < right->start; + } +}; + +// Returns true if the "required" restriction check should be ignored for the +// given field. +inline static bool ShouldIgnoreRequiredFieldCheck(const FieldDescriptor* field, + const Options& options) { + return false; +} + +// Returns true if the message type has any required fields. If it doesn't, +// we can optimize out calls to its IsInitialized() method. +// +// already_seen is used to avoid checking the same type multiple times +// (and also to protect against recursion). +static bool HasRequiredFields(const Descriptor* type, const Options& options, + hash_set<const Descriptor*>* already_seen) { + if (already_seen->count(type) > 0) { + // Since the first occurrence of a required field causes the whole + // function to return true, we can assume that if the type is already + // in the cache it didn't have any required fields. + return false; + } + already_seen->insert(type); + + // If the type has extensions, an extension with message type could contain + // required fields, so we have to be conservative and assume such an + // extension exists. + if (type->extension_range_count() > 0) return true; + + for (int i = 0; i < type->field_count(); i++) { + const FieldDescriptor* field = type->field(i); + if (field->is_required()) { + return true; + } + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !ShouldIgnoreRequiredFieldCheck(field, options)) { + if (HasRequiredFields(field->message_type(), options, already_seen)) { + return true; + } + } + } + + return false; +} + +static bool HasRequiredFields(const Descriptor* type, const Options& options) { + hash_set<const Descriptor*> already_seen; + return HasRequiredFields(type, options, &already_seen); +} + +// This returns an estimate of the compiler's alignment for the field. This +// can't guarantee to be correct because the generated code could be compiled on +// different systems with different alignment rules. The estimates below assume +// 64-bit pointers. +int EstimateAlignmentSize(const FieldDescriptor* field) { + if (field == NULL) return 0; + if (field->is_repeated()) return 8; + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: + return 1; + + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_ENUM: + case FieldDescriptor::CPPTYPE_FLOAT: + return 4; + + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + return 8; + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; // Make compiler happy. +} + +// FieldGroup is just a helper for OptimizePadding below. It holds a vector of +// fields that are grouped together because they have compatible alignment, and +// a preferred location in the final field ordering. +class FieldGroup { + public: + FieldGroup() + : preferred_location_(0) {} + + // A group with a single field. + FieldGroup(float preferred_location, const FieldDescriptor* field) + : preferred_location_(preferred_location), + fields_(1, field) {} + + // Append the fields in 'other' to this group. + void Append(const FieldGroup& other) { + if (other.fields_.empty()) { + return; + } + // Preferred location is the average among all the fields, so we weight by + // the number of fields on each FieldGroup object. + preferred_location_ = + (preferred_location_ * fields_.size() + + (other.preferred_location_ * other.fields_.size())) / + (fields_.size() + other.fields_.size()); + fields_.insert(fields_.end(), other.fields_.begin(), other.fields_.end()); + } + + void SetPreferredLocation(float location) { preferred_location_ = location; } + const vector<const FieldDescriptor*>& fields() const { return fields_; } + + // FieldGroup objects sort by their preferred location. + bool operator<(const FieldGroup& other) const { + return preferred_location_ < other.preferred_location_; + } + + private: + // "preferred_location_" is an estimate of where this group should go in the + // final list of fields. We compute this by taking the average index of each + // field in this group in the original ordering of fields. This is very + // approximate, but should put this group close to where its member fields + // originally went. + float preferred_location_; + vector<const FieldDescriptor*> fields_; + // We rely on the default copy constructor and operator= so this type can be + // used in a vector. +}; + +// Reorder 'fields' so that if the fields are output into a c++ class in the new +// order, the alignment padding is minimized. We try to do this while keeping +// each field as close as possible to its original position so that we don't +// reduce cache locality much for function that access each field in order. +void OptimizePadding(vector<const FieldDescriptor*>* fields) { + // First divide fields into those that align to 1 byte, 4 bytes or 8 bytes. + vector<FieldGroup> aligned_to_1, aligned_to_4, aligned_to_8; + for (int i = 0; i < fields->size(); ++i) { + switch (EstimateAlignmentSize((*fields)[i])) { + case 1: aligned_to_1.push_back(FieldGroup(i, (*fields)[i])); break; + case 4: aligned_to_4.push_back(FieldGroup(i, (*fields)[i])); break; + case 8: aligned_to_8.push_back(FieldGroup(i, (*fields)[i])); break; + default: + GOOGLE_LOG(FATAL) << "Unknown alignment size."; + } + } + + // Now group fields aligned to 1 byte into sets of 4, and treat those like a + // single field aligned to 4 bytes. + for (int i = 0; i < aligned_to_1.size(); i += 4) { + FieldGroup field_group; + for (int j = i; j < aligned_to_1.size() && j < i + 4; ++j) { + field_group.Append(aligned_to_1[j]); + } + aligned_to_4.push_back(field_group); + } + // Sort by preferred location to keep fields as close to their original + // location as possible. Using stable_sort ensures that the output is + // consistent across runs. + std::stable_sort(aligned_to_4.begin(), aligned_to_4.end()); + + // Now group fields aligned to 4 bytes (or the 4-field groups created above) + // into pairs, and treat those like a single field aligned to 8 bytes. + for (int i = 0; i < aligned_to_4.size(); i += 2) { + FieldGroup field_group; + for (int j = i; j < aligned_to_4.size() && j < i + 2; ++j) { + field_group.Append(aligned_to_4[j]); + } + if (i == aligned_to_4.size() - 1) { + // Move incomplete 4-byte block to the end. + field_group.SetPreferredLocation(fields->size() + 1); + } + aligned_to_8.push_back(field_group); + } + // Sort by preferred location. + std::stable_sort(aligned_to_8.begin(), aligned_to_8.end()); + + // Now pull out all the FieldDescriptors in order. + fields->clear(); + for (int i = 0; i < aligned_to_8.size(); ++i) { + fields->insert(fields->end(), + aligned_to_8[i].fields().begin(), + aligned_to_8[i].fields().end()); + } +} + +string MessageTypeProtoName(const FieldDescriptor* field) { + return field->message_type()->full_name(); +} + +// Emits an if-statement with a condition that evaluates to true if |field| is +// considered non-default (will be sent over the wire), for message types +// without true field presence. Should only be called if +// !HasFieldPresence(message_descriptor). +bool EmitFieldNonDefaultCondition(io::Printer* printer, + const string& prefix, + const FieldDescriptor* field) { + // Merge and serialize semantics: primitive fields are merged/serialized only + // if non-zero (numeric) or non-empty (string). + if (!field->is_repeated() && !field->containing_oneof()) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + printer->Print( + "if ($prefix$$name$().size() > 0) {\n", + "prefix", prefix, + "name", FieldName(field)); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Message fields still have has_$name$() methods. + printer->Print( + "if ($prefix$has_$name$()) {\n", + "prefix", prefix, + "name", FieldName(field)); + } else { + printer->Print( + "if ($prefix$$name$() != 0) {\n", + "prefix", prefix, + "name", FieldName(field)); + } + printer->Indent(); + return true; + } else if (field->containing_oneof()) { + printer->Print( + "if (has_$name$()) {\n", + "name", FieldName(field)); + printer->Indent(); + return true; + } + return false; +} + +// Does the given field have a has_$name$() method? +bool HasHasMethod(const FieldDescriptor* field) { + if (HasFieldPresence(field->file())) { + // In proto1/proto2, every field has a has_$name$() method. + return true; + } + // For message types without true field presence, only fields with a message + // type have a has_$name$() method. + return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE; +} + +// Collects map entry message type information. +void CollectMapInfo(const Descriptor* descriptor, + map<string, string>* variables) { + GOOGLE_CHECK(IsMapEntryMessage(descriptor)); + const FieldDescriptor* key = descriptor->FindFieldByName("key"); + const FieldDescriptor* val = descriptor->FindFieldByName("value"); + (*variables)["key"] = PrimitiveTypeName(key->cpp_type()); + switch (val->cpp_type()) { + case FieldDescriptor::CPPTYPE_MESSAGE: + (*variables)["val"] = FieldMessageTypeName(val); + break; + case FieldDescriptor::CPPTYPE_ENUM: + (*variables)["val"] = ClassName(val->enum_type(), true); + break; + default: + (*variables)["val"] = PrimitiveTypeName(val->cpp_type()); + } + (*variables)["key_wire_type"] = + "::google::protobuf::internal::WireFormatLite::TYPE_" + + ToUpper(DeclaredTypeMethodName(key->type())); + (*variables)["val_wire_type"] = + "::google::protobuf::internal::WireFormatLite::TYPE_" + + ToUpper(DeclaredTypeMethodName(val->type())); +} + +// Does the given field have a private (internal helper only) has_$name$() +// method? +bool HasPrivateHasMethod(const FieldDescriptor* field) { + // Only for oneofs in message types with no field presence. has_$name$(), + // based on the oneof case, is still useful internally for generated code. + return (!HasFieldPresence(field->file()) && + field->containing_oneof() != NULL); +} + +} // anonymous namespace + +// =================================================================== + +MessageGenerator::MessageGenerator(const Descriptor* descriptor, + const Options& options) + : descriptor_(descriptor), + classname_(ClassName(descriptor, false)), + options_(options), + field_generators_(descriptor, options), + nested_generators_(new google::protobuf::scoped_ptr< + MessageGenerator>[descriptor->nested_type_count()]), + enum_generators_( + new google::protobuf::scoped_ptr<EnumGenerator>[descriptor->enum_type_count()]), + extension_generators_(new google::protobuf::scoped_ptr< + ExtensionGenerator>[descriptor->extension_count()]), + use_dependent_base_(false) { + + for (int i = 0; i < descriptor->nested_type_count(); i++) { + nested_generators_[i].reset( + new MessageGenerator(descriptor->nested_type(i), options)); + } + + for (int i = 0; i < descriptor->enum_type_count(); i++) { + enum_generators_[i].reset( + new EnumGenerator(descriptor->enum_type(i), options)); + } + + for (int i = 0; i < descriptor->extension_count(); i++) { + extension_generators_[i].reset( + new ExtensionGenerator(descriptor->extension(i), options)); + } + + num_required_fields_ = 0; + for (int i = 0; i < descriptor->field_count(); i++) { + if (descriptor->field(i)->is_required()) { + ++num_required_fields_; + } + if (options.proto_h && IsFieldDependent(descriptor->field(i))) { + use_dependent_base_ = true; + } + } + if (options.proto_h && descriptor->oneof_decl_count() > 0) { + // Always make oneofs dependent. + use_dependent_base_ = true; + } +} + +MessageGenerator::~MessageGenerator() {} + +void MessageGenerator:: +FillMessageForwardDeclarations(map<string, const Descriptor*>* class_names) { + (*class_names)[classname_] = descriptor_; + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // map entry message doesn't need forward declaration. Since map entry + // message cannot be a top level class, we just need to avoid calling + // GenerateForwardDeclaration here. + if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; + nested_generators_[i]->FillMessageForwardDeclarations(class_names); + } +} + +void MessageGenerator:: +FillEnumForwardDeclarations(map<string, const EnumDescriptor*>* enum_names) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->FillEnumForwardDeclarations(enum_names); + } + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->FillForwardDeclaration(enum_names); + } +} + +void MessageGenerator:: +GenerateEnumDefinitions(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateEnumDefinitions(printer); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDefinition(printer); + } +} + +void MessageGenerator:: +GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } +} + +void MessageGenerator:: +GenerateDependentFieldAccessorDeclarations(io::Printer* printer) { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + PrintFieldComment(printer, field); + + map<string, string> vars; + SetCommonFieldVariables(field, &vars, options_); + + if (use_dependent_base_ && IsFieldDependent(field)) { + // If the message is dependent, the inline clear_*() method will need + // to delete the message type, so it must be in the dependent base + // class. (See also GenerateFieldAccessorDeclarations.) + printer->Print(vars, "$deprecated_attr$void clear_$name$();\n"); + } + // Generate type-specific accessor declarations. + field_generators_.get(field).GenerateDependentAccessorDeclarations(printer); + printer->Print("\n"); + } +} + +void MessageGenerator:: +GenerateFieldAccessorDeclarations(io::Printer* printer) { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + PrintFieldComment(printer, field); + + map<string, string> vars; + SetCommonFieldVariables(field, &vars, options_); + vars["constant_name"] = FieldConstantName(field); + + bool dependent_field = use_dependent_base_ && IsFieldDependent(field); + if (dependent_field && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !field->is_map()) { + // If this field is dependent, the dependent base class determines + // the message type from the derived class (which is a template + // parameter). This typedef is for that: + printer->Print( + "private:\n" + "typedef $field_type$ $dependent_type$;\n" + "public:\n", + "field_type", FieldMessageTypeName(field), + "dependent_type", DependentTypeName(field)); + } + + if (field->is_repeated()) { + printer->Print(vars, "$deprecated_attr$int $name$_size() const;\n"); + } else if (HasHasMethod(field)) { + printer->Print(vars, "$deprecated_attr$bool has_$name$() const;\n"); + } else if (HasPrivateHasMethod(field)) { + printer->Print(vars, + "private:\n" + "bool has_$name$() const;\n" + "public:\n"); + } + + if (!dependent_field) { + // If this field is dependent, then its clear_() method is in the + // depenent base class. (See also GenerateDependentAccessorDeclarations.) + printer->Print(vars, "$deprecated_attr$void clear_$name$();\n"); + } + printer->Print(vars, + "$deprecated_attr$static const int $constant_name$ = " + "$number$;\n"); + + // Generate type-specific accessor declarations. + field_generators_.get(field).GenerateAccessorDeclarations(printer); + + printer->Print("\n"); + } + + if (descriptor_->extension_range_count() > 0) { + // Generate accessors for extensions. We just call a macro located in + // extension_set.h since the accessors about 80 lines of static code. + printer->Print( + "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n", + "classname", classname_); + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "$camel_oneof_name$Case $oneof_name$_case() const;\n", + "camel_oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true), + "oneof_name", descriptor_->oneof_decl(i)->name()); + } +} + +void MessageGenerator:: +GenerateDependentFieldAccessorDefinitions(io::Printer* printer) { + if (!use_dependent_base_) return; + + printer->Print("// $classname$\n\n", "classname", + DependentBaseClassTemplateName(descriptor_)); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + PrintFieldComment(printer, field); + + // These functions are not really dependent: they are part of the + // (non-dependent) derived class. However, they need to live outside + // any #ifdef guards, so we treat them as if they were dependent. + // + // See the comment in FileGenerator::GenerateInlineFunctionDefinitions + // for a more complete explanation. + if (use_dependent_base_ && IsFieldDependent(field)) { + map<string, string> vars; + SetCommonFieldVariables(field, &vars, options_); + vars["inline"] = "inline "; + if (field->containing_oneof()) { + vars["field_name"] = UnderscoresToCamelCase(field->name(), true); + vars["oneof_name"] = field->containing_oneof()->name(); + vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); + GenerateOneofMemberHasBits(field, vars, printer); + } else if (!field->is_repeated()) { + // There will be no header guard, so this always has to be inline. + GenerateSingularFieldHasBits(field, vars, printer); + } + // vars needed for clear_(), which is in the dependent base: + // (See also GenerateDependentFieldAccessorDeclarations.) + vars["tmpl"] = "template<class T>\n"; + vars["dependent_classname"] = + DependentBaseClassTemplateName(descriptor_) + "<T>"; + vars["this_message"] = DependentBaseDownCast(); + vars["this_const_message"] = DependentBaseConstDownCast(); + GenerateFieldClear(field, vars, printer); + } + + // Generate type-specific accessors. + field_generators_.get(field) + .GenerateDependentInlineAccessorDefinitions(printer); + + printer->Print("\n"); + } + + // Generate has_$name$() and clear_has_$name$() functions for oneofs + // Similar to other has-bits, these must always be in the header if we + // are using a dependent base class. + GenerateOneofHasBits(printer, true /* is_inline */); +} + +void MessageGenerator:: +GenerateSingularFieldHasBits(const FieldDescriptor* field, + map<string, string> vars, + io::Printer* printer) { + if (HasFieldPresence(descriptor_->file())) { + // N.B.: without field presence, we do not use has-bits or generate + // has_$name$() methods. + vars["has_array_index"] = SimpleItoa(field->index() / 32); + vars["has_mask"] = StrCat(strings::Hex(1u << (field->index() % 32), + strings::ZERO_PAD_8)); + printer->Print(vars, + "$inline$" + "bool $classname$::has_$name$() const {\n" + " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" + "}\n" + "$inline$" + "void $classname$::set_has_$name$() {\n" + " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" + "}\n" + "$inline$" + "void $classname$::clear_has_$name$() {\n" + " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" + "}\n"); + } else { + // Message fields have a has_$name$() method. + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + bool is_lazy = false; + if (is_lazy) { + printer->Print(vars, + "$inline$" + "bool $classname$::has_$name$() const {\n" + " return !$name$_.IsCleared();\n" + "}\n"); + } else { + printer->Print(vars, + "$inline$" + "bool $classname$::has_$name$() const {\n" + " return !_is_default_instance_ && $name$_ != NULL;\n" + "}\n"); + } + } + } +} + +void MessageGenerator:: +GenerateOneofHasBits(io::Printer* printer, bool is_inline) { + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + map<string, string> vars; + vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + vars["cap_oneof_name"] = + ToUpper(descriptor_->oneof_decl(i)->name()); + vars["classname"] = classname_; + vars["inline"] = (is_inline ? "inline " : ""); + printer->Print( + vars, + "$inline$" + "bool $classname$::has_$oneof_name$() const {\n" + " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" + "}\n" + "$inline$" + "void $classname$::clear_has_$oneof_name$() {\n" + " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" + "}\n"); + } +} + +void MessageGenerator:: +GenerateOneofMemberHasBits(const FieldDescriptor* field, + const map<string, string>& vars, + io::Printer* printer) { + // Singular field in a oneof + // N.B.: Without field presence, we do not use has-bits or generate + // has_$name$() methods, but oneofs still have set_has_$name$(). + // Oneofs also have has_$name$() but only as a private helper + // method, so that generated code is slightly cleaner (vs. comparing + // _oneof_case_[index] against a constant everywhere). + printer->Print(vars, + "$inline$" + "bool $classname$::has_$name$() const {\n" + " return $oneof_name$_case() == k$field_name$;\n" + "}\n"); + printer->Print(vars, + "$inline$" + "void $classname$::set_has_$name$() {\n" + " _oneof_case_[$oneof_index$] = k$field_name$;\n" + "}\n"); +} + +void MessageGenerator:: +GenerateFieldClear(const FieldDescriptor* field, + const map<string, string>& vars, + io::Printer* printer) { + // Generate clear_$name$() (See GenerateFieldAccessorDeclarations and + // GenerateDependentFieldAccessorDeclarations, $dependent_classname$ is + // set by the Generate*Definitions functions.) + printer->Print(vars, + "$tmpl$" + "$inline$" + "void $dependent_classname$::clear_$name$() {\n"); + + printer->Indent(); + + if (field->containing_oneof()) { + // Clear this field only if it is the active field in this oneof, + // otherwise ignore + printer->Print(vars, + "if ($this_message$has_$name$()) {\n"); + printer->Indent(); + field_generators_.get(field) + .GenerateClearingCode(printer); + printer->Print(vars, + "$this_message$clear_has_$oneof_name$();\n"); + printer->Outdent(); + printer->Print("}\n"); + } else { + field_generators_.get(field) + .GenerateClearingCode(printer); + if (HasFieldPresence(descriptor_->file())) { + if (!field->is_repeated()) { + printer->Print(vars, + "$this_message$clear_has_$name$();\n"); + } + } + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { + printer->Print("// $classname$\n\n", "classname", classname_); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + PrintFieldComment(printer, field); + + map<string, string> vars; + SetCommonFieldVariables(field, &vars, options_); + vars["inline"] = is_inline ? "inline " : ""; + if (use_dependent_base_ && IsFieldDependent(field)) { + vars["tmpl"] = "template<class T>\n"; + vars["dependent_classname"] = + DependentBaseClassTemplateName(descriptor_) + "<T>"; + vars["this_message"] = "reinterpret_cast<T*>(this)->"; + vars["this_const_message"] = "reinterpret_cast<const T*>(this)->"; + } else { + vars["tmpl"] = ""; + vars["dependent_classname"] = vars["classname"]; + vars["this_message"] = ""; + vars["this_const_message"] = ""; + } + + // Generate has_$name$() or $name$_size(). + if (field->is_repeated()) { + printer->Print(vars, + "$inline$" + "int $classname$::$name$_size() const {\n" + " return $name$_.size();\n" + "}\n"); + } else if (field->containing_oneof()) { + vars["field_name"] = UnderscoresToCamelCase(field->name(), true); + vars["oneof_name"] = field->containing_oneof()->name(); + vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); + if (!use_dependent_base_ || !IsFieldDependent(field)) { + GenerateOneofMemberHasBits(field, vars, printer); + } + } else { + // Singular field. + if (!use_dependent_base_ || !IsFieldDependent(field)) { + GenerateSingularFieldHasBits(field, vars, printer); + } + } + + if (!use_dependent_base_ || !IsFieldDependent(field)) { + GenerateFieldClear(field, vars, printer); + } + + // Generate type-specific accessors. + field_generators_.get(field).GenerateInlineAccessorDefinitions(printer, + is_inline); + + printer->Print("\n"); + } + + if (!use_dependent_base_) { + // Generate has_$name$() and clear_has_$name$() functions for oneofs + // If we aren't using a dependent base, they can be with the other functions + // that are #ifdef-guarded. + GenerateOneofHasBits(printer, is_inline); + } +} + +// Helper for the code that emits the Clear() method. +static bool CanClearByZeroing(const FieldDescriptor* field) { + if (field->is_repeated() || field->is_extension()) return false; + switch (field->cpp_type()) { + case internal::WireFormatLite::CPPTYPE_ENUM: + return field->default_value_enum()->number() == 0; + case internal::WireFormatLite::CPPTYPE_INT32: + return field->default_value_int32() == 0; + case internal::WireFormatLite::CPPTYPE_INT64: + return field->default_value_int64() == 0; + case internal::WireFormatLite::CPPTYPE_UINT32: + return field->default_value_uint32() == 0; + case internal::WireFormatLite::CPPTYPE_UINT64: + return field->default_value_uint64() == 0; + case internal::WireFormatLite::CPPTYPE_FLOAT: + return field->default_value_float() == 0; + case internal::WireFormatLite::CPPTYPE_DOUBLE: + return field->default_value_double() == 0; + case internal::WireFormatLite::CPPTYPE_BOOL: + return field->default_value_bool() == false; + default: + return false; + } +} + +void MessageGenerator:: +GenerateDependentBaseClassDefinition(io::Printer* printer) { + if (!use_dependent_base_) { + return; + } + + map<string, string> vars; + vars["classname"] = DependentBaseClassTemplateName(descriptor_); + vars["full_name"] = descriptor_->full_name(); + vars["superclass"] = SuperClassName(descriptor_, options_); + + printer->Print(vars, + "template <class T>\n" + "class $classname$ : public $superclass$ " + "/* @@protoc_insertion_point(dep_base_class_definition:$full_name$) */ {\n" + " public:\n"); + printer->Indent(); + + printer->Print(vars, + "$classname$() {}\n" + "virtual ~$classname$() {}\n" + "\n"); + + // Generate dependent accessor methods for all fields. + GenerateDependentFieldAccessorDeclarations(printer); + + printer->Outdent(); + printer->Print("};\n"); +} + +void MessageGenerator:: +GenerateClassDefinition(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // map entry message doesn't need class definition. Since map entry message + // cannot be a top level class, we just need to avoid calling + // GenerateClassDefinition here. + if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; + nested_generators_[i]->GenerateClassDefinition(printer); + printer->Print("\n"); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + + if (use_dependent_base_) { + GenerateDependentBaseClassDefinition(printer); + printer->Print("\n"); + } + + map<string, string> vars; + vars["classname"] = classname_; + vars["full_name"] = descriptor_->full_name(); + vars["field_count"] = SimpleItoa(descriptor_->field_count()); + vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count()); + if (options_.dllexport_decl.empty()) { + vars["dllexport"] = ""; + } else { + vars["dllexport"] = options_.dllexport_decl + " "; + } + if (use_dependent_base_) { + vars["superclass"] = + DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; + } else { + vars["superclass"] = SuperClassName(descriptor_, options_); + } + printer->Print(vars, + "class $dllexport$$classname$ : public $superclass$ " + "/* @@protoc_insertion_point(class_definition:$full_name$) */ " + "{\n"); + printer->Annotate("classname", descriptor_); + if (use_dependent_base_) { + printer->Print(vars, " friend class $superclass$;\n"); + } + printer->Print(" public:\n"); + printer->Indent(); + + printer->Print(vars, + "$classname$();\n" + "virtual ~$classname$();\n" + "\n" + "$classname$(const $classname$& from);\n" + "\n" + "inline $classname$& operator=(const $classname$& from) {\n" + " CopyFrom(from);\n" + " return *this;\n" + "}\n" + "\n"); + + if (PreserveUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n" + " return _internal_metadata_.unknown_fields();\n" + "}\n" + "\n" + "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n" + " return _internal_metadata_.mutable_unknown_fields();\n" + "}\n" + "\n"); + } else { + if (SupportsArenas(descriptor_)) { + printer->Print( + "inline const ::std::string& unknown_fields() const {\n" + " return _unknown_fields_.Get(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n" + "}\n" + "\n" + "inline ::std::string* mutable_unknown_fields() {\n" + " return _unknown_fields_.Mutable(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n" + " GetArenaNoVirtual());\n" + "}\n" + "\n"); + } else { + printer->Print( + "inline const ::std::string& unknown_fields() const {\n" + " return _unknown_fields_.GetNoArena(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n" + "}\n" + "\n" + "inline ::std::string* mutable_unknown_fields() {\n" + " return _unknown_fields_.MutableNoArena(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n" + "}\n" + "\n"); + } + } + } + + // N.B.: We exclude GetArena() when arena support is disabled, falling back on + // MessageLite's implementation which returns NULL rather than generating our + // own method which returns NULL, in order to reduce code size. + if (SupportsArenas(descriptor_)) { + // virtual method version of GetArenaNoVirtual(), required for generic dispatch given a + // MessageLite* (e.g., in RepeatedField::AddAllocated()). + printer->Print( + "inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }\n" + "inline void* GetMaybeArenaPointer() const {\n" + " return MaybeArenaPtr();\n" + "}\n"); + } + + // Only generate this member if it's not disabled. + if (HasDescriptorMethods(descriptor_->file(), options_) && + !descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print(vars, + "static const ::google::protobuf::Descriptor* descriptor();\n"); + } + + printer->Print(vars, + "static const $classname$& default_instance();\n" + "\n"); + + // Generate enum values for every field in oneofs. One list is generated for + // each oneof with an additional *_NOT_SET value. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "enum $camel_oneof_name$Case {\n", + "camel_oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + printer->Print( + "k$field_name$ = $field_number$,\n", + "field_name", + UnderscoresToCamelCase( + descriptor_->oneof_decl(i)->field(j)->name(), true), + "field_number", + SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number())); + } + printer->Print( + "$cap_oneof_name$_NOT_SET = 0,\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "};\n" + "\n"); + } + + if (!StaticInitializersForced(descriptor_->file(), options_)) { + printer->Print(vars, + "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" + "// Returns the internal default instance pointer. This function can\n" + "// return NULL thus should not be used by the user. This is intended\n" + "// for Protobuf internal code. Please use default_instance() declared\n" + "// above instead.\n" + "static inline const $classname$* internal_default_instance() {\n" + " return default_instance_;\n" + "}\n" + "#endif\n" + "\n"); + } + + + if (SupportsArenas(descriptor_)) { + printer->Print(vars, + "void UnsafeArenaSwap($classname$* other);\n"); + } + + if (IsAnyMessage(descriptor_)) { + printer->Print(vars, + "// implements Any -----------------------------------------------\n" + "\n" + "void PackFrom(const ::google::protobuf::Message& message);\n" + "void PackFrom(const ::google::protobuf::Message& message,\n" + " const ::std::string& type_url_prefix);\n" + "bool UnpackTo(::google::protobuf::Message* message) const;\n" + "template<typename T> bool Is() const {\n" + " return _any_metadata_.Is<T>();\n" + "}\n" + "\n"); + } + + printer->Print(vars, + "void Swap($classname$* other);\n" + "\n" + "// implements Message ----------------------------------------------\n" + "\n" + "inline $classname$* New() const { return New(NULL); }\n" + "\n" + "$classname$* New(::google::protobuf::Arena* arena) const;\n"); + + if (HasGeneratedMethods(descriptor_->file(), options_)) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { + printer->Print(vars, + "void CopyFrom(const ::google::protobuf::Message& from);\n" + "void MergeFrom(const ::google::protobuf::Message& from);\n"); + } else { + printer->Print(vars, + "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n"); + } + + printer->Print(vars, + "void CopyFrom(const $classname$& from);\n" + "void MergeFrom(const $classname$& from);\n" + "void Clear();\n" + "bool IsInitialized() const;\n" + "\n" + "int ByteSize() const;\n" + "bool MergePartialFromCodedStream(\n" + " ::google::protobuf::io::CodedInputStream* input);\n" + "void SerializeWithCachedSizes(\n" + " ::google::protobuf::io::CodedOutputStream* output) const;\n"); + // DiscardUnknownFields() is implemented in message.cc using reflections. We + // need to implement this function in generated code for messages. + if (!UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "void DiscardUnknownFields();\n"); + } + if (HasFastArraySerialization(descriptor_->file(), options_)) { + printer->Print( + "::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(\n" + " bool deterministic, ::google::protobuf::uint8* output) const;\n" + "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const {\n" + " return InternalSerializeWithCachedSizesToArray(false, output);\n" + "}\n"); + } + } + + // Check all FieldDescriptors including those in oneofs to estimate + // whether ::std::string is likely to be used, and depending on that + // estimate, set uses_string_ to true or false. That contols + // whether to force initialization of empty_string_ in SharedCtor(). + // It's often advantageous to do so to keep "is empty_string_ + // inited?" code from appearing all over the place. + vector<const FieldDescriptor*> descriptors; + for (int i = 0; i < descriptor_->field_count(); i++) { + descriptors.push_back(descriptor_->field(i)); + } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + descriptors.push_back(descriptor_->oneof_decl(i)->field(j)); + } + } + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + const Descriptor* nested_type = descriptor_->nested_type(i); + if (IsMapEntryMessage(nested_type)) { + descriptors.push_back(nested_type->FindFieldByName("key")); + descriptors.push_back(nested_type->FindFieldByName("value")); + } + } + uses_string_ = false; + if (PreserveUnknownFields(descriptor_) && + !UseUnknownFieldSet(descriptor_->file(), options_)) { + uses_string_ = true; + } + for (int i = 0; i < descriptors.size(); i++) { + const FieldDescriptor* field = descriptors[i]; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + switch (field->options().ctype()) { + default: uses_string_ = true; break; + } + } + } + + printer->Print( + "int GetCachedSize() const { return _cached_size_; }\n" + "private:\n" + "void SharedCtor();\n" + "void SharedDtor();\n" + "void SetCachedSize(int size) const;\n" + "void InternalSwap($classname$* other);\n", + "classname", classname_); + if (SupportsArenas(descriptor_)) { + printer->Print( + "protected:\n" + "explicit $classname$(::google::protobuf::Arena* arena);\n" + "private:\n" + "static void ArenaDtor(void* object);\n" + "inline void RegisterArenaDtor(::google::protobuf::Arena* arena);\n", + "classname", classname_); + } + + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "private:\n" + "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" + " return _internal_metadata_.arena();\n" + "}\n" + "inline void* MaybeArenaPtr() const {\n" + " return _internal_metadata_.raw_arena_ptr();\n" + "}\n" + "public:\n" + "\n"); + } else { + printer->Print( + "private:\n" + "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n" + " return _arena_ptr_;\n" + "}\n" + "inline ::google::protobuf::Arena* MaybeArenaPtr() const {\n" + " return _arena_ptr_;\n" + "}\n" + "public:\n" + "\n"); + } + + if (HasDescriptorMethods(descriptor_->file(), options_)) { + printer->Print( + "::google::protobuf::Metadata GetMetadata() const;\n" + "\n"); + } else { + printer->Print( + "::std::string GetTypeName() const;\n" + "\n"); + } + + printer->Print( + "// nested types ----------------------------------------------------\n" + "\n"); + + // Import all nested message classes into this class's scope with typedefs. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + const Descriptor* nested_type = descriptor_->nested_type(i); + if (!IsMapEntryMessage(nested_type)) { + printer->Print("typedef $nested_full_name$ $nested_name$;\n", + "nested_name", nested_type->name(), + "nested_full_name", ClassName(nested_type, false)); + } + } + + if (descriptor_->nested_type_count() > 0) { + printer->Print("\n"); + } + + // Import all nested enums and their values into this class's scope with + // typedefs and constants. + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateSymbolImports(printer); + printer->Print("\n"); + } + + printer->Print( + "// accessors -------------------------------------------------------\n" + "\n"); + + // Generate accessor methods for all fields. + GenerateFieldAccessorDeclarations(printer); + + // Declare extension identifiers. + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_[i]->GenerateDeclaration(printer); + } + + + printer->Print( + "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); + + // Generate private members. + printer->Outdent(); + printer->Print(" private:\n"); + printer->Indent(); + + + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->is_repeated()) { + // set_has_***() generated in all proto1/2 code and in oneofs (only) for + // messages without true field presence. + if (HasFieldPresence(descriptor_->file()) || + descriptor_->field(i)->containing_oneof()) { + printer->Print( + "inline void set_has_$name$();\n", + "name", FieldName(descriptor_->field(i))); + } + // clear_has_***() generated only for non-oneof fields + // in proto1/2. + if (!descriptor_->field(i)->containing_oneof() && + HasFieldPresence(descriptor_->file())) { + printer->Print( + "inline void clear_has_$name$();\n", + "name", FieldName(descriptor_->field(i))); + } + } + } + printer->Print("\n"); + + // Generate oneof function declarations + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "inline bool has_$oneof_name$() const;\n" + "void clear_$oneof_name$();\n" + "inline void clear_has_$oneof_name$();\n\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + + if (HasGeneratedMethods(descriptor_->file(), options_) && + !descriptor_->options().message_set_wire_format() && + num_required_fields_ > 1) { + printer->Print( + "// helper for ByteSize()\n" + "int RequiredFieldsByteSizeFallback() const;\n\n"); + } + + // Prepare decls for _cached_size_ and _has_bits_. Their position in the + // output will be determined later. + + bool need_to_emit_cached_size = true; + // TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it. + const string cached_size_decl = "mutable int _cached_size_;\n"; + + // TODO(jieluo) - Optimize _has_bits_ for repeated and oneof fields. + size_t sizeof_has_bits = (descriptor_->field_count() + 31) / 32 * 4; + if (descriptor_->field_count() == 0) { + // Zero-size arrays aren't technically allowed, and MSVC in particular + // doesn't like them. We still need to declare these arrays to make + // other code compile. Since this is an uncommon case, we'll just declare + // them with size 1 and waste some space. Oh well. + sizeof_has_bits = 4; + } + const string has_bits_decl = sizeof_has_bits == 0 ? "" : + "::google::protobuf::uint32 _has_bits_[" + SimpleItoa(sizeof_has_bits / 4) + "];\n"; + + + // To minimize padding, data members are divided into three sections: + // (1) members assumed to align to 8 bytes + // (2) members corresponding to message fields, re-ordered to optimize + // alignment. + // (3) members assumed to align to 4 bytes. + + // Members assumed to align to 8 bytes: + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "::google::protobuf::internal::ExtensionSet _extensions_;\n" + "\n"); + } + + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n"); + } else { + printer->Print( + "::google::protobuf::internal::ArenaStringPtr _unknown_fields_;\n" + "::google::protobuf::Arena* _arena_ptr_;\n" + "\n"); + } + + if (SupportsArenas(descriptor_)) { + printer->Print( + "friend class ::google::protobuf::Arena;\n" + "typedef void InternalArenaConstructable_;\n" + "typedef void DestructorSkippable_;\n"); + } + + if (HasFieldPresence(descriptor_->file())) { + // _has_bits_ is frequently accessed, so to reduce code size and improve + // speed, it should be close to the start of the object. But, try not to + // waste space:_has_bits_ by itself always makes sense if its size is a + // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together + // will work well. + printer->Print(has_bits_decl.c_str()); + if ((sizeof_has_bits % 8) != 0) { + printer->Print(cached_size_decl.c_str()); + need_to_emit_cached_size = false; + } + } else { + // Without field presence, we need another way to disambiguate the default + // instance, because the default instance's submessage fields (if any) store + // pointers to the default instances of the submessages even when they + // aren't present. Alternatives to this approach might be to (i) use a + // tagged pointer on all message fields, setting a tag bit for "not really + // present, just default instance"; or (ii) comparing |this| against the + // return value from GeneratedMessageFactory::GetPrototype() in all + // has_$field$() calls. However, both of these options are much more + // expensive (in code size and CPU overhead) than just checking a field in + // the message. Long-term, the best solution would be to rearchitect the + // default instance design not to store pointers to submessage default + // instances, and have reflection get those some other way; but that change + // would have too much impact on proto2. + printer->Print( + "bool _is_default_instance_;\n"); + } + + // Field members: + + // List fields which doesn't belong to any oneof + vector<const FieldDescriptor*> fields; + hash_map<string, int> fieldname_to_chunk; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + const FieldDescriptor* field = descriptor_->field(i); + fields.push_back(field); + fieldname_to_chunk[FieldName(field)] = i / 8; + } + } + OptimizePadding(&fields); + // Emit some private and static members + runs_of_fields_ = vector< vector<string> >(1); + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + const FieldGenerator& generator = field_generators_.get(field); + generator.GenerateStaticMembers(printer); + generator.GeneratePrivateMembers(printer); + if (CanClearByZeroing(field)) { + const string& fieldname = FieldName(field); + if (!runs_of_fields_.back().empty() && + (fieldname_to_chunk[runs_of_fields_.back().back()] != + fieldname_to_chunk[fieldname])) { + runs_of_fields_.push_back(vector<string>()); + } + runs_of_fields_.back().push_back(fieldname); + } else if (!runs_of_fields_.back().empty()) { + runs_of_fields_.push_back(vector<string>()); + } + } + + // For each oneof generate a union + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "union $camel_oneof_name$Union {\n" + // explicit empty constructor is needed when union contains + // ArenaStringPtr members for string fields. + " $camel_oneof_name$Union() {}\n", + "camel_oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + field_generators_.get(descriptor_->oneof_decl(i)-> + field(j)).GeneratePrivateMembers(printer); + } + printer->Outdent(); + printer->Print( + "} $oneof_name$_;\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + field_generators_.get(descriptor_->oneof_decl(i)-> + field(j)).GenerateStaticMembers(printer); + } + } + + // Members assumed to align to 4 bytes: + + if (need_to_emit_cached_size) { + printer->Print(cached_size_decl.c_str()); + need_to_emit_cached_size = false; + } + + // Generate _oneof_case_. + if (descriptor_->oneof_decl_count() > 0) { + printer->Print(vars, + "::google::protobuf::uint32 _oneof_case_[$oneof_decl_count$];\n" + "\n"); + } + + // Generate _any_metadata_ for the Any type. + if (IsAnyMessage(descriptor_)) { + printer->Print(vars, + "::google::protobuf::internal::AnyMetadata _any_metadata_;\n"); + } + + // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as + // friends so that they can access private static variables like + // default_instance_ and reflection_. + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), options_, printer, + // With static initializers. + "friend void $dllexport_decl$ $adddescriptorsname$();\n", + // Without. + "friend void $dllexport_decl$ $adddescriptorsname$_impl();\n", + // Vars. + "dllexport_decl", options_.dllexport_decl, "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); + + printer->Print( + "friend void $assigndescriptorsname$();\n" + "friend void $shutdownfilename$();\n" + "\n", + "assigndescriptorsname", + GlobalAssignDescriptorsName(descriptor_->file()->name()), + "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name())); + + printer->Print( + "void InitAsDefaultInstance();\n" + "static $classname$* default_instance_;\n", + "classname", classname_); + + printer->Outdent(); + printer->Print(vars, "};"); + GOOGLE_DCHECK(!need_to_emit_cached_size); +} + +void MessageGenerator:: +GenerateDependentInlineMethods(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // map entry message doesn't need inline methods. Since map entry message + // cannot be a top level class, we just need to avoid calling + // GenerateInlineMethods here. + if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; + nested_generators_[i]->GenerateDependentInlineMethods(printer); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + + GenerateDependentFieldAccessorDefinitions(printer); +} + +void MessageGenerator:: +GenerateInlineMethods(io::Printer* printer, bool is_inline) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // map entry message doesn't need inline methods. Since map entry message + // cannot be a top level class, we just need to avoid calling + // GenerateInlineMethods here. + if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; + nested_generators_[i]->GenerateInlineMethods(printer, is_inline); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + + GenerateFieldAccessorDefinitions(printer, is_inline); + + // Generate oneof_case() functions. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + map<string, string> vars; + vars["class_name"] = classname_; + vars["camel_oneof_name"] = UnderscoresToCamelCase( + descriptor_->oneof_decl(i)->name(), true); + vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + vars["inline"] = is_inline ? "inline " : ""; + printer->Print( + vars, + "$inline$" + "$class_name$::$camel_oneof_name$Case $class_name$::" + "$oneof_name$_case() const {\n" + " return $class_name$::$camel_oneof_name$Case(" + "_oneof_case_[$oneof_index$]);\n" + "}\n"); + } +} + +void MessageGenerator:: +GenerateDescriptorDeclarations(io::Printer* printer) { + if (!IsMapEntryMessage(descriptor_)) { + printer->Print( + "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n" + "const ::google::protobuf::internal::GeneratedMessageReflection*\n" + " $name$_reflection_ = NULL;\n", + "name", classname_); + } else { + printer->Print( + "const ::google::protobuf::Descriptor* $name$_descriptor_ = NULL;\n", + "name", classname_); + } + + // Generate oneof default instance for reflection usage. + if (descriptor_->oneof_decl_count() > 0) { + printer->Print("struct $name$OneofInstance {\n", + "name", classname_); + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print(" "); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field) != FieldOptions::STRING)) { + printer->Print("const "); + } + field_generators_.get(field).GeneratePrivateMembers(printer); + } + } + + printer->Print("}* $name$_default_oneof_instance_ = NULL;\n", + "name", classname_); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateDescriptorDeclarations(printer); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + printer->Print( + "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n", + "name", ClassName(descriptor_->enum_type(i), false)); + } +} + +void MessageGenerator:: +GenerateDescriptorInitializer(io::Printer* printer, int index) { + // TODO(kenton): Passing the index to this method is redundant; just use + // descriptor_->index() instead. + map<string, string> vars; + vars["classname"] = classname_; + vars["index"] = SimpleItoa(index); + + // Obtain the descriptor from the parent's descriptor. + if (descriptor_->containing_type() == NULL) { + printer->Print(vars, + "$classname$_descriptor_ = file->message_type($index$);\n"); + } else { + vars["parent"] = ClassName(descriptor_->containing_type(), false); + printer->Print(vars, + "$classname$_descriptor_ = " + "$parent$_descriptor_->nested_type($index$);\n"); + } + + if (IsMapEntryMessage(descriptor_)) return; + + // Generate the offsets. + GenerateOffsets(printer); + + const bool pass_pool_and_factory = false; + vars["fn"] = pass_pool_and_factory ? + "new ::google::protobuf::internal::GeneratedMessageReflection" : + "::google::protobuf::internal::GeneratedMessageReflection" + "::NewGeneratedMessageReflection"; + // Construct the reflection object. + printer->Print(vars, + "$classname$_reflection_ =\n" + " $fn$(\n" + " $classname$_descriptor_,\n" + " $classname$::default_instance_,\n" + " $classname$_offsets_,\n"); + if (!HasFieldPresence(descriptor_->file())) { + // If we don't have field presence, then _has_bits_ does not exist. + printer->Print(vars, + " -1,\n"); + } else { + printer->Print(vars, + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n"); + } + + // Unknown field offset: either points to the unknown field set if embedded + // directly, or indicates that the unknown field set is stored as part of the + // internal metadata if not. + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print(vars, + " -1,\n"); + } else { + printer->Print(vars, + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _unknown_fields_),\n"); + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print(vars, + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _extensions_),\n"); + } else { + // No extensions. + printer->Print(vars, + " -1,\n"); + } + + if (descriptor_->oneof_decl_count() > 0) { + printer->Print(vars, + " $classname$_default_oneof_instance_,\n" + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _oneof_case_[0]),\n"); + } + + if (pass_pool_and_factory) { + printer->Print( + " ::google::protobuf::DescriptorPool::generated_pool(),\n"); + printer->Print(vars, + " ::google::protobuf::MessageFactory::generated_factory(),\n"); + } + + printer->Print(vars, + " sizeof($classname$),\n"); + + // Arena offset: either an offset to the metadata struct that contains the + // arena pointer and unknown field set (in a space-efficient way) if we use + // that implementation strategy, or an offset directly to the arena pointer if + // not (because e.g. we don't have an unknown field set). + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print(vars, + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _internal_metadata_),\n"); + } else { + printer->Print(vars, + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _arena_),\n"); + } + + // is_default_instance_ offset. + if (HasFieldPresence(descriptor_->file())) { + printer->Print(vars, + " -1);\n"); + } else { + printer->Print(vars, + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _is_default_instance_));\n"); + } + + // Handle nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateDescriptorInitializer(printer, i); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDescriptorInitializer(printer, i); + } +} + +void MessageGenerator:: +GenerateTypeRegistrations(io::Printer* printer) { + // Register this message type with the message factory. + if (!IsMapEntryMessage(descriptor_)) { + printer->Print( + "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n" + " $classname$_descriptor_, &$classname$::default_instance());\n", + "classname", classname_); + } + else { + map<string, string> vars; + CollectMapInfo(descriptor_, &vars); + vars["classname"] = classname_; + + const FieldDescriptor* val = descriptor_->FindFieldByName("value"); + if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO2 && + val->type() == FieldDescriptor::TYPE_ENUM) { + const EnumValueDescriptor* default_value = val->default_value_enum(); + vars["default_enum_value"] = Int32ToString(default_value->number()); + } else { + vars["default_enum_value"] = "0"; + } + + printer->Print(vars, + "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n" + " $classname$_descriptor_,\n" + " ::google::protobuf::internal::MapEntry<\n" + " $key$,\n" + " $val$,\n" + " $key_wire_type$,\n" + " $val_wire_type$,\n" + " $default_enum_value$>::CreateDefaultInstance(\n" + " $classname$_descriptor_));\n"); + } + + // Handle nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateTypeRegistrations(printer); + } +} + +void MessageGenerator:: +GenerateDefaultInstanceAllocator(io::Printer* printer) { + // Construct the default instances of all fields, as they will be used + // when creating the default instance of the entire message. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateDefaultInstanceAllocator(printer); + } + + if (IsMapEntryMessage(descriptor_)) return; + + // Construct the default instance. We can't call InitAsDefaultInstance() yet + // because we need to make sure all default instances that this one might + // depend on are constructed first. + printer->Print( + "$classname$::default_instance_ = new $classname$();\n", + "classname", classname_); + + if ((descriptor_->oneof_decl_count() > 0) && + HasDescriptorMethods(descriptor_->file(), options_)) { + printer->Print( + "$classname$_default_oneof_instance_ = new $classname$OneofInstance();\n", + "classname", classname_); + } + + // Handle nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateDefaultInstanceAllocator(printer); + } + +} + +void MessageGenerator:: +GenerateDefaultInstanceInitializer(io::Printer* printer) { + printer->Print( + "$classname$::default_instance_->InitAsDefaultInstance();\n", + "classname", classname_); + + // Register extensions. + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_[i]->GenerateRegistration(printer); + } + + // Handle nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // map entry message doesn't need to initialize default instance manually. + // Since map entry message cannot be a top level class, we just need to + // avoid calling DefaultInstanceInitializer here. + if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; + nested_generators_[i]->GenerateDefaultInstanceInitializer(printer); + } +} + +void MessageGenerator:: +GenerateShutdownCode(io::Printer* printer) { + printer->Print( + "delete $classname$::default_instance_;\n", + "classname", classname_); + + if (HasDescriptorMethods(descriptor_->file(), options_)) { + if (descriptor_->oneof_decl_count() > 0) { + printer->Print( + "delete $classname$_default_oneof_instance_;\n", + "classname", classname_); + } + printer->Print( + "delete $classname$_reflection_;\n", + "classname", classname_); + } + + // Handle default instances of fields. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateShutdownCode(printer); + } + + // Handle nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; + nested_generators_[i]->GenerateShutdownCode(printer); + } +} + +void MessageGenerator:: +GenerateClassMethods(io::Printer* printer) { + // mutable_unknown_fields wrapper function for LazyStringOutputStream + // callback. + if (PreserveUnknownFields(descriptor_) && + !UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "static ::std::string* MutableUnknownFieldsFor$classname$(\n" + " $classname$* ptr) {\n" + " return ptr->mutable_unknown_fields();\n" + "}\n" + "\n", + "classname", classname_); + } + if (IsAnyMessage(descriptor_)) { + printer->Print( + "void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n" + " _any_metadata_.PackFrom(message);\n" + "}\n" + "\n" + "void $classname$::PackFrom(const ::google::protobuf::Message& message,\n" + " const ::std::string& type_url_prefix) {\n" + " _any_metadata_.PackFrom(message, type_url_prefix);\n" + "}\n" + "\n" + "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\n" + " return _any_metadata_.UnpackTo(message);\n" + "}\n" + "\n", + "classname", classname_); + } + + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateMethods(printer); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // map entry message doesn't need class methods. Since map entry message + // cannot be a top level class, we just need to avoid calling + // GenerateClassMethods here. + if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; + nested_generators_[i]->GenerateClassMethods(printer); + printer->Print("\n"); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + + // Generate non-inline field definitions. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateNonInlineAccessorDefinitions(printer); + } + + // Generate field number constants. + printer->Print("#if !defined(_MSC_VER) || _MSC_VER >= 1900\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor *field = descriptor_->field(i); + printer->Print( + "const int $classname$::$constant_name$;\n", + "classname", ClassName(FieldScope(field), false), + "constant_name", FieldConstantName(field)); + } + printer->Print( + "#endif // !defined(_MSC_VER) || _MSC_VER >= 1900\n" + "\n"); + + // Define extension identifiers. + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_[i]->GenerateDefinition(printer); + } + + GenerateStructors(printer); + printer->Print("\n"); + + if (descriptor_->oneof_decl_count() > 0) { + GenerateOneofClear(printer); + printer->Print("\n"); + } + + if (HasGeneratedMethods(descriptor_->file(), options_)) { + GenerateClear(printer); + printer->Print("\n"); + + GenerateMergeFromCodedStream(printer); + printer->Print("\n"); + + GenerateSerializeWithCachedSizes(printer); + printer->Print("\n"); + + if (HasFastArraySerialization(descriptor_->file(), options_)) { + GenerateSerializeWithCachedSizesToArray(printer); + printer->Print("\n"); + } + + GenerateByteSize(printer); + printer->Print("\n"); + + GenerateMergeFrom(printer); + printer->Print("\n"); + + GenerateCopyFrom(printer); + printer->Print("\n"); + + GenerateIsInitialized(printer); + printer->Print("\n"); + } + + GenerateSwap(printer); + printer->Print("\n"); + + if (HasDescriptorMethods(descriptor_->file(), options_)) { + printer->Print( + "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" + " protobuf_AssignDescriptorsOnce();\n" + " ::google::protobuf::Metadata metadata;\n" + " metadata.descriptor = $classname$_descriptor_;\n" + " metadata.reflection = $classname$_reflection_;\n" + " return metadata;\n" + "}\n" + "\n", + "classname", classname_); + } else { + printer->Print( + "::std::string $classname$::GetTypeName() const {\n" + " return \"$type_name$\";\n" + "}\n" + "\n", + "classname", classname_, + "type_name", descriptor_->full_name()); + } + +} + +void MessageGenerator:: +GenerateOffsets(io::Printer* printer) { + printer->Print("static const int $classname$_offsets_[$field_count$] = {\n", + "classname", classname_, "field_count", + SimpleItoa(std::max(1, descriptor_->field_count() + + descriptor_->oneof_decl_count()))); + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->containing_oneof()) { + printer->Print( + "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(" + "$classname$_default_oneof_instance_, $name$_),\n", + "classname", classname_, + "name", FieldName(field)); + } else { + printer->Print( + "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " + "$name$_),\n", + "classname", classname_, + "name", FieldName(field)); + } + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + printer->Print( + "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", + "classname", classname_, + "name", oneof->name()); + } + + printer->Outdent(); + printer->Print("};\n"); +} + +void MessageGenerator:: +GenerateSharedConstructorCode(io::Printer* printer) { + printer->Print( + "void $classname$::SharedCtor() {\n", + "classname", classname_); + printer->Indent(); + + if (!HasFieldPresence(descriptor_->file())) { + printer->Print( + " _is_default_instance_ = false;\n"); + } + + printer->Print(StrCat( + uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "", + "_cached_size_ = 0;\n").c_str()); + + if (PreserveUnknownFields(descriptor_) && + !UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "_unknown_fields_.UnsafeSetDefault(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateConstructorCode(printer); + } + } + + if (HasFieldPresence(descriptor_->file())) { + printer->Print( + "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "clear_has_$oneof_name$();\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + + printer->Outdent(); + printer->Print("}\n\n"); +} + +void MessageGenerator:: +GenerateSharedDestructorCode(io::Printer* printer) { + printer->Print( + "void $classname$::SharedDtor() {\n", + "classname", classname_); + printer->Indent(); + if (SupportsArenas(descriptor_)) { + // Do nothing when the message is allocated in an arena. + printer->Print( + "if (GetArenaNoVirtual() != NULL) {\n" + " return;\n" + "}\n" + "\n"); + } + + // Write the desctructor for _unknown_fields_ in lite runtime. + if (PreserveUnknownFields(descriptor_) && + !UseUnknownFieldSet(descriptor_->file(), options_)) { + if (SupportsArenas(descriptor_)) { + printer->Print( + "_unknown_fields_.Destroy(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n" + " GetArenaNoVirtual());\n"); + } else { + printer->Print( + "_unknown_fields_.DestroyNoArena(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"); + } + } + + // Write the destructors for each field except oneof members. + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateDestructorCode(printer); + } + } + + // Generate code to destruct oneofs. Clearing should do the work. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "if (has_$oneof_name$()) {\n" + " clear_$oneof_name$();\n" + "}\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), options_, printer, + // With static initializers. + "if (this != default_instance_) {\n", + // Without. + "if (this != &default_instance()) {\n"); + + // We need to delete all embedded messages. + // TODO(kenton): If we make unset messages point at default instances + // instead of NULL, then it would make sense to move this code into + // MessageFieldGenerator::GenerateDestructorCode(). + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (!field->is_repeated() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Skip oneof members + if (!field->containing_oneof()) { + printer->Print( + " delete $name$_;\n", + "name", FieldName(field)); + } + } + } + + printer->Outdent(); + printer->Print( + " }\n" + "}\n" + "\n"); +} + +void MessageGenerator:: +GenerateArenaDestructorCode(io::Printer* printer) { + // Generate the ArenaDtor() method. Track whether any fields actually produced + // code that needs to be called. + printer->Print( + "void $classname$::ArenaDtor(void* object) {\n", + "classname", classname_); + printer->Indent(); + + // This code is placed inside a static method, rather than an ordinary one, + // since that simplifies Arena's destructor list (ordinary function pointers + // rather than member function pointers). _this is the object being + // destructed. + printer->Print( + "$classname$* _this = reinterpret_cast< $classname$* >(object);\n" + // avoid an "unused variable" warning in case no fields have dtor code. + "(void)_this;\n", + "classname", classname_); + + bool need_registration = false; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (field_generators_.get(descriptor_->field(i)) + .GenerateArenaDestructorCode(printer)) { + need_registration = true; + } + } + printer->Outdent(); + printer->Print( + "}\n"); + + if (need_registration) { + printer->Print( + "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n" + " if (arena != NULL) {\n" + " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n" + " }\n" + "}\n", + "classname", classname_); + } else { + printer->Print( + "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n" + "}\n", + "classname", classname_); + } +} + +void MessageGenerator:: +GenerateStructors(io::Printer* printer) { + string superclass; + if (use_dependent_base_) { + superclass = + DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; + } else { + superclass = SuperClassName(descriptor_, options_); + } + string initializer_with_arena = superclass + "()"; + + if (descriptor_->extension_range_count() > 0) { + initializer_with_arena += ",\n _extensions_(arena)"; + } + + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + initializer_with_arena += ",\n _internal_metadata_(arena)"; + } else { + initializer_with_arena += ",\n _arena_ptr_(arena)"; + } + + // Initialize member variables with arena constructor. + for (int i = 0; i < descriptor_->field_count(); i++) { + bool has_arena_constructor = descriptor_->field(i)->is_repeated(); + if (has_arena_constructor) { + initializer_with_arena += string(",\n ") + + FieldName(descriptor_->field(i)) + string("_(arena)"); + } + } + + if (IsAnyMessage(descriptor_)) { + initializer_with_arena += ",\n _any_metadata_(&type_url, &value_)"; + } + + string initializer_null; + initializer_null = (UseUnknownFieldSet(descriptor_->file(), options_) ? + ", _internal_metadata_(NULL)" : ", _arena_ptr_(NULL)"); + if (IsAnyMessage(descriptor_)) { + initializer_null += ", _any_metadata_(&type_url_, &value_)"; + } + + printer->Print( + "$classname$::$classname$()\n" + " : $superclass$()$initializer$ {\n" + " SharedCtor();\n" + " // @@protoc_insertion_point(constructor:$full_name$)\n" + "}\n", + "classname", classname_, + "superclass", superclass, + "full_name", descriptor_->full_name(), + "initializer", initializer_null); + + if (SupportsArenas(descriptor_)) { + printer->Print( + "\n" + "$classname$::$classname$(::google::protobuf::Arena* arena)\n" + " : $initializer$ {\n" + " SharedCtor();\n" + " RegisterArenaDtor(arena);\n" + " // @@protoc_insertion_point(arena_constructor:$full_name$)\n" + "}\n", + "initializer", initializer_with_arena, + "classname", classname_, + "superclass", superclass, + "full_name", descriptor_->full_name()); + } + + printer->Print( + "\n" + "void $classname$::InitAsDefaultInstance() {\n", + "classname", classname_); + + if (!HasFieldPresence(descriptor_->file())) { + printer->Print( + " _is_default_instance_ = true;\n"); + } + + // The default instance needs all of its embedded message pointers + // cross-linked to other default instances. We can't do this initialization + // in the constructor because some other default instances may not have been + // constructed yet at that time. + // TODO(kenton): Maybe all message fields (even for non-default messages) + // should be initialized to point at default instances rather than NULL? + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (!field->is_repeated() && + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + (field->containing_oneof() == NULL || + HasDescriptorMethods(descriptor_->file(), options_))) { + string name; + if (field->containing_oneof()) { + name = classname_ + "_default_oneof_instance_->"; + } + name += FieldName(field); + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), options_, printer, + // With static initializers. + " $name$_ = const_cast< $type$*>(&$type$::default_instance());\n", + // Without. + " $name$_ = const_cast< $type$*>(\n" + " $type$::internal_default_instance());\n", + // Vars. + "name", name, "type", FieldMessageTypeName(field)); + } else if (field->containing_oneof() && + HasDescriptorMethods(descriptor_->file(), options_)) { + field_generators_.get(descriptor_->field(i)) + .GenerateConstructorCode(printer); + } + } + printer->Print( + "}\n" + "\n"); + + // Generate the copy constructor. + printer->Print( + "$classname$::$classname$(const $classname$& from)\n" + " : $superclass$()", + "classname", classname_, + "superclass", superclass, + "full_name", descriptor_->full_name()); + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + ",\n _internal_metadata_(NULL)"); + } else if (!UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print(",\n _arena_ptr_(NULL)"); + } + if (IsAnyMessage(descriptor_)) { + printer->Print(",\n _any_metadata_(&type_url_, &value_)"); + } + printer->Print(" {\n"); + printer->Print( + " SharedCtor();\n" + " MergeFrom(from);\n" + " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" + "}\n" + "\n", + "classname", classname_, + "superclass", superclass, + "full_name", descriptor_->full_name()); + + // Generate the shared constructor code. + GenerateSharedConstructorCode(printer); + + // Generate the destructor. + printer->Print( + "$classname$::~$classname$() {\n" + " // @@protoc_insertion_point(destructor:$full_name$)\n" + " SharedDtor();\n" + "}\n" + "\n", + "classname", classname_, + "full_name", descriptor_->full_name()); + + // Generate the shared destructor code. + GenerateSharedDestructorCode(printer); + + // Generate the arena-specific destructor code. + if (SupportsArenas(descriptor_)) { + GenerateArenaDestructorCode(printer); + } + + // Generate SetCachedSize. + printer->Print( + "void $classname$::SetCachedSize(int size) const {\n" + " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" + " _cached_size_ = size;\n" + " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" + "}\n", + "classname", classname_); + + // Only generate this member if it's not disabled. + if (HasDescriptorMethods(descriptor_->file(), options_) && + !descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print( + "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" + " protobuf_AssignDescriptorsOnce();\n" + " return $classname$_descriptor_;\n" + "}\n" + "\n", + "classname", classname_, + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); + } + + printer->Print( + "const $classname$& $classname$::default_instance() {\n", + "classname", classname_); + + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), options_, printer, + // With static initializers. + " if (default_instance_ == NULL) $adddescriptorsname$();\n", + // Without. + " $adddescriptorsname$();\n", + // Vars. + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); + + printer->Print( + " return *default_instance_;\n" + "}\n" + "\n" + "$classname$* $classname$::default_instance_ = NULL;\n" + "\n", + "classname", classname_); + + if (SupportsArenas(descriptor_)) { + printer->Print( + "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n" + " return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n" + "}\n", + "classname", classname_); + } else { + printer->Print( + "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n" + " $classname$* n = new $classname$;\n" + " if (arena != NULL) {\n" + " arena->Own(n);\n" + " }\n" + " return n;\n" + "}\n", + "classname", classname_); + } + +} + +// Return the number of bits set in n, a non-negative integer. +static int popcnt(uint32 n) { + int result = 0; + while (n != 0) { + result += (n & 1); + n = n / 2; + } + return result; +} + +void MessageGenerator:: +GenerateClear(io::Printer* printer) { + printer->Print( + "void $classname$::Clear() {\n" + "// @@protoc_insertion_point(message_clear_start:$full_name$)\n", + "classname", classname_, "full_name", descriptor_->full_name()); + printer->Indent(); + + // Step 1: Extensions + if (descriptor_->extension_range_count() > 0) { + printer->Print("_extensions_.Clear();\n"); + } + + // Step 2: Everything but extensions, repeateds, unions. + // These are handled in chunks of 8. The first chunk is + // the non-extensions-non-repeateds-non-unions in + // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), + // and the second chunk is the same for + // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15), + // etc. + set<int> step2_indices; + hash_map<string, int> fieldname_to_chunk; + hash_map<int, string> memsets_for_chunk; + hash_map<int, int> memset_field_count_for_chunk; + hash_set<string> handled; // fields that appear anywhere in memsets_for_chunk + hash_map<int, uint32> fields_mask_for_chunk; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!field->is_repeated() && !field->containing_oneof()) { + step2_indices.insert(i); + int chunk = i / 8; + fieldname_to_chunk[FieldName(field)] = chunk; + fields_mask_for_chunk[chunk] |= static_cast<uint32>(1) << (i % 32); + } + } + + // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0. + // The generated code uses two macros to help it clear runs of fields: + // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the + // positions of two fields in the Message. + // ZR_ zeroes a non-empty range of fields via memset. + const char* macros = + "#if defined(__clang__)\n" + "#define ZR_HELPER_(f) \\\n" + " _Pragma(\"clang diagnostic push\") \\\n" + " _Pragma(\"clang diagnostic ignored \\\"-Winvalid-offsetof\\\"\") \\\n" + " __builtin_offsetof($classname$, f) \\\n" + " _Pragma(\"clang diagnostic pop\")\n" + "#else\n" + "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n" + " &reinterpret_cast<$classname$*>(16)->f)\n" + "#endif\n\n" + "#define ZR_(first, last) do {\\\n" + " ::memset(&first, 0,\\\n" + " ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n" + "} while (0)\n\n"; + for (int i = 0; i < runs_of_fields_.size(); i++) { + const vector<string>& run = runs_of_fields_[i]; + if (run.size() < 2) continue; + const string& first_field_name = run[0]; + const string& last_field_name = run.back(); + int chunk = fieldname_to_chunk[run[0]]; + memsets_for_chunk[chunk].append( + "ZR_(" + first_field_name + "_, " + last_field_name + "_);\n"); + for (int j = 0; j < run.size(); j++) { + GOOGLE_DCHECK_EQ(chunk, fieldname_to_chunk[run[j]]); + handled.insert(run[j]); + } + memset_field_count_for_chunk[chunk] += run.size(); + } + const bool macros_are_needed = handled.size() > 0; + if (macros_are_needed) { + printer->Outdent(); + printer->Print(macros, + "classname", classname_); + printer->Indent(); + } + // Step 2b: Finish step 2, ignoring fields handled in step 2a. + int last_index = -1; + bool chunk_block_in_progress = false; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (step2_indices.count(i) == 0) continue; + const FieldDescriptor* field = descriptor_->field(i); + const string fieldname = FieldName(field); + if (i / 8 != last_index / 8 || last_index < 0) { + // End previous chunk, if there was one. + if (chunk_block_in_progress) { + printer->Outdent(); + printer->Print("}\n"); + chunk_block_in_progress = false; + } + // Start chunk. + const string& memsets = memsets_for_chunk[i / 8]; + uint32 mask = fields_mask_for_chunk[i / 8]; + int count = popcnt(mask); + GOOGLE_DCHECK_GE(count, 1); + if (count == 1 || + (count <= 4 && count == memset_field_count_for_chunk[i / 8])) { + // No "if" here because the chunk is trivial. + } else { + if (HasFieldPresence(descriptor_->file())) { + printer->Print( + "if (_has_bits_[$index$ / 32] & $mask$u) {\n", + "index", SimpleItoa(i / 8 * 8), + "mask", SimpleItoa(mask)); + printer->Indent(); + chunk_block_in_progress = true; + } + } + printer->Print(memsets.c_str()); + } + last_index = i; + if (handled.count(fieldname) > 0) continue; + + // It's faster to just overwrite primitive types, but we should + // only clear strings and messages if they were set. + // TODO(kenton): Let the CppFieldGenerator decide this somehow. + bool should_check_bit = + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; + + bool have_enclosing_if = false; + if (should_check_bit && + // If no field presence, then always clear strings/messages as well. + HasFieldPresence(descriptor_->file())) { + printer->Print("if (has_$name$()) {\n", "name", fieldname); + printer->Indent(); + have_enclosing_if = true; + } + + if (use_dependent_base_ && IsFieldDependent(field)) { + printer->Print("clear_$name$();\n", "name", fieldname); + } else { + field_generators_.get(field).GenerateClearingCode(printer); + } + + if (have_enclosing_if) { + printer->Outdent(); + printer->Print("}\n"); + } + } + + if (chunk_block_in_progress) { + printer->Outdent(); + printer->Print("}\n"); + } + if (macros_are_needed) { + printer->Outdent(); + printer->Print("\n#undef ZR_HELPER_\n#undef ZR_\n\n"); + printer->Indent(); + } + + // Step 3: Repeated fields don't use _has_bits_; emit code to clear them here. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (field->is_repeated()) { + if (use_dependent_base_ && IsFieldDependent(field)) { + printer->Print("clear_$name$();\n", "name", FieldName(field)); + } else { + field_generators_.get(field).GenerateClearingCode(printer); + } + } + } + + // Step 4: Unions. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "clear_$oneof_name$();\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + + if (HasFieldPresence(descriptor_->file())) { + // Step 5: Everything else. + printer->Print( + "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); + } + + if (PreserveUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "if (_internal_metadata_.have_unknown_fields()) {\n" + " mutable_unknown_fields()->Clear();\n" + "}\n"); + } else { + if (SupportsArenas(descriptor_)) { + printer->Print( + "_unknown_fields_.ClearToEmpty(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n" + " GetArenaNoVirtual());\n"); + } else { + printer->Print( + "_unknown_fields_.ClearToEmptyNoArena(\n" + " &::google::protobuf::internal::GetEmptyStringAlreadyInited());\n"); + } + } + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateOneofClear(io::Printer* printer) { + // Generated function clears the active field and union case (e.g. foo_case_). + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + map<string, string> oneof_vars; + oneof_vars["classname"] = classname_; + oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name(); + oneof_vars["full_name"] = descriptor_->full_name(); + string message_class; + + printer->Print(oneof_vars, + "void $classname$::clear_$oneofname$() {\n" + "// @@protoc_insertion_point(one_of_clear_start:" + "$full_name$)\n"); + printer->Indent(); + printer->Print(oneof_vars, + "switch($oneofname$_case()) {\n"); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case k$field_name$: {\n", + "field_name", UnderscoresToCamelCase(field->name(), true)); + printer->Indent(); + // We clear only allocated objects in oneofs + if (!IsStringOrMessage(field)) { + printer->Print( + "// No need to clear\n"); + } else { + field_generators_.get(field).GenerateClearingCode(printer); + } + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n" + "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n", + "oneof_index", SimpleItoa(i), + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + } +} + +void MessageGenerator:: +GenerateSwap(io::Printer* printer) { + if (SupportsArenas(descriptor_)) { + // Generate the Swap member function. This is a lightweight wrapper around + // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory + // ownership situation: swapping across arenas or between an arena and a + // heap requires copying. + printer->Print( + "void $classname$::Swap($classname$* other) {\n" + " if (other == this) return;\n" + " if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n" + " InternalSwap(other);\n" + " } else {\n" + " $classname$ temp;\n" + " temp.MergeFrom(*this);\n" + " CopyFrom(*other);\n" + " other->CopyFrom(temp);\n" + " }\n" + "}\n" + "void $classname$::UnsafeArenaSwap($classname$* other) {\n" + " if (other == this) return;\n" + " GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n" + " InternalSwap(other);\n" + "}\n", + "classname", classname_); + } else { + printer->Print( + "void $classname$::Swap($classname$* other) {\n" + " if (other == this) return;\n" + " InternalSwap(other);\n" + "}\n", + "classname", classname_); + } + + // Generate the UnsafeArenaSwap member function. + printer->Print("void $classname$::InternalSwap($classname$* other) {\n", + "classname", classname_); + printer->Indent(); + + if (HasGeneratedMethods(descriptor_->file(), options_)) { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + field_generators_.get(field).GenerateSwappingCode(printer); + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "std::swap($oneof_name$_, other->$oneof_name$_);\n" + "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n", + "oneof_name", descriptor_->oneof_decl(i)->name(), + "i", SimpleItoa(i)); + } + + if (HasFieldPresence(descriptor_->file())) { + for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) { + printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", + "i", SimpleItoa(i)); + } + } + + // Ignore PreserveUnknownFields here - always swap internal_metadata as it + // may contain more than just unknown fields. + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "_internal_metadata_.Swap(&other->_internal_metadata_);\n"); + } else { + printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); + } + + printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); + if (descriptor_->extension_range_count() > 0) { + printer->Print("_extensions_.Swap(&other->_extensions_);\n"); + } + } else { + printer->Print("GetReflection()->Swap(this, other);"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateMergeFrom(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { + // Generate the generalized MergeFrom (aka that which takes in the Message + // base class as a parameter). + printer->Print( + "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n" + "// @@protoc_insertion_point(generalized_merge_from_start:" + "$full_name$)\n" + " if (GOOGLE_PREDICT_FALSE(&from == this)) {\n" + " ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);\n" + " }\n", + "classname", classname_, "full_name", descriptor_->full_name()); + printer->Indent(); + + // Cast the message to the proper type. If we find that the message is + // *not* of the proper type, we can still call Merge via the reflection + // system, as the GOOGLE_CHECK above ensured that we have the same descriptor + // for each message. + printer->Print( + "const $classname$* source = \n" + " ::google::protobuf::internal::DynamicCastToGenerated<const $classname$>(\n" + " &from);\n" + "if (source == NULL) {\n" + "// @@protoc_insertion_point(generalized_merge_from_cast_fail:" + "$full_name$)\n" + " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" + "} else {\n" + "// @@protoc_insertion_point(generalized_merge_from_cast_success:" + "$full_name$)\n" + " MergeFrom(*source);\n" + "}\n", + "classname", classname_, "full_name", descriptor_->full_name()); + + printer->Outdent(); + printer->Print("}\n\n"); + } else { + // Generate CheckTypeAndMergeFrom(). + printer->Print( + "void $classname$::CheckTypeAndMergeFrom(\n" + " const ::google::protobuf::MessageLite& from) {\n" + " MergeFrom(*::google::protobuf::down_cast<const $classname$*>(&from));\n" + "}\n" + "\n", + "classname", classname_); + } + + // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast. + printer->Print( + "void $classname$::MergeFrom(const $classname$& from) {\n" + "// @@protoc_insertion_point(class_specific_merge_from_start:" + "$full_name$)\n" + " if (GOOGLE_PREDICT_FALSE(&from == this)) {\n" + " ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);\n" + " }\n", + "classname", classname_, "full_name", descriptor_->full_name()); + printer->Indent(); + + // Merge Repeated fields. These fields do not require a + // check as we can simply iterate over them. + for (int i = 0; i < descriptor_->field_count(); ++i) { + const FieldDescriptor* field = descriptor_->field(i); + + if (field->is_repeated()) { + field_generators_.get(field).GenerateMergingCode(printer); + } + } + + // Merge oneof fields. Oneof field requires oneof case check. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + printer->Print( + "switch (from.$oneofname$_case()) {\n", + "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case k$field_name$: {\n", + "field_name", UnderscoresToCamelCase(field->name(), true)); + printer->Indent(); + field_generators_.get(field).GenerateMergingCode(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n"); + } + + // Merge Optional and Required fields (after a _has_bit check). + int last_index = -1; + + for (int i = 0; i < descriptor_->field_count(); ++i) { + const FieldDescriptor* field = descriptor_->field(i); + + if (!field->is_repeated() && !field->containing_oneof()) { + if (HasFieldPresence(descriptor_->file())) { + // See above in GenerateClear for an explanation of this. + if (i / 8 != last_index / 8 || last_index < 0) { + if (last_index >= 0) { + printer->Outdent(); + printer->Print("}\n"); + } + printer->Print( + "if (from._has_bits_[$index$ / 32] & " + "(0xffu << ($index$ % 32))) {\n", + "index", SimpleItoa(field->index())); + printer->Indent(); + } + } + + last_index = i; + + bool have_enclosing_if = false; + if (HasFieldPresence(descriptor_->file())) { + printer->Print( + "if (from.has_$name$()) {\n", + "name", FieldName(field)); + printer->Indent(); + have_enclosing_if = true; + } else { + // Merge semantics without true field presence: primitive fields are + // merged only if non-zero (numeric) or non-empty (string). + have_enclosing_if = EmitFieldNonDefaultCondition( + printer, "from.", field); + } + + field_generators_.get(field).GenerateMergingCode(printer); + + if (have_enclosing_if) { + printer->Outdent(); + printer->Print("}\n"); + } + } + } + + if (HasFieldPresence(descriptor_->file()) && + last_index >= 0) { + printer->Outdent(); + printer->Print("}\n"); + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); + } + + if (PreserveUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "if (from._internal_metadata_.have_unknown_fields()) {\n" + " mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n" + "}\n"); + } else { + printer->Print( + "if (!from.unknown_fields().empty()) {\n" + " mutable_unknown_fields()->append(from.unknown_fields());\n" + "}\n"); + } + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateCopyFrom(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_->file(), options_)) { + // Generate the generalized CopyFrom (aka that which takes in the Message + // base class as a parameter). + printer->Print( + "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n" + "// @@protoc_insertion_point(generalized_copy_from_start:" + "$full_name$)\n", + "classname", classname_, "full_name", descriptor_->full_name()); + printer->Indent(); + + printer->Print( + "if (&from == this) return;\n" + "Clear();\n" + "MergeFrom(from);\n"); + + printer->Outdent(); + printer->Print("}\n\n"); + } + + // Generate the class-specific CopyFrom. + printer->Print( + "void $classname$::CopyFrom(const $classname$& from) {\n" + "// @@protoc_insertion_point(class_specific_copy_from_start:" + "$full_name$)\n", + "classname", classname_, "full_name", descriptor_->full_name()); + printer->Indent(); + + printer->Print( + "if (&from == this) return;\n" + "Clear();\n" + "MergeFrom(from);\n"); + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "bool $classname$::MergePartialFromCodedStream(\n" + " ::google::protobuf::io::CodedInputStream* input) {\n", + "classname", classname_); + + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), options_, printer, + // With static initializers. + " return _extensions_.ParseMessageSet(input, default_instance_,\n" + " mutable_unknown_fields());\n", + // Without. + " return _extensions_.ParseMessageSet(input, &default_instance(),\n" + " mutable_unknown_fields());\n", + // Vars. + "classname", classname_); + + printer->Print( + "}\n"); + return; + } + + printer->Print( + "bool $classname$::MergePartialFromCodedStream(\n" + " ::google::protobuf::io::CodedInputStream* input) {\n" + "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\n" + " ::google::protobuf::uint32 tag;\n", + "classname", classname_); + + if (PreserveUnknownFields(descriptor_) && + !UseUnknownFieldSet(descriptor_->file(), options_)) { + // Use LazyStringOutputString to avoid initializing unknown fields string + // unless it is actually needed. For the same reason, disable eager refresh + // on the CodedOutputStream. + printer->Print( + " ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n" + " ::google::protobuf::internal::NewPermanentCallback(\n" + " &MutableUnknownFieldsFor$classname$, this));\n" + " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" + " &unknown_fields_string, false);\n", + "classname", classname_); + } + + printer->Print( + " // @@protoc_insertion_point(parse_start:$full_name$)\n", + "full_name", descriptor_->full_name()); + + printer->Indent(); + printer->Print("for (;;) {\n"); + printer->Indent(); + + google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields( + SortFieldsByNumber(descriptor_)); + uint32 maxtag = descriptor_->field_count() == 0 ? 0 : + WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]); + const int kCutoff0 = 127; // fits in 1-byte varint + const int kCutoff1 = (127 << 7) + 127; // fits in 2-byte varint + printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = " + "input->ReadTagWithCutoff($max$);\n" + "tag = p.first;\n" + "if (!p.second) goto handle_unusual;\n", + "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 : + (maxtag <= kCutoff1 ? kCutoff1 : + maxtag))); + if (descriptor_->field_count() > 0) { + // We don't even want to print the switch() if we have no fields because + // MSVC dislikes switch() statements that contain only a default value. + + // Note: If we just switched on the tag rather than the field number, we + // could avoid the need for the if() to check the wire type at the beginning + // of each case. However, this is actually a bit slower in practice as it + // creates a jump table that is 8x larger and sparser, and meanwhile the + // if()s are highly predictable. + printer->Print("switch (::google::protobuf::internal::WireFormatLite::" + "GetTagFieldNumber(tag)) {\n"); + + printer->Indent(); + + // Find repeated messages and groups now, to simplify what follows. + hash_set<int> fields_with_parse_loop; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = ordered_fields[i]; + if (field->is_repeated() && + (field->type() == FieldDescriptor::TYPE_MESSAGE || + field->type() == FieldDescriptor::TYPE_GROUP)) { + fields_with_parse_loop.insert(i); + } + } + + // need_label is true if we generated "goto parse_$name$" while handling the + // previous field. + bool need_label = false; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = ordered_fields[i]; + const bool loops = fields_with_parse_loop.count(i) > 0; + const bool next_field_loops = fields_with_parse_loop.count(i + 1) > 0; + + PrintFieldComment(printer, field); + + printer->Print( + "case $number$: {\n", + "number", SimpleItoa(field->number())); + printer->Indent(); + const FieldGenerator& field_generator = field_generators_.get(field); + + // Emit code to parse the common, expected case. + printer->Print("if (tag == $commontag$) {\n", + "commontag", SimpleItoa(WireFormat::MakeTag(field))); + + if (need_label || + (field->is_repeated() && !field->is_packed() && !loops)) { + printer->Print( + " parse_$name$:\n", + "name", field->name()); + } + if (loops) { + printer->Print( + " DO_(input->IncrementRecursionDepth());\n" + " parse_loop_$name$:\n", + "name", field->name()); + } + + printer->Indent(); + if (field->is_packed()) { + field_generator.GenerateMergeFromCodedStreamWithPacking(printer); + } else { + field_generator.GenerateMergeFromCodedStream(printer); + } + printer->Outdent(); + + // Emit code to parse unexpectedly packed or unpacked values. + if (field->is_packed()) { + internal::WireFormatLite::WireType wiretype = + WireFormat::WireTypeForFieldType(field->type()); + printer->Print("} else if (tag == $uncommontag$) {\n", + "uncommontag", SimpleItoa( + internal::WireFormatLite::MakeTag( + field->number(), wiretype))); + printer->Indent(); + field_generator.GenerateMergeFromCodedStream(printer); + printer->Outdent(); + } else if (field->is_packable() && !field->is_packed()) { + internal::WireFormatLite::WireType wiretype = + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; + printer->Print("} else if (tag == $uncommontag$) {\n", + "uncommontag", SimpleItoa( + internal::WireFormatLite::MakeTag( + field->number(), wiretype))); + printer->Indent(); + field_generator.GenerateMergeFromCodedStreamWithPacking(printer); + printer->Outdent(); + } + + printer->Print( + "} else {\n" + " goto handle_unusual;\n" + "}\n"); + + // switch() is slow since it can't be predicted well. Insert some if()s + // here that attempt to predict the next tag. + // For non-packed repeated fields, expect the same tag again. + if (loops) { + printer->Print( + "if (input->ExpectTag($tag$)) goto parse_loop_$name$;\n", + "tag", SimpleItoa(WireFormat::MakeTag(field)), + "name", field->name()); + } else if (field->is_repeated() && !field->is_packed()) { + printer->Print( + "if (input->ExpectTag($tag$)) goto parse_$name$;\n", + "tag", SimpleItoa(WireFormat::MakeTag(field)), + "name", field->name()); + } + + // Have we emitted "if (input->ExpectTag($next_tag$)) ..." yet? + bool emitted_goto_next_tag = false; + + // For repeated messages/groups, we need to decrement recursion depth, + // unless the next tag is also for a repeated message/group. + if (loops) { + if (next_field_loops) { + const FieldDescriptor* next_field = ordered_fields[i + 1]; + printer->Print( + "if (input->ExpectTag($next_tag$)) goto parse_loop_$next_name$;\n", + "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)), + "next_name", next_field->name()); + emitted_goto_next_tag = true; + } + printer->Print( + "input->UnsafeDecrementRecursionDepth();\n"); + } + + // If there are more fields, expect the next one. + need_label = false; + if (!emitted_goto_next_tag) { + if (i + 1 == descriptor_->field_count()) { + // Expect EOF. + // TODO(kenton): Expect group end-tag? + printer->Print( + "if (input->ExpectAtEnd()) goto success;\n"); + } else { + const FieldDescriptor* next_field = ordered_fields[i + 1]; + printer->Print( + "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n", + "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)), + "next_name", next_field->name()); + need_label = true; + } + } + + printer->Print( + "break;\n"); + + printer->Outdent(); + printer->Print("}\n\n"); + } + + printer->Print("default: {\n"); + printer->Indent(); + } + + printer->Outdent(); + printer->Print("handle_unusual:\n"); + printer->Indent(); + // If tag is 0 or an end-group tag then this must be the end of the message. + printer->Print( + "if (tag == 0 ||\n" + " ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n" + " goto success;\n" + "}\n"); + + // Handle extension ranges. + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "if ("); + for (int i = 0; i < descriptor_->extension_range_count(); i++) { + const Descriptor::ExtensionRange* range = + descriptor_->extension_range(i); + if (i > 0) printer->Print(" ||\n "); + + uint32 start_tag = WireFormatLite::MakeTag( + range->start, static_cast<WireFormatLite::WireType>(0)); + uint32 end_tag = WireFormatLite::MakeTag( + range->end, static_cast<WireFormatLite::WireType>(0)); + + if (range->end > FieldDescriptor::kMaxNumber) { + printer->Print( + "($start$u <= tag)", + "start", SimpleItoa(start_tag)); + } else { + printer->Print( + "($start$u <= tag && tag < $end$u)", + "start", SimpleItoa(start_tag), + "end", SimpleItoa(end_tag)); + } + } + printer->Print(") {\n"); + if (PreserveUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), options_, printer, + // With static initializers. + " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" + " mutable_unknown_fields()));\n", + // Without. + " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" + " mutable_unknown_fields()));\n"); + } else { + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), options_, printer, + // With static initializers. + " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" + " &unknown_fields_stream));\n", + // Without. + " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" + " &unknown_fields_stream));\n"); + } + } else { + PrintHandlingOptionalStaticInitializers( + descriptor_->file(), options_, printer, + // With static initializers. + " DO_(_extensions_.ParseField(tag, input, default_instance_);\n", + // Without. + " DO_(_extensions_.ParseField(tag, input, &default_instance());\n"); + } + printer->Print( + " continue;\n" + "}\n"); + } + + // We really don't recognize this tag. Skip it. + if (PreserveUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" + " input, tag, mutable_unknown_fields()));\n"); + } else { + printer->Print( + "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n" + " input, tag, &unknown_fields_stream));\n"); + } + } else { + printer->Print( + "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n"); + } + + if (descriptor_->field_count() > 0) { + printer->Print("break;\n"); + printer->Outdent(); + printer->Print("}\n"); // default: + printer->Outdent(); + printer->Print("}\n"); // switch + } + + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" // for (;;) + "success:\n" + " // @@protoc_insertion_point(parse_success:$full_name$)\n" + " return true;\n" + "failure:\n" + " // @@protoc_insertion_point(parse_failure:$full_name$)\n" + " return false;\n" + "#undef DO_\n" + "}\n", "full_name", descriptor_->full_name()); +} + +void MessageGenerator::GenerateSerializeOneField( + io::Printer* printer, const FieldDescriptor* field, bool to_array) { + PrintFieldComment(printer, field); + + bool have_enclosing_if = false; + if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) { + printer->Print( + "if (has_$name$()) {\n", + "name", FieldName(field)); + printer->Indent(); + have_enclosing_if = true; + } else if (!HasFieldPresence(descriptor_->file())) { + have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field); + } + + if (to_array) { + field_generators_.get(field).GenerateSerializeWithCachedSizesToArray( + printer); + } else { + field_generators_.get(field).GenerateSerializeWithCachedSizes(printer); + } + + if (have_enclosing_if) { + printer->Outdent(); + printer->Print("}\n"); + } + printer->Print("\n"); +} + +void MessageGenerator::GenerateSerializeOneExtensionRange( + io::Printer* printer, const Descriptor::ExtensionRange* range, + bool to_array) { + map<string, string> vars; + vars["start"] = SimpleItoa(range->start); + vars["end"] = SimpleItoa(range->end); + printer->Print(vars, + "// Extension range [$start$, $end$)\n"); + if (to_array) { + printer->Print(vars, + "target = _extensions_.InternalSerializeWithCachedSizesToArray(\n" + " $start$, $end$, false, target);\n\n"); + } else { + printer->Print(vars, + "_extensions_.SerializeWithCachedSizes(\n" + " $start$, $end$, output);\n\n"); + } +} + +void MessageGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "void $classname$::SerializeWithCachedSizes(\n" + " ::google::protobuf::io::CodedOutputStream* output) const {\n" + " _extensions_.SerializeMessageSetWithCachedSizes(output);\n", + "classname", classname_); + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); + printer->Print( + " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" + " unknown_fields(), output);\n"); + printer->Print( + "}\n"); + return; + } + + printer->Print( + "void $classname$::SerializeWithCachedSizes(\n" + " ::google::protobuf::io::CodedOutputStream* output) const {\n", + "classname", classname_); + printer->Indent(); + + printer->Print( + "// @@protoc_insertion_point(serialize_start:$full_name$)\n", + "full_name", descriptor_->full_name()); + + GenerateSerializeWithCachedSizesBody(printer, false); + + printer->Print( + "// @@protoc_insertion_point(serialize_end:$full_name$)\n", + "full_name", descriptor_->full_name()); + + printer->Outdent(); + printer->Print( + "}\n"); +} + +void MessageGenerator:: +GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesToArray(\n" + " bool deterministic, ::google::protobuf::uint8* target) const {\n" + " target = _extensions_." + "InternalSerializeMessageSetWithCachedSizesToArray(\n" + " deterministic, target);\n", + "classname", classname_); + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); + printer->Print( + " target = ::google::protobuf::internal::WireFormat::\n" + " SerializeUnknownMessageSetItemsToArray(\n" + " unknown_fields(), target);\n"); + printer->Print( + " return target;\n" + "}\n"); + return; + } + + printer->Print( + "::google::protobuf::uint8* $classname$::InternalSerializeWithCachedSizesToArray(\n" + " bool deterministic, ::google::protobuf::uint8* target) const {\n", + "classname", classname_); + printer->Indent(); + + printer->Print( + "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", + "full_name", descriptor_->full_name()); + + GenerateSerializeWithCachedSizesBody(printer, true); + + printer->Print( + "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n", + "full_name", descriptor_->full_name()); + + printer->Outdent(); + printer->Print( + " return target;\n" + "}\n"); +} + +void MessageGenerator:: +GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { + google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields( + SortFieldsByNumber(descriptor_)); + + vector<const Descriptor::ExtensionRange*> sorted_extensions; + for (int i = 0; i < descriptor_->extension_range_count(); ++i) { + sorted_extensions.push_back(descriptor_->extension_range(i)); + } + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeSorter()); + + // Merge the fields and the extension ranges, both sorted by field number. + int i, j; + for (i = 0, j = 0; + i < descriptor_->field_count() || j < sorted_extensions.size(); + ) { + if (i == descriptor_->field_count()) { + GenerateSerializeOneExtensionRange(printer, + sorted_extensions[j++], + to_array); + } else if (j == sorted_extensions.size()) { + GenerateSerializeOneField(printer, ordered_fields[i++], to_array); + } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) { + GenerateSerializeOneField(printer, ordered_fields[i++], to_array); + } else { + GenerateSerializeOneExtensionRange(printer, + sorted_extensions[j++], + to_array); + } + } + + if (PreserveUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n"); + printer->Indent(); + if (to_array) { + printer->Print( + "target = " + "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n" + " unknown_fields(), target);\n"); + } else { + printer->Print( + "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" + " unknown_fields(), output);\n"); + } + printer->Outdent(); + + printer->Print( + "}\n"); + } else { + printer->Print( + "output->WriteRaw(unknown_fields().data(),\n" + " static_cast<int>(unknown_fields().size()));\n"); + } + } +} + +static vector<uint32> RequiredFieldsBitMask(const Descriptor* desc) { + vector<uint32> result; + uint32 mask = 0; + for (int i = 0; i < desc->field_count(); i++) { + if (i > 0 && i % 32 == 0) { + result.push_back(mask); + mask = 0; + } + if (desc->field(i)->is_required()) { + mask |= (1 << (i & 31)); + } + } + if (mask != 0) { + result.push_back(mask); + } + return result; +} + +// Create an expression that evaluates to +// "for all i, (_has_bits_[i] & masks[i]) == masks[i]" +// masks is allowed to be shorter than _has_bits_, but at least one element of +// masks must be non-zero. +static string ConditionalToCheckBitmasks(const vector<uint32>& masks) { + vector<string> parts; + for (int i = 0; i < masks.size(); i++) { + if (masks[i] == 0) continue; + string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); + // Each xor evaluates to 0 if the expected bits are present. + parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); + } + GOOGLE_CHECK(!parts.empty()); + // If we have multiple parts, each expected to be 0, then bitwise-or them. + string result = parts.size() == 1 ? parts[0] : + StrCat("(", Join(parts, "\n | "), ")"); + return result + " == 0"; +} + +void MessageGenerator:: +GenerateByteSize(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "int $classname$::ByteSize() const {\n" + "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n" + " int total_size = _extensions_.MessageSetByteSize();\n", + "classname", classname_, "full_name", descriptor_->full_name()); + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_)); + printer->Print( + "if (_internal_metadata_.have_unknown_fields()) {\n" + " total_size += ::google::protobuf::internal::WireFormat::\n" + " ComputeUnknownMessageSetItemsSize(unknown_fields());\n" + "}\n"); + printer->Print( + " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" + " _cached_size_ = total_size;\n" + " GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" + " return total_size;\n" + "}\n"); + return; + } + + if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { + // Emit a function (rarely used, we hope) that handles the required fields + // by checking for each one individually. + printer->Print( + "int $classname$::RequiredFieldsByteSizeFallback() const {\n" + "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:" + "$full_name$)\n", + "classname", classname_, "full_name", descriptor_->full_name()); + printer->Indent(); + printer->Print("int total_size = 0;\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->is_required()) { + printer->Print("\n" + "if (has_$name$()) {\n", + "name", FieldName(field)); + printer->Indent(); + PrintFieldComment(printer, field); + field_generators_.get(field).GenerateByteSize(printer); + printer->Outdent(); + printer->Print("}\n"); + } + } + printer->Print("\n" + "return total_size;\n"); + printer->Outdent(); + printer->Print("}\n"); + } + + printer->Print( + "int $classname$::ByteSize() const {\n" + "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n", + "classname", classname_, "full_name", descriptor_->full_name()); + printer->Indent(); + printer->Print( + "int total_size = 0;\n" + "\n"); + + // Handle required fields (if any). We expect all of them to be + // present, so emit one conditional that checks for that. If they are all + // present then the fast path executes; otherwise the slow path executes. + if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) { + // The fast path works if all required fields are present. + vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(descriptor_); + printer->Print((string("if (") + + ConditionalToCheckBitmasks(masks_for_has_bits) + + ") { // All required fields are present.\n").c_str()); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!field->is_required()) continue; + PrintFieldComment(printer, field); + field_generators_.get(field).GenerateByteSize(printer); + printer->Print("\n"); + } + printer->Outdent(); + printer->Print("} else {\n" // the slow path + " total_size += RequiredFieldsByteSizeFallback();\n" + "}\n"); + } else { + // num_required_fields_ <= 1: no need to be tricky + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!field->is_required()) continue; + PrintFieldComment(printer, field); + printer->Print("if (has_$name$()) {\n", + "name", FieldName(field)); + printer->Indent(); + field_generators_.get(field).GenerateByteSize(printer); + printer->Outdent(); + printer->Print("}\n"); + } + } + + // Handle optional fields (worry below about repeateds, oneofs, etc.). + // These are handled in chunks of 8. The first chunk is + // the non-requireds-non-repeateds-non-unions-non-extensions in + // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), + // and the second chunk is the same for + // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15), + // etc. + hash_map<int, uint32> fields_mask_for_chunk; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!field->is_required() && !field->is_repeated() && + !field->containing_oneof()) { + fields_mask_for_chunk[i / 8] |= static_cast<uint32>(1) << (i % 32); + } + } + + int last_index = -1; + bool chunk_block_in_progress = false; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (!field->is_required() && !field->is_repeated() && + !field->containing_oneof()) { + // See above in GenerateClear for an explanation of this. + // TODO(kenton): Share code? Unclear how to do so without + // over-engineering. + if (i / 8 != last_index / 8 || last_index < 0) { + // End previous chunk, if there was one. + if (chunk_block_in_progress) { + printer->Outdent(); + printer->Print("}\n"); + chunk_block_in_progress = false; + } + // Start chunk. + uint32 mask = fields_mask_for_chunk[i / 8]; + int count = popcnt(mask); + GOOGLE_DCHECK_GE(count, 1); + if (count == 1) { + // No "if" here because the chunk is trivial. + } else { + if (HasFieldPresence(descriptor_->file())) { + printer->Print( + "if (_has_bits_[$index$ / 32] & $mask$u) {\n", + "index", SimpleItoa(i), + "mask", SimpleItoa(mask)); + printer->Indent(); + chunk_block_in_progress = true; + } + } + } + last_index = i; + + PrintFieldComment(printer, field); + + bool have_enclosing_if = false; + if (HasFieldPresence(descriptor_->file())) { + printer->Print( + "if (has_$name$()) {\n", + "name", FieldName(field)); + printer->Indent(); + have_enclosing_if = true; + } else { + // Without field presence: field is serialized only if it has a + // non-default value. + have_enclosing_if = EmitFieldNonDefaultCondition( + printer, "this->", field); + } + + field_generators_.get(field).GenerateByteSize(printer); + + if (have_enclosing_if) { + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + } + } + } + + if (chunk_block_in_progress) { + printer->Outdent(); + printer->Print("}\n"); + } + + // Repeated fields don't use _has_bits_ so we count them in a separate + // pass. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (field->is_repeated()) { + PrintFieldComment(printer, field); + field_generators_.get(field).GenerateByteSize(printer); + printer->Print("\n"); + } + } + + // Fields inside a oneof don't use _has_bits_ so we count them in a separate + // pass. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "switch ($oneofname$_case()) {\n", + "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + PrintFieldComment(printer, field); + printer->Print( + "case k$field_name$: {\n", + "field_name", UnderscoresToCamelCase(field->name(), true)); + printer->Indent(); + field_generators_.get(field).GenerateByteSize(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n"); + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "total_size += _extensions_.ByteSize();\n" + "\n"); + } + + if (PreserveUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_->file(), options_)) { + printer->Print( + "if (_internal_metadata_.have_unknown_fields()) {\n" + " total_size +=\n" + " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n" + " unknown_fields());\n" + "}\n"); + } else { + printer->Print( + "total_size += unknown_fields().size();\n" + "\n"); + } + } + + // We update _cached_size_ even though this is a const method. In theory, + // this is not thread-compatible, because concurrent writes have undefined + // results. In practice, since any concurrent writes will be writing the + // exact same value, it works on all common processors. In a future version + // of C++, _cached_size_ should be made into an atomic<int>. + printer->Print( + "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" + "_cached_size_ = total_size;\n" + "GOOGLE_SAFE_CONCURRENT_WRITES_END();\n" + "return total_size;\n"); + + printer->Outdent(); + printer->Print("}\n"); +} + +void MessageGenerator:: +GenerateIsInitialized(io::Printer* printer) { + printer->Print( + "bool $classname$::IsInitialized() const {\n", + "classname", classname_); + printer->Indent(); + + if (HasFieldPresence(descriptor_->file())) { + // Check that all required fields in this message are set. We can do this + // most efficiently by checking 32 "has bits" at a time. + int has_bits_array_size = (descriptor_->field_count() + 31) / 32; + for (int i = 0; i < has_bits_array_size; i++) { + uint32 mask = 0; + for (int bit = 0; bit < 32; bit++) { + int index = i * 32 + bit; + if (index >= descriptor_->field_count()) break; + const FieldDescriptor* field = descriptor_->field(index); + + if (field->is_required()) { + mask |= 1 << bit; + } + } + + if (mask != 0) { + printer->Print( + "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n", + "i", SimpleItoa(i), + "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8))); + } + } + } + + // Now check that all embedded messages are initialized. + printer->Print("\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + !ShouldIgnoreRequiredFieldCheck(field, options_) && + HasRequiredFields(field->message_type(), options_)) { + if (field->is_repeated()) { + printer->Print( + "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))" + " return false;\n", + "name", FieldName(field)); + } else { + if (field->options().weak() || !field->containing_oneof()) { + // For weak fields, use the data member (::google::protobuf::Message*) instead + // of the getter to avoid a link dependency on the weak message type + // which is only forward declared. + printer->Print( + "if (has_$name$()) {\n" + " if (!this->$name$_->IsInitialized()) return false;\n" + "}\n", + "name", FieldName(field)); + } else { + printer->Print( + "if (has_$name$()) {\n" + " if (!this->$name$().IsInitialized()) return false;\n" + "}\n", + "name", FieldName(field)); + } + } + } + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "\n" + "if (!_extensions_.IsInitialized()) return false;"); + } + + printer->Outdent(); + printer->Print( + " return true;\n" + "}\n"); +} + + +} // namespace cpp +} // namespace compiler +} // namespace protobuf +} // namespace google |