diff options
Diffstat (limited to 'src/google/protobuf/compiler/cpp')
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_enum.cc | 6 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_enum_field.cc | 2 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_file.cc | 185 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_helpers.cc | 19 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_helpers.h | 14 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_map_field.cc | 4 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_message.cc | 147 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_message.h | 6 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_message_field.cc | 4 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_primitive_field.cc | 50 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_service.cc | 7 | ||||
-rw-r--r-- | src/google/protobuf/compiler/cpp/cpp_string_field.cc | 9 |
12 files changed, 208 insertions, 245 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 9493d5f8..6a8a83d1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -251,13 +251,15 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { vars["classname"] = classname_; vars["index_in_metadata"] = SimpleItoa(index_in_metadata_); vars["constexpr"] = options_.proto_h ? "constexpr " : ""; + vars["file_namespace"] = FileLevelNamespace(descriptor_->file()->name()); if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print( vars, "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n" - " protobuf_AssignDescriptorsOnce();\n" - " return file_level_enum_descriptors[$index_in_metadata$];\n" + " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" + " return " + "$file_namespace$::file_level_enum_descriptors[$index_in_metadata$];\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index b6658079..44a86fc8 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -230,7 +230,7 @@ void EnumOneofFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { printer->Print( variables_, - " $classname$_default_oneof_instance_.$name$_ = $default$;\n"); + "_$classname$_default_instance_.$name$_ = $default$;\n"); } // =================================================================== diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index 9cfd6ec6..0e5e2f18 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -284,8 +284,13 @@ void FileGenerator::GenerateSource(io::Printer* printer) { if (IsMapEntryMessage(message_generators_[i]->descriptor_)) continue; printer->Print( "class $classname$DefaultTypeInternal : " - "public ::google::protobuf::internal::ExplicitlyConstructed<$classname$> {};\n" - "$classname$DefaultTypeInternal _$classname$_default_instance_;\n", + "public ::google::protobuf::internal::ExplicitlyConstructed<$classname$> {\n", + "classname", message_generators_[i]->classname_); + printer->Indent(); + message_generators_[i]->GenerateExtraDefaultFields(printer); + printer->Outdent(); + printer->Print( + "} _$classname$_default_instance_;\n", "classname", message_generators_[i]->classname_); } @@ -301,6 +306,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) { } } + printer->Print( + "\n" + "namespace $file_namespace$ {\n" + "\n", + "file_namespace", FileLevelNamespace(file_->name())); + if (HasDescriptorMethods(file_, options_)) { printer->Print( "\n" @@ -324,10 +335,6 @@ void FileGenerator::GenerateSource(io::Printer* printer) { "size", SimpleItoa(file_->service_count())); } - for (int i = 0; i < message_generators_.size(); i++) { - message_generators_[i]->GenerateDescriptorDeclarations(printer); - } - printer->Print( "\n" "} // namespace\n" @@ -338,6 +345,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) { // library, all this does is initialize default instances.) GenerateBuildDescriptors(printer); + printer->Print( + "\n" + "} // namespace $file_namespace$\n" + "\n", + "file_namespace", FileLevelNamespace(file_->name())); + // Generate enums. for (int i = 0; i < enum_generators_.size(); i++) { enum_generators_[i]->GenerateMethods(printer); @@ -473,28 +486,16 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { if (HasDescriptorMethods(file_, options_)) { if (!message_generators_.empty()) { - printer->Print( - "\n" - "const ::google::protobuf::uint32* $offsetfunname$() GOOGLE_ATTRIBUTE_COLD;\n" - "const ::google::protobuf::uint32* $offsetfunname$() {\n", - "offsetfunname", GlobalOffsetTableName(file_->name())); - printer->Indent(); - - printer->Print("static const ::google::protobuf::uint32 offsets[] = {\n"); + printer->Print("const ::google::protobuf::uint32 TableStruct::offsets[] = {\n"); printer->Indent(); std::vector<std::pair<size_t, size_t> > pairs; for (int i = 0; i < message_generators_.size(); i++) { pairs.push_back(message_generators_[i]->GenerateOffsets(printer)); } printer->Outdent(); - printer->Outdent(); - printer->Print( - " };\n" - " return offsets;\n" - "}\n" - "\n"); - printer->Print( + "};\n" + "\n" "static const ::google::protobuf::internal::MigrationSchema schemas[] = {\n"); printer->Indent(); { @@ -508,25 +509,17 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { printer->Outdent(); printer->Print( "};\n" - "\n" - "static const ::google::protobuf::internal::DefaultInstanceData " - "file_default_instances[] = {\n"); + "\nstatic " + "::google::protobuf::Message const * const file_default_instances[] = {\n"); printer->Indent(); for (int i = 0; i < message_generators_.size(); i++) { const Descriptor* descriptor = message_generators_[i]->descriptor_; if (IsMapEntryMessage(descriptor)) continue; - string oneof_default = "NULL"; - if (message_generators_[i]->descriptor_->oneof_decl_count()) { - oneof_default = - "&" + ClassName(descriptor, false) + "_default_oneof_instance_"; - } printer->Print( - "{reinterpret_cast<const " - "::google::protobuf::Message*>(&_$classname$_default_instance_), " - "$oneof_default$},\n", - "classname", ClassName(descriptor, false), "oneof_default", - oneof_default); + "reinterpret_cast<const " + "::google::protobuf::Message*>(&_$classname$_default_instance_),\n", + "classname", ClassName(descriptor, false)); } printer->Outdent(); printer->Print( @@ -535,12 +528,11 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { } else { // we still need these symbols to exist printer->Print( - "inline ::google::protobuf::uint32* $offsetfunname$() { return NULL; }\n" + // MSVC doesn't like empty arrays, so we add a dummy. + "const ::google::protobuf::uint32 TableStruct::offsets[] = { ~0u };\n" "static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;\n" - "static const ::google::protobuf::internal::DefaultInstanceData* " - "file_default_instances = NULL;\n", - "offsetfunname", - GlobalOffsetTableName(file_->name())); + "static const ::google::protobuf::Message* const* " + "file_default_instances = NULL;\n"); } // --------------------------------------------------------------- @@ -557,11 +549,11 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // is requested *during* static init then AddDescriptors() may not have // been called yet, so we call it manually. Note that it's fine if // AddDescriptors() is called multiple times. - " $adddescriptorsname$();\n" + " AddDescriptors();\n" " ::google::protobuf::MessageFactory* factory = $factory$;\n" " AssignDescriptors(\n" " \"$filename$\", schemas, file_default_instances, " - "$offsetfunname$(), factory,\n" + "TableStruct::offsets, factory,\n" " $metadata$, $enum_descriptors$, $service_descriptors$);\n" "}\n" "\n" @@ -570,9 +562,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { " ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);\n" "}\n" "\n", - "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), - "offsetfunname", GlobalOffsetTableName(file_->name()), "filename", - file_->name(), "metadata", + "filename", file_->name(), "metadata", !message_generators_.empty() ? "file_level_metadata" : "NULL", "enum_descriptors", !enum_generators_.empty() ? "file_level_enum_descriptors" : "NULL", @@ -616,8 +606,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown. printer->Print( "\n" - "void $shutdownfilename$() {\n", - "shutdownfilename", GlobalShutdownFileName(file_->name())); + "void TableStruct::Shutdown() {\n"); printer->Indent(); for (int i = 0; i < message_generators_.size(); i++) { @@ -630,13 +619,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // ----------------------------------------------------------------- - // Now generate the InitDefaults() function. + // Now generate the InitDefaultsImpl() function. printer->Print( - "void $initdefaultsname$_impl() {\n" + "void TableStruct::InitDefaultsImpl() {\n" " GOOGLE_PROTOBUF_VERIFY_VERSION;\n\n" - "", - // Vars. - "initdefaultsname", GlobalInitDefaultsName(file_->name())); + // Force initialization of primitive values we depend on. + " ::google::protobuf::internal::InitProtobufDefaults();\n"); printer->Indent(); @@ -645,17 +633,13 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { for (int i = 0; i < file_->dependency_count(); i++) { const FileDescriptor* dependency = file_->dependency(i); // Print the namespace prefix for the dependency. - string add_desc_name = QualifiedFileLevelSymbol( - dependency->package(), GlobalInitDefaultsName(dependency->name())); + string file_namespace = QualifiedFileLevelSymbol( + dependency->package(), FileLevelNamespace(dependency->name())); // Call its AddDescriptors function. - printer->Print( - "$name$();\n", - "name", add_desc_name); + printer->Print("$file_namespace$::InitDefaults();\n", "file_namespace", + file_namespace); } - // Force initialization of primitive values we depend on. - printer->Print("::google::protobuf::internal::InitProtobufDefaults();\n"); - // Allocate and initialize default instances. This can't be done lazily // since default instances are returned by simple accessors and are used with // extensions. Speaking of which, we also register extensions at this time. @@ -672,21 +656,17 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { printer->Print( "}\n" "\n" - "void $initdefaultsname$() {\n" + "void InitDefaults() {\n" " static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n" - " ::google::protobuf::GoogleOnceInit(&once, &$initdefaultsname$_impl);\n" - "}\n", - "initdefaultsname", GlobalInitDefaultsName(file_->name())); + " ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);\n" + "}\n"); // ----------------------------------------------------------------- // Now generate the AddDescriptors() function. printer->Print( - "void $adddescriptorsname$_impl() {\n" - " $initdefaultsname$();\n", - // Vars. - "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), - "initdefaultsname", GlobalInitDefaultsName(file_->name())); + "void AddDescriptorsImpl() {\n" + " InitDefaults();\n"); printer->Indent(); if (HasDescriptorMethods(file_, options_)) { @@ -702,12 +682,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { printer->Print("static const char descriptor[] = {\n"); printer->Indent(); -#ifdef _MSC_VER - bool breakdown_large_file = true; -#else - bool breakdown_large_file = false; -#endif - if (breakdown_large_file && file_data.size() > 66538) { + if (file_data.size() > 66535) { // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535 // bytes in length". Declare a static array of characters rather than use // a string literal. Only write 25 bytes per line. @@ -748,42 +723,36 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { for (int i = 0; i < file_->dependency_count(); i++) { const FileDescriptor* dependency = file_->dependency(i); // Print the namespace prefix for the dependency. - string add_desc_name = QualifiedFileLevelSymbol( - dependency->package(), GlobalAddDescriptorsName(dependency->name())); + string file_namespace = QualifiedFileLevelSymbol( + dependency->package(), FileLevelNamespace(dependency->name())); // Call its AddDescriptors function. - printer->Print("$adddescriptorsname$();\n", "adddescriptorsname", - add_desc_name); + printer->Print("$file_namespace$::AddDescriptors();\n", "file_namespace", + file_namespace); } printer->Print( - "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n", - "shutdownfilename", GlobalShutdownFileName(file_->name())); + "::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);\n"); printer->Outdent(); printer->Print( "}\n" "\n" - "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n" - "void $adddescriptorsname$() {\n" - " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n" - " &$adddescriptorsname$_impl);\n" - "}\n", - "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); + "void AddDescriptors() {\n" + " static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n" + " ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);\n" + "}\n"); if (!StaticInitializersForced(file_, options_)) { - printer->Print("#ifndef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"); + printer->Print("#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"); } printer->Print( // With static initializers. "// Force AddDescriptors() to be called at static initialization time.\n" - "struct StaticDescriptorInitializer_$filename$ {\n" - " StaticDescriptorInitializer_$filename$() {\n" - " $adddescriptorsname$();\n" + "struct StaticDescriptorInitializer {\n" + " StaticDescriptorInitializer() {\n" + " AddDescriptors();\n" " }\n" - "} static_descriptor_initializer_$filename$_;\n", - // Vars. - "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename", - FilenameIdentifier(file_->name())); + "} static_descriptor_initializer;\n"); if (!StaticInitializersForced(file_, options_)) { printer->Print("#endif // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"); } @@ -884,10 +853,11 @@ void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { // OK, it's now safe to #include other files. printer->Print( - "#include <google/protobuf/arena.h>\n" - "#include <google/protobuf/arenastring.h>\n" - "#include <google/protobuf/generated_message_util.h>\n" - "#include <google/protobuf/metadata.h>\n"); + "#include <google/protobuf/io/coded_stream.h>\n" + "#include <google/protobuf/arena.h>\n" + "#include <google/protobuf/arenastring.h>\n" + "#include <google/protobuf/generated_message_util.h>\n" + "#include <google/protobuf/metadata.h>\n"); if (!message_generators_.empty()) { if (HasDescriptorMethods(file_, options_)) { @@ -982,12 +952,21 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations( // functions, so that we can declare them to be friends of each class. printer->Print( "\n" + "namespace $file_namespace$ {\n" "// Internal implementation detail -- do not call these.\n" - "void $dllexport_decl$$adddescriptorsname$();\n" - "void $dllexport_decl$$initdefaultsname$();\n", - "initdefaultsname", GlobalInitDefaultsName(file_->name()), - "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), - "dllexport_decl", + "struct $dllexport_decl$TableStruct {\n" + " static const ::google::protobuf::uint32 offsets[];\n" + // The following function(s) need to be able to access private members of + // the messages defined in the file. So we make them static members. + // This is the internal implementation of InitDefaults. It should only + // be called by InitDefaults which makes sure it will be called only once. + " static void InitDefaultsImpl();\n" + " static void Shutdown();\n" + "};\n" + "void $dllexport_decl$AddDescriptors();\n" + "void $dllexport_decl$InitDefaults();\n" + "} // namespace $file_namespace$\n", + "file_namespace", FileLevelNamespace(file_->name()), "dllexport_decl", options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " "); } diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 5a37b9d7..3c4dddc5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -440,23 +440,8 @@ string FilenameIdentifier(const string& filename) { return result; } -// Return the name of the AddDescriptors() function for a given file. -string GlobalAddDescriptorsName(const string& filename) { - return "protobuf_AddDesc_" + FilenameIdentifier(filename); -} - -string GlobalInitDefaultsName(const string& filename) { - return "protobuf_InitDefaults_" + FilenameIdentifier(filename); -} - -// Return the name of the AssignDescriptors() function for a given file. -string GlobalOffsetTableName(const string& filename) { - return "protobuf_Offsets_" + FilenameIdentifier(filename); -} - -// Return the name of the ShutdownFile() function for a given file. -string GlobalShutdownFileName(const string& filename) { - return "protobuf_ShutdownFile_" + FilenameIdentifier(filename); +string FileLevelNamespace(const string& filename) { + return "protobuf_" + FilenameIdentifier(filename); } // Return the qualified C++ name for a file level symbol. diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index c988bda8..0f297ec8 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -144,21 +144,13 @@ string DefaultValue(const FieldDescriptor* field); // Convert a file name into a valid identifier. string FilenameIdentifier(const string& filename); -// Return the name of the AddDescriptors() function for a given file. -string GlobalAddDescriptorsName(const string& filename); - -// Return the name of the InitDefaults() function for a given file. -string GlobalInitDefaultsName(const string& filename); - -// Return the name of the offset table function for a given file. -string GlobalOffsetTableName(const string& filename); +// For each .proto file generates a unique namespace. In this namespace global +// definitions are put to prevent collisions. +string FileLevelNamespace(const string& filename); // Return the qualified C++ name for a file level symbol. string QualifiedFileLevelSymbol(const string& package, const string& name); -// Return the name of the ShutdownFile() function for a given file. -string GlobalShutdownFileName(const string& filename); - // Escape C++ trigraphs by escaping question marks to \? string EscapeTrigraphs(const string& to_escape); diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index 5c4b56f7..b4eaf485 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -49,6 +49,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor, const Options& options) { SetCommonFieldVariables(descriptor, variables, options); (*variables)["type"] = ClassName(descriptor->message_type(), false); + (*variables)["file_namespace"] = + FileLevelNamespace(descriptor->file()->name()); (*variables)["stream_writer"] = (*variables)["declared_type"] + (HasFastArraySerialization(descriptor->message_type()->file(), options) @@ -174,7 +176,7 @@ GenerateConstructorCode(io::Printer* printer) const { if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print(variables_, "$name$_.SetAssignDescriptorCallback(\n" - " protobuf_AssignDescriptorsOnce);\n" + " $file_namespace$::protobuf_AssignDescriptorsOnce);\n" "$name$_.SetEntryDescriptor(\n" " &$type$_descriptor);\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 2d3d5640..32f05f25 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -505,6 +505,7 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, classname_(ClassName(descriptor, false)), options_(options), field_generators_(descriptor, options), + max_has_bit_index_(0), nested_generators_(new google::protobuf::scoped_ptr< MessageGenerator>[descriptor->nested_type_count()]), enum_generators_( @@ -523,7 +524,7 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, OptimizePadding(&optimized_order_, options_); if (HasFieldPresence(descriptor_->file())) { - int has_bit_index = 0; + // We use -1 as a sentinel. has_bit_indices_.resize(descriptor_->field_count(), -1); for (int i = 0; i < optimized_order_.size(); i++) { const FieldDescriptor* field = optimized_order_[i]; @@ -532,19 +533,7 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, continue; } - has_bit_indices_[field->index()] = has_bit_index; - has_bit_index++; - } - - // Assign fields that do not use has bits to be at the end. This can be - // removed once we shrink the has bits we assign. - // - // TODO(ckennelly): Shrink the has bits for these fields. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (has_bit_indices_[field->index()] < 0) { - has_bit_indices_[field->index()] = has_bit_index++; - } + has_bit_indices_[field->index()] = max_has_bit_index_++; } } @@ -581,9 +570,8 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, MessageGenerator::~MessageGenerator() {} size_t MessageGenerator::HasBitsSize() const { - // 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) { + size_t sizeof_has_bits = (max_has_bit_index_ + 31) / 32 * 4; + if (sizeof_has_bits == 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 @@ -642,8 +630,28 @@ GenerateDependentFieldAccessorDeclarations(io::Printer* printer) { void MessageGenerator:: GenerateFieldAccessorDeclarations(io::Printer* printer) { + // optimized_fields_ does not contain fields where + // field->containing_oneof() != NULL + // so we need to iterate over those as well. + // + // We place the non-oneof fields in optimized_order_, as that controls the + // order of the _has_bits_ entries and we want GDB's pretty printers to be + // able to infer these indices from the k[FIELDNAME]FieldNumber order. + std::vector<const FieldDescriptor*> ordered_fields; + ordered_fields.reserve(descriptor_->field_count()); + + ordered_fields.insert( + ordered_fields.begin(), optimized_order_.begin(), optimized_order_.end()); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); + if (field->containing_oneof() == NULL) { + continue; + } + ordered_fields.push_back(field); + } + + for (int i = 0; i < ordered_fields.size(); i++) { + const FieldDescriptor* field = ordered_fields[i]; PrintFieldComment(printer, field); @@ -1191,12 +1199,14 @@ GenerateClassDefinition(io::Printer* printer) { } if (HasFastArraySerialization(descriptor_->file(), options_)) { printer->Print( - "::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(\n" - " bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;\n" - "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output)\n" - " const PROTOBUF_FINAL {\n" - " return InternalSerializeWithCachedSizesToArray(false, output);\n" - "}\n"); + "::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(\n" + " bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;\n" + "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output)\n" + " const PROTOBUF_FINAL {\n" + " return InternalSerializeWithCachedSizesToArray(\n" + " ::google::protobuf::io::CodedOutputStream::" + "IsDefaultSerializationDeterministic(), output);\n" + "}\n"); } } @@ -1447,25 +1457,15 @@ GenerateClassDefinition(io::Printer* printer) { "::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_. - printer->Print("friend void $dllexport_decl$ $initdefaultsname$_impl();\n", - // Vars. - "dllexport_decl", options_.dllexport_decl, "initdefaultsname", - GlobalInitDefaultsName(descriptor_->file()->name())); - printer->Print("friend void $dllexport_decl$ $adddescriptorsname$_impl();\n", - // Vars. - "dllexport_decl", options_.dllexport_decl, - "adddescriptorsname", - GlobalAddDescriptorsName(descriptor_->file()->name())); - + // The TableStruct struct needs access to the private parts, in order to + // construct the offsets of all members. + // Some InitDefault and Shutdown are defined as static member functions of + // TableStruct such that they are also allowed to access private members. printer->Print( - "friend const ::google::protobuf::uint32* $offsetfunname$();\n" - "friend void $shutdownfilename$();\n" - "\n", - "offsetfunname", GlobalOffsetTableName(descriptor_->file()->name()), - "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name())); + "friend struct $dllexport_decl$ $file_namespace$::TableStruct;\n", + // Vars. + "dllexport_decl", options_.dllexport_decl, "file_namespace", + FileLevelNamespace(descriptor_->file()->name())); printer->Outdent(); printer->Print("};"); @@ -1510,15 +1510,13 @@ GenerateInlineMethods(io::Printer* printer, bool is_inline) { } void MessageGenerator:: -GenerateDescriptorDeclarations(io::Printer* printer) { +GenerateExtraDefaultFields(io::Printer* printer) { // Generate oneof default instance for reflection usage. if (descriptor_->oneof_decl_count() > 0) { - printer->Print("struct $name$OneofInstance {\n", - "name", classname_); + printer->Print("public:\n"); 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)) { @@ -1527,8 +1525,6 @@ GenerateDescriptorDeclarations(io::Printer* printer) { field_generators_.get(field).GeneratePrivateMembers(printer); } } - - printer->Print("} $name$_default_oneof_instance_;\n", "name", classname_); } } @@ -1555,6 +1551,7 @@ GenerateTypeRegistrations(io::Printer* printer) { std::map<string, string> vars; CollectMapInfo(descriptor_, &vars); vars["classname"] = classname_; + vars["file_namespace"] = FileLevelNamespace(descriptor_->file()->name()); const FieldDescriptor* val = descriptor_->FindFieldByName("value"); if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO2 && @@ -1570,7 +1567,8 @@ GenerateTypeRegistrations(io::Printer* printer) { printer->Print( vars, "const ::google::protobuf::Descriptor* $classname$_descriptor = " - "file_level_metadata[$index_in_metadata$].descriptor;\n" + "$file_namespace$::file_level_metadata[$index_in_metadata$].descriptor;" + "\n" "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n" " $classname$_descriptor,\n" " ::google::protobuf::internal::MapEntry<\n" @@ -1620,7 +1618,7 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) { HasDescriptorMethods(descriptor_->file(), options_))) { string name; if (field->containing_oneof()) { - name = classname_ + "_default_oneof_instance_."; + name = "_" + classname_ + "_default_instance_."; } else { name = "_" + classname_ + "_default_instance_.get_mutable()->"; } @@ -1740,11 +1738,12 @@ GenerateClassMethods(io::Printer* printer) { if (HasDescriptorMethods(descriptor_->file(), options_)) { printer->Print( "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" - " protobuf_AssignDescriptorsOnce();\n" - " return file_level_metadata[$index$];\n" + " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" + " return $file_namespace$::file_level_metadata[$index$];\n" "}\n" "\n", - "classname", classname_, "index", SimpleItoa(index_in_metadata_)); + "classname", classname_, "index", SimpleItoa(index_in_metadata_), + "file_namespace", FileLevelNamespace(descriptor_->file()->name())); } else { printer->Print( "::std::string $classname$::GetTypeName() const {\n" @@ -1798,7 +1797,7 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( if (field->containing_oneof()) { printer->Print( "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(" - "(&$classname$_default_oneof_instance_), $name$_),\n", + "(&_$classname$_default_instance_), $name$_),\n", "classname", classname_, "name", FieldName(field)); } else { printer->Print( @@ -1820,7 +1819,9 @@ std::pair<size_t, size_t> MessageGenerator::GenerateOffsets( if (HasFieldPresence(descriptor_->file())) { entries += has_bit_indices_.size(); for (int i = 0; i < has_bit_indices_.size(); i++) { - printer->Print("$index$,\n", "index", SimpleItoa(has_bit_indices_[i])); + const string index = has_bit_indices_[i] >= 0 ? + SimpleItoa(has_bit_indices_[i]) : "~0u"; + printer->Print("$index$,\n", "index", index); } } @@ -1849,9 +1850,10 @@ GenerateSharedConstructorCode(io::Printer* printer) { IsMapEntryMessage(descriptor_->nested_type(i))) { printer->Print( "const ::google::protobuf::Descriptor*& $type$_descriptor = " - "file_level_metadata[$index$].descriptor;\n", + "$file_namespace$::file_level_metadata[$index$].descriptor;\n", "type", ClassName(descriptor_->nested_type(i), false), "index", - SimpleItoa(nested_generators_[i]->index_in_metadata_)); + SimpleItoa(nested_generators_[i]->index_in_metadata_), + "file_namespace", FileLevelNamespace(descriptor_->file()->name())); } } @@ -2086,14 +2088,14 @@ GenerateStructors(io::Printer* printer) { "$classname$::$classname$()\n" " : $superclass$()$initializer$ {\n" " if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {\n" - " $initdefaultsname$();\n" + " $file_namespace$::InitDefaults();\n" " }\n" " SharedCtor();\n" " // @@protoc_insertion_point(constructor:$full_name$)\n" "}\n", "classname", classname_, "superclass", superclass, "full_name", descriptor_->full_name(), "initializer", initializer_null, - "initdefaultsname", GlobalInitDefaultsName(descriptor_->file()->name())); + "file_namespace", FileLevelNamespace(descriptor_->file()->name())); if (SupportsArenas(descriptor_)) { printer->Print( @@ -2102,7 +2104,7 @@ GenerateStructors(io::Printer* printer) { // When arenas are used it's safe to assume we have finished // static init time (protos with arenas are unsafe during static init) "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" - " $initdefaultsname$();\n" + " $file_namespace$::InitDefaults();\n" "#endif // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" " SharedCtor();\n" " RegisterArenaDtor(arena);\n" @@ -2110,8 +2112,7 @@ GenerateStructors(io::Printer* printer) { "}\n", "initializer", initializer_with_arena, "classname", classname_, "superclass", superclass, "full_name", descriptor_->full_name(), - "initdefaultsname", - GlobalInitDefaultsName(descriptor_->file()->name())); + "file_namespace", FileLevelNamespace(descriptor_->file()->name())); } // Generate the copy constructor. @@ -2182,9 +2183,10 @@ GenerateStructors(io::Printer* printer) { IsMapEntryMessage(descriptor_->nested_type(i))) { printer->Print( "const ::google::protobuf::Descriptor*& $type$_descriptor = " - "file_level_metadata[$index$].descriptor;\n", + "$file_namespace$::file_level_metadata[$index$].descriptor;\n", "type", ClassName(descriptor_->nested_type(i), false), "index", - SimpleItoa(nested_generators_[i]->index_in_metadata_)); + SimpleItoa(nested_generators_[i]->index_in_metadata_), + "file_namespace", FileLevelNamespace(descriptor_->file()->name())); } } @@ -2265,20 +2267,21 @@ GenerateStructors(io::Printer* printer) { !descriptor_->options().no_standard_descriptor_accessor()) { printer->Print( "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" - " protobuf_AssignDescriptorsOnce();\n" - " return file_level_metadata[$index$].descriptor;\n" + " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" + " return $file_namespace$::file_level_metadata[$index$].descriptor;\n" "}\n" "\n", - "index", SimpleItoa(index_in_metadata_), "classname", classname_); + "index", SimpleItoa(index_in_metadata_), "classname", classname_, + "file_namespace", FileLevelNamespace(descriptor_->file()->name())); } printer->Print( "const $classname$& $classname$::default_instance() {\n" - " $initdefaultsname$();\n" + " $file_namespace$::InitDefaults();\n" " return *internal_default_instance();\n" "}\n\n", - "classname", classname_, "initdefaultsname", - GlobalInitDefaultsName(descriptor_->file()->name())); + "classname", classname_, "file_namespace", + FileLevelNamespace(descriptor_->file()->name())); if (SupportsArenas(descriptor_)) { printer->Print( @@ -2630,7 +2633,7 @@ GenerateSwap(io::Printer* printer) { } if (HasFieldPresence(descriptor_->file())) { - for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) { + for (int i = 0; i < HasBitsSize() / 4; ++i) { printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", "i", SimpleItoa(i)); } @@ -3260,7 +3263,7 @@ void MessageGenerator::GenerateSerializeOneExtensionRange( if (to_array) { printer->Print(vars, "target = _extensions_.InternalSerializeWithCachedSizesToArray(\n" - " $start$, $end$, false, target);\n\n"); + " $start$, $end$, deterministic, target);\n\n"); } else { printer->Print(vars, "_extensions_.SerializeWithCachedSizes(\n" @@ -3335,7 +3338,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { "classname", classname_); printer->Indent(); - printer->Print("(void)deterministic; // Unused\n"); + printer->Print("(void)deterministic; // Unused\n"); printer->Print( "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", "full_name", descriptor_->full_name()); diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index c5efff12..1a804a16 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -91,9 +91,8 @@ class MessageGenerator { // Source file stuff. - // Generate code which declares all the global descriptor pointers which - // will be initialized by the methods below. - void GenerateDescriptorDeclarations(io::Printer* printer); + // Generate extra fields + void GenerateExtraDefaultFields(io::Printer* printer); // Generate code that calls MessageFactory::InternalRegisterGeneratedMessage() // for all types. @@ -201,6 +200,7 @@ class MessageGenerator { // optimized_order_ excludes oneof fields. std::vector<const FieldDescriptor *> optimized_order_; std::vector<int> has_bit_indices_; + int max_has_bit_index_; google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > nested_generators_; google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_; google::protobuf::scoped_array<google::protobuf::scoped_ptr<ExtensionGenerator> > extension_generators_; diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index 91449657..c3d1745c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -487,9 +487,6 @@ GenerateClearingCode(io::Printer* printer) const { void MessageFieldGenerator:: GenerateMessageClearingCode(io::Printer* printer) const { - std::map<string, string> variables(variables_); - variables["type"] = FieldMessageTypeName(descriptor_); - if (!HasFieldPresence(descriptor_->file())) { // If we don't have has-bits, message presence is indicated only by ptr != // NULL. Thus on clear, we need to delete the object. @@ -1035,7 +1032,6 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, "}\n"); } - if (!dependent_field_) { printer->Print(variables, "$inline$" diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index 240a6e0a..a68891a3 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -245,7 +245,7 @@ void PrimitiveOneofFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { printer->Print( variables_, - " $classname$_default_oneof_instance_.$name$_ = $default$;\n"); + "_$classname$_default_instance_.$name$_ = $default$;\n"); } void PrimitiveOneofFieldGenerator:: @@ -373,6 +373,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { + bool array_written = false; if (descriptor_->is_packed()) { // Write the tag and the size. printer->Print(variables_, @@ -381,21 +382,30 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { "$number$, " "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, " "output);\n" - " output->WriteVarint32(_$name$_cached_byte_size_);\n" - "}\n"); + " output->WriteVarint32(_$name$_cached_byte_size_);\n"); + + if (FixedSize(descriptor_->type()) > 0) { + printer->Print(variables_, + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$Array(\n" + " this->$name$().data(), this->$name$_size(), output);\n"); + array_written = true; // Wrote array all at once + } + printer->Print(variables_, "}\n"); } - printer->Print(variables_, - "for (int i = 0; i < this->$name$_size(); i++) {\n"); - if (descriptor_->is_packed()) { + if (!array_written) { printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n" - " this->$name$(i), output);\n"); - } else { - printer->Print(variables_, - " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" - " $number$, this->$name$(i), output);\n"); + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (descriptor_->is_packed()) { + printer->Print(variables_, + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n" + " this->$name$(i), output);\n"); + } else { + printer->Print(variables_, + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(i), output);\n"); + } + printer->Print("}\n"); } - printer->Print("}\n"); } void RepeatedPrimitiveFieldGenerator:: @@ -428,21 +438,17 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: GenerateByteSize(io::Printer* printer) const { - printer->Print(variables_, - "{\n" - " size_t data_size = 0;\n" - " unsigned int count = this->$name$_size();\n"); + printer->Print(variables_, "{\n"); printer->Indent(); int fixed_size = FixedSize(descriptor_->type()); if (fixed_size == -1) { printer->Print(variables_, - "for (unsigned int i = 0; i < count; i++) {\n" - " data_size += ::google::protobuf::internal::WireFormatLite::\n" - " $declared_type$Size(this->$name$(i));\n" - "}\n"); + "size_t data_size = ::google::protobuf::internal::WireFormatLite::\n" + " $declared_type$Size(this->$name$_);\n"); } else { printer->Print(variables_, - "data_size = $fixed_size$UL * count;\n"); + "unsigned int count = this->$name$_size();\n" + "size_t data_size = $fixed_size$UL * count;\n"); } if (descriptor_->is_packed()) { diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc index d6b1ddc5..95357d9f 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.cc +++ b/src/google/protobuf/compiler/cpp/cpp_service.cc @@ -46,6 +46,7 @@ ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor, const Options& options) : descriptor_(descriptor) { vars_["classname"] = descriptor_->name(); + vars_["file_namespace"] = FileLevelNamespace(descriptor_->file()->name()); vars_["full_name"] = descriptor_->full_name(); if (options.dllexport_decl.empty()) { vars_["dllexport"] = ""; @@ -178,8 +179,8 @@ void ServiceGenerator::GenerateImplementation(io::Printer* printer) { "$classname$::~$classname$() {}\n" "\n" "const ::google::protobuf::ServiceDescriptor* $classname$::descriptor() {\n" - " protobuf_AssignDescriptorsOnce();\n" - " return file_level_service_descriptors[$index$];\n" + " $file_namespace$::protobuf_AssignDescriptorsOnce();\n" + " return $file_namespace$::file_level_service_descriptors[$index$];\n" "}\n" "\n" "const ::google::protobuf::ServiceDescriptor* $classname$::GetDescriptor() {\n" @@ -241,7 +242,7 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { " ::google::protobuf::Message* response,\n" " ::google::protobuf::Closure* done) {\n" " GOOGLE_DCHECK_EQ(method->service(), " - "file_level_service_descriptors[$index$]);\n" + "$file_namespace$::file_level_service_descriptors[$index$]);\n" " switch(method->index()) {\n"); for (int i = 0; i < descriptor_->method_count(); i++) { diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 2874de7d..359e5e26 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -762,7 +762,7 @@ void StringOneofFieldGenerator:: GenerateConstructorCode(io::Printer* printer) const { printer->Print( variables_, - "$classname$_default_oneof_instance_.$name$_.UnsafeSetDefault(\n" + "_$classname$_default_instance_.$name$_.UnsafeSetDefault(\n" " $default_variable$);\n"); } @@ -838,9 +838,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const { "$deprecated_attr$void add_$name$(const ::std::string& value);\n" "$deprecated_attr$void add_$name$(const char* value);\n" "$deprecated_attr$void add_$name$(const $pointer_type$* value, size_t size)" - ";\n"); - - printer->Print(variables_, + ";\n" "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() " "const;\n" "$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()" @@ -898,8 +896,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" " $name$_.Add()->assign(reinterpret_cast<const char*>(value), size);\n" " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" - "}\n"); - printer->Print(variables, + "}\n" "$inline$const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_list:$full_name$)\n" |