| Index: third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc
|
| index 4eb89f432064f78065b4bbaf07ca960e1c74cf41..b86f080294c5dd7461d6adb4dc5a13bcdd9bd1d9 100644
|
| --- a/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc
|
| @@ -1,6 +1,6 @@
|
| // Protocol Buffers - Google's data interchange format
|
| // Copyright 2008 Google Inc. All rights reserved.
|
| -// http://code.google.com/p/protobuf/
|
| +// 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
|
| @@ -33,6 +33,13 @@
|
| // Sanjay Ghemawat, Jeff Dean, and others.
|
|
|
| #include <google/protobuf/compiler/cpp/cpp_file.h>
|
| +#include <map>
|
| +#include <memory>
|
| +#ifndef _SHARED_PTR_H
|
| +#include <google/protobuf/stubs/shared_ptr.h>
|
| +#endif
|
| +#include <set>
|
| +
|
| #include <google/protobuf/compiler/cpp/cpp_enum.h>
|
| #include <google/protobuf/compiler/cpp/cpp_service.h>
|
| #include <google/protobuf/compiler/cpp/cpp_extension.h>
|
| @@ -50,18 +57,17 @@ namespace cpp {
|
|
|
| // ===================================================================
|
|
|
| -FileGenerator::FileGenerator(const FileDescriptor* file,
|
| - const Options& options)
|
| - : file_(file),
|
| - message_generators_(
|
| - new scoped_ptr<MessageGenerator>[file->message_type_count()]),
|
| - enum_generators_(
|
| - new scoped_ptr<EnumGenerator>[file->enum_type_count()]),
|
| - service_generators_(
|
| - new scoped_ptr<ServiceGenerator>[file->service_count()]),
|
| - extension_generators_(
|
| - new scoped_ptr<ExtensionGenerator>[file->extension_count()]),
|
| - options_(options) {
|
| +FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
|
| + : file_(file),
|
| + message_generators_(
|
| + new google::protobuf::scoped_ptr<MessageGenerator>[file->message_type_count()]),
|
| + enum_generators_(
|
| + new google::protobuf::scoped_ptr<EnumGenerator>[file->enum_type_count()]),
|
| + service_generators_(
|
| + new google::protobuf::scoped_ptr<ServiceGenerator>[file->service_count()]),
|
| + extension_generators_(
|
| + new google::protobuf::scoped_ptr<ExtensionGenerator>[file->extension_count()]),
|
| + options_(options) {
|
|
|
| for (int i = 0; i < file->message_type_count(); i++) {
|
| message_generators_[i].reset(
|
| @@ -88,178 +94,126 @@ FileGenerator::FileGenerator(const FileDescriptor* file,
|
|
|
| FileGenerator::~FileGenerator() {}
|
|
|
| -void FileGenerator::GenerateHeader(io::Printer* printer) {
|
| +void FileGenerator::GenerateProtoHeader(io::Printer* printer) {
|
| + if (!options_.proto_h) {
|
| + return;
|
| + }
|
| +
|
| string filename_identifier = FilenameIdentifier(file_->name());
|
| + GenerateTopHeaderGuard(printer, filename_identifier);
|
|
|
| - // Generate top of header.
|
| - printer->Print(
|
| - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
| - "// source: $filename$\n"
|
| - "\n"
|
| - "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
|
| - "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
|
| - "\n"
|
| - "#include <string>\n"
|
| - "\n",
|
| - "filename", file_->name(),
|
| - "filename_identifier", filename_identifier);
|
|
|
| + GenerateLibraryIncludes(printer);
|
|
|
| - printer->Print(
|
| - "#include <google/protobuf/stubs/common.h>\n"
|
| - "\n");
|
| + for (int i = 0; i < file_->public_dependency_count(); i++) {
|
| + const FileDescriptor* dep = file_->public_dependency(i);
|
| + const char* extension = ".proto.h";
|
| + string dependency = StripProto(dep->name()) + extension;
|
| + printer->Print(
|
| + "#include \"$dependency$\" // IWYU pragma: export\n",
|
| + "dependency", dependency);
|
| + }
|
|
|
| - // Verify the protobuf library header version is compatible with the protoc
|
| - // version before going any further.
|
| printer->Print(
|
| - "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
|
| - "#error This file was generated by a newer version of protoc which is\n"
|
| - "#error incompatible with your Protocol Buffer headers. Please update\n"
|
| - "#error your headers.\n"
|
| - "#endif\n"
|
| - "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
|
| - "#error This file was generated by an older version of protoc which is\n"
|
| - "#error incompatible with your Protocol Buffer headers. Please\n"
|
| - "#error regenerate this file with a newer version of protoc.\n"
|
| - "#endif\n"
|
| - "\n",
|
| - "min_header_version",
|
| - SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
|
| - "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
|
| + "// @@protoc_insertion_point(includes)\n");
|
|
|
| - // OK, it's now safe to #include other files.
|
| - printer->Print(
|
| - "#include <google/protobuf/generated_message_util.h>\n");
|
| - if (file_->message_type_count() > 0) {
|
| - if (HasDescriptorMethods(file_)) {
|
| - printer->Print(
|
| - "#include <google/protobuf/message.h>\n");
|
| - } else {
|
| - printer->Print(
|
| - "#include <google/protobuf/message_lite.h>\n");
|
| - }
|
| - }
|
| - printer->Print(
|
| - "#include <google/protobuf/repeated_field.h>\n"
|
| - "#include <google/protobuf/extension_set.h>\n");
|
|
|
| - if (HasUnknownFields(file_)) {
|
| - printer->Print(
|
| - "#include <google/protobuf/unknown_field_set.h>\n");
|
| - }
|
| + GenerateForwardDeclarations(printer);
|
|
|
| - if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) {
|
| - printer->Print(
|
| - "#include <google/protobuf/generated_enum_reflection.h>\n");
|
| - }
|
| + // Open namespace.
|
| + GenerateNamespaceOpeners(printer);
|
|
|
| - if (HasGenericServices(file_)) {
|
| - printer->Print(
|
| - "#include <google/protobuf/service.h>\n");
|
| - }
|
| + GenerateGlobalStateFunctionDeclarations(printer);
|
|
|
| - if (HasUnknownFields(file_) && file_->message_type_count() > 0) {
|
| - printer->Print(
|
| - "#include <google/protobuf/unknown_field_set.h>\n");
|
| - }
|
| + printer->Print("\n");
|
|
|
| + GenerateEnumDefinitions(printer);
|
|
|
| - for (int i = 0; i < file_->dependency_count(); i++) {
|
| - printer->Print(
|
| - "#include \"$dependency$.pb.h\"\n",
|
| - "dependency", StripProto(file_->dependency(i)->name()));
|
| - }
|
| + printer->Print(kThickSeparator);
|
| + printer->Print("\n");
|
|
|
| + GenerateMessageDefinitions(printer);
|
|
|
| - printer->Print(
|
| - "// @@protoc_insertion_point(includes)\n");
|
| + printer->Print("\n");
|
| + printer->Print(kThickSeparator);
|
| + printer->Print("\n");
|
|
|
| + GenerateServiceDefinitions(printer);
|
|
|
| - // Open namespace.
|
| - GenerateNamespaceOpeners(printer);
|
| + GenerateExtensionIdentifiers(printer);
|
| +
|
| + printer->Print("\n");
|
| + printer->Print(kThickSeparator);
|
| + printer->Print("\n");
|
| +
|
| + GenerateInlineFunctionDefinitions(printer);
|
|
|
| - // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
|
| - // functions, so that we can declare them to be friends of each class.
|
| printer->Print(
|
| "\n"
|
| - "// Internal implementation detail -- do not call these.\n"
|
| - "void $dllexport_decl$ $adddescriptorsname$();\n",
|
| - "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
|
| - "dllexport_decl", options_.dllexport_decl);
|
| + "// @@protoc_insertion_point(namespace_scope)\n"
|
| + "\n");
|
| +
|
| + // Close up namespace.
|
| + GenerateNamespaceClosers(printer);
|
| +
|
| + // We need to specialize some templates in the ::google::protobuf namespace:
|
| + GenerateProto2NamespaceEnumSpecializations(printer);
|
|
|
| printer->Print(
|
| - // Note that we don't put dllexport_decl on these because they are only
|
| - // called by the .pb.cc file in which they are defined.
|
| - "void $assigndescriptorsname$();\n"
|
| - "void $shutdownfilename$();\n"
|
| - "\n",
|
| - "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
|
| - "shutdownfilename", GlobalShutdownFileName(file_->name()));
|
| + "\n"
|
| + "// @@protoc_insertion_point(global_scope)\n"
|
| + "\n");
|
|
|
| - // Generate forward declarations of classes.
|
| - for (int i = 0; i < file_->message_type_count(); i++) {
|
| - message_generators_[i]->GenerateForwardDeclaration(printer);
|
| - }
|
| + GenerateBottomHeaderGuard(printer, filename_identifier);
|
| +}
|
|
|
| - printer->Print("\n");
|
| +void FileGenerator::GeneratePBHeader(io::Printer* printer) {
|
| + string filename_identifier =
|
| + FilenameIdentifier(file_->name() + (options_.proto_h ? ".pb.h" : ""));
|
| + GenerateTopHeaderGuard(printer, filename_identifier);
|
|
|
| - // Generate enum definitions.
|
| - for (int i = 0; i < file_->message_type_count(); i++) {
|
| - message_generators_[i]->GenerateEnumDefinitions(printer);
|
| - }
|
| - for (int i = 0; i < file_->enum_type_count(); i++) {
|
| - enum_generators_[i]->GenerateDefinition(printer);
|
| + if (options_.proto_h) {
|
| + printer->Print("#include \"$basename$.proto.h\" // IWYU pragma: export\n",
|
| + "basename", StripProto(file_->name()));
|
| + } else {
|
| + GenerateLibraryIncludes(printer);
|
| }
|
| + GenerateDependencyIncludes(printer);
|
|
|
| - printer->Print(kThickSeparator);
|
| - printer->Print("\n");
|
| + printer->Print(
|
| + "// @@protoc_insertion_point(includes)\n");
|
|
|
| - // Generate class definitions.
|
| - for (int i = 0; i < file_->message_type_count(); i++) {
|
| - if (i > 0) {
|
| - printer->Print("\n");
|
| - printer->Print(kThinSeparator);
|
| - printer->Print("\n");
|
| - }
|
| - message_generators_[i]->GenerateClassDefinition(printer);
|
| - }
|
|
|
| - printer->Print("\n");
|
| - printer->Print(kThickSeparator);
|
| - printer->Print("\n");
|
|
|
| - if (HasGenericServices(file_)) {
|
| - // Generate service definitions.
|
| - for (int i = 0; i < file_->service_count(); i++) {
|
| - if (i > 0) {
|
| - printer->Print("\n");
|
| - printer->Print(kThinSeparator);
|
| - printer->Print("\n");
|
| - }
|
| - service_generators_[i]->GenerateDeclarations(printer);
|
| - }
|
| + // Open namespace.
|
| + GenerateNamespaceOpeners(printer);
|
| +
|
| + if (!options_.proto_h) {
|
| + GenerateGlobalStateFunctionDeclarations(printer);
|
| + GenerateMessageForwardDeclarations(printer);
|
|
|
| printer->Print("\n");
|
| +
|
| + GenerateEnumDefinitions(printer);
|
| +
|
| printer->Print(kThickSeparator);
|
| printer->Print("\n");
|
| - }
|
|
|
| - // Declare extension identifiers.
|
| - for (int i = 0; i < file_->extension_count(); i++) {
|
| - extension_generators_[i]->GenerateDeclaration(printer);
|
| - }
|
| + GenerateMessageDefinitions(printer);
|
|
|
| - printer->Print("\n");
|
| - printer->Print(kThickSeparator);
|
| - printer->Print("\n");
|
| + printer->Print("\n");
|
| + printer->Print(kThickSeparator);
|
| + printer->Print("\n");
|
|
|
| - // Generate class inline methods.
|
| - for (int i = 0; i < file_->message_type_count(); i++) {
|
| - if (i > 0) {
|
| - printer->Print(kThinSeparator);
|
| - printer->Print("\n");
|
| - }
|
| - message_generators_[i]->GenerateInlineMethods(printer);
|
| + GenerateServiceDefinitions(printer);
|
| +
|
| + GenerateExtensionIdentifiers(printer);
|
| +
|
| + printer->Print("\n");
|
| + printer->Print(kThickSeparator);
|
| + printer->Print("\n");
|
| +
|
| + GenerateInlineFunctionDefinitions(printer);
|
| }
|
|
|
| printer->Print(
|
| @@ -269,27 +223,9 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
| // Close up namespace.
|
| GenerateNamespaceClosers(printer);
|
|
|
| - // Emit GetEnumDescriptor specializations into google::protobuf namespace:
|
| - if (HasDescriptorMethods(file_)) {
|
| - // The SWIG conditional is to avoid a null-pointer dereference
|
| - // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
|
| - // namespace X { void Y<Z::W>(); }
|
| - // which appears in GetEnumDescriptor() specializations.
|
| - printer->Print(
|
| - "\n"
|
| - "#ifndef SWIG\n"
|
| - "namespace google {\nnamespace protobuf {\n"
|
| - "\n");
|
| - for (int i = 0; i < file_->message_type_count(); i++) {
|
| - message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
| - }
|
| - for (int i = 0; i < file_->enum_type_count(); i++) {
|
| - enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
| - }
|
| - printer->Print(
|
| - "\n"
|
| - "} // namespace google\n} // namespace protobuf\n"
|
| - "#endif // SWIG\n");
|
| + if (!options_.proto_h) {
|
| + // We need to specialize some templates in the ::google::protobuf namespace:
|
| + GenerateProto2NamespaceEnumSpecializations(printer);
|
| }
|
|
|
| printer->Print(
|
| @@ -297,30 +233,39 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
|
| "// @@protoc_insertion_point(global_scope)\n"
|
| "\n");
|
|
|
| - printer->Print(
|
| - "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
|
| - "filename_identifier", filename_identifier);
|
| + GenerateBottomHeaderGuard(printer, filename_identifier);
|
| }
|
|
|
| void FileGenerator::GenerateSource(io::Printer* printer) {
|
| + bool well_known = IsWellKnownMessage(file_);
|
| + string header =
|
| + StripProto(file_->name()) + (options_.proto_h ? ".proto.h" : ".pb.h");
|
| printer->Print(
|
| "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
| "// source: $filename$\n"
|
| "\n"
|
| -
|
| // The generated code calls accessors that might be deprecated. We don't
|
| // want the compiler to warn in generated code.
|
| "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n"
|
| - "#include \"$basename$.pb.h\"\n"
|
| + "#include $left$$header$$right$\n"
|
| "\n"
|
| "#include <algorithm>\n" // for swap()
|
| "\n"
|
| "#include <google/protobuf/stubs/common.h>\n"
|
| + "#include <google/protobuf/stubs/port.h>\n"
|
| "#include <google/protobuf/stubs/once.h>\n"
|
| "#include <google/protobuf/io/coded_stream.h>\n"
|
| "#include <google/protobuf/wire_format_lite_inl.h>\n",
|
| "filename", file_->name(),
|
| - "basename", StripProto(file_->name()));
|
| + "header", header,
|
| + "left", well_known ? "<" : "\"",
|
| + "right", well_known ? ">" : "\"");
|
| +
|
| + // Unknown fields implementation in lite mode uses StringOutputStream
|
| + if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
|
| + printer->Print(
|
| + "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
|
| + }
|
|
|
| if (HasDescriptorMethods(file_)) {
|
| printer->Print(
|
| @@ -330,6 +275,18 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
| "#include <google/protobuf/wire_format.h>\n");
|
| }
|
|
|
| + if (options_.proto_h) {
|
| + // Use the smaller .proto.h files.
|
| + for (int i = 0; i < file_->dependency_count(); i++) {
|
| + const FileDescriptor* dep = file_->dependency(i);
|
| + const char* extension = ".proto.h";
|
| + string dependency = StripProto(dep->name()) + extension;
|
| + printer->Print(
|
| + "#include \"$dependency$\"\n",
|
| + "dependency", dependency);
|
| + }
|
| + }
|
| +
|
| printer->Print(
|
| "// @@protoc_insertion_point(includes)\n");
|
|
|
| @@ -374,10 +331,29 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
|
|
| // Generate classes.
|
| for (int i = 0; i < file_->message_type_count(); i++) {
|
| + if (i == 0 && HasGeneratedMethods(file_)) {
|
| + printer->Print(
|
| + "\n"
|
| + "namespace {\n"
|
| + "\n"
|
| + "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
|
| + "GOOGLE_ATTRIBUTE_NOINLINE static void MergeFromFail(int line) {\n"
|
| + " GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n"
|
| + "}\n"
|
| + "\n"
|
| + "} // namespace\n"
|
| + "\n");
|
| + }
|
| printer->Print("\n");
|
| printer->Print(kThickSeparator);
|
| printer->Print("\n");
|
| message_generators_[i]->GenerateClassMethods(printer);
|
| +
|
| + printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n");
|
| + // Generate class inline methods.
|
| + message_generators_[i]->GenerateInlineMethods(printer,
|
| + /* is_inline = */ false);
|
| + printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n");
|
| }
|
|
|
| if (HasGenericServices(file_)) {
|
| @@ -406,6 +382,59 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
|
| "// @@protoc_insertion_point(global_scope)\n");
|
| }
|
|
|
| +class FileGenerator::ForwardDeclarations {
|
| + public:
|
| + ~ForwardDeclarations() {
|
| + for (map<string, ForwardDeclarations *>::iterator it = namespaces_.begin(),
|
| + end = namespaces_.end();
|
| + it != end; ++it) {
|
| + delete it->second;
|
| + }
|
| + namespaces_.clear();
|
| + }
|
| +
|
| + ForwardDeclarations* AddOrGetNamespace(const string& ns_name) {
|
| + ForwardDeclarations*& ns = namespaces_[ns_name];
|
| + if (ns == NULL) {
|
| + ns = new ForwardDeclarations;
|
| + }
|
| + return ns;
|
| + }
|
| +
|
| + set<string>& classes() { return classes_; }
|
| + set<string>& enums() { return enums_; }
|
| +
|
| + void Print(io::Printer* printer) const {
|
| + for (set<string>::const_iterator it = enums_.begin(), end = enums_.end();
|
| + it != end; ++it) {
|
| + printer->Print("enum $enumname$ : int;\n"
|
| + "bool $enumname$_IsValid(int value);\n",
|
| + "enumname", it->c_str());
|
| + }
|
| + for (set<string>::const_iterator it = classes_.begin(),
|
| + end = classes_.end();
|
| + it != end; ++it) {
|
| + printer->Print("class $classname$;\n", "classname", it->c_str());
|
| + }
|
| + for (map<string, ForwardDeclarations *>::const_iterator
|
| + it = namespaces_.begin(),
|
| + end = namespaces_.end();
|
| + it != end; ++it) {
|
| + printer->Print("namespace $nsname$ {\n",
|
| + "nsname", it->first);
|
| + it->second->Print(printer);
|
| + printer->Print("} // namespace $nsname$\n",
|
| + "nsname", it->first);
|
| + }
|
| + }
|
| +
|
| +
|
| + private:
|
| + map<string, ForwardDeclarations*> namespaces_;
|
| + set<string> classes_;
|
| + set<string> enums_;
|
| +};
|
| +
|
| void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
| // AddDescriptors() is a file-level procedure which adds the encoded
|
| // FileDescriptorProto for this .proto file to the global DescriptorPool for
|
| @@ -547,17 +576,12 @@ 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.
|
| - vector<string> dependency_package_parts;
|
| - SplitStringUsing(dependency->package(), ".", &dependency_package_parts);
|
| - printer->Print("::");
|
| - for (int j = 0; j < dependency_package_parts.size(); j++) {
|
| - printer->Print("$name$::",
|
| - "name", dependency_package_parts[j]);
|
| - }
|
| + string add_desc_name = QualifiedFileLevelSymbol(
|
| + dependency->package(), GlobalAddDescriptorsName(dependency->name()));
|
| // Call its AddDescriptors function.
|
| printer->Print(
|
| "$name$();\n",
|
| - "name", GlobalAddDescriptorsName(dependency->name()));
|
| + "name", add_desc_name);
|
| }
|
|
|
| if (HasDescriptorMethods(file_)) {
|
| @@ -569,20 +593,60 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
|
| string file_data;
|
| file_proto.SerializeToString(&file_data);
|
|
|
| - printer->Print(
|
| - "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
|
| -
|
| - // Only write 40 bytes per line.
|
| - static const int kBytesPerLine = 40;
|
| - for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
|
| - printer->Print("\n \"$data$\"",
|
| - "data",
|
| - EscapeTrigraphs(
|
| - CEscape(file_data.substr(i, kBytesPerLine))));
|
| +#ifdef _MSC_VER
|
| + bool breakdown_large_file = true;
|
| +#else
|
| + bool breakdown_large_file = false;
|
| +#endif
|
| + // 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.
|
| + if (breakdown_large_file && file_data.size() > 65535) {
|
| + // This has to be explicitly marked as a signed char because the generated
|
| + // code puts negative values in the array, and sometimes plain char is
|
| + // unsigned. That implicit narrowing conversion is not allowed in C++11.
|
| + // <http://stackoverflow.com/questions/4434140/narrowing-conversions-in-c0x-is-it-just-me-or-does-this-sound-like-a-breakin>
|
| + // has details on why.
|
| + printer->Print(
|
| + "static const signed char descriptor[] = {\n");
|
| + printer->Indent();
|
| +
|
| + // Only write 25 bytes per line.
|
| + static const int kBytesPerLine = 25;
|
| + for (int i = 0; i < file_data.size();) {
|
| + for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
|
| + printer->Print(
|
| + "$char$, ",
|
| + "char", SimpleItoa(file_data[i]));
|
| + }
|
| + printer->Print(
|
| + "\n");
|
| + }
|
| +
|
| + printer->Outdent();
|
| + printer->Print(
|
| + "};\n");
|
| +
|
| + printer->Print(
|
| + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n",
|
| + "size", SimpleItoa(file_data.size()));
|
| +
|
| + } else {
|
| + printer->Print(
|
| + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(");
|
| +
|
| + // Only write 40 bytes per line.
|
| + static const int kBytesPerLine = 40;
|
| + for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
|
| + printer->Print("\n \"$data$\"",
|
| + "data",
|
| + EscapeTrigraphs(
|
| + CEscape(file_data.substr(i, kBytesPerLine))));
|
| }
|
| printer->Print(
|
| ", $size$);\n",
|
| - "size", SimpleItoa(file_data.size()));
|
| + "size", SimpleItoa(file_data.size()));
|
| + }
|
|
|
| // Call MessageFactory::InternalRegisterGeneratedFile().
|
| printer->Print(
|
| @@ -651,6 +715,328 @@ void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) {
|
| }
|
| }
|
|
|
| +void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
|
| + ForwardDeclarations decls;
|
| + for (int i = 0; i < file_->dependency_count(); i++) {
|
| + FileGenerator dependency(file_->dependency(i), options_);
|
| + dependency.FillForwardDeclarations(&decls);
|
| + }
|
| + FillForwardDeclarations(&decls);
|
| + decls.Print(printer);
|
| +}
|
| +
|
| +void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
|
| + for (int i = 0; i < file_->public_dependency_count(); i++) {
|
| + FileGenerator dependency(file_->public_dependency(i), options_);
|
| + dependency.FillForwardDeclarations(decls);
|
| + }
|
| + for (int i = 0; i < package_parts_.size(); i++) {
|
| + decls = decls->AddOrGetNamespace(package_parts_[i]);
|
| + }
|
| + // Generate enum definitions.
|
| + for (int i = 0; i < file_->message_type_count(); i++) {
|
| + message_generators_[i]->FillEnumForwardDeclarations(&decls->enums());
|
| + }
|
| + for (int i = 0; i < file_->enum_type_count(); i++) {
|
| + enum_generators_[i]->FillForwardDeclaration(&decls->enums());
|
| + }
|
| + // Generate forward declarations of classes.
|
| + for (int i = 0; i < file_->message_type_count(); i++) {
|
| + message_generators_[i]->FillMessageForwardDeclarations(
|
| + &decls->classes());
|
| + }
|
| +}
|
| +
|
| +void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer,
|
| + const string& filename_identifier) {
|
| + // Generate top of header.
|
| + printer->Print(
|
| + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
|
| + "// source: $filename$\n"
|
| + "\n"
|
| + "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n"
|
| + "#define PROTOBUF_$filename_identifier$__INCLUDED\n"
|
| + "\n"
|
| + "#include <string>\n"
|
| + "\n",
|
| + "filename", file_->name(),
|
| + "filename_identifier", filename_identifier);
|
| +}
|
| +
|
| +void FileGenerator::GenerateBottomHeaderGuard(
|
| + io::Printer* printer, const string& filename_identifier) {
|
| + printer->Print(
|
| + "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n",
|
| + "filename_identifier", filename_identifier);
|
| +}
|
| +
|
| +void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
|
| +
|
| + printer->Print(
|
| + "#include <google/protobuf/stubs/common.h>\n"
|
| + "\n");
|
| +
|
| + // Verify the protobuf library header version is compatible with the protoc
|
| + // version before going any further.
|
| + printer->Print(
|
| + "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n"
|
| + "#error This file was generated by a newer version of protoc which is\n"
|
| + "#error incompatible with your Protocol Buffer headers. Please update\n"
|
| + "#error your headers.\n"
|
| + "#endif\n"
|
| + "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n"
|
| + "#error This file was generated by an older version of protoc which is\n"
|
| + "#error incompatible with your Protocol Buffer headers. Please\n"
|
| + "#error regenerate this file with a newer version of protoc.\n"
|
| + "#endif\n"
|
| + "\n",
|
| + "min_header_version",
|
| + SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc),
|
| + "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION));
|
| +
|
| + // 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");
|
| + if (UseUnknownFieldSet(file_)) {
|
| + printer->Print(
|
| + "#include <google/protobuf/metadata.h>\n");
|
| + }
|
| + if (file_->message_type_count() > 0) {
|
| + if (HasDescriptorMethods(file_)) {
|
| + printer->Print(
|
| + "#include <google/protobuf/message.h>\n");
|
| + } else {
|
| + printer->Print(
|
| + "#include <google/protobuf/message_lite.h>\n");
|
| + }
|
| + }
|
| + printer->Print(
|
| + "#include <google/protobuf/repeated_field.h>\n"
|
| + "#include <google/protobuf/extension_set.h>\n");
|
| + if (HasMapFields(file_)) {
|
| + printer->Print(
|
| + "#include <google/protobuf/map.h>\n");
|
| + if (HasDescriptorMethods(file_)) {
|
| + printer->Print(
|
| + "#include <google/protobuf/map_field_inl.h>\n");
|
| + } else {
|
| + printer->Print(
|
| + "#include <google/protobuf/map_field_lite.h>\n");
|
| + }
|
| + }
|
| +
|
| + if (HasEnumDefinitions(file_)) {
|
| + if (HasDescriptorMethods(file_)) {
|
| + printer->Print(
|
| + "#include <google/protobuf/generated_enum_reflection.h>\n");
|
| + } else {
|
| + printer->Print(
|
| + "#include <google/protobuf/generated_enum_util.h>\n");
|
| + }
|
| + }
|
| +
|
| + if (HasGenericServices(file_)) {
|
| + printer->Print(
|
| + "#include <google/protobuf/service.h>\n");
|
| + }
|
| +
|
| + if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
|
| + printer->Print(
|
| + "#include <google/protobuf/unknown_field_set.h>\n");
|
| + }
|
| +
|
| +
|
| + if (IsAnyMessage(file_)) {
|
| + printer->Print(
|
| + "#include <google/protobuf/any.h>\n");
|
| + }
|
| +}
|
| +
|
| +void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
|
| + set<string> public_import_names;
|
| + for (int i = 0; i < file_->public_dependency_count(); i++) {
|
| + public_import_names.insert(file_->public_dependency(i)->name());
|
| + }
|
| +
|
| + for (int i = 0; i < file_->dependency_count(); i++) {
|
| + bool well_known = IsWellKnownMessage(file_->dependency(i));
|
| + const string& name = file_->dependency(i)->name();
|
| + bool public_import = (public_import_names.count(name) != 0);
|
| +
|
| + printer->Print(
|
| + "#include $left$$dependency$.pb.h$right$$iwyu$\n",
|
| + "dependency", StripProto(name),
|
| + "iwyu", (public_import) ? " // IWYU pragma: export" : "",
|
| + "left", well_known ? "<" : "\"",
|
| + "right", well_known ? ">" : "\"");
|
| + }
|
| +}
|
| +
|
| +void FileGenerator::GenerateGlobalStateFunctionDeclarations(
|
| + io::Printer* printer) {
|
| + // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
|
| + // functions, so that we can declare them to be friends of each class.
|
| + printer->Print(
|
| + "\n"
|
| + "// Internal implementation detail -- do not call these.\n"
|
| + "void $dllexport_decl$$adddescriptorsname$();\n",
|
| + "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
|
| + "dllexport_decl",
|
| + options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
|
| +
|
| + printer->Print(
|
| + // Note that we don't put dllexport_decl on these because they are only
|
| + // called by the .pb.cc file in which they are defined.
|
| + "void $assigndescriptorsname$();\n"
|
| + "void $shutdownfilename$();\n"
|
| + "\n",
|
| + "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()),
|
| + "shutdownfilename", GlobalShutdownFileName(file_->name()));
|
| +}
|
| +
|
| +void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) {
|
| + set<string> classes;
|
| + for (int i = 0; i < file_->message_type_count(); i++) {
|
| + message_generators_[i]->FillMessageForwardDeclarations(&classes);
|
| + }
|
| + for (set<string>::const_iterator it = classes.begin(), end = classes.end();
|
| + it != end; ++it) {
|
| + printer->Print("class $classname$;\n", "classname", it->c_str());
|
| + }
|
| +}
|
| +
|
| +void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
|
| + // Generate class definitions.
|
| + for (int i = 0; i < file_->message_type_count(); i++) {
|
| + if (i > 0) {
|
| + printer->Print("\n");
|
| + printer->Print(kThinSeparator);
|
| + printer->Print("\n");
|
| + }
|
| + message_generators_[i]->GenerateClassDefinition(printer);
|
| + }
|
| +}
|
| +
|
| +void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
|
| + // Generate enum definitions.
|
| + for (int i = 0; i < file_->message_type_count(); i++) {
|
| + message_generators_[i]->GenerateEnumDefinitions(printer);
|
| + }
|
| + for (int i = 0; i < file_->enum_type_count(); i++) {
|
| + enum_generators_[i]->GenerateDefinition(printer);
|
| + }
|
| +}
|
| +
|
| +void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
|
| + if (HasGenericServices(file_)) {
|
| + // Generate service definitions.
|
| + for (int i = 0; i < file_->service_count(); i++) {
|
| + if (i > 0) {
|
| + printer->Print("\n");
|
| + printer->Print(kThinSeparator);
|
| + printer->Print("\n");
|
| + }
|
| + service_generators_[i]->GenerateDeclarations(printer);
|
| + }
|
| +
|
| + printer->Print("\n");
|
| + printer->Print(kThickSeparator);
|
| + printer->Print("\n");
|
| + }
|
| +}
|
| +
|
| +void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
|
| + // Declare extension identifiers.
|
| + for (int i = 0; i < file_->extension_count(); i++) {
|
| + extension_generators_[i]->GenerateDeclaration(printer);
|
| + }
|
| +}
|
| +
|
| +void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
|
| + // An aside about inline functions in .proto.h mode:
|
| + //
|
| + // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally
|
| + // moving much of the inline functions to the .pb.cc file, which can be a
|
| + // significant performance benefit for compilation time, at the expense
|
| + // of non-inline function calls.
|
| + //
|
| + // However, in .proto.h mode, the definition of the internal dependent
|
| + // base class must remain in the header, and can never be out-lined. The
|
| + // dependent base class also needs access to has-bit manipuation
|
| + // functions, so the has-bit functions must be unconditionally inlined in
|
| + // proto_h mode.
|
| + //
|
| + // This gives us three flavors of functions:
|
| + //
|
| + // 1. Functions on the message not used by the internal dependent base
|
| + // class: in .proto.h mode, only some functions are defined on the
|
| + // message class; others are defined on the dependent base class.
|
| + // These are guarded and can be out-lined. These are generated by
|
| + // GenerateInlineMethods, and include has_* bit functions in
|
| + // non-proto_h mode.
|
| + //
|
| + // 2. Functions on the internal dependent base class: these functions
|
| + // are dependent on a template parameter, so they always need to
|
| + // remain in the header.
|
| + //
|
| + // 3. Functions on the message that are used by the dependent base: the
|
| + // dependent base class down casts itself to the message
|
| + // implementation class to access these functions (the has_* bit
|
| + // manipulation functions). Unlike #1, these functions must
|
| + // unconditionally remain in the header. These are emitted by
|
| + // GenerateDependentInlineMethods, even though they are not actually
|
| + // dependent.
|
| +
|
| + printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
|
| + // Generate class inline methods.
|
| + for (int i = 0; i < file_->message_type_count(); i++) {
|
| + if (i > 0) {
|
| + printer->Print(kThinSeparator);
|
| + printer->Print("\n");
|
| + }
|
| + message_generators_[i]->GenerateInlineMethods(printer,
|
| + /* is_inline = */ true);
|
| + }
|
| + printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
|
| +
|
| + for (int i = 0; i < file_->message_type_count(); i++) {
|
| + if (i > 0) {
|
| + printer->Print(kThinSeparator);
|
| + printer->Print("\n");
|
| + }
|
| + // Methods of the dependent base class must always be inline in the header.
|
| + message_generators_[i]->GenerateDependentInlineMethods(printer);
|
| + }
|
| +}
|
| +
|
| +void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
|
| + io::Printer* printer) {
|
| + // Emit GetEnumDescriptor specializations into google::protobuf namespace:
|
| + if (HasEnumDefinitions(file_)) {
|
| + // The SWIG conditional is to avoid a null-pointer dereference
|
| + // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
|
| + // namespace X { void Y<Z::W>(); }
|
| + // which appears in GetEnumDescriptor() specializations.
|
| + printer->Print(
|
| + "\n"
|
| + "#ifndef SWIG\n"
|
| + "namespace google {\nnamespace protobuf {\n"
|
| + "\n");
|
| + for (int i = 0; i < file_->message_type_count(); i++) {
|
| + message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
| + }
|
| + for (int i = 0; i < file_->enum_type_count(); i++) {
|
| + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
|
| + }
|
| + printer->Print(
|
| + "\n"
|
| + "} // namespace protobuf\n} // namespace google\n"
|
| + "#endif // SWIG\n");
|
| + }
|
| +}
|
| +
|
| } // namespace cpp
|
| } // namespace compiler
|
| } // namespace protobuf
|
|
|