aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler')
-rw-r--r--src/google/protobuf/compiler/code_generator.cc28
-rw-r--r--src/google/protobuf/compiler/code_generator.h41
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc59
-rw-r--r--src/google/protobuf/compiler/command_line_interface.h5
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc86
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc39
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_extension.cc30
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h7
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc163
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc41
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h19
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc855
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h10
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc49
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc47
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc104
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc6
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc2
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.cc38
-rw-r--r--src/google/protobuf/compiler/java/java_map_field_lite.cc6
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc2
-rw-r--r--src/google/protobuf/compiler/java/java_message_builder.cc13
-rw-r--r--src/google/protobuf/compiler/java/java_message_field_lite.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_message_lite.cc4
-rw-r--r--src/google/protobuf/compiler/java/java_service.cc20
-rw-r--r--src/google/protobuf/compiler/java/java_service.h3
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.cc2
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.cc777
-rwxr-xr-xsrc/google/protobuf/compiler/js/js_generator.h87
-rw-r--r--src/google/protobuf/compiler/main.cc10
-rw-r--r--src/google/protobuf/compiler/plugin.cc39
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc340
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h47
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc19
40 files changed, 1865 insertions, 1143 deletions
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index 473eb4e6..f6ff1e5d 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -36,6 +36,7 @@
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
@@ -43,6 +44,33 @@ namespace protobuf {
namespace compiler {
CodeGenerator::~CodeGenerator() {}
+
+bool CodeGenerator::GenerateAll(
+ const vector<const FileDescriptor*>& files,
+ const string& parameter,
+ GeneratorContext* generator_context,
+ string* error) const {
+ // Default implemenation is just to call the per file method, and prefix any
+ // error string with the file to provide context.
+ bool succeeded = true;
+ for (int i = 0; i < files.size(); i++) {
+ const FileDescriptor* file = files[i];
+ succeeded = Generate(file, parameter, generator_context, error);
+ if (!succeeded && error && error->empty()) {
+ *error = "Code generator returned false but provided no error "
+ "description.";
+ }
+ if (error && !error->empty()) {
+ *error = file->name() + ": " + *error;
+ break;
+ }
+ if (!succeeded) {
+ break;
+ }
+ }
+ return succeeded;
+}
+
GeneratorContext::~GeneratorContext() {}
io::ZeroCopyOutputStream*
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index b989f151..642bbfad 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -66,11 +66,11 @@ class LIBPROTOC_EXPORT CodeGenerator {
// Generates code for the given proto file, generating one or more files in
// the given output directory.
//
- // A parameter to be passed to the generator can be specified on the
- // command line. This is intended to be used by Java and similar languages
- // to specify which specific class from the proto file is to be generated,
- // though it could have other uses as well. It is empty if no parameter was
- // given.
+ // A parameter to be passed to the generator can be specified on the command
+ // line. This is intended to be used to pass generator specific parameters.
+ // It is empty if no parameter was given. ParseGeneratorParameter (below),
+ // can be used to accept multiple parameters within the single parameter
+ // command line flag.
//
// Returns true if successful. Otherwise, sets *error to a description of
// the problem (e.g. "invalid parameter") and returns false.
@@ -79,18 +79,11 @@ class LIBPROTOC_EXPORT CodeGenerator {
GeneratorContext* generator_context,
string* error) const = 0;
- // Generates code for all given proto files, generating one or more files in
- // the given output directory.
- //
- // This method should be called instead of |Generate()| when
- // |HasGenerateAll()| returns |true|. It is used to emulate legacy semantics
- // when more than one `.proto` file is specified on one compiler invocation.
+ // Generates code for all given proto files.
//
- // WARNING: Please do not use unless legacy semantics force the code generator
- // to produce a single output file for all input files, or otherwise require
- // an examination of all input files first. The canonical code generator
- // design produces one output file per input .proto file, and we do not wish
- // to encourage alternate designs.
+ // WARNING: The canonical code generator design produces one or two output
+ // files per input .proto file, and we do not wish to encourage alternate
+ // designs.
//
// A parameter is given as passed on the command line, as in |Generate()|
// above.
@@ -100,15 +93,13 @@ class LIBPROTOC_EXPORT CodeGenerator {
virtual bool GenerateAll(const vector<const FileDescriptor*>& files,
const string& parameter,
GeneratorContext* generator_context,
- string* error) const {
- *error = "Unimplemented GenerateAll() method.";
- return false;
- }
-
- // Returns true if the code generator expects to receive all FileDescriptors
- // at once (via |GenerateAll()|), rather than one at a time (via
- // |Generate()|). This is required to implement legacy semantics.
- virtual bool HasGenerateAll() const { return false; }
+ string* error) const;
+
+ // This is no longer used, but this class is part of the opensource protobuf
+ // library, so it has to remain to keep vtables the same for the current
+ // version of the library. When protobufs does a api breaking change, the
+ // method can be removed.
+ virtual bool HasGenerateAll() const { return true; }
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index bb781b0a..0d1c30ce 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -704,6 +704,7 @@ CommandLineInterface::CommandLineInterface()
: mode_(MODE_COMPILE),
print_mode_(PRINT_NONE),
error_format_(ERROR_FORMAT_GCC),
+ direct_dependencies_explicitly_set_(false),
imports_in_descriptor_set_(false),
source_info_in_descriptor_set_(false),
disallow_services_(false),
@@ -784,6 +785,24 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) {
"--disallow_services was used." << endl;
return 1;
}
+
+ // Enforce --direct_dependencies
+ if (direct_dependencies_explicitly_set_) {
+ bool indirect_imports = false;
+ for (int i = 0; i < parsed_file->dependency_count(); i++) {
+ if (direct_dependencies_.find(parsed_file->dependency(i)->name()) ==
+ direct_dependencies_.end()) {
+ indirect_imports = true;
+ cerr << parsed_file->name()
+ << ": File is imported but not declared in "
+ << "--direct_dependencies: "
+ << parsed_file->dependency(i)->name() << std::endl;
+ }
+ }
+ if (indirect_imports) {
+ return 1;
+ }
+ }
}
// We construct a separate GeneratorContext for each output location. Note
@@ -897,6 +916,7 @@ void CommandLineInterface::Clear() {
executable_name_.clear();
proto_path_.clear();
input_files_.clear();
+ direct_dependencies_.clear();
output_directives_.clear();
codec_type_.clear();
descriptor_set_name_.clear();
@@ -907,6 +927,7 @@ void CommandLineInterface::Clear() {
imports_in_descriptor_set_ = false;
source_info_in_descriptor_set_ = false;
disallow_services_ = false;
+ direct_dependencies_explicitly_set_ = false;
}
bool CommandLineInterface::MakeInputsBeProtoPathRelative(
@@ -1154,6 +1175,21 @@ CommandLineInterface::InterpretArgument(const string& name,
proto_path_.push_back(pair<string, string>(virtual_path, disk_path));
}
+ } else if (name == "--direct_dependencies") {
+ if (direct_dependencies_explicitly_set_) {
+ std::cerr << name << " may only be passed once. To specify multiple "
+ "direct dependencies, pass them all as a single "
+ "parameter separated by '"
+ << kPathSeparator << "'." << std::endl;
+ return PARSE_ARGUMENT_FAIL;
+ }
+
+ direct_dependencies_explicitly_set_ = true;
+ vector<string> direct = Split(
+ value, kPathSeparator, true);
+ GOOGLE_DCHECK(direct_dependencies_.empty());
+ direct_dependencies_.insert(direct.begin(), direct.end());
+
} else if (name == "-o" || name == "--descriptor_set_out") {
if (!descriptor_set_name_.empty()) {
std::cerr << name << " may only be passed once." << std::endl;
@@ -1447,24 +1483,11 @@ bool CommandLineInterface::GenerateOutput(
}
parameters.append(generator_parameters_[output_directive.name]);
}
- if (output_directive.generator->HasGenerateAll()) {
- if (!output_directive.generator->GenerateAll(
- parsed_files, parameters, generator_context, &error)) {
- // Generator returned an error.
- std::cerr << output_directive.name << ": "
- << ": " << error << std::endl;
- return false;
- }
- } else {
- for (int i = 0; i < parsed_files.size(); i++) {
- if (!output_directive.generator->Generate(parsed_files[i], parameters,
- generator_context, &error)) {
- // Generator returned an error.
- std::cerr << output_directive.name << ": " << parsed_files[i]->name()
- << ": " << error << std::endl;
- return false;
- }
- }
+ if (!output_directive.generator->GenerateAll(
+ parsed_files, parameters, generator_context, &error)) {
+ // Generator returned an error.
+ std::cerr << output_directive.name << ": " << error << std::endl;
+ return false;
}
}
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index 32084567..c38e65a3 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -352,6 +352,11 @@ class LIBPROTOC_EXPORT CommandLineInterface {
vector<pair<string, string> > proto_path_; // Search path for proto files.
vector<string> input_files_; // Names of the input proto files.
+ // Names of proto files which are allowed to be imported. Used by build
+ // systems to enforce depend-on-what-you-import.
+ set<string> direct_dependencies_;
+ bool direct_dependencies_explicitly_set_;
+
// output_directives_ lists all the files we are supposed to output and what
// generator to use for each.
struct OutputDirective {
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index dee438c6..56a07dbf 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -871,6 +871,92 @@ TEST_F(CommandLineInterfaceTest, AllowServicesHasService) {
ExpectGenerated("test_generator", "", "foo.proto", "Foo");
}
+TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing_EmptyList) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "message Foo { optional Bar bar = 1; }");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar { optional string text = 1; }");
+
+ Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
+ "--direct_dependencies= foo.proto");
+
+ ExpectErrorText(
+ "foo.proto: File is imported but not declared in --direct_dependencies: "
+ "bar.proto\n");
+}
+
+TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "import \"bla.proto\";\n"
+ "message Foo { optional Bar bar = 1; optional Bla bla = 2; }");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar { optional string text = 1; }");
+ CreateTempFile("bla.proto",
+ "syntax = \"proto2\";\n"
+ "message Bla { optional int64 number = 1; }");
+
+ Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
+ "--direct_dependencies=bla.proto foo.proto");
+
+ ExpectErrorText(
+ "foo.proto: File is imported but not declared in --direct_dependencies: "
+ "bar.proto\n");
+}
+
+TEST_F(CommandLineInterfaceTest, DirectDependencies_NoViolation) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "message Foo { optional Bar bar = 1; }");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar { optional string text = 1; }");
+
+ Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
+ "--direct_dependencies=bar.proto foo.proto");
+
+ ExpectNoErrors();
+}
+
+TEST_F(CommandLineInterfaceTest, DirectDependencies_NoViolation_MultiImports) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n"
+ "import \"bar.proto\";\n"
+ "import \"bla.proto\";\n"
+ "message Foo { optional Bar bar = 1; optional Bla bla = 2; }");
+ CreateTempFile("bar.proto",
+ "syntax = \"proto2\";\n"
+ "message Bar { optional string text = 1; }");
+ CreateTempFile("bla.proto",
+ "syntax = \"proto2\";\n"
+ "message Bla { optional int64 number = 1; }");
+
+ Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
+ "--direct_dependencies=bar.proto:bla.proto foo.proto");
+
+ ExpectNoErrors();
+}
+
+TEST_F(CommandLineInterfaceTest, DirectDependencies_ProvidedMultipleTimes) {
+ CreateTempFile("foo.proto",
+ "syntax = \"proto2\";\n");
+
+ Run("protocol_compiler --test_out=$tmpdir --proto_path=$tmpdir "
+ "--direct_dependencies=bar.proto --direct_dependencies=bla.proto "
+ "foo.proto");
+
+ ExpectErrorText(
+ "--direct_dependencies may only be passed once. To specify multiple "
+ "direct dependencies, pass them all as a single parameter separated by "
+ "':'.\n");
+}
+
TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
// Test that we can accept working-directory-relative input files.
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index 77451ab1..deef290b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -99,7 +99,6 @@ class MockGeneratorContext : public GeneratorContext {
&actual_contents, true));
EXPECT_TRUE(actual_contents == *expected_contents)
<< physical_filename << " needs to be regenerated. Please run "
- "google/protobuf/compiler/release_compiler.sh and "
"generate_descriptor_proto.sh. Then add this file "
"to your CL.";
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 62b7ed4e..6ced26bc 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -260,7 +260,7 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) {
printer->Print(vars,
"bool $classname$_IsValid(int value) {\n"
- " switch(value) {\n");
+ " switch (value) {\n");
// Multiple values may have the same number. Make sure we only cover
// each number once by first constructing a set containing all valid
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index ffd81529..c3dfa817 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -83,13 +83,13 @@ void EnumFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
- "$inline$ $type$ $classname$::$name$() const {\n"
+ "$inline$$type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return static_cast< $type$ >($name$_);\n"
"}\n"
- "$inline$ void $classname$::set_$name$($type$ value) {\n");
+ "$inline$void $classname$::set_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables,
" assert($type$_IsValid(value));\n");
@@ -187,16 +187,16 @@ void EnumOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
- "$inline$ $type$ $classname$::$name$() const {\n"
+ "$inline$$type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return static_cast< $type$ >($oneof_prefix$$name$_);\n"
" }\n"
" return static_cast< $type$ >($default$);\n"
"}\n"
- "$inline$ void $classname$::set_$name$($type$ value) {\n");
+ "$inline$void $classname$::set_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables,
" assert($type$_IsValid(value));\n");
@@ -263,13 +263,13 @@ void RepeatedEnumFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
- "$inline$ $type$ $classname$::$name$(int index) const {\n"
+ "$inline$$type$ $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return static_cast< $type$ >($name$_.Get(index));\n"
"}\n"
- "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n");
+ "$inline$void $classname$::set_$name$(int index, $type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables,
" assert($type$_IsValid(value));\n");
@@ -278,7 +278,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" $name$_.Set(index, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::add_$name$($type$ value) {\n");
+ "$inline$void $classname$::add_$name$($type$ value) {\n");
if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables,
" assert($type$_IsValid(value));\n");
@@ -288,12 +288,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n");
printer->Print(variables,
- "$inline$ const ::google::protobuf::RepeatedField<int>&\n"
+ "$inline$const ::google::protobuf::RepeatedField<int>&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "$inline$ ::google::protobuf::RepeatedField<int>*\n"
+ "$inline$::google::protobuf::RepeatedField<int>*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
@@ -311,6 +311,11 @@ GenerateMergingCode(io::Printer* printer) const {
}
void RepeatedEnumFieldGenerator::
+GenerateUnsafeMergingCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_.UnsafeMergeFrom(from.$name$_);\n");
+}
+
+void RepeatedEnumFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
@@ -475,10 +480,11 @@ void RepeatedEnumFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
"{\n"
- " int data_size = 0;\n");
+ " size_t data_size = 0;\n"
+ " unsigned int count = this->$name$_size();");
printer->Indent();
printer->Print(variables_,
- "for (int i = 0; i < this->$name$_size(); i++) {\n"
+ "for (unsigned int i = 0; i < count; i++) {\n"
" data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
" this->$name$(i));\n"
"}\n");
@@ -489,13 +495,14 @@ GenerateByteSize(io::Printer* printer) const {
" total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
"}\n"
+ "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
- "_$name$_cached_byte_size_ = data_size;\n"
+ "_$name$_cached_byte_size_ = cached_size;\n"
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"total_size += data_size;\n");
} else {
printer->Print(variables_,
- "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
+ "total_size += ($tag_size$UL * count) + data_size;\n");
}
printer->Outdent();
printer->Print("}\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
index fe21c575..57ffeec5 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
@@ -101,6 +101,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateUnsafeMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index c42f1627..4554c72c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -178,28 +178,30 @@ void ExtensionGenerator::GenerateRegistration(io::Printer* printer) {
switch (descriptor_->cpp_type()) {
case FieldDescriptor::CPPTYPE_ENUM:
- printer->Print(vars,
- "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
- " &$extendee$::default_instance(),\n"
- " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
+ printer->Print(
+ vars,
+ "::google::protobuf::internal::ExtensionSet::RegisterEnumExtension(\n"
+ " $extendee$::internal_default_instance(),\n"
+ " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
printer->Print(
" &$type$_IsValid);\n",
"type", ClassName(descriptor_->enum_type(), true));
break;
case FieldDescriptor::CPPTYPE_MESSAGE:
- printer->Print(vars,
- "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
- " &$extendee$::default_instance(),\n"
- " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
printer->Print(
- " &$type$::default_instance());\n",
- "type", ClassName(descriptor_->message_type(), true));
+ vars,
+ "::google::protobuf::internal::ExtensionSet::RegisterMessageExtension(\n"
+ " $extendee$::internal_default_instance(),\n"
+ " $number$, $field_type$, $is_repeated$, $is_packed$,\n");
+ printer->Print(" $type$::internal_default_instance());\n", "type",
+ ClassName(descriptor_->message_type(), true));
break;
default:
- printer->Print(vars,
- "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
- " &$extendee$::default_instance(),\n"
- " $number$, $field_type$, $is_repeated$, $is_packed$);\n");
+ printer->Print(
+ vars,
+ "::google::protobuf::internal::ExtensionSet::RegisterExtension(\n"
+ " $extendee$::internal_default_instance(),\n"
+ " $number$, $field_type$, $is_repeated$, $is_packed$);\n");
break;
}
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 3b012527..fdd338a6 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -136,6 +136,13 @@ class FieldGenerator {
// GenerateMergeFrom method.
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
+ // The same, but the generated code may or may not check the possibility that
+ // the two objects being merged have the same address. To be safe, callers
+ // should avoid calling this unless they know the objects are different.
+ virtual void GenerateUnsafeMergingCode(io::Printer* printer) const {
+ GenerateMergingCode(printer);
+ }
+
// Generate lines of code (statements, not declarations) which swaps
// this field and the corresponding field of another message, which
// is stored in the generated code variable "other". This is used to
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index b3eca660..369497ce 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -89,7 +89,7 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
new ExtensionGenerator(file->extension(i), options));
}
- SplitStringUsing(file_->package(), ".", &package_parts_);
+ package_parts_ = Split(file_->package(), ".", true);
}
FileGenerator::~FileGenerator() {}
@@ -336,6 +336,20 @@ void FileGenerator::GenerateSource(io::Printer* printer) {
// Generate classes.
for (int i = 0; i < file_->message_type_count(); i++) {
+ if (i == 0 && HasGeneratedMethods(file_, options_)) {
+ printer->Print(
+ "\n"
+ "namespace {\n"
+ "\n"
+ "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD"
+ " GOOGLE_ATTRIBUTE_NORETURN;\n"
+ "static void MergeFromFail(int line) {\n"
+ " ::google::protobuf::internal::MergeFromFail(__FILE__, line);\n"
+ "}\n"
+ "\n"
+ "} // namespace\n"
+ "\n");
+ }
printer->Print("\n");
printer->Print(kThickSeparator);
printer->Print("\n");
@@ -449,6 +463,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors()
// and we only use AddDescriptors() to allocate default instances.
+
if (HasDescriptorMethods(file_, options_)) {
printer->Print(
"\n"
@@ -500,15 +515,15 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// AssignDescriptors(). All later times, waits for the first call to
// complete and then returns.
printer->Print(
- "namespace {\n"
- "\n"
- "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
- "inline void protobuf_AssignDescriptorsOnce() {\n"
- " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
- " &$assigndescriptorsname$);\n"
- "}\n"
- "\n",
- "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
+ "namespace {\n"
+ "\n"
+ "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n"
+ "void protobuf_AssignDescriptorsOnce() {\n"
+ " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n"
+ " &$assigndescriptorsname$);\n"
+ "}\n"
+ "\n",
+ "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()));
// protobuf_RegisterTypes(): Calls
// MessageFactory::InternalRegisterGeneratedType() for each message type.
@@ -548,44 +563,68 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
// -----------------------------------------------------------------
- // Now generate the AddDescriptors() function.
- PrintHandlingOptionalStaticInitializers(
- file_, options_, printer,
- // With static initializers.
- // Note that we don't need any special synchronization in the following
- // code
- // because it is called at static init time before any threads exist.
- "void $adddescriptorsname$() GOOGLE_ATTRIBUTE_COLD;\n"
- "void $adddescriptorsname$() {\n"
- " static bool already_here = false;\n"
- " if (already_here) return;\n"
- " already_here = true;\n"
- " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
- "\n",
- // Without.
- "void $adddescriptorsname$_impl() {\n"
+ // Now generate the InitDefaults() function.
+ printer->Print(
+ "void $initdefaultsname$_impl() {\n"
" GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
"\n",
// Vars.
- "adddescriptorsname", GlobalAddDescriptorsName(file_->name()));
+ "initdefaultsname", GlobalInitDefaultsName(file_->name()));
printer->Indent();
- // Call the AddDescriptors() methods for all of our dependencies, to make
+ // Call the InitDefaults() methods for all of our dependencies, to make
// sure they get added first.
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()));
+ dependency->package(), GlobalInitDefaultsName(dependency->name()));
// Call its AddDescriptors function.
printer->Print(
"$name$();\n",
"name", add_desc_name);
}
+ // 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.
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
+ }
+ for (int i = 0; i < file_->extension_count(); i++) {
+ extension_generators_[i]->GenerateRegistration(printer);
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
+ }
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n"
+ "GOOGLE_PROTOBUF_DECLARE_ONCE($initdefaultsname$_once_);\n"
+ "void $initdefaultsname$() {\n"
+ " ::google::protobuf::GoogleOnceInit(&$initdefaultsname$_once_,\n"
+ " &$initdefaultsname$_impl);\n"
+ "}\n",
+ "initdefaultsname", GlobalInitDefaultsName(file_->name()));
+
+ // -----------------------------------------------------------------
+
+ // Now generate the AddDescriptors() function.
+ printer->Print(
+ "void $adddescriptorsname$_impl() {\n"
+ " GOOGLE_PROTOBUF_VERIFY_VERSION;\n"
+ "\n"
+ " $initdefaultsname$();\n",
+ // Vars.
+ "adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
+ "initdefaultsname", GlobalInitDefaultsName(file_->name()));
+
+ printer->Indent();
if (HasDescriptorMethods(file_, options_)) {
- // Embed the descriptor. We simply serialize the entire FileDescriptorProto
+ // Embed the descriptor. We simply serialize the entire
+ // FileDescriptorProto
// and embed it as a string literal, which is parsed and built into real
// descriptors at initialization time.
FileDescriptorProto file_proto;
@@ -655,30 +694,37 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
"filename", file_->name());
}
- // 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.
- for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateDefaultInstanceAllocator(printer);
- }
- for (int i = 0; i < file_->extension_count(); i++) {
- extension_generators_[i]->GenerateRegistration(printer);
- }
- for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateDefaultInstanceInitializer(printer);
+ // Call the AddDescriptors() methods for all of our dependencies, to make
+ // sure they get added first.
+ 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()));
+ // Call its AddDescriptors function.
+ printer->Print("$adddescriptorsname$();\n", "adddescriptorsname",
+ add_desc_name);
}
printer->Print(
- "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
- "shutdownfilename", GlobalShutdownFileName(file_->name()));
+ "::google::protobuf::internal::OnShutdown(&$shutdownfilename$);\n",
+ "shutdownfilename", GlobalShutdownFileName(file_->name()));
printer->Outdent();
printer->Print(
- "}\n"
- "\n");
+ "}\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()));
- PrintHandlingOptionalStaticInitializers(
- file_, options_, printer,
+ if (!StaticInitializersForced(file_, options_)) {
+ 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"
@@ -686,15 +732,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
" $adddescriptorsname$();\n"
" }\n"
"} static_descriptor_initializer_$filename$_;\n",
- // Without.
- "GOOGLE_PROTOBUF_DECLARE_ONCE($adddescriptorsname$_once_);\n"
- "void $adddescriptorsname$() {\n"
- " ::google::protobuf::GoogleOnceInit(&$adddescriptorsname$_once_,\n"
- " &$adddescriptorsname$_impl);\n"
- "}\n",
// Vars.
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()), "filename",
FilenameIdentifier(file_->name()));
+ if (!StaticInitializersForced(file_, options_)) {
+ printer->Print("#endif // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n");
+ }
}
void FileGenerator::GenerateNamespaceOpeners(io::Printer* printer) {
@@ -892,12 +935,14 @@ void FileGenerator::GenerateGlobalStateFunctionDeclarations(
// 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 + " ");
+ "\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",
+ options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " ");
printer->Print(
// Note that we don't put dllexport_decl on these because they are only
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 2ad4d36a..6d844cc2 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -415,7 +415,8 @@ string DefaultValue(const FieldDescriptor* field) {
CEscape(field->default_value_string())) +
"\"";
case FieldDescriptor::CPPTYPE_MESSAGE:
- return FieldMessageTypeName(field) + "::default_instance()";
+ return "*" + FieldMessageTypeName(field) +
+ "::internal_default_instance()";
}
// Can't actually get here; make compiler happy. (We could add a default
// case above but then we wouldn't get the nice compiler warning when a
@@ -444,6 +445,10 @@ 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 GlobalAssignDescriptorsName(const string& filename) {
return "protobuf_AssignDesc_" + FilenameIdentifier(filename);
@@ -500,40 +505,6 @@ bool StaticInitializersForced(const FileDescriptor* file,
return false;
}
-void PrintHandlingOptionalStaticInitializers(
- const FileDescriptor* file, const Options& options, io::Printer* printer,
- const char* with_static_init, const char* without_static_init,
- const char* var1, const string& val1, const char* var2,
- const string& val2) {
- map<string, string> vars;
- if (var1) {
- vars[var1] = val1;
- }
- if (var2) {
- vars[var2] = val2;
- }
- PrintHandlingOptionalStaticInitializers(
- vars, file, options, printer, with_static_init, without_static_init);
-}
-
-void PrintHandlingOptionalStaticInitializers(const map<string, string>& vars,
- const FileDescriptor* file,
- const Options& options,
- io::Printer* printer,
- const char* with_static_init,
- const char* without_static_init) {
- if (StaticInitializersForced(file, options)) {
- printer->Print(vars, with_static_init);
- } else {
- printer->Print(vars, (string(
- "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n") +
- without_static_init +
- "#else\n" +
- with_static_init +
- "#endif\n").c_str());
- }
-}
-
static bool HasMapFields(const Descriptor* descriptor) {
for (int i = 0; i < descriptor->field_count(); ++i) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 018acfca..3a0c0388 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -147,6 +147,9 @@ 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 AssignDescriptors() function for a given file.
string GlobalAssignDescriptorsName(const string& filename);
@@ -223,22 +226,6 @@ inline bool HasFastArraySerialization(const FileDescriptor* file,
bool StaticInitializersForced(const FileDescriptor* file,
const Options& options);
-// Prints 'with_static_init' if static initializers have to be used for the
-// provided file. Otherwise emits both 'with_static_init' and
-// 'without_static_init' using #ifdef.
-void PrintHandlingOptionalStaticInitializers(
- const FileDescriptor* file, const Options& options, io::Printer* printer,
- const char* with_static_init, const char* without_static_init,
- const char* var1 = NULL, const string& val1 = "", const char* var2 = NULL,
- const string& val2 = "");
-
-void PrintHandlingOptionalStaticInitializers(const map<string, string>& vars,
- const FileDescriptor* file,
- const Options& options,
- io::Printer* printer,
- const char* with_static_init,
- const char* without_static_init);
-
inline bool IsMapEntryMessage(const Descriptor* descriptor) {
return descriptor->options().map_entry();
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index 0588e34e..31ac9ca7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -399,7 +399,8 @@ void MapFieldGenerator::GenerateSerializeWithCachedSizes(
void MapFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
- "total_size += $tag_size$ * this->$name$_size();\n"
+ "total_size += $tag_size$ *\n"
+ " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
"{\n"
" ::google::protobuf::scoped_ptr<$map_classname$> entry;\n"
" for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 1f1a0f1c..f5648663 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -85,14 +85,13 @@ struct FieldOrderingByNumber {
// 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()];
+std::vector<const FieldDescriptor*> SortFieldsByNumber(
+ const Descriptor* descriptor) {
+ std::vector<const FieldDescriptor*> fields(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());
+ std::sort(fields.begin(), fields.end(), FieldOrderingByNumber());
return fields;
}
@@ -227,59 +226,150 @@ class FieldGroup {
// used in a vector.
};
+// Helper for the code that emits the Clear() method.
+bool CanInitializeByZeroing(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;
+ }
+}
+
// 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.
+// order, fields of similiar family (see below) are together and within each
+// family, alignment padding is minimized.
+//
+// We try to do this while keeping each field as close as possible to its
+// declaration order (from the .proto file) so that we don't reduce cache
+// locality much for function that access each field in order. This is also the
+// only (weak) signal we have for author intent concerning field layout.
+//
+// TODO(ckennelly): Update these functions to use the optimized layout order
+// for their access patterns.
+//
+// TODO(ckennelly): If/when we have profiles available for the compiler, use
+// those rather than respect declaration order.
+//
+// We classify each field into a particular "family" of fields, that we perform
+// the same operation on in our generated functions.
+//
+// REPEATED is placed first, as the C++ compiler automatically initializes
+// these fields in layout order.
+//
+// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and
+// calls ArenaStringPtr::Destroy on each.
+//
+// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls
+// delete on each. We initialize these fields with a NULL pointer (see
+// MessageFieldGenerator::GenerateConstructorCode).
+// TODO(ckennelly): memset these in SharedCtor.
+//
+// ZERO_INITIALIZABLE is memset in Clear/SharedCtor
+//
+// OTHER these fields are initialized one-by-one.
void OptimizePadding(vector<const FieldDescriptor*>* fields) {
+ // The sorted numeric order of Family determines the declaration order in the
+ // memory layout.
+ enum Family {
+ REPEATED = 0,
+ STRING = 1,
+ MESSAGE = 2,
+ ZERO_INITIALIZABLE = 3,
+ OTHER = 4,
+ kMaxFamily
+ };
+
// 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;
+ vector<FieldGroup> aligned_to_1[kMaxFamily];
+ vector<FieldGroup> aligned_to_4[kMaxFamily];
+ vector<FieldGroup> aligned_to_8[kMaxFamily];
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.";
+ const FieldDescriptor* field = (*fields)[i];
+
+ Family f = OTHER;
+ if (field->is_repeated()) {
+ f = REPEATED;
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ f = STRING;
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ f = MESSAGE;
+ } else if (CanInitializeByZeroing(field)) {
+ f = ZERO_INITIALIZABLE;
}
- }
- // 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]);
+ switch (EstimateAlignmentSize(field)) {
+ case 1: aligned_to_1[f].push_back(FieldGroup(i, field)); break;
+ case 4: aligned_to_4[f].push_back(FieldGroup(i, field)); break;
+ case 8: aligned_to_8[f].push_back(FieldGroup(i, field)); break;
+ default:
+ GOOGLE_LOG(FATAL) << "Unknown alignment size.";
}
- 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);
+ // For each family, group fields to optimize padding.
+ for (int f = 0; f < kMaxFamily; f++) {
+ // 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[f].size(); i += 4) {
+ FieldGroup field_group;
+ for (int j = i; j < aligned_to_1[f].size() && j < i + 4; ++j) {
+ field_group.Append(aligned_to_1[f][j]);
+ }
+ aligned_to_4[f].push_back(field_group);
+ }
+ // Sort by preferred location to keep fields as close to their declaration
+ // order as possible. Using stable_sort ensures that the output is
+ // consistent across runs.
+ std::stable_sort(aligned_to_4[f].begin(), aligned_to_4[f].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[f].size(); i += 2) {
+ FieldGroup field_group;
+ for (int j = i; j < aligned_to_4[f].size() && j < i + 2; ++j) {
+ field_group.Append(aligned_to_4[f][j]);
+ }
+ if (i == aligned_to_4[f].size() - 1) {
+ if (f == OTHER) {
+ // Move incomplete 4-byte block to the beginning. This is done to
+ // pair with the (possible) leftover blocks from the
+ // ZERO_INITIALIZABLE family.
+ field_group.SetPreferredLocation(-1);
+ } else {
+ // Move incomplete 4-byte block to the end.
+ field_group.SetPreferredLocation(fields->size() + 1);
+ }
+ }
+ aligned_to_8[f].push_back(field_group);
}
- aligned_to_8.push_back(field_group);
+ // Sort by preferred location.
+ std::stable_sort(aligned_to_8[f].begin(), aligned_to_8[f].end());
}
- // 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());
+ for (int f = 0; f < kMaxFamily; ++f) {
+ for (int i = 0; i < aligned_to_8[f].size(); ++i) {
+ fields->insert(fields->end(),
+ aligned_to_8[f][i].fields().begin(),
+ aligned_to_8[f][i].fields().end());
+ }
}
}
@@ -337,6 +427,20 @@ bool HasHasMethod(const FieldDescriptor* field) {
return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
}
+size_t HasBitsSize(const Descriptor* descriptor) {
+ // 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;
+ }
+
+ return sizeof_has_bits;
+}
+
// Collects map entry message type information.
void CollectMapInfo(const Descriptor* descriptor,
map<string, string>* variables) {
@@ -389,6 +493,15 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
ExtensionGenerator>[descriptor->extension_count()]),
use_dependent_base_(false) {
+ // Compute optimized field order to be used for layout and initialization
+ // purposes.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ optimized_order_.push_back(descriptor_->field(i));
+ }
+ }
+ OptimizePadding(&optimized_order_);
+
for (int i = 0; i < descriptor->nested_type_count(); i++) {
nested_generators_[i].reset(
new MessageGenerator(descriptor->nested_type(i), options));
@@ -644,11 +757,12 @@ GenerateSingularFieldHasBits(const FieldDescriptor* field,
" return !$name$_.IsCleared();\n"
"}\n");
} else {
- printer->Print(vars,
- "$inline$"
- "bool $classname$::has_$name$() const {\n"
- " return !_is_default_instance_ && $name$_ != NULL;\n"
- "}\n");
+ printer->Print(
+ vars,
+ "$inline$"
+ "bool $classname$::has_$name$() const {\n"
+ " return this != internal_default_instance() && $name$_ != NULL;\n"
+ "}\n");
}
}
}
@@ -805,31 +919,6 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool 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_) {
@@ -1009,19 +1098,13 @@ GenerateClassDefinition(io::Printer* printer) {
"\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"
+ // TODO(gerbens) make this private, while still granting other protos access.
+ printer->Print(
+ vars,
"static inline const $classname$* internal_default_instance() {\n"
- " return default_instance_;\n"
+ " return &default_instance_.get();\n"
"}\n"
- "#endif\n"
"\n");
- }
if (SupportsArenas(descriptor_)) {
@@ -1068,7 +1151,7 @@ GenerateClassDefinition(io::Printer* printer) {
"void Clear();\n"
"bool IsInitialized() const;\n"
"\n"
- "int ByteSize() const;\n"
+ "size_t ByteSizeLong() const;\n"
"bool MergePartialFromCodedStream(\n"
" ::google::protobuf::io::CodedInputStream* input);\n"
"void SerializeWithCachedSizes(\n"
@@ -1131,7 +1214,8 @@ GenerateClassDefinition(io::Printer* printer) {
"void SharedCtor();\n"
"void SharedDtor();\n"
"void SetCachedSize(int size) const;\n"
- "void InternalSwap($classname$* other);\n",
+ "void InternalSwap($classname$* other);\n"
+ "void UnsafeMergeFrom(const $classname$& from);\n",
"classname", classname_);
if (SupportsArenas(descriptor_)) {
printer->Print(
@@ -1260,8 +1344,8 @@ GenerateClassDefinition(io::Printer* printer) {
!descriptor_->options().message_set_wire_format() &&
num_required_fields_ > 1) {
printer->Print(
- "// helper for ByteSize()\n"
- "int RequiredFieldsByteSizeFallback() const;\n\n");
+ "// helper for ByteSizeLong()\n"
+ "size_t RequiredFieldsByteSizeFallback() const;\n\n");
}
// Prepare decls for _cached_size_ and _has_bits_. Their position in the
@@ -1271,18 +1355,10 @@ GenerateClassDefinition(io::Printer* printer) {
// 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 size_t sizeof_has_bits = HasBitsSize(descriptor_);
const string has_bits_decl = sizeof_has_bits == 0 ? "" :
- "::google::protobuf::uint32 _has_bits_[" + SimpleItoa(sizeof_has_bits / 4) + "];\n";
-
+ "::google::protobuf::internal::HasBits<" + SimpleItoa(sizeof_has_bits / 4) +
+ "> _has_bits_;\n";
// To minimize padding, data members are divided into three sections:
// (1) members assumed to align to 8 bytes
@@ -1326,45 +1402,27 @@ GenerateClassDefinition(io::Printer* printer) {
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];
+ for (int i = 0; i < optimized_order_.size(); ++i) {
+ const FieldDescriptor* field = optimized_order_[i];
const FieldGenerator& generator = field_generators_.get(field);
generator.GenerateStaticMembers(printer);
generator.GeneratePrivateMembers(printer);
- if (CanClearByZeroing(field)) {
+ if (CanInitializeByZeroing(field)) {
const string& fieldname = FieldName(field);
if (!runs_of_fields_.back().empty() &&
(fieldname_to_chunk[runs_of_fields_.back().back()] !=
@@ -1424,15 +1482,15 @@ GenerateClassDefinition(io::Printer* printer) {
// 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 $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()));
printer->Print(
"friend void $assigndescriptorsname$();\n"
@@ -1443,12 +1501,12 @@ GenerateClassDefinition(io::Printer* printer) {
"shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name()));
printer->Print(
- "void InitAsDefaultInstance();\n"
- "static $classname$* default_instance_;\n",
- "classname", classname_);
+ "void InitAsDefaultInstance();\n"
+ "static ::google::protobuf::internal::ExplicitlyConstructed<$classname$> default_instance_;\n",
+ "classname", classname_);
printer->Outdent();
- printer->Print(vars, "};");
+ printer->Print("};");
GOOGLE_DCHECK(!need_to_emit_cached_size);
}
@@ -1578,18 +1636,18 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
"::NewGeneratedMessageReflection";
// Construct the reflection object.
printer->Print(vars,
- "$classname$_reflection_ =\n"
- " $fn$(\n"
- " $classname$_descriptor_,\n"
- " $classname$::default_instance_,\n"
- " $classname$_offsets_,\n");
+ "$classname$_reflection_ =\n"
+ " $fn$(\n"
+ " $classname$_descriptor_,\n"
+ " $classname$::internal_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");
+ " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_),\n");
}
// Unknown field offset: either points to the unknown field set if embedded
@@ -1637,22 +1695,12 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
// 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");
+ " 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");
+ " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+ "$classname$, _arena_));\n");
}
// Handle nested types.
@@ -1670,11 +1718,11 @@ 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 {
+ "::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(\n"
+ " $classname$_descriptor_, "
+ "$classname$::internal_default_instance());\n",
+ "classname", classname_);
+ } else {
map<string, string> vars;
CollectMapInfo(descriptor_, &vars);
vars["classname"] = classname_;
@@ -1708,6 +1756,12 @@ GenerateTypeRegistrations(io::Printer* printer) {
void MessageGenerator::
GenerateDefaultInstanceAllocator(io::Printer* printer) {
+ // Force initialization of primitive values we depend on.
+ printer->Print(
+ StrCat(
+ uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "")
+ .c_str());
+
// 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++) {
@@ -1720,9 +1774,8 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) {
// 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_);
+ printer->Print("$classname$::default_instance_.DefaultConstruct();\n",
+ "classname", classname_);
if ((descriptor_->oneof_decl_count() > 0) &&
HasDescriptorMethods(descriptor_->file(), options_)) {
@@ -1741,8 +1794,9 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) {
void MessageGenerator::
GenerateDefaultInstanceInitializer(io::Printer* printer) {
printer->Print(
- "$classname$::default_instance_->InitAsDefaultInstance();\n",
- "classname", classname_);
+ "$classname$::default_instance_.get_mutable()->InitAsDefaultInstance();"
+ "\n",
+ "classname", classname_);
// Register extensions.
for (int i = 0; i < descriptor_->extension_count(); i++) {
@@ -1761,10 +1815,6 @@ GenerateDefaultInstanceInitializer(io::Printer* 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(
@@ -1894,6 +1944,12 @@ GenerateClassMethods(io::Printer* printer) {
GenerateIsInitialized(printer);
printer->Print("\n");
+ } else {
+ printer->Print(
+ "void $classname$::UnsafeMergeFrom(const $classname$& from) {\n"
+ " MergeFrom(from);\n"
+ "}\n",
+ "classname", classname_);
}
GenerateSwap(printer);
@@ -1966,15 +2022,15 @@ GenerateSharedConstructorCode(io::Printer* printer) {
"classname", classname_);
printer->Indent();
- if (!HasFieldPresence(descriptor_->file())) {
- printer->Print(
- " _is_default_instance_ = false;\n");
+ bool need_to_clear_cached_size = true;
+ // We reproduce the logic used for laying out _cached_sized_ in the class
+ // definition, as to initialize it in-order.
+ if (HasFieldPresence(descriptor_->file()) &&
+ (HasBitsSize(descriptor_) % 8) != 0) {
+ printer->Print("_cached_size_ = 0;\n");
+ need_to_clear_cached_size = false;
}
- 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(
@@ -1982,16 +2038,52 @@ GenerateSharedConstructorCode(io::Printer* printer) {
" &::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);
+ const FieldDescriptor* last_start = NULL;
+ // RunMap maps from fields that start each run to the number of fields in that
+ // run. This is optimized for the common case that there are very few runs in
+ // a message and that most of the eligible fields appear together.
+ typedef hash_map<const FieldDescriptor*, size_t> RunMap;
+ RunMap runs;
+
+ for (int i = 0; i < optimized_order_.size(); ++i) {
+ const FieldDescriptor* field = optimized_order_[i];
+ // TODO(ckennelly): Scalar messages (raw pointers) can be initialized by
+ // zero as well.
+ if (CanInitializeByZeroing(field)) {
+ if (last_start == NULL) {
+ last_start = field;
+ }
+
+ runs[last_start]++;
+ } else {
+ last_start = NULL;
}
}
- if (HasFieldPresence(descriptor_->file())) {
- printer->Print(
- "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+ for (int i = 0; i < optimized_order_.size(); ++i) {
+ const FieldDescriptor* field = optimized_order_[i];
+ RunMap::const_iterator it = runs.find(field);
+
+ // We only apply the memset technique to runs of more than one field, as
+ // assignment is better than memset for generated code clarity.
+ if (it != runs.end() && it->second > 1) {
+ // Use a memset, then skip run_length fields.
+ const size_t run_length = it->second;
+ const string first_field_name = FieldName(field);
+ const string last_field_name =
+ FieldName(optimized_order_[i + run_length - 1]);
+
+ printer->Print(
+ "::memset(&$first$_, 0, reinterpret_cast<char*>(&$last$_) -\n"
+ " reinterpret_cast<char*>(&$first$_) + sizeof($last$_));\n",
+ "first", first_field_name,
+ "last", last_field_name);
+
+ i += run_length - 1;
+ // ++i at the top of the loop.
+ } else {
+ field_generators_.get(field).GenerateConstructorCode(printer);
+ }
}
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
@@ -2000,6 +2092,10 @@ GenerateSharedConstructorCode(io::Printer* printer) {
"oneof_name", descriptor_->oneof_decl(i)->name());
}
+ if (need_to_clear_cached_size) {
+ printer->Print("_cached_size_ = 0;\n");
+ }
+
printer->Outdent();
printer->Print("}\n\n");
}
@@ -2013,7 +2109,8 @@ GenerateSharedDestructorCode(io::Printer* printer) {
if (SupportsArenas(descriptor_)) {
// Do nothing when the message is allocated in an arena.
printer->Print(
- "if (GetArenaNoVirtual() != NULL) {\n"
+ "::google::protobuf::Arena* arena = GetArenaNoVirtual();\n"
+ "if (arena != NULL) {\n"
" return;\n"
"}\n"
"\n");
@@ -2026,7 +2123,7 @@ GenerateSharedDestructorCode(io::Printer* printer) {
printer->Print(
"_unknown_fields_.Destroy(\n"
" &::google::protobuf::internal::GetEmptyStringAlreadyInited(),\n"
- " GetArenaNoVirtual());\n");
+ " arena);\n");
} else {
printer->Print(
"_unknown_fields_.DestroyNoArena(\n"
@@ -2035,11 +2132,10 @@ GenerateSharedDestructorCode(io::Printer* printer) {
}
// 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);
- }
+ // optimized_order_ does not contain oneof fields.
+ for (int i = 0; i < optimized_order_.size(); i++) {
+ const FieldDescriptor* field = optimized_order_[i];
+ field_generators_.get(field).GenerateDestructorCode(printer);
}
// Generate code to destruct oneofs. Clearing should do the work.
@@ -2051,13 +2147,6 @@ GenerateSharedDestructorCode(io::Printer* printer) {
"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
@@ -2069,16 +2158,13 @@ GenerateSharedDestructorCode(io::Printer* printer) {
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
// Skip oneof members
if (!field->containing_oneof()) {
- printer->Print(
- " delete $name$_;\n",
- "name", FieldName(field));
+ printer->Print("delete $name$_;\n", "name", FieldName(field));
}
}
}
printer->Outdent();
printer->Print(
- " }\n"
"}\n"
"\n");
}
@@ -2151,16 +2237,18 @@ GenerateStructors(io::Printer* printer) {
}
// Initialize member variables with arena constructor.
- for (int i = 0; i < descriptor_->field_count(); i++) {
- bool has_arena_constructor = descriptor_->field(i)->is_repeated();
+ for (int i = 0; i < optimized_order_.size(); i++) {
+ const FieldDescriptor* field = optimized_order_[i];
+
+ bool has_arena_constructor = field->is_repeated();
if (has_arena_constructor) {
initializer_with_arena += string(",\n ") +
- FieldName(descriptor_->field(i)) + string("_(arena)");
+ FieldName(field) + string("_(arena)");
}
}
if (IsAnyMessage(descriptor_)) {
- initializer_with_arena += ",\n _any_metadata_(&type_url, &value_)";
+ initializer_with_arena += ",\n _any_metadata_(&type_url_, &value_)";
}
string initializer_null;
@@ -2173,27 +2261,31 @@ GenerateStructors(io::Printer* printer) {
printer->Print(
"$classname$::$classname$()\n"
" : $superclass$()$initializer$ {\n"
+ " if (this != internal_default_instance()) $initdefaultsname$();\n"
" SharedCtor();\n"
" // @@protoc_insertion_point(constructor:$full_name$)\n"
"}\n",
- "classname", classname_,
- "superclass", superclass,
- "full_name", descriptor_->full_name(),
- "initializer", initializer_null);
+ "classname", classname_, "superclass", superclass, "full_name",
+ descriptor_->full_name(), "initializer", initializer_null,
+ "initdefaultsname", GlobalInitDefaultsName(descriptor_->file()->name()));
if (SupportsArenas(descriptor_)) {
printer->Print(
- "\n"
"$classname$::$classname$(::google::protobuf::Arena* arena)\n"
" : $initializer$ {\n"
+ // 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"
+ "#endif // GOOGLE_PROTOBUF_NO_STATIC_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());
+ "initializer", initializer_with_arena, "classname", classname_,
+ "superclass", superclass, "full_name", descriptor_->full_name(),
+ "initdefaultsname",
+ GlobalInitDefaultsName(descriptor_->file()->name()));
}
printer->Print(
@@ -2201,11 +2293,6 @@ GenerateStructors(io::Printer* printer) {
"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
@@ -2224,11 +2311,7 @@ GenerateStructors(io::Printer* printer) {
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.
+ printer->Print(
" $name$_ = const_cast< $type$*>(\n"
" $type$::internal_default_instance());\n",
// Vars.
@@ -2262,7 +2345,7 @@ GenerateStructors(io::Printer* printer) {
printer->Print(" {\n");
printer->Print(
" SharedCtor();\n"
- " MergeFrom(from);\n"
+ " UnsafeMergeFrom(from);\n"
" // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
"}\n"
"\n",
@@ -2304,37 +2387,29 @@ GenerateStructors(io::Printer* printer) {
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()));
+ "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n"
+ " protobuf_AssignDescriptorsOnce();\n"
+ " return $classname$_descriptor_;\n"
+ "}\n"
+ "\n",
+ "classname", classname_, "initdefaultsname",
+ GlobalInitDefaultsName(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()));
+ "const $classname$& $classname$::default_instance() {\n"
+ " $initdefaultsname$();\n"
+ " return *internal_default_instance();\n"
+ "}\n",
+ "classname", classname_, "initdefaultsname",
+ GlobalInitDefaultsName(descriptor_->file()->name()));
printer->Print(
- " return *default_instance_;\n"
- "}\n"
- "\n"
- "$classname$* $classname$::default_instance_ = NULL;\n"
- "\n",
- "classname", classname_);
+ "\n"
+ "::google::protobuf::internal::ExplicitlyConstructed<$classname$> "
+ "$classname$::default_instance_;\n"
+ "\n",
+ "classname", classname_);
if (SupportsArenas(descriptor_)) {
printer->Print(
@@ -2463,7 +2538,7 @@ GenerateClear(io::Printer* printer) {
int count = popcnt(mask);
GOOGLE_DCHECK_GE(count, 1);
if (count == 1 ||
- (count <= 4 && count == memset_field_count_for_chunk[i / 8])) {
+ count == memset_field_count_for_chunk[i / 8]) {
// No "if" here because the chunk is trivial.
} else {
if (HasFieldPresence(descriptor_->file())) {
@@ -2540,8 +2615,7 @@ GenerateClear(io::Printer* printer) {
if (HasFieldPresence(descriptor_->file())) {
// Step 5: Everything else.
- printer->Print(
- "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+ printer->Print("_has_bits_.Clear();\n");
}
if (PreserveUnknownFields(descriptor_)) {
@@ -2584,7 +2658,7 @@ GenerateOneofClear(io::Printer* printer) {
"$full_name$)\n");
printer->Indent();
printer->Print(oneof_vars,
- "switch($oneofname$_case()) {\n");
+ "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);
@@ -2639,7 +2713,7 @@ GenerateSwap(io::Printer* printer) {
" InternalSwap(other);\n"
" } else {\n"
" $classname$ temp;\n"
- " temp.MergeFrom(*this);\n"
+ " temp.UnsafeMergeFrom(*this);\n"
" CopyFrom(*other);\n"
" other->CopyFrom(temp);\n"
" }\n"
@@ -2715,9 +2789,7 @@ GenerateMergeFrom(io::Printer* printer) {
"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",
+ " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
"classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
@@ -2726,7 +2798,7 @@ GenerateMergeFrom(io::Printer* printer) {
// system, as the GOOGLE_CHECK above ensured that we have the same descriptor
// for each message.
printer->Print(
- "const $classname$* source = \n"
+ "const $classname$* source =\n"
" ::google::protobuf::internal::DynamicCastToGenerated<const $classname$>(\n"
" &from);\n"
"if (source == NULL) {\n"
@@ -2736,7 +2808,7 @@ GenerateMergeFrom(io::Printer* printer) {
"} else {\n"
"// @@protoc_insertion_point(generalized_merge_from_cast_success:"
"$full_name$)\n"
- " MergeFrom(*source);\n"
+ " UnsafeMergeFrom(*source);\n"
"}\n",
"classname", classname_, "full_name", descriptor_->full_name());
@@ -2758,9 +2830,15 @@ GenerateMergeFrom(io::Printer* printer) {
"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",
+ " if (GOOGLE_PREDICT_TRUE(&from != this)) {\n"
+ " UnsafeMergeFrom(from);\n"
+ " } else {\n"
+ " MergeFromFail(__LINE__);\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "void $classname$::UnsafeMergeFrom(const $classname$& from) {\n"
+ " GOOGLE_DCHECK(&from != this);\n",
"classname", classname_, "full_name", descriptor_->full_name());
printer->Indent();
@@ -2770,7 +2848,7 @@ GenerateMergeFrom(io::Printer* printer) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->is_repeated()) {
- field_generators_.get(field).GenerateMergingCode(printer);
+ field_generators_.get(field).GenerateUnsafeMergingCode(printer);
}
}
@@ -2865,7 +2943,8 @@ GenerateMergeFrom(io::Printer* printer) {
if (UseUnknownFieldSet(descriptor_->file(), options_)) {
printer->Print(
"if (from._internal_metadata_.have_unknown_fields()) {\n"
- " mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"
+ " ::google::protobuf::UnknownFieldSet::MergeToInternalMetdata(\n"
+ " from.unknown_fields(), &_internal_metadata_);\n"
"}\n");
} else {
printer->Print(
@@ -2911,7 +2990,7 @@ GenerateCopyFrom(io::Printer* printer) {
printer->Print(
"if (&from == this) return;\n"
"Clear();\n"
- "MergeFrom(from);\n");
+ "UnsafeMergeFrom(from);\n");
printer->Outdent();
printer->Print("}\n");
@@ -2926,13 +3005,9 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
" ::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"
+ printer->Print(
+ " return _extensions_.ParseMessageSet(input, "
+ "internal_default_instance(),\n"
" mutable_unknown_fields());\n",
// Vars.
"classname", classname_);
@@ -2971,8 +3046,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
printer->Print("for (;;) {\n");
printer->Indent();
- google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
- SortFieldsByNumber(descriptor_));
+ std::vector<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
@@ -3000,7 +3075,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
// 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++) {
+ for (int i = 0; i < ordered_fields.size(); i++) {
const FieldDescriptor* field = ordered_fields[i];
if (field->is_repeated() &&
(field->type() == FieldDescriptor::TYPE_MESSAGE ||
@@ -3012,7 +3087,13 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
// 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++) {
+ // Pay attention to whether we are in a run of fields from the same oneof.
+ // Motivation: it would be unusual to parse multiple values for a single
+ // oneof, since only the last would be used.
+ const FieldDescriptor* last_of_current_oneof = NULL;
+ // The following is valid iff last_of_current_oneof is non-NULL.
+ int index_of_last_of_current_oneof = -1;
+ for (int i = 0; i < ordered_fields.size(); 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;
@@ -3111,21 +3192,53 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
"input->UnsafeDecrementRecursionDepth();\n");
}
- // If there are more fields, expect the next one.
+ // If there are more fields, expect the next one, unless we just parsed
+ // a oneof and the next field would be from the same oneof. (There's no
+ // reason to expect something that makes what we just read irrelevant,
+ // so guess something after the current string of fields from this oneof.)
need_label = false;
if (!emitted_goto_next_tag) {
- if (i + 1 == descriptor_->field_count()) {
+ // delta is the distance in ordered_fields[] from the current field to
+ // the field we'll guess is next.
+ int delta = last_of_current_oneof == NULL
+ ? 1
+ : std::max(index_of_last_of_current_oneof - i, 1);
+ if (i == index_of_last_of_current_oneof) {
+ printer->Outdent();
+ printer->Print(
+ " after_$last$:\n",
+ "last", FieldName(last_of_current_oneof));
+ printer->Indent();
+ last_of_current_oneof = NULL;
+ } else if (last_of_current_oneof == NULL) {
+ delta = 1;
+ // Check for the unlikely case that delta > 1 is better.
+ if (field->containing_oneof() != NULL) {
+ while (i + delta < ordered_fields.size() &&
+ ordered_fields[i + delta]->containing_oneof() ==
+ field->containing_oneof()) {
+ index_of_last_of_current_oneof = i + delta;
+ last_of_current_oneof = ordered_fields[i + delta];
+ ++delta;
+ }
+ }
+ }
+ if (delta > 1) {
+ printer->Print(
+ "goto after_$last$;\n",
+ "last", FieldName(last_of_current_oneof));
+ } else if (i + delta == 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];
+ const FieldDescriptor* next_field = ordered_fields[i + delta];
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;
+ need_label = delta == 1;
}
}
@@ -3179,31 +3292,21 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
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"
+ printer->Print(
+ " DO_(_extensions_.ParseField(tag, input, "
+ "internal_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"
+ printer->Print(
+ " DO_(_extensions_.ParseField(tag, input, "
+ "internal_default_instance(),\n"
" &unknown_fields_stream));\n");
}
} else {
- PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), options_, printer,
+ printer->Print(
// With static initializers.
- " DO_(_extensions_.ParseField(tag, input, default_instance_);\n",
- // Without.
- " DO_(_extensions_.ParseField(tag, input, &default_instance());\n");
+ " DO_(_extensions_.ParseField(tag, input, "
+ "internal_default_instance());\n");
}
printer->Print(
" continue;\n"
@@ -3248,6 +3351,43 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
"}\n", "full_name", descriptor_->full_name());
}
+void MessageGenerator::GenerateSerializeOneofFields(
+ io::Printer* printer, const vector<const FieldDescriptor*>& fields,
+ bool to_array) {
+ GOOGLE_CHECK(!fields.empty());
+ if (fields.size() == 1) {
+ GenerateSerializeOneField(printer, fields[0], to_array);
+ return;
+ }
+ // We have multiple mutually exclusive choices. Emit a switch statement.
+ const OneofDescriptor* oneof = fields[0]->containing_oneof();
+ printer->Print(
+ "switch ($oneofname$_case()) {\n",
+ "oneofname", oneof->name());
+ printer->Indent();
+ for (int i = 0; i < fields.size(); i++) {
+ const FieldDescriptor* field = fields[i];
+ printer->Print(
+ "case k$field_name$:\n",
+ "field_name", UnderscoresToCamelCase(field->name(), true));
+ printer->Indent();
+ if (to_array) {
+ field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
+ printer);
+ } else {
+ field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
+ }
+ printer->Print(
+ "break;\n");
+ printer->Outdent();
+ }
+ printer->Outdent();
+ // Doing nothing is an option.
+ printer->Print(
+ " default: ;\n"
+ "}\n");
+}
+
void MessageGenerator::GenerateSerializeOneField(
io::Printer* printer, const FieldDescriptor* field, bool to_array) {
PrintFieldComment(printer, field);
@@ -3382,10 +3522,61 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) {
void MessageGenerator::
GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
- google::protobuf::scoped_array<const FieldDescriptor * > ordered_fields(
- SortFieldsByNumber(descriptor_));
+ // If there are multiple fields in a row from the same oneof then we
+ // coalesce them and emit a switch statement. This is more efficient
+ // because it lets the C++ compiler know this is a "at most one can happen"
+ // situation. If we emitted "if (has_x()) ...; if (has_y()) ..." the C++
+ // compiler's emitted code might check has_y() even when has_x() is true.
+ class LazySerializerEmitter {
+ public:
+ LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer,
+ bool to_array)
+ : mg_(mg),
+ printer_(printer),
+ to_array_(to_array),
+ eager_(!HasFieldPresence(mg->descriptor_->file())) {}
+
+ ~LazySerializerEmitter() { Flush(); }
+
+ // If conditions allow, try to accumulate a run of fields from the same
+ // oneof, and handle them at the next Flush().
+ void Emit(const FieldDescriptor* field) {
+ if (eager_ || MustFlush(field)) {
+ Flush();
+ }
+ if (field->containing_oneof() == NULL) {
+ mg_->GenerateSerializeOneField(printer_, field, to_array_);
+ } else {
+ v_.push_back(field);
+ }
+ }
- vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ void Flush() {
+ if (!v_.empty()) {
+ mg_->GenerateSerializeOneofFields(printer_, v_, to_array_);
+ v_.clear();
+ }
+ }
+
+ private:
+ // If we have multiple fields in v_ then they all must be from the same
+ // oneof. Would adding field to v_ break that invariant?
+ bool MustFlush(const FieldDescriptor* field) {
+ return !v_.empty() &&
+ v_[0]->containing_oneof() != field->containing_oneof();
+ }
+
+ MessageGenerator* mg_;
+ io::Printer* printer_;
+ const bool to_array_;
+ const bool eager_;
+ vector<const FieldDescriptor*> v_;
+ };
+
+ std::vector<const FieldDescriptor*> ordered_fields =
+ SortFieldsByNumber(descriptor_);
+
+ std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
sorted_extensions.push_back(descriptor_->extension_range(i));
}
@@ -3393,22 +3584,26 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
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);
+ {
+ LazySerializerEmitter e(this, printer, to_array);
+ int i, j;
+ for (i = 0, j = 0;
+ i < ordered_fields.size() || j < sorted_extensions.size();) {
+ if (i == descriptor_->field_count()) {
+ e.Flush();
+ GenerateSerializeOneExtensionRange(printer,
+ sorted_extensions[j++],
+ to_array);
+ } else if (j == sorted_extensions.size()) {
+ e.Emit(ordered_fields[i++]);
+ } else if (ordered_fields[i]->number() < sorted_extensions[j]->start) {
+ e.Emit(ordered_fields[i++]);
+ } else {
+ e.Flush();
+ GenerateSerializeOneExtensionRange(printer,
+ sorted_extensions[j++],
+ to_array);
+ }
}
}
@@ -3480,9 +3675,9 @@ GenerateByteSize(io::Printer* printer) {
if (descriptor_->options().message_set_wire_format()) {
// Special-case MessageSet.
printer->Print(
- "int $classname$::ByteSize() const {\n"
+ "size_t $classname$::ByteSizeLong() const {\n"
"// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n"
- " int total_size = _extensions_.MessageSetByteSize();\n",
+ " size_t total_size = _extensions_.MessageSetByteSize();\n",
"classname", classname_, "full_name", descriptor_->full_name());
GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
printer->Print(
@@ -3491,8 +3686,9 @@ GenerateByteSize(io::Printer* printer) {
" ComputeUnknownMessageSetItemsSize(unknown_fields());\n"
"}\n");
printer->Print(
+ " int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n"
" GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
- " _cached_size_ = total_size;\n"
+ " _cached_size_ = cached_size;\n"
" GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
" return total_size;\n"
"}\n");
@@ -3503,12 +3699,12 @@ GenerateByteSize(io::Printer* printer) {
// 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"
+ "size_t $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");
+ printer->Print("size_t total_size = 0;\n");
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
if (field->is_required()) {
@@ -3529,12 +3725,12 @@ GenerateByteSize(io::Printer* printer) {
}
printer->Print(
- "int $classname$::ByteSize() const {\n"
+ "size_t $classname$::ByteSizeLong() 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"
+ "size_t total_size = 0;\n"
"\n");
// Handle required fields (if any). We expect all of them to be
@@ -3727,8 +3923,9 @@ GenerateByteSize(io::Printer* printer) {
// 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(
+ "int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n"
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
- "_cached_size_ = total_size;\n"
+ "_cached_size_ = cached_size;\n"
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"return total_size;\n");
@@ -3804,7 +4001,9 @@ GenerateIsInitialized(io::Printer* printer) {
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"\n"
- "if (!_extensions_.IsInitialized()) return false;\n");
+ "if (!_extensions_.IsInitialized()) {\n"
+ " return false;\n"
+ "}\n");
}
printer->Outdent();
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index b1e3fe21..3bdc0ed3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -165,6 +165,11 @@ class MessageGenerator {
void GenerateSerializeOneField(io::Printer* printer,
const FieldDescriptor* field,
bool unbounded);
+ // Generate a switch statement to serialize 2+ fields from the same oneof.
+ // Or, if fields.size() == 1, just call GenerateSerializeOneField().
+ void GenerateSerializeOneofFields(
+ io::Printer* printer, const vector<const FieldDescriptor*>& fields,
+ bool to_array);
void GenerateSerializeOneExtensionRange(
io::Printer* printer, const Descriptor::ExtensionRange* range,
bool unbounded);
@@ -189,6 +194,11 @@ class MessageGenerator {
string classname_;
Options options_;
FieldGeneratorMap field_generators_;
+ // optimized_order_ is the order we layout the message's fields in the class.
+ // This is reused to initialize the fields in-order for cache efficiency.
+ //
+ // optimized_order_ excludes oneof fields.
+ vector<const FieldDescriptor *> optimized_order_;
vector< vector<string> > runs_of_fields_; // that might be trivially cleared
google::protobuf::scoped_array<google::protobuf::scoped_ptr<MessageGenerator> > nested_generators_;
google::protobuf::scoped_array<google::protobuf::scoped_ptr<EnumGenerator> > enum_generators_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index d021035d..ca7bae02 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -161,8 +161,7 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions(
" if ($name$_ == NULL) {\n"
" return NULL;\n"
" } else {\n"
- " $type$* temp = new $type$;\n"
- " temp->MergeFrom(*$name$_);\n"
+ " $type$* temp = new $type$(*$name$_);\n"
" $name$_ = NULL;\n"
" return temp;\n"
" }\n"
@@ -346,23 +345,29 @@ GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const {
void MessageFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
+ if (dependent_field_) {
+ // for dependent fields we cannot access its internal_default_instance,
+ // because the type is incomplete.
+ // TODO(gerbens) deprecate dependent base class.
+ map<string, string> variables(variables_);
+ variables["inline"] = is_inline ? "inline " : "";
+ printer->Print(variables,
+ "$inline$const $type$& $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return $name$_ != NULL ? *$name$_\n"
+ " : *internal_default_instance()->$name$_;\n"
+ "}\n");
+ return;
+ }
+
map<string, string> variables(variables_);
variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
"$inline$const $type$& $classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n");
-
- PrintHandlingOptionalStaticInitializers(
- variables, descriptor_->file(), options_, printer,
- // With static initializers.
- " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n",
- // Without.
- " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
- printer->Print(variables, "}\n");
-
- if (dependent_field_) {
- return;
- }
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return $name$_ != NULL ? *$name$_\n"
+ " : *$type$::internal_default_instance();\n"
+ "}\n");
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
@@ -663,8 +668,8 @@ InternalGenerateInlineAccessorDefinitions(const map<string, string>& variables,
" if ($this_message$GetArenaNoVirtual() != NULL) {\n"
// N.B.: safe to use the underlying field pointer here because we are sure
// that it is non-NULL (because has_$name$() returned true).
- " $dependent_typename$* temp = new $dependent_typename$;\n"
- " temp->MergeFrom(*$field_member$);\n"
+ " $dependent_typename$* temp = "
+ "new $dependent_typename$(*$field_member$);\n"
" $field_member$ = NULL;\n"
" return temp;\n"
" } else {\n"
@@ -1041,12 +1046,18 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
- "total_size += $tag_size$ * this->$name$_size();\n"
- "for (int i = 0; i < this->$name$_size(); i++) {\n"
+ "{\n"
+ " unsigned int count = this->$name$_size();\n");
+ printer->Indent();
+ printer->Print(variables_,
+ "total_size += $tag_size$UL * count;\n"
+ "for (unsigned int i = 0; i < count; i++) {\n"
" total_size +=\n"
" ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
" this->$name$(i));\n"
"}\n");
+ printer->Outdent();
+ printer->Print("}\n");
}
} // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 650f0381..54b3d24a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -123,13 +123,13 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
- "$inline$ $type$ $classname$::$name$() const {\n"
+ "$inline$$type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "$inline$ void $classname$::set_$name$($type$ value) {\n"
+ "$inline$void $classname$::set_$name$($type$ value) {\n"
" $set_hasbit$\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
@@ -159,10 +159,10 @@ GenerateConstructorCode(io::Printer* printer) const {
void PrimitiveFieldGenerator::
GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
+ "$set_hasbit$\n"
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" $type$, $wire_format_field_type$>(\n"
- " input, &$name$_)));\n"
- "$set_hasbit$\n");
+ " input, &$name$_)));\n");
}
void PrimitiveFieldGenerator::
@@ -207,16 +207,16 @@ PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {}
void PrimitiveOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
- "$inline$ $type$ $classname$::$name$() const {\n"
+ "$inline$$type$ $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_;\n"
" }\n"
" return $default$;\n"
"}\n"
- "$inline$ void $classname$::set_$name$($type$ value) {\n"
+ "$inline$void $classname$::set_$name$($type$ value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -298,27 +298,27 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
- "$inline$ $type$ $classname$::$name$(int index) const {\n"
+ "$inline$$type$ $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.Get(index);\n"
"}\n"
- "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n"
+ "$inline$void $classname$::set_$name$(int index, $type$ value) {\n"
" $name$_.Set(index, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::add_$name$($type$ value) {\n"
+ "$inline$void $classname$::add_$name$($type$ value) {\n"
" $name$_.Add(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n");
printer->Print(variables,
- "$inline$ const ::google::protobuf::RepeatedField< $type$ >&\n"
+ "$inline$const ::google::protobuf::RepeatedField< $type$ >&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "$inline$ ::google::protobuf::RepeatedField< $type$ >*\n"
+ "$inline$::google::protobuf::RepeatedField< $type$ >*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
@@ -336,6 +336,11 @@ GenerateMergingCode(io::Printer* printer) const {
}
void RepeatedPrimitiveFieldGenerator::
+GenerateUnsafeMergingCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_.UnsafeMergeFrom(from.$name$_);\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
@@ -420,18 +425,19 @@ void RepeatedPrimitiveFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
"{\n"
- " int data_size = 0;\n");
+ " size_t data_size = 0;\n"
+ " unsigned int count = this->$name$_size();\n");
printer->Indent();
int fixed_size = FixedSize(descriptor_->type());
if (fixed_size == -1) {
printer->Print(variables_,
- "for (int i = 0; i < this->$name$_size(); i++) {\n"
+ "for (unsigned int i = 0; i < count; i++) {\n"
" data_size += ::google::protobuf::internal::WireFormatLite::\n"
" $declared_type$Size(this->$name$(i));\n"
"}\n");
} else {
printer->Print(variables_,
- "data_size = $fixed_size$ * this->$name$_size();\n");
+ "data_size = $fixed_size$UL * count;\n");
}
if (descriptor_->is_packed()) {
@@ -440,13 +446,16 @@ GenerateByteSize(io::Printer* printer) const {
" total_size += $tag_size$ +\n"
" ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
"}\n"
+ "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
"GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
- "_$name$_cached_byte_size_ = data_size;\n"
+ "_$name$_cached_byte_size_ = cached_size;\n"
"GOOGLE_SAFE_CONCURRENT_WRITES_END();\n"
"total_size += data_size;\n");
} else {
printer->Print(variables_,
- "total_size += $tag_size$ * this->$name$_size() + data_size;\n");
+ "total_size += $tag_size$ *\n"
+ " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
+ "total_size += data_size;\n");
}
printer->Outdent();
printer->Print("}\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
index 655ebde4..23cc697e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
@@ -103,6 +103,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
+ virtual void GenerateUnsafeMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 1d743457..aee3d1ea 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -166,25 +166,25 @@ void StringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
- "$inline$ const ::std::string& $classname$::$name$() const {\n"
+ "$inline$const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.Get($default_variable$);\n"
"}\n"
- "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$void $classname$::set_$name$(const ::std::string& value) {\n"
" $set_hasbit$\n"
" $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::set_$name$(const char* value) {\n"
+ "$inline$void $classname$::set_$name$(const char* value) {\n"
" $set_hasbit$\n"
" $name$_.Set($default_variable$, $string_piece$(value),\n"
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "$inline$ "
+ "$inline$"
"void $classname$::set_$name$(const $pointer_type$* value,\n"
" size_t size) {\n"
" $set_hasbit$\n"
@@ -192,24 +192,24 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$::std::string* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n"
"}\n"
- "$inline$ ::std::string* $classname$::$release_name$() {\n"
+ "$inline$::std::string* $classname$::$release_name$() {\n"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
" $clear_hasbit$\n"
" return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
"}\n"
- "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ "$inline$::std::string* $classname$::unsafe_arena_release_$name$() {\n"
" // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" $clear_hasbit$\n"
" return $name$_.UnsafeArenaRelease($default_variable$,\n"
" GetArenaNoVirtual());\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if ($name$ != NULL) {\n"
" $set_hasbit$\n"
" } else {\n"
@@ -219,7 +219,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(\n"
+ "$inline$void $classname$::unsafe_arena_set_allocated_$name$(\n"
" ::std::string* $name$) {\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" if ($name$ != NULL) {\n"
@@ -235,21 +235,21 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
} else {
// No-arena case.
printer->Print(variables,
- "$inline$ const ::std::string& $classname$::$name$() const {\n"
+ "$inline$const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.GetNoArena($default_variable$);\n"
"}\n"
- "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$void $classname$::set_$name$(const ::std::string& value) {\n"
" $set_hasbit$\n"
" $name$_.SetNoArena($default_variable$, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::set_$name$(const char* value) {\n"
+ "$inline$void $classname$::set_$name$(const char* value) {\n"
" $set_hasbit$\n"
" $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "$inline$ "
+ "$inline$"
"void $classname$::set_$name$(const $pointer_type$* value, "
"size_t size) {\n"
" $set_hasbit$\n"
@@ -257,17 +257,17 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" $string_piece$(reinterpret_cast<const char*>(value), size));\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$::std::string* $classname$::mutable_$name$() {\n"
" $set_hasbit$\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.MutableNoArena($default_variable$);\n"
"}\n"
- "$inline$ ::std::string* $classname$::$release_name$() {\n"
+ "$inline$::std::string* $classname$::$release_name$() {\n"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
" $clear_hasbit$\n"
" return $name$_.ReleaseNoArena($default_variable$);\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if ($name$ != NULL) {\n"
" $set_hasbit$\n"
" } else {\n"
@@ -339,8 +339,10 @@ GenerateConstructorCode(io::Printer* printer) const {
void StringFieldGenerator::
GenerateDestructorCode(io::Printer* printer) const {
if (SupportsArenas(descriptor_)) {
+ // The variable |arena| is defined by the enclosing code.
+ // See MessageGenerator::GenerateSharedDestructorCode.
printer->Print(variables_,
- "$name$_.Destroy($default_variable$, GetArenaNoVirtual());\n");
+ "$name$_.Destroy($default_variable$, arena);\n");
} else {
printer->Print(variables_,
"$name$_.DestroyNoArena($default_variable$);\n");
@@ -426,17 +428,17 @@ void StringOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
if (SupportsArenas(descriptor_)) {
printer->Print(variables,
- "$inline$ const ::std::string& $classname$::$name$() const {\n"
+ "$inline$const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_.Get($default_variable$);\n"
" }\n"
" return *$default_variable$;\n"
"}\n"
- "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$void $classname$::set_$name$(const ::std::string& value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -446,7 +448,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::set_$name$(const char* value) {\n"
+ "$inline$void $classname$::set_$name$(const char* value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -456,7 +458,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" $string_piece$(value), GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "$inline$ "
+ "$inline$"
"void $classname$::set_$name$(const $pointer_type$* value,\n"
" size_t size) {\n"
" if (!has_$name$()) {\n"
@@ -469,7 +471,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$::std::string* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -479,7 +481,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" GetArenaNoVirtual());\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
"}\n"
- "$inline$ ::std::string* $classname$::$release_name$() {\n"
+ "$inline$::std::string* $classname$::$release_name$() {\n"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
@@ -489,7 +491,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return NULL;\n"
" }\n"
"}\n"
- "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ "$inline$::std::string* $classname$::unsafe_arena_release_$name$() {\n"
" // @@protoc_insertion_point(field_unsafe_arena_release:$full_name$)\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" if (has_$name$()) {\n"
@@ -500,7 +502,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return NULL;\n"
" }\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if (!has_$name$()) {\n"
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
" }\n"
@@ -512,7 +514,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::unsafe_arena_set_allocated_$name$("
+ "$inline$void $classname$::unsafe_arena_set_allocated_$name$("
"::std::string* $name$) {\n"
" GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
" if (!has_$name$()) {\n"
@@ -530,14 +532,14 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
} else {
// No-arena case.
printer->Print(variables,
- "$inline$ const ::std::string& $classname$::$name$() const {\n"
+ "$inline$const ::std::string& $classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_.GetNoArena($default_variable$);\n"
" }\n"
" return *$default_variable$;\n"
"}\n"
- "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n"
+ "$inline$void $classname$::set_$name$(const ::std::string& value) {\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
@@ -547,7 +549,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::set_$name$(const char* value) {\n"
+ "$inline$void $classname$::set_$name$(const char* value) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -557,7 +559,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" $string_piece$(value));\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "$inline$ "
+ "$inline$"
"void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
@@ -568,7 +570,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" reinterpret_cast<const char*>(value), size));\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "$inline$ ::std::string* $classname$::mutable_$name$() {\n"
+ "$inline$::std::string* $classname$::mutable_$name$() {\n"
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
@@ -577,7 +579,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
"}\n"
- "$inline$ ::std::string* $classname$::$release_name$() {\n"
+ "$inline$::std::string* $classname$::$release_name$() {\n"
" // @@protoc_insertion_point(field_release:$full_name$)\n"
" if (has_$name$()) {\n"
" clear_has_$oneof_name$();\n"
@@ -586,7 +588,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer,
" return NULL;\n"
" }\n"
"}\n"
- "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ "$inline$void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
" if (!has_$name$()) {\n"
" $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
" }\n"
@@ -732,55 +734,55 @@ void RepeatedStringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer,
bool is_inline) const {
map<string, string> variables(variables_);
- variables["inline"] = is_inline ? "inline" : "";
+ variables["inline"] = is_inline ? "inline " : "";
printer->Print(variables,
- "$inline$ const ::std::string& $classname$::$name$(int index) const {\n"
+ "$inline$const ::std::string& $classname$::$name$(int index) const {\n"
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return $name$_.$cppget$(index);\n"
"}\n"
- "$inline$ ::std::string* $classname$::mutable_$name$(int index) {\n"
+ "$inline$::std::string* $classname$::mutable_$name$(int index) {\n"
" // @@protoc_insertion_point(field_mutable:$full_name$)\n"
" return $name$_.Mutable(index);\n"
"}\n"
- "$inline$ void $classname$::set_$name$(int index, const ::std::string& value) {\n"
+ "$inline$void $classname$::set_$name$(int index, const ::std::string& value) {\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
" $name$_.Mutable(index)->assign(value);\n"
"}\n"
- "$inline$ void $classname$::set_$name$(int index, const char* value) {\n"
+ "$inline$void $classname$::set_$name$(int index, const char* value) {\n"
" $name$_.Mutable(index)->assign(value);\n"
" // @@protoc_insertion_point(field_set_char:$full_name$)\n"
"}\n"
- "$inline$ void "
+ "$inline$void "
"$classname$::set_$name$"
"(int index, const $pointer_type$* value, size_t size) {\n"
" $name$_.Mutable(index)->assign(\n"
" reinterpret_cast<const char*>(value), size);\n"
" // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
"}\n"
- "$inline$ ::std::string* $classname$::add_$name$() {\n"
+ "$inline$::std::string* $classname$::add_$name$() {\n"
" // @@protoc_insertion_point(field_add_mutable:$full_name$)\n"
" return $name$_.Add();\n"
"}\n"
- "$inline$ void $classname$::add_$name$(const ::std::string& value) {\n"
+ "$inline$void $classname$::add_$name$(const ::std::string& value) {\n"
" $name$_.Add()->assign(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n"
- "$inline$ void $classname$::add_$name$(const char* value) {\n"
+ "$inline$void $classname$::add_$name$(const char* value) {\n"
" $name$_.Add()->assign(value);\n"
" // @@protoc_insertion_point(field_add_char:$full_name$)\n"
"}\n"
- "$inline$ void "
+ "$inline$void "
"$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,
- "$inline$ const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
+ "$inline$const ::google::protobuf::RepeatedPtrField< ::std::string>&\n"
"$classname$::$name$() const {\n"
" // @@protoc_insertion_point(field_list:$full_name$)\n"
" return $name$_;\n"
"}\n"
- "$inline$ ::google::protobuf::RepeatedPtrField< ::std::string>*\n"
+ "$inline$::google::protobuf::RepeatedPtrField< ::std::string>*\n"
"$classname$::mutable_$name$() {\n"
" // @@protoc_insertion_point(field_mutable_list:$full_name$)\n"
" return &$name$_;\n"
@@ -798,6 +800,11 @@ GenerateMergingCode(io::Printer* printer) const {
}
void RepeatedStringFieldGenerator::
+GenerateUnsafeMergingCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_.UnsafeMergeFrom(from.$name$_);\n");
+}
+
+void RepeatedStringFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
@@ -858,7 +865,8 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
void RepeatedStringFieldGenerator::
GenerateByteSize(io::Printer* printer) const {
printer->Print(variables_,
- "total_size += $tag_size$ * this->$name$_size();\n"
+ "total_size += $tag_size$ *\n"
+ " ::google::protobuf::internal::FromIntSize(this->$name$_size());\n"
"for (int i = 0; i < this->$name$_size(); i++) {\n"
" total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n"
" this->$name$(i));\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index cb4e8772..1dea7663 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -110,6 +110,7 @@ class RepeatedStringFieldGenerator : public FieldGenerator {
bool is_inline) const;
void GenerateClearingCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateUnsafeMergingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateMergeFromCodedStream(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index b7b6039a..d214ef0a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -129,12 +129,12 @@ TEST(GeneratedDescriptorTest, IdenticalDescriptors) {
// Test that descriptors are generated correctly by converting them to
// FileDescriptorProtos and comparing.
- FileDescriptorProto generated_decsriptor_proto, parsed_descriptor_proto;
- generated_descriptor->CopyTo(&generated_decsriptor_proto);
+ FileDescriptorProto generated_descriptor_proto, parsed_descriptor_proto;
+ generated_descriptor->CopyTo(&generated_descriptor_proto);
parsed_descriptor->CopyTo(&parsed_descriptor_proto);
EXPECT_EQ(parsed_descriptor_proto.DebugString(),
- generated_decsriptor_proto.DebugString());
+ generated_descriptor_proto.DebugString());
}
#if !defined(GOOGLE_PROTOBUF_CMAKE_BUILD) && !defined(_MSC_VER)
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 5e387285..3cbc530e 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -189,8 +189,6 @@ void MaybeRestartJavaMethod(io::Printer* printer,
*bytecode_estimate = 0;
}
}
-
-
} // namespace
FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options,
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 16c5bec5..07aa3565 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -92,7 +92,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
const JavaType valueJavaType = GetJavaType(value);
(*variables)["key_type"] = TypeName(key, name_resolver, false);
- (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
+ string boxed_key_type = TypeName(key, name_resolver, true);
+ (*variables)["boxed_key_type"] = boxed_key_type;
+ // Used for calling the serialization function.
+ (*variables)["short_key_type"] =
+ boxed_key_type.substr(boxed_key_type.rfind('.') + 1);
(*variables)["key_wire_type"] = WireType(key);
(*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
(*variables)["key_null_check"] = IsReferenceType(keyJavaType) ?
@@ -147,6 +151,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
name_resolver->GetImmutableClassName(descriptor->file()) +
".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
"_descriptor, ";
+ (*variables)["ver"] = GeneratedCodeVersionSuffix();
}
} // namespace
@@ -661,21 +666,23 @@ GenerateParsingCode(io::Printer* printer) const {
variables_,
"com.google.protobuf.ByteString bytes = input.readBytes();\n"
"com.google.protobuf.MapEntry<$type_parameters$>\n"
- "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n");
+ "$name$__ = $default_entry$.getParserForType().parseFrom(bytes);\n");
printer->Print(
variables_,
- "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
+ "if ($value_enum_type$.forNumber($name$__.getValue()) == null) {\n"
" unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
"} else {\n"
- " $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
+ " $name$_.getMutableMap().put(\n"
+ " $name$__.getKey(), $name$__.getValue());\n"
"}\n");
} else {
printer->Print(
variables_,
"com.google.protobuf.MapEntry<$type_parameters$>\n"
- "$name$ = input.readMessage(\n"
+ "$name$__ = input.readMessage(\n"
" $default_entry$.getParserForType(), extensionRegistry);\n"
- "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
+ "$name$_.getMutableMap().put(\n"
+ " $name$__.getKey(), $name$__.getValue());\n");
}
}
@@ -688,15 +695,12 @@ void ImmutableMapFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(
variables_,
- "for (java.util.Map.Entry<$type_parameters$> entry\n"
- " : internalGet$capitalized_name$().getMap().entrySet()) {\n"
- " com.google.protobuf.MapEntry<$type_parameters$>\n"
- " $name$ = $default_entry$.newBuilderForType()\n"
- " .setKey(entry.getKey())\n"
- " .setValue(entry.getValue())\n"
- " .build();\n"
- " output.writeMessage($number$, $name$);\n"
- "}\n");
+ "com.google.protobuf.GeneratedMessage$ver$\n"
+ " .serialize$short_key_type$MapTo(\n"
+ " output,\n"
+ " internalGet$capitalized_name$(),\n"
+ " $default_entry$,\n"
+ " $number$);\n");
}
void ImmutableMapFieldGenerator::
@@ -706,12 +710,12 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
"for (java.util.Map.Entry<$type_parameters$> entry\n"
" : internalGet$capitalized_name$().getMap().entrySet()) {\n"
" com.google.protobuf.MapEntry<$type_parameters$>\n"
- " $name$ = $default_entry$.newBuilderForType()\n"
+ " $name$__ = $default_entry$.newBuilderForType()\n"
" .setKey(entry.getKey())\n"
" .setValue(entry.getValue())\n"
" .build();\n"
" size += com.google.protobuf.CodedOutputStream\n"
- " .computeMessageSize($number$, $name$);\n"
+ " .computeMessageSize($number$, $name$__);\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
index 0d3bea17..5f102e07 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -765,14 +765,14 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(
variables_,
"com.google.protobuf.ByteString bytes = input.readBytes();\n"
- "java.util.Map.Entry<$type_parameters$> $name$ =\n"
+ "java.util.Map.Entry<$type_parameters$> $name$__ =\n"
" $default_entry$.parseEntry(bytes, extensionRegistry);\n");
printer->Print(
variables_,
- "if ($value_enum_type$.forNumber($name$.getValue()) == null) {\n"
+ "if ($value_enum_type$.forNumber($name$__.getValue()) == null) {\n"
" super.mergeLengthDelimitedField($number$, bytes);\n"
"} else {\n"
- " $name$_.put($name$);\n"
+ " $name$_.put($name$__);\n"
"}\n");
} else {
printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 6c80d070..68d28b05 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -928,7 +928,7 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
case FieldDescriptor::LABEL_REPEATED:
if (IsMapEntry(field->message_type())) {
printer->Print(
- "for ($type$ item : get$name$().values()) {\n"
+ "for ($type$ item : get$name$Map().values()) {\n"
" if (!item.isInitialized()) {\n"
" memoizedIsInitialized = 0;\n"
" return false;\n"
diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc
index 42154694..cd82c51a 100644
--- a/src/google/protobuf/compiler/java/java_message_builder.cc
+++ b/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -184,6 +184,11 @@ Generate(io::Printer* printer) {
"}\n"
"\n");
} else {
+ // Override methods declared in GeneratedMessage to return the concrete
+ // generated type so callsites won't depend on GeneratedMessage. This
+ // is needed to keep binary compatibility when we change generated code
+ // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
+ // we changed all generated code to subclass GeneratedMessageV3).
printer->Print(
"public final Builder setUnknownFields(\n"
" final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
@@ -456,6 +461,11 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
"\n",
"classname", name_resolver_->GetImmutableClassName(descriptor_));
+ // Override methods declared in GeneratedMessage to return the concrete
+ // generated type so callsites won't depend on GeneratedMessage. This
+ // is needed to keep binary compatibility when we change generated code
+ // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
+ // we changed all generated code to subclass GeneratedMessageV3).
printer->Print(
"public Builder clone() {\n"
" return (Builder) super.clone();\n"
@@ -596,7 +606,6 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
" return this;\n"
"}\n"
"\n");
-
}
}
@@ -690,7 +699,7 @@ void MessageBuilderGenerator::GenerateIsInitialized(
case FieldDescriptor::LABEL_REPEATED:
if (IsMapEntry(field->message_type())) {
printer->Print(
- "for ($type$ item : get$name$().values()) {\n"
+ "for ($type$ item : get$name$Map().values()) {\n"
" if (!item.isInitialized()) {\n"
" return false;\n"
" }\n"
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
index 14281816..cba18360 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -145,6 +145,7 @@ GenerateInterfaceMembers(io::Printer* printer) const {
void ImmutableMessageFieldLiteGenerator::
GenerateMembers(io::Printer* printer) const {
+
printer->Print(variables_,
"private $type$ $name$_;\n");
PrintExtraFieldInfo(variables_, printer);
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 7c8c4a03..0c5a1f8a 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -179,6 +179,7 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
/* immutable = */ true);
+
// The builder_type stores the super type name of the nested Builder class.
string builder_type;
if (descriptor_->extension_range_count() > 0) {
@@ -203,7 +204,6 @@ void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
}
printer->Indent();
-
GenerateConstructor(printer);
// Nested types
@@ -748,7 +748,7 @@ void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized(
case FieldDescriptor::LABEL_REPEATED:
if (IsMapEntry(field->message_type())) {
printer->Print(
- "for ($type$ item : get$name$().values()) {\n"
+ "for ($type$ item : get$name$Map().values()) {\n"
" if (!item.isInitialized()) {\n"
" if (shouldMemoize) {\n"
" memoizedIsInitialized = 0;\n"
diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc
index 9f34f010..cfa8295d 100644
--- a/src/google/protobuf/compiler/java/java_service.cc
+++ b/src/google/protobuf/compiler/java/java_service.cc
@@ -184,6 +184,10 @@ void ImmutableServiceGenerator::GenerateAbstractMethods(io::Printer* printer) {
}
}
+string ImmutableServiceGenerator::GetOutput(const MethodDescriptor* method) {
+ return name_resolver_->GetImmutableClassName(method->output_type());
+}
+
void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) {
printer->Print(
"\n"
@@ -209,8 +213,7 @@ void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) {
vars["method"] = UnderscoresToCamelCase(method);
vars["input"] = name_resolver_->GetImmutableClassName(
method->input_type());
- vars["output"] = name_resolver_->GetImmutableClassName(
- method->output_type());
+ vars["output"] = GetOutput(method);
printer->Print(vars,
"case $index$:\n"
" this.$method$(controller, ($input$)request,\n"
@@ -257,8 +260,7 @@ void ImmutableServiceGenerator::GenerateCallBlockingMethod(
vars["method"] = UnderscoresToCamelCase(method);
vars["input"] = name_resolver_->GetImmutableClassName(
method->input_type());
- vars["output"] = name_resolver_->GetImmutableClassName(
- method->output_type());
+ vars["output"] = GetOutput(method);
printer->Print(vars,
"case $index$:\n"
" return impl.$method$(controller, ($input$)request);\n");
@@ -353,8 +355,7 @@ void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) {
map<string, string> vars;
vars["index"] = SimpleItoa(i);
- vars["output"] = name_resolver_->GetImmutableClassName(
- method->output_type());
+ vars["output"] = GetOutput(method);
printer->Print(vars,
"channel.callMethod(\n"
" getDescriptor().getMethods().get($index$),\n"
@@ -418,8 +419,7 @@ void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) {
map<string, string> vars;
vars["index"] = SimpleItoa(i);
- vars["output"] = name_resolver_->GetImmutableClassName(
- method->output_type());
+ vars["output"] = GetOutput(method);
printer->Print(vars,
"return ($output$) channel.callBlockingMethod(\n"
" getDescriptor().getMethods().get($index$),\n"
@@ -443,7 +443,7 @@ void ImmutableServiceGenerator::GenerateMethodSignature(io::Printer* printer,
map<string, string> vars;
vars["name"] = UnderscoresToCamelCase(method);
vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
- vars["output"] = name_resolver_->GetImmutableClassName(method->output_type());
+ vars["output"] = GetOutput(method);
vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : "";
printer->Print(vars,
"public $abstract$ void $name$(\n"
@@ -458,7 +458,7 @@ void ImmutableServiceGenerator::GenerateBlockingMethodSignature(
map<string, string> vars;
vars["method"] = UnderscoresToCamelCase(method);
vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
- vars["output"] = name_resolver_->GetImmutableClassName(method->output_type());
+ vars["output"] = GetOutput(method);
printer->Print(vars,
"\n"
"public $output$ $method$(\n"
diff --git a/src/google/protobuf/compiler/java/java_service.h b/src/google/protobuf/compiler/java/java_service.h
index 5fc9e2f6..12b3f942 100644
--- a/src/google/protobuf/compiler/java/java_service.h
+++ b/src/google/protobuf/compiler/java/java_service.h
@@ -122,6 +122,9 @@ class ImmutableServiceGenerator : public ServiceGenerator {
void GenerateBlockingMethodSignature(io::Printer* printer,
const MethodDescriptor* method);
+ // Return the output type of the method.
+ string GetOutput(const MethodDescriptor* method);
+
Context* context_;
ClassNameResolver* name_resolver_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableServiceGenerator);
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index 52893721..18bf1f51 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -119,7 +119,6 @@ void SharedCodeGenerator::Generate(GeneratorContext* context,
}
}
-
void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) {
// Embed the descriptor. We simply serialize the entire FileDescriptorProto
// and embed it as a string literal, which is parsed and built into real
@@ -134,7 +133,6 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) {
FileDescriptorProto file_proto;
file_->CopyTo(&file_proto);
-
string file_data;
file_proto.SerializeToString(&file_data);
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index 58c77d00..1a882057 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -153,8 +153,8 @@ string StripProto(const string& filename) {
// Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript
// file foo/bar/baz.js.
-string GetJSFilename(const string& filename) {
- return StripProto(filename) + "_pb.js";
+string GetJSFilename(const GeneratorOptions& options, const string& filename) {
+ return StripProto(filename) + options.GetFileNameExtension();
}
// Given a filename like foo/bar/baz.proto, returns the root directory
@@ -273,7 +273,7 @@ string GetPath(const GeneratorOptions& options,
string MaybeCrossFileRef(const GeneratorOptions& options,
const FileDescriptor* from_file,
const Descriptor* to_message) {
- if (options.import_style == GeneratorOptions::IMPORT_COMMONJS &&
+ if (options.import_style == GeneratorOptions::kImportCommonJs &&
from_file != to_message->file()) {
// Cross-file ref in CommonJS needs to use the module alias instead of
// the global name.
@@ -405,21 +405,24 @@ string ToFileName(const string& input) {
// that top-level extensions should go in.
string GetExtensionFileName(const GeneratorOptions& options,
const FileDescriptor* file) {
- return options.output_dir + "/" + ToFileName(GetPath(options, file)) + ".js";
+ return options.output_dir + "/" + ToFileName(GetPath(options, file)) +
+ options.GetFileNameExtension();
}
// When we're generating one output file per type name, this is the filename
// that a top-level message should go in.
string GetMessageFileName(const GeneratorOptions& options,
const Descriptor* desc) {
- return options.output_dir + "/" + ToFileName(desc->name()) + ".js";
+ return options.output_dir + "/" + ToFileName(desc->name()) +
+ options.GetFileNameExtension();
}
// When we're generating one output file per type name, this is the filename
// that a top-level message should go in.
string GetEnumFileName(const GeneratorOptions& options,
const EnumDescriptor* desc) {
- return options.output_dir + "/" + ToFileName(desc->name()) + ".js";
+ return options.output_dir + "/" + ToFileName(desc->name()) +
+ options.GetFileNameExtension();
}
// Returns the message/response ID, if set.
@@ -444,9 +447,19 @@ bool IgnoreField(const FieldDescriptor* field) {
}
+// Used inside Google only -- do not remove.
+bool ShouldTreatMapsAsRepeatedFields(const FileDescriptor& descriptor) {
+ return false;
+}
+
// Do we ignore this message type?
bool IgnoreMessage(const GeneratorOptions& options, const Descriptor* d) {
- return d->options().map_entry();
+ return d->options().map_entry() &&
+ !ShouldTreatMapsAsRepeatedFields(*d->file());
+}
+
+bool IsMap(const GeneratorOptions& options, const FieldDescriptor* field) {
+ return field->is_map() && !ShouldTreatMapsAsRepeatedFields(*field->file());
}
// Does JSPB ignore this entire oneof? True only if all fields are ignored.
@@ -459,10 +472,8 @@ bool IgnoreOneof(const OneofDescriptor* oneof) {
return true;
}
-string JSIdent(const GeneratorOptions& options,
- const FieldDescriptor* field,
- bool is_upper_camel,
- bool is_map) {
+string JSIdent(const GeneratorOptions& options, const FieldDescriptor* field,
+ bool is_upper_camel, bool is_map, bool drop_list) {
string result;
if (field->type() == FieldDescriptor::TYPE_GROUP) {
result = is_upper_camel ?
@@ -473,10 +484,10 @@ string JSIdent(const GeneratorOptions& options,
ToUpperCamel(ParseLowerUnderscore(field->name())) :
ToLowerCamel(ParseLowerUnderscore(field->name()));
}
- if (is_map || (field->is_map())) {
+ if (is_map || IsMap(options, field)) {
// JSPB-style or proto3-style map.
result += "Map";
- } else if (field->is_repeated()) {
+ } else if (!drop_list && field->is_repeated()) {
// Repeated field.
result += "List";
}
@@ -485,11 +496,10 @@ string JSIdent(const GeneratorOptions& options,
string JSObjectFieldName(const GeneratorOptions& options,
const FieldDescriptor* field) {
- string name = JSIdent(
- options,
- field,
- /* is_upper_camel = */ false,
- /* is_map = */ false);
+ string name = JSIdent(options, field,
+ /* is_upper_camel = */ false,
+ /* is_map = */ false,
+ /* drop_list = */ false);
if (IsReserved(name)) {
name = "pb_" + name;
}
@@ -514,10 +524,11 @@ string JSByteGetterSuffix(BytesMode bytes_mode) {
// name, e.g. MyField for .getMyField().
string JSGetterName(const GeneratorOptions& options,
const FieldDescriptor* field,
- BytesMode bytes_mode = BYTES_DEFAULT) {
+ BytesMode bytes_mode = BYTES_DEFAULT,
+ bool drop_list = false) {
string name = JSIdent(options, field,
/* is_upper_camel = */ true,
- /* is_map = */ false);
+ /* is_map = */ false, drop_list);
if (field->type() == FieldDescriptor::TYPE_BYTES) {
string suffix = JSByteGetterSuffix(bytes_mode);
if (!suffix.empty()) {
@@ -535,7 +546,8 @@ string JSMapGetterName(const GeneratorOptions& options,
const FieldDescriptor* field) {
return JSIdent(options, field,
/* is_upper_camel = */ true,
- /* is_map = */ true);
+ /* is_map = */ true,
+ /* drop_list = */ false);
}
@@ -768,6 +780,10 @@ string MaybeNumberString(const FieldDescriptor* field, const string& orig) {
}
string JSFieldDefault(const FieldDescriptor* field) {
+ if (field->is_repeated()) {
+ return "[]";
+ }
+
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
return MaybeNumberString(
@@ -909,20 +925,91 @@ string JSTypeName(const GeneratorOptions& options,
}
}
-bool HasFieldPresence(const FieldDescriptor* field);
+bool UseBrokenPresenceSemantics(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ return options.broken_proto3_semantics;
+ } else if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO2) {
+ return false;
+ } else {
+ GOOGLE_LOG(FATAL) << "We can only handle syntax=proto2 and syntax=proto3.";
+ return false;
+ }
+}
+
+// Returns true for fields that return "null" from accessors when they are
+// unset. This should normally only be true for non-repeated submessages, but
+// we have legacy users who relied on old behavior where accessors behaved this
+// way.
+bool ReturnsNullWhenUnset(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ field->is_optional()) {
+ return true;
+ }
+
+ // TODO(haberman): remove this case and unconditionally return false.
+ return UseBrokenPresenceSemantics(options, field) && !field->is_repeated() &&
+ !field->has_default_value();
+}
+
+// In a sane world, this would be the same as ReturnsNullWhenUnset(). But in
+// the status quo, some fields declare that they never return null/undefined
+// even though they actually do:
+// * required fields
+// * optional enum fields
+// * proto3 primitive fields.
+bool DeclaredReturnTypeIsNullable(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (field->is_required() || field->type() == FieldDescriptor::TYPE_ENUM) {
+ return false;
+ }
+
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+ field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ return false;
+ }
+
+ return ReturnsNullWhenUnset(options, field);
+}
+
+bool SetterAcceptsUndefined(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (ReturnsNullWhenUnset(options, field)) {
+ return true;
+ }
+
+ // Broken presence semantics always accepts undefined for setters.
+ return UseBrokenPresenceSemantics(options, field);
+}
+
+bool SetterAcceptsNull(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (ReturnsNullWhenUnset(options, field)) {
+ return true;
+ }
+
+ // With broken presence semantics, fields with defaults accept "null" for
+ // setters, but other fields do not. This is a strange quirk of the old
+ // codegen.
+ return UseBrokenPresenceSemantics(options, field) &&
+ field->has_default_value();
+}
+
+// Returns types which are known to by non-nullable by default.
+// The style guide requires that we omit "!" in this case.
+bool IsPrimitive(const string& type) {
+ return type == "undefined" || type == "string" || type == "number" ||
+ type == "boolean";
+}
string JSFieldTypeAnnotation(const GeneratorOptions& options,
const FieldDescriptor* field,
- bool force_optional,
+ bool is_setter_argument,
bool force_present,
bool singular_if_not_packed,
BytesMode bytes_mode = BYTES_DEFAULT) {
- bool is_primitive =
- (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM &&
- field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE &&
- (field->type() != FieldDescriptor::TYPE_BYTES ||
- bytes_mode == BYTES_B64));
-
+ GOOGLE_CHECK(!(is_setter_argument && force_present));
string jstype = JSTypeName(options, field, bytes_mode);
if (field->is_repeated() &&
@@ -931,27 +1018,35 @@ string JSFieldTypeAnnotation(const GeneratorOptions& options,
bytes_mode == BYTES_DEFAULT) {
jstype = "(Array<!Uint8Array>|Array<string>)";
} else {
- if (!is_primitive) {
+ if (!IsPrimitive(jstype)) {
jstype = "!" + jstype;
}
jstype = "Array.<" + jstype + ">";
}
- if (!force_optional) {
- jstype = "!" + jstype;
- }
}
- if (field->is_optional() && is_primitive &&
- force_optional && !force_present) {
- jstype += "?";
- } else if (field->is_required() && !is_primitive && !force_optional) {
- jstype = "!" + jstype;
- }
+ bool is_null_or_undefined = false;
- if (force_optional && HasFieldPresence(field)) {
- jstype += "|undefined";
+ if (is_setter_argument) {
+ if (SetterAcceptsNull(options, field)) {
+ jstype = "?" + jstype;
+ is_null_or_undefined = true;
+ }
+
+ if (SetterAcceptsUndefined(options, field)) {
+ jstype += "|undefined";
+ is_null_or_undefined = true;
+ }
+ } else if (force_present) {
+ // Don't add null or undefined.
+ } else {
+ if (DeclaredReturnTypeIsNullable(options, field)) {
+ jstype = "?" + jstype;
+ is_null_or_undefined = true;
+ }
}
- if (force_present && jstype[0] != '!' && !is_primitive) {
+
+ if (!is_null_or_undefined && !IsPrimitive(jstype)) {
jstype = "!" + jstype;
}
@@ -1007,9 +1102,10 @@ string JSReturnDoc(const GeneratorOptions& options,
return "";
}
-bool HasRepeatedFields(const Descriptor* desc) {
+bool HasRepeatedFields(const GeneratorOptions& options,
+ const Descriptor* desc) {
for (int i = 0; i < desc->field_count(); i++) {
- if (desc->field(i)->is_repeated() && !desc->field(i)->is_map()) {
+ if (desc->field(i)->is_repeated() && !IsMap(options, desc->field(i))) {
return true;
}
}
@@ -1020,8 +1116,9 @@ static const char* kRepeatedFieldArrayName = ".repeatedFields_";
string RepeatedFieldsArrayName(const GeneratorOptions& options,
const Descriptor* desc) {
- return HasRepeatedFields(desc) ?
- (GetPath(options, desc) + kRepeatedFieldArrayName) : "null";
+ return HasRepeatedFields(options, desc)
+ ? (GetPath(options, desc) + kRepeatedFieldArrayName)
+ : "null";
}
bool HasOneofFields(const Descriptor* desc) {
@@ -1041,10 +1138,11 @@ string OneofFieldsArrayName(const GeneratorOptions& options,
(GetPath(options, desc) + kOneofGroupArrayName) : "null";
}
-string RepeatedFieldNumberList(const Descriptor* desc) {
+string RepeatedFieldNumberList(const GeneratorOptions& options,
+ const Descriptor* desc) {
std::vector<string> numbers;
for (int i = 0; i < desc->field_count(); i++) {
- if (desc->field(i)->is_repeated() && !desc->field(i)->is_map()) {
+ if (desc->field(i)->is_repeated() && !IsMap(options, desc->field(i))) {
numbers.push_back(JSFieldIndex(desc->field(i)));
}
}
@@ -1108,7 +1206,7 @@ string JSExtensionsObjectName(const GeneratorOptions& options,
const FileDescriptor* from_file,
const Descriptor* desc) {
if (desc->full_name() == "google.protobuf.bridge.MessageSet") {
- // TODO(haberman): fix this for the IMPORT_COMMONJS case.
+ // TODO(haberman): fix this for the kImportCommonJs case.
return "jspb.Message.messageSetExtensions";
} else {
return MaybeCrossFileRef(options, from_file, desc) + ".extensions";
@@ -1130,7 +1228,7 @@ const FieldDescriptor* MapFieldValue(const FieldDescriptor* field) {
string FieldDefinition(const GeneratorOptions& options,
const FieldDescriptor* field) {
- if (field->is_map()) {
+ if (IsMap(options, field)) {
const FieldDescriptor* key_field = MapFieldKey(field);
const FieldDescriptor* value_field = MapFieldValue(field);
string key_type = ProtoTypeName(options, key_field);
@@ -1254,47 +1352,24 @@ string GetPivot(const Descriptor* desc) {
return SimpleItoa(pivot);
}
-// Returns true for fields that represent "null" as distinct from the default
-// value. See http://go/proto3#heading=h.kozewqqcqhuz for more information.
-bool HasFieldPresence(const FieldDescriptor* field) {
- if (field->is_repeated()) {
+// Whether this field represents presence. For fields with presence, we
+// generate extra methods (clearFoo() and hasFoo()) for this field.
+bool HasFieldPresence(const GeneratorOptions& options,
+ const FieldDescriptor* field) {
+ if (field->is_repeated() || field->is_map()) {
+ // We say repeated fields and maps don't have presence, but we still do
+ // generate clearFoo() methods for them through a special case elsewhere.
return false;
}
- return
- (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ||
- (field->containing_oneof() != NULL) ||
- (field->file()->syntax() != FileDescriptor::SYNTAX_PROTO3);
-}
-
-// For proto3 fields without presence, returns a string representing the default
-// value in JavaScript. See http://go/proto3#heading=h.kozewqqcqhuz for more
-// information.
-string Proto3PrimitiveFieldDefault(const FieldDescriptor* field) {
- switch (field->cpp_type()) {
- case FieldDescriptor::CPPTYPE_INT32:
- case FieldDescriptor::CPPTYPE_INT64:
- case FieldDescriptor::CPPTYPE_UINT32:
- case FieldDescriptor::CPPTYPE_UINT64: {
- return "0";
- }
-
- case FieldDescriptor::CPPTYPE_ENUM:
- case FieldDescriptor::CPPTYPE_FLOAT:
- case FieldDescriptor::CPPTYPE_DOUBLE:
- return "0";
-
- case FieldDescriptor::CPPTYPE_BOOL:
- return "false";
-
- case FieldDescriptor::CPPTYPE_STRING: // includes BYTES
- return "\"\"";
-
- default:
- // MESSAGE is handled separately.
- assert(false);
- return "";
+ if (UseBrokenPresenceSemantics(options, field)) {
+ // Proto3 files with broken presence semantics have field presence.
+ return true;
}
+
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
+ field->containing_oneof() != NULL ||
+ field->file()->syntax() == FileDescriptor::SYNTAX_PROTO2;
}
// We use this to implement the semantics that same file can be generated
@@ -1524,8 +1599,19 @@ void Generator::GenerateProvides(const GeneratorOptions& options,
std::set<string>* provided) const {
for (std::set<string>::iterator it = provided->begin();
it != provided->end(); ++it) {
- printer->Print("goog.provide('$name$');\n",
- "name", *it);
+ if (options.import_style == GeneratorOptions::kImportClosure) {
+ printer->Print("goog.provide('$name$');\n", "name", *it);
+ } else {
+ // We aren't using Closure's import system, but we use goog.exportSymbol()
+ // to construct the expected tree of objects, eg.
+ //
+ // goog.exportSymbol('foo.bar.Baz', null, this);
+ //
+ // // Later generated code expects foo.bar = {} to exist:
+ // foo.bar.Baz = function() { /* ... */ }
+ printer->Print("goog.exportSymbol('$name$', null, global);\n", "name",
+ *it);
+ }
}
}
@@ -1548,7 +1634,7 @@ void Generator::GenerateRequiresForLibrary(
const GeneratorOptions& options, io::Printer* printer,
const vector<const FileDescriptor*>& files,
std::set<string>* provided) const {
- GOOGLE_CHECK_EQ(options.import_style, GeneratorOptions::IMPORT_CLOSURE);
+ GOOGLE_CHECK_EQ(options.import_style, GeneratorOptions::kImportClosure);
// For Closure imports we need to import every message type individually.
std::set<string> required;
std::set<string> forwards;
@@ -1623,6 +1709,10 @@ void Generator::GenerateRequiresImpl(const GeneratorOptions& options,
}
}
if (require_extension) {
+ if (options.binary) {
+ printer->Print(
+ "goog.require('jspb.ExtensionFieldBinaryInfo');\n");
+ }
printer->Print(
"goog.require('jspb.ExtensionFieldInfo');\n");
}
@@ -1755,14 +1845,13 @@ void Generator::GenerateClass(const GeneratorOptions& options,
GenerateClassDeserializeBinary(options, printer, desc);
GenerateClassSerializeBinary(options, printer, desc);
}
- GenerateClassClone(options, printer, desc);
GenerateClassRegistration(options, printer, desc);
GenerateClassFields(options, printer, desc);
if (IsExtendable(desc) && desc->full_name() != "google.protobuf.bridge.MessageSet") {
GenerateClassExtensionFieldInfo(options, printer, desc);
}
- if (options.import_style != GeneratorOptions:: IMPORT_CLOSURE) {
+ if (options.import_style != GeneratorOptions::kImportClosure) {
for (int i = 0; i < desc->extension_count(); i++) {
GenerateExtension(options, printer, desc->extension(i));
}
@@ -1820,7 +1909,7 @@ void Generator::GenerateClassConstructor(const GeneratorOptions& options,
void Generator::GenerateClassFieldInfo(const GeneratorOptions& options,
io::Printer* printer,
const Descriptor* desc) const {
- if (HasRepeatedFields(desc)) {
+ if (HasRepeatedFields(options, desc)) {
printer->Print(
"/**\n"
" * List of repeated fields within this message type.\n"
@@ -1831,7 +1920,7 @@ void Generator::GenerateClassFieldInfo(const GeneratorOptions& options,
"\n",
"classname", GetPath(options, desc),
"rptfieldarray", kRepeatedFieldArrayName,
- "rptfields", RepeatedFieldNumberList(desc));
+ "rptfields", RepeatedFieldNumberList(options, desc));
}
if (HasOneofFields(desc)) {
@@ -2000,14 +2089,59 @@ void Generator::GenerateClassToObject(const GeneratorOptions& options,
"classname", GetPath(options, desc));
}
+void Generator::GenerateFieldValueExpression(io::Printer* printer,
+ const char *obj_reference,
+ const FieldDescriptor* field,
+ bool use_default) const {
+ bool is_float_or_double =
+ field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
+ field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE;
+ if (use_default) {
+ if (is_float_or_double) {
+ // Coerce "Nan" and "Infinity" to actual float values.
+ //
+ // This will change null to 0, but that doesn't matter since we're getting
+ // with a default.
+ printer->Print("+");
+ }
+
+ printer->Print(
+ "jspb.Message.getFieldWithDefault($obj$, $index$, $default$)",
+ "obj", obj_reference,
+ "index", JSFieldIndex(field),
+ "default", JSFieldDefault(field));
+ } else {
+ if (is_float_or_double) {
+ if (field->is_required()) {
+ // Use "+" to convert all fields to numeric (including null).
+ printer->Print(
+ "+jspb.Message.getField($obj$, $index$)",
+ "index", JSFieldIndex(field),
+ "obj", obj_reference);
+ } else {
+ // Converts "NaN" and "Infinity" while preserving null.
+ printer->Print(
+ "jspb.Message.get$cardinality$FloatingPointField($obj$, $index$)",
+ "cardinality", field->is_repeated() ? "Repeated" : "Optional",
+ "index", JSFieldIndex(field),
+ "obj", obj_reference);
+ }
+ } else {
+ printer->Print("jspb.Message.getField($obj$, $index$)",
+ "index", JSFieldIndex(field),
+ "obj", obj_reference);
+ }
+ }
+}
+
void Generator::GenerateClassFieldToObject(const GeneratorOptions& options,
io::Printer* printer,
const FieldDescriptor* field) const {
printer->Print("$fieldname$: ",
"fieldname", JSObjectFieldName(options, field));
- if (field->is_map()) {
- printer->Print("(f = msg.get$name$(true)) ? f.toArray() : []",
+ if (IsMap(options, field)) {
+ printer->Print("(f = msg.get$name$()) ? f.toArray() : []",
"name", JSGetterName(options, field));
} else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
// Message field.
@@ -2024,40 +2158,29 @@ void Generator::GenerateClassFieldToObject(const GeneratorOptions& options,
"getter", JSGetterName(options, field),
"type", SubmessageTypeRef(options, field));
}
+ } else if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ // For bytes fields we want to always return the B64 data.
+ printer->Print("msg.get$getter$()",
+ "getter", JSGetterName(options, field, BYTES_B64));
} else {
- // Simple field (singular or repeated).
- if ((!HasFieldPresence(field) && !field->is_repeated()) ||
- field->type() == FieldDescriptor::TYPE_BYTES) {
- // Delegate to the generated get<field>() method in order not to duplicate
- // the proto3-field-default-value or byte-coercion logic here.
- printer->Print("msg.get$getter$()",
- "getter", JSGetterName(options, field, BYTES_B64));
- } else {
- if (field->has_default_value()) {
- printer->Print("!msg.has$name$() ? $defaultValue$ : ",
- "name", JSGetterName(options, field),
- "defaultValue", JSFieldDefault(field));
- }
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
- field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
- if (field->is_repeated()) {
- printer->Print("jspb.Message.getRepeatedFloatingPointField("
- "msg, $index$)",
- "index", JSFieldIndex(field));
- } else if (field->is_optional() && !field->has_default_value()) {
- printer->Print("jspb.Message.getOptionalFloatingPointField("
- "msg, $index$)",
- "index", JSFieldIndex(field));
- } else {
- // Convert "NaN" to NaN.
- printer->Print("+jspb.Message.getField(msg, $index$)",
- "index", JSFieldIndex(field));
- }
- } else {
- printer->Print("jspb.Message.getField(msg, $index$)",
- "index", JSFieldIndex(field));
- }
+ bool use_default = field->has_default_value();
+
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+ // Repeated fields get initialized to their default in the constructor
+ // (why?), so we emit a plain getField() call for them.
+ !field->is_repeated() && !UseBrokenPresenceSemantics(options, field)) {
+ // Proto3 puts all defaults (including implicit defaults) in toObject().
+ // But for proto2 we leave the existing semantics unchanged: unset fields
+ // without default are unset.
+ use_default = true;
}
+
+ // We don't implement this by calling the accessors, because the semantics
+ // of the accessors are changing independently of the toObject() semantics.
+ // We are migrating the accessors to return defaults instead of null, but
+ // it may take longer to migrate toObject (or we might not want to do it at
+ // all). So we want to generate independent code.
+ GenerateFieldValueExpression(printer, "msg", field, use_default);
}
}
@@ -2091,8 +2214,7 @@ void Generator::GenerateClassFieldFromObject(
const GeneratorOptions& options,
io::Printer* printer,
const FieldDescriptor* field) const {
-
- if (field->is_map()) {
+ if (IsMap(options, field)) {
// `msg` is a newly-constructed message object that has not yet built any
// map containers wrapping underlying arrays, so we can simply directly set
// the array here without fear of a stale wrapper.
@@ -2133,21 +2255,6 @@ void Generator::GenerateClassFieldFromObject(
}
}
-void Generator::GenerateClassClone(const GeneratorOptions& options,
- io::Printer* printer,
- const Descriptor* desc) const {
- printer->Print(
- "/**\n"
- " * Creates a deep clone of this proto. No data is shared with the "
- "original.\n"
- " * @return {!$name$} The clone.\n"
- " */\n"
- "$name$.prototype.cloneMessage = function() {\n"
- " return /** @type {!$name$} */ (jspb.Message.cloneMessage(this));\n"
- "};\n\n\n",
- "name", GetPath(options, desc));
-}
-
void Generator::GenerateClassRegistration(const GeneratorOptions& options,
io::Printer* printer,
const Descriptor* desc) const {
@@ -2175,12 +2282,11 @@ void GenerateBytesWrapper(const GeneratorOptions& options,
io::Printer* printer,
const FieldDescriptor* field,
BytesMode bytes_mode) {
- string type =
- JSFieldTypeAnnotation(options, field,
- /* force_optional = */ false,
- /* force_present = */ !HasFieldPresence(field),
- /* singular_if_not_packed = */ false,
- bytes_mode);
+ string type = JSFieldTypeAnnotation(
+ options, field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false, bytes_mode);
printer->Print(
"/**\n"
" * $fielddef$\n"
@@ -2208,20 +2314,20 @@ void GenerateBytesWrapper(const GeneratorOptions& options,
void Generator::GenerateClassField(const GeneratorOptions& options,
io::Printer* printer,
const FieldDescriptor* field) const {
- if (field->is_map()) {
+ if (IsMap(options, field)) {
const FieldDescriptor* key_field = MapFieldKey(field);
const FieldDescriptor* value_field = MapFieldValue(field);
// Map field: special handling to instantiate the map object on demand.
string key_type =
JSFieldTypeAnnotation(
options, key_field,
- /* force_optional = */ false,
+ /* is_setter_argument = */ false,
/* force_present = */ true,
/* singular_if_not_packed = */ false);
string value_type =
JSFieldTypeAnnotation(
options, value_field,
- /* force_optional = */ false,
+ /* is_setter_argument = */ false,
/* force_present = */ true,
/* singular_if_not_packed = */ false);
@@ -2275,7 +2381,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"fielddef", FieldDefinition(options, field),
"comment", FieldComments(field, BYTES_DEFAULT),
"type", JSFieldTypeAnnotation(options, field,
- /* force_optional = */ false,
+ /* is_setter_argument = */ false,
/* force_present = */ false,
/* singular_if_not_packed = */ false));
printer->Print(
@@ -2289,7 +2395,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"class", GetPath(options, field->containing_type()),
"name", JSGetterName(options, field),
"type", JSFieldTypeAnnotation(options, field,
- /* force_optional = */ false,
+ /* is_setter_argument = */ false,
/* force_present = */ false,
/* singular_if_not_packed = */ false),
"rpt", (field->is_repeated() ? "Repeated" : ""),
@@ -2298,12 +2404,12 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"required", (field->label() == FieldDescriptor::LABEL_REQUIRED ?
", 1" : ""));
printer->Print(
- "/** @param {$optionaltype$} value $returndoc$ */\n"
+ "/** @param {$optionaltype$} value$returndoc$ */\n"
"$class$.prototype.set$name$ = function(value) {\n"
" jspb.Message.set$oneoftag$$repeatedtag$WrapperField(",
"optionaltype",
JSFieldTypeAnnotation(options, field,
- /* force_optional = */ true,
+ /* is_setter_argument = */ true,
/* force_present = */ false,
/* singular_if_not_packed = */ false),
"returndoc", JSReturnDoc(options, field),
@@ -2322,16 +2428,9 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
(", " + JSOneofArray(options, field)) : ""),
"returnvalue", JSReturnClause(field));
- printer->Print(
- "$class$.prototype.clear$name$ = function() {\n"
- " this.set$name$($clearedvalue$);$returnvalue$\n"
- "};\n"
- "\n"
- "\n",
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field),
- "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
- "returnvalue", JSReturnClause(field));
+ if (field->is_repeated()) {
+ GenerateRepeatedMessageHelperMethods(options, printer, field);
+ }
} else {
bool untyped =
@@ -2345,12 +2444,12 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
BytesMode bytes_mode =
field->type() == FieldDescriptor::TYPE_BYTES && !options.binary ?
BYTES_B64 : BYTES_DEFAULT;
- string typed_annotation =
- JSFieldTypeAnnotation(options, field,
- /* force_optional = */ false,
- /* force_present = */ !HasFieldPresence(field),
- /* singular_if_not_packed = */ false,
- /* bytes_mode = */ bytes_mode);
+ string typed_annotation = JSFieldTypeAnnotation(
+ options, field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false,
+ /* bytes_mode = */ bytes_mode);
if (untyped) {
printer->Print(
"/**\n"
@@ -2382,36 +2481,21 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
"type", typed_annotation);
}
- // For proto3 fields without presence, use special getters that will return
- // defaults when the field is unset, possibly constructing a value if
- // required.
- if (!HasFieldPresence(field) && !field->is_repeated()) {
- printer->Print("jspb.Message.getFieldProto3(this, $index$, $default$)",
- "index", JSFieldIndex(field),
- "default", Proto3PrimitiveFieldDefault(field));
- } else {
- if (!field->is_repeated()) {
- printer->Print("!this.has$name$() ? $defaultValue$ : ",
- "name", JSGetterName(options, field),
- "defaultValue", JSFieldDefault(field));
- }
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT ||
- field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
- if (field->is_repeated()) {
- printer->Print("jspb.Message.getRepeatedFloatingPointField("
- "this, $index$)",
- "index", JSFieldIndex(field));
- } else {
- // Convert "NaN" to NaN.
- printer->Print("+jspb.Message.getField(this, $index$)",
- "index", JSFieldIndex(field));
- }
- } else {
- printer->Print("jspb.Message.getField(this, $index$)",
- "index", JSFieldIndex(field));
- }
+ bool use_default = !ReturnsNullWhenUnset(options, field);
+
+ // Raw fields with no default set should just return undefined.
+ if (untyped && !field->has_default_value()) {
+ use_default = false;
+ }
+
+ // Repeated fields get initialized to their default in the constructor
+ // (why?), so we emit a plain getField() call for them.
+ if (field->is_repeated()) {
+ use_default = false;
}
+ GenerateFieldValueExpression(printer, "this", field, use_default);
+
if (untyped) {
printer->Print(
";\n"
@@ -2434,17 +2518,17 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
if (untyped) {
printer->Print(
"/**\n"
- " * @param {*} value $returndoc$\n"
+ " * @param {*} value$returndoc$\n"
" */\n",
"returndoc", JSReturnDoc(options, field));
} else {
printer->Print(
- "/** @param {$optionaltype$} value $returndoc$ */\n",
- "optionaltype",
- JSFieldTypeAnnotation(options, field,
- /* force_optional = */ true,
- /* force_present = */ !HasFieldPresence(field),
- /* singular_if_not_packed = */ false),
+ "/** @param {$optionaltype$} value$returndoc$ */\n", "optionaltype",
+ JSFieldTypeAnnotation(
+ options, field,
+ /* is_setter_argument = */ true,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false),
"returndoc", JSReturnDoc(options, field));
}
printer->Print(
@@ -2471,36 +2555,70 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
if (untyped) {
printer->Print(
"/**\n"
- " * Clears the value. $returndoc$\n"
+ " * Clears the value.$returndoc$\n"
" */\n",
"returndoc", JSReturnDoc(options, field));
}
- if (HasFieldPresence(field) || field->is_repeated()) {
- printer->Print(
- "$class$.prototype.clear$name$ = function() {\n"
- " jspb.Message.set$oneoftag$Field(this, $index$$oneofgroup$, ",
- "class", GetPath(options, field->containing_type()),
- "name", JSGetterName(options, field),
- "oneoftag", (field->containing_oneof() ? "Oneof" : ""),
- "oneofgroup", (field->containing_oneof() ?
- (", " + JSOneofArray(options, field)) : ""),
- "index", JSFieldIndex(field));
- printer->Print(
- "$clearedvalue$);$returnvalue$\n"
- "};\n"
- "\n"
- "\n",
- "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
- "returnvalue", JSReturnClause(field));
+
+ if (field->is_repeated()) {
+ GenerateRepeatedPrimitiveHelperMethods(options, printer, field, untyped);
}
}
- if (HasFieldPresence(field)) {
+ // Generate clearFoo() method for map fields, repeated fields, and other
+ // fields with presence.
+ if (IsMap(options, field)) {
+ printer->Print(
+ "$class$.prototype.clear$name$ = function() {\n"
+ " this.get$name$().clear();$returnvalue$\n"
+ "};\n"
+ "\n"
+ "\n",
+ "class", GetPath(options, field->containing_type()),
+ "name", JSGetterName(options, field),
+ "returnvalue", JSReturnClause(field));
+ } else if (field->is_repeated() ||
+ (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ !field->is_required())) {
+ // Fields where we can delegate to the regular setter.
+ printer->Print(
+ "$class$.prototype.clear$name$ = function() {\n"
+ " this.set$name$($clearedvalue$);$returnvalue$\n"
+ "};\n"
+ "\n"
+ "\n",
+ "class", GetPath(options, field->containing_type()),
+ "name", JSGetterName(options, field),
+ "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
+ "returnvalue", JSReturnClause(field));
+ } else if (HasFieldPresence(options, field)) {
+ // Fields where we can't delegate to the regular setter because it doesn't
+ // accept "undefined" as an argument.
+ printer->Print(
+ "$class$.prototype.clear$name$ = function() {\n"
+ " jspb.Message.set$maybeoneof$Field(this, "
+ "$index$$maybeoneofgroup$, ",
+ "class", GetPath(options, field->containing_type()),
+ "name", JSGetterName(options, field),
+ "maybeoneof", (field->containing_oneof() ? "Oneof" : ""),
+ "maybeoneofgroup", (field->containing_oneof() ?
+ (", " + JSOneofArray(options, field)) : ""),
+ "index", JSFieldIndex(field));
+ printer->Print(
+ "$clearedvalue$);$returnvalue$\n"
+ "};\n"
+ "\n"
+ "\n",
+ "clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
+ "returnvalue", JSReturnClause(field));
+ }
+
+ if (HasFieldPresence(options, field)) {
printer->Print(
"/**\n"
" * Returns whether this field is set.\n"
- " * @return{!boolean}\n"
+ " * @return {!boolean}\n"
" */\n"
"$class$.prototype.has$name$ = function() {\n"
" return jspb.Message.getField(this, $index$) != null;\n"
@@ -2513,6 +2631,59 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
}
}
+void Generator::GenerateRepeatedPrimitiveHelperMethods(
+ const GeneratorOptions& options, io::Printer* printer,
+ const FieldDescriptor* field, bool untyped) const {
+ printer->Print(
+ "/**\n"
+ " * @param {!$optionaltype$} value\n"
+ " * @param {number=} opt_index\n"
+ " */\n"
+ "$class$.prototype.add$name$ = function(value, opt_index) {\n"
+ " jspb.Message.addToRepeatedField(this, $index$",
+ "class", GetPath(options, field->containing_type()), "name",
+ JSGetterName(options, field, BYTES_DEFAULT,
+ /* drop_list = */ true),
+ "optionaltype", JSTypeName(options, field, BYTES_DEFAULT), "index",
+ JSFieldIndex(field));
+ printer->Print(
+ "$oneofgroup$, $type$value$rptvalueinit$$typeclose$, opt_index);\n"
+ "};\n"
+ "\n"
+ "\n",
+ "type", untyped ? "/** @type{string|number|boolean|!Uint8Array} */(" : "",
+ "typeclose", untyped ? ")" : "", "oneofgroup",
+ (field->containing_oneof() ? (", " + JSOneofArray(options, field)) : ""),
+ "rptvalueinit", "");
+}
+
+void Generator::GenerateRepeatedMessageHelperMethods(
+ const GeneratorOptions& options, io::Printer* printer,
+ const FieldDescriptor* field) const {
+ printer->Print(
+ "/**\n"
+ " * @param {!$optionaltype$=} opt_value\n"
+ " * @param {number=} opt_index\n"
+ " * @return {!$optionaltype$}\n"
+ " */\n"
+ "$class$.prototype.add$name$ = function(opt_value, opt_index) {\n"
+ " return jspb.Message.addTo$repeatedtag$WrapperField(",
+ "optionaltype", JSTypeName(options, field, BYTES_DEFAULT), "class",
+ GetPath(options, field->containing_type()), "name",
+ JSGetterName(options, field, BYTES_DEFAULT,
+ /* drop_list = */ true),
+ "repeatedtag", (field->is_repeated() ? "Repeated" : ""));
+
+ printer->Print(
+ "this, $index$$oneofgroup$, opt_value, $ctor$, opt_index);\n"
+ "};\n"
+ "\n"
+ "\n",
+ "index", JSFieldIndex(field), "oneofgroup",
+ (field->containing_oneof() ? (", " + JSOneofArray(options, field)) : ""),
+ "ctor", GetPath(options, field->message_type()));
+}
+
void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
io::Printer* printer,
const Descriptor* desc) const {
@@ -2554,7 +2725,7 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options,
"so that it\n"
" * works in OPTIMIZED mode.\n"
" *\n"
- " * @type {!Object.<number, jspb.ExtensionFieldInfo>}\n"
+ " * @type {!Object.<number, jspb.ExtensionFieldBinaryInfo>}\n"
" */\n"
"$class$.extensionsBinary = {};\n"
"\n",
@@ -2636,7 +2807,7 @@ void Generator::GenerateClassDeserializeBinaryField(
printer->Print(" case $num$:\n",
"num", SimpleItoa(field->number()));
- if (field->is_map()) {
+ if (IsMap(options, field)) {
const FieldDescriptor* key_field = MapFieldKey(field);
const FieldDescriptor* value_field = MapFieldValue(field);
printer->Print(
@@ -2757,11 +2928,18 @@ void Generator::GenerateClassSerializeBinaryField(
const GeneratorOptions& options,
io::Printer* printer,
const FieldDescriptor* field) const {
- if (HasFieldPresence(field) &&
+ if (HasFieldPresence(options, field) &&
field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
+ string typed_annotation = JSFieldTypeAnnotation(
+ options, field,
+ /* is_setter_argument = */ false,
+ /* force_present = */ false,
+ /* singular_if_not_packed = */ false,
+ /* bytes_mode = */ BYTES_DEFAULT);
printer->Print(
- " f = jspb.Message.getField(this, $index$);\n",
- "index", JSFieldIndex(field));
+ " f = /** @type {$type$} */ (jspb.Message.getField(this, $index$));\n",
+ "index", JSFieldIndex(field),
+ "type", typed_annotation);
} else {
printer->Print(
" f = this.get$name$($nolazy$);\n",
@@ -2770,17 +2948,16 @@ void Generator::GenerateClassSerializeBinaryField(
"nolazy", (field->is_map()) ? "true" : "");
}
-
// Print an `if (condition)` statement that evaluates to true if the field
// goes on the wire.
- if (field->is_map()) {
+ if (IsMap(options, field)) {
printer->Print(
" if (f && f.getLength() > 0) {\n");
} else if (field->is_repeated()) {
printer->Print(
" if (f.length > 0) {\n");
} else {
- if (HasFieldPresence(field)) {
+ if (HasFieldPresence(options, field)) {
printer->Print(
" if (f != null) {\n");
} else {
@@ -2820,7 +2997,7 @@ void Generator::GenerateClassSerializeBinaryField(
}
// Write the field on the wire.
- if (field->is_map()) {
+ if (IsMap(options, field)) {
const FieldDescriptor* key_field = MapFieldKey(field);
const FieldDescriptor* value_field = MapFieldValue(field);
printer->Print(
@@ -2845,7 +3022,7 @@ void Generator::GenerateClassSerializeBinaryField(
"index", SimpleItoa(field->number()));
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
- !(field->is_map())) {
+ !IsMap(options, field)) {
printer->Print(
",\n"
" $submsg$.serializeBinaryToWriter\n",
@@ -2907,7 +3084,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
"class", extension_scope,
"extensionType", JSFieldTypeAnnotation(
options, field,
- /* force_optional = */ false,
+ /* is_setter_argument = */ false,
/* force_present = */ true,
/* singular_if_not_packed = */ false));
printer->Print(
@@ -2946,11 +3123,11 @@ void Generator::GenerateExtension(const GeneratorOptions& options,
"binaryMessageSerializeFn",
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
(SubmessageTypeRef(options, field) +
- ".serializeBinaryToWriter") : "null",
+ ".serializeBinaryToWriter") : "undefined",
"binaryMessageDeserializeFn",
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
(SubmessageTypeRef(options, field) +
- ".deserializeBinaryFromReader") : "null");
+ ".deserializeBinaryFromReader") : "undefined");
printer->Print(
" $isPacked$);\n",
@@ -3005,17 +3182,31 @@ bool GeneratorOptions::ParseFromOptions(
library = options[i].second;
} else if (options[i].first == "import_style") {
if (options[i].second == "closure") {
- import_style = IMPORT_CLOSURE;
+ import_style = kImportClosure;
} else if (options[i].second == "commonjs") {
- import_style = IMPORT_COMMONJS;
+ import_style = kImportCommonJs;
} else if (options[i].second == "browser") {
- import_style = IMPORT_BROWSER;
+ import_style = kImportBrowser;
} else if (options[i].second == "es6") {
- import_style = IMPORT_ES6;
+ import_style = kImportEs6;
} else {
*error = "Unknown import style " + options[i].second + ", expected " +
"one of: closure, commonjs, browser, es6.";
}
+ } else if (options[i].first == "extension") {
+ extension = options[i].second;
+ } else if (options[i].first == "one_output_file_per_input_file") {
+ if (!options[i].second.empty()) {
+ *error = "Unexpected option value for one_output_file_per_input_file";
+ return false;
+ }
+ one_output_file_per_input_file = true;
+ } else if (options[i].first == "broken_proto3_semantics") {
+ if (!options[i].second.empty()) {
+ *error = "Unexpected option value for broken_proto3_semantics";
+ return false;
+ }
+ broken_proto3_semantics = true;
} else {
// Assume any other option is an output directory, as long as it is a bare
// `key` rather than a `key=value` option.
@@ -3027,14 +3218,37 @@ bool GeneratorOptions::ParseFromOptions(
}
}
- if (!library.empty() && import_style != IMPORT_CLOSURE) {
- *error = "The library option should only be used for "
- "import_style=closure";
+ if (import_style != kImportClosure &&
+ (add_require_for_enums || testonly || !library.empty() ||
+ error_on_name_conflict || broken_proto3_semantics ||
+ extension != ".js" || one_output_file_per_input_file)) {
+ *error =
+ "The add_require_for_enums, testonly, library, error_on_name_conflict, "
+ "broken_proto3_semantics, extension, and "
+ "one_output_file_per_input_file options should only be used for "
+ "import_style=closure";
+ return false;
}
return true;
}
+GeneratorOptions::OutputMode GeneratorOptions::output_mode() const {
+ // We use one output file per input file if we are not using Closure or if
+ // this is explicitly requested.
+ if (import_style != kImportClosure || one_output_file_per_input_file) {
+ return kOneOutputFilePerInputFile;
+ }
+
+ // If a library name is provided, we put everything in that one file.
+ if (!library.empty()) {
+ return kEverythingInOneFile;
+ }
+
+ // Otherwise, we create one output file per type.
+ return kOneOutputFilePerType;
+}
+
void Generator::GenerateFilesInDepOrder(
const GeneratorOptions& options,
io::Printer* printer,
@@ -3081,7 +3295,7 @@ void Generator::GenerateFile(const GeneratorOptions& options,
GenerateHeader(options, printer);
// Generate "require" statements.
- if (options.import_style == GeneratorOptions::IMPORT_COMMONJS) {
+ if (options.import_style == GeneratorOptions::kImportCommonJs) {
printer->Print("var jspb = require('google-protobuf');\n");
printer->Print("var goog = jspb;\n");
printer->Print("var global = Function('return this')();\n\n");
@@ -3091,42 +3305,43 @@ void Generator::GenerateFile(const GeneratorOptions& options,
printer->Print(
"var $alias$ = require('$file$');\n",
"alias", ModuleAlias(name),
- "file", GetRootPath(file->name(), name) + GetJSFilename(name));
+ "file", GetRootPath(file->name(), name) + GetJSFilename(options, name));
}
}
- // We aren't using Closure's import system, but we use goog.exportSymbol()
- // to construct the expected tree of objects, eg.
- //
- // goog.exportSymbol('foo.bar.Baz', null, this);
- //
- // // Later generated code expects foo.bar = {} to exist:
- // foo.bar.Baz = function() { /* ... */ }
set<string> provided;
-
- // Cover the case where this file declares extensions but no messages.
- // This will ensure that the file-level object will be declared to hold
- // the extensions.
+ set<const FieldDescriptor*> extensions;
for (int i = 0; i < file->extension_count(); i++) {
- provided.insert(file->extension(i)->full_name());
+ // We honor the jspb::ignore option here only when working with
+ // Closure-style imports. Use of this option is discouraged and so we want
+ // to avoid adding new support for it.
+ if (options.import_style == GeneratorOptions::kImportClosure &&
+ IgnoreField(file->extension(i))) {
+ continue;
+ }
+ provided.insert(GetPath(options, file) + "." +
+ JSObjectFieldName(options, file->extension(i)));
+ extensions.insert(file->extension(i));
}
FindProvidesForFile(options, printer, file, &provided);
- for (std::set<string>::iterator it = provided.begin();
- it != provided.end(); ++it) {
- printer->Print("goog.exportSymbol('$name$', null, global);\n",
- "name", *it);
+ GenerateProvides(options, printer, &provided);
+ vector<const FileDescriptor*> files;
+ files.push_back(file);
+ if (options.import_style == GeneratorOptions::kImportClosure) {
+ GenerateRequiresForLibrary(options, printer, files, &provided);
}
GenerateClassesAndEnums(options, printer, file);
- // Extensions nested inside messages are emitted inside
- // GenerateClassesAndEnums().
- for (int i = 0; i < file->extension_count(); i++) {
- GenerateExtension(options, printer, file->extension(i));
+ // Generate code for top-level extensions. Extensions nested inside messages
+ // are emitted inside GenerateClassesAndEnums().
+ for (set<const FieldDescriptor*>::const_iterator it = extensions.begin();
+ it != extensions.end(); ++it) {
+ GenerateExtension(options, printer, *it);
}
- if (options.import_style == GeneratorOptions::IMPORT_COMMONJS) {
+ if (options.import_style == GeneratorOptions::kImportCommonJs) {
printer->Print("goog.object.extend(exports, $package$);\n",
"package", GetPath(options, file));
}
@@ -3144,15 +3359,10 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
}
- // There are three schemes for where output files go:
- //
- // - import_style = IMPORT_CLOSURE, library non-empty: all output in one file
- // - import_style = IMPORT_CLOSURE, library empty: one output file per type
- // - import_style != IMPORT_CLOSURE: one output file per .proto file
- if (options.import_style == GeneratorOptions::IMPORT_CLOSURE &&
- options.library != "") {
+ if (options.output_mode() == GeneratorOptions::kEverythingInOneFile) {
// All output should go in a single file.
- string filename = options.output_dir + "/" + options.library + ".js";
+ string filename = options.output_dir + "/" + options.library +
+ options.GetFileNameExtension();
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
GOOGLE_CHECK(output.get());
io::Printer printer(output.get(), '$');
@@ -3187,7 +3397,7 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
if (printer.failed()) {
return false;
}
- } else if (options.import_style == GeneratorOptions::IMPORT_CLOSURE) {
+ } else if (options.output_mode() == GeneratorOptions::kOneOutputFilePerType) {
set<const void*> allowed_set;
if (!GenerateJspbAllowedSet(options, files, &allowed_set, error)) {
return false;
@@ -3279,13 +3489,14 @@ bool Generator::GenerateAll(const vector<const FileDescriptor*>& files,
}
}
}
- } else {
+ } else /* options.output_mode() == kOneOutputFilePerInputFile */ {
// Generate one output file per input (.proto) file.
for (int i = 0; i < files.size(); i++) {
const google::protobuf::FileDescriptor* file = files[i];
- string filename = options.output_dir + "/" + GetJSFilename(file->name());
+ string filename =
+ options.output_dir + "/" + GetJSFilename(options, file->name());
google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
GOOGLE_CHECK(output.get());
io::Printer printer(output.get(), '$');
diff --git a/src/google/protobuf/compiler/js/js_generator.h b/src/google/protobuf/compiler/js/js_generator.h
index 056c9897..4ca3493c 100755
--- a/src/google/protobuf/compiler/js/js_generator.h
+++ b/src/google/protobuf/compiler/js/js_generator.h
@@ -36,6 +36,8 @@
#include <string>
#include <set>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/code_generator.h>
namespace google {
@@ -53,43 +55,74 @@ namespace compiler {
namespace js {
struct GeneratorOptions {
- // Add a `goog.requires()` call for each enum type used. If not set, a forward
- // declaration with `goog.forwardDeclare` is produced instead.
- bool add_require_for_enums;
- // Set this as a test-only module via `goog.setTestOnly();`.
- bool testonly;
// Output path.
string output_dir;
// Namespace prefix.
string namespace_prefix;
- // Create a library with name <name>_lib.js rather than a separate .js file
- // per type?
- string library;
- // Error if there are two types that would generate the same output file?
- bool error_on_name_conflict;
// Enable binary-format support?
bool binary;
// What style of imports should be used.
enum ImportStyle {
- IMPORT_CLOSURE, // goog.require()
- IMPORT_COMMONJS, // require()
- IMPORT_BROWSER, // no import statements
- IMPORT_ES6, // import { member } from ''
+ kImportClosure, // goog.require()
+ kImportCommonJs, // require()
+ kImportBrowser, // no import statements
+ kImportEs6, // import { member } from ''
} import_style;
GeneratorOptions()
- : add_require_for_enums(false),
- testonly(false),
- output_dir("."),
+ : output_dir("."),
namespace_prefix(""),
+ binary(false),
+ import_style(kImportClosure),
+ add_require_for_enums(false),
+ testonly(false),
library(""),
error_on_name_conflict(false),
- binary(false),
- import_style(IMPORT_CLOSURE) {}
+ broken_proto3_semantics(false),
+ extension(".js"),
+ one_output_file_per_input_file(false) {}
bool ParseFromOptions(
const vector< pair< string, string > >& options,
string* error);
+
+ // Returns the file name extension to use for generated code.
+ string GetFileNameExtension() const {
+ return import_style == kImportClosure ? extension : "_pb.js";
+ }
+
+ enum OutputMode {
+ // Create an output file for each input .proto file.
+ kOneOutputFilePerInputFile,
+ // Create an output file for each type.
+ kOneOutputFilePerType,
+ // Put everything in a single file named by the library option.
+ kEverythingInOneFile,
+ };
+
+ // Indicates how to output the generated code based on the provided options.
+ OutputMode output_mode() const;
+
+ // The remaining options are only relevant when we are using kImportClosure.
+
+ // Add a `goog.requires()` call for each enum type used. If not set, a
+ // forward declaration with `goog.forwardDeclare` is produced instead.
+ bool add_require_for_enums;
+ // Set this as a test-only module via `goog.setTestOnly();`.
+ bool testonly;
+ // Create a library with name <name>_lib.js rather than a separate .js file
+ // per type?
+ string library;
+ // Error if there are two types that would generate the same output file?
+ bool error_on_name_conflict;
+ // Preserve the broken proto3 semantics from the old codegen? This amounts
+ // to using proto2 field presence semantics even for proto3 files. DO NOT
+ // USE except for migrating legacy code.
+ bool broken_proto3_semantics;
+ // The extension to use for output file names.
+ string extension;
+ // Create a separate output file for each input file?
+ bool one_output_file_per_input_file;
};
// CodeGenerator implementation which generates a JavaScript source file and
@@ -207,6 +240,11 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
io::Printer* printer,
const FileDescriptor* file) const;
+ void GenerateFieldValueExpression(io::Printer* printer,
+ const char* obj_reference,
+ const FieldDescriptor* field,
+ bool use_default) const;
+
// Generate definition for one class.
void GenerateClass(const GeneratorOptions& options,
io::Printer* printer,
@@ -276,6 +314,17 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
io::Printer* printer,
const FieldDescriptor* field) const;
+ // Generate addFoo() method for repeated primitive fields.
+ void GenerateRepeatedPrimitiveHelperMethods(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field,
+ bool untyped) const;
+
+ // Generate addFoo() method for repeated message fields.
+ void GenerateRepeatedMessageHelperMethods(const GeneratorOptions& options,
+ io::Printer* printer,
+ const FieldDescriptor* field) const;
+
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
};
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index b83b8f32..aca2a5b9 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -32,14 +32,20 @@
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/cpp/cpp_generator.h>
+
+#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
#include <google/protobuf/compiler/python/python_generator.h>
#include <google/protobuf/compiler/java/java_generator.h>
+#endif // ! OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
+
+#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
#include <google/protobuf/compiler/javanano/javanano_generator.h>
#include <google/protobuf/compiler/php/php_generator.h>
#include <google/protobuf/compiler/ruby/ruby_generator.h>
#include <google/protobuf/compiler/csharp/csharp_generator.h>
#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
#include <google/protobuf/compiler/js/js_generator.h>
+#endif // ! OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
int main(int argc, char* argv[]) {
@@ -51,12 +57,15 @@ int main(int argc, char* argv[]) {
cli.RegisterGenerator("--cpp_out", "--cpp_opt", &cpp_generator,
"Generate C++ header and source.");
+#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
// Proto2 Java
google::protobuf::compiler::java::JavaGenerator java_generator;
cli.RegisterGenerator("--java_out", &java_generator,
"Generate Java source file.");
+#endif // !OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
+#ifndef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
// Proto2 Python
google::protobuf::compiler::python::Generator py_generator;
cli.RegisterGenerator("--python_out", &py_generator,
@@ -91,6 +100,7 @@ int main(int argc, char* argv[]) {
google::protobuf::compiler::js::Generator js_generator;
cli.RegisterGenerator("--js_out", &js_generator,
"Generate JavaScript source.");
+#endif // !OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
return cli.Run(argc, argv);
}
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index 2ff50f61..e1087601 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -118,35 +118,16 @@ bool GenerateCode(const CodeGeneratorRequest& request,
GeneratorResponseContext context(response, parsed_files);
- if (generator.HasGenerateAll()) {
- string error;
- bool succeeded = generator.GenerateAll(
- parsed_files, request.parameter(), &context, &error);
-
- if (!succeeded && error.empty()) {
- error = "Code generator returned false but provided no error "
- "description.";
- }
- if (!error.empty()) {
- response->set_error(error);
- }
- } else {
- for (int i = 0; i < parsed_files.size(); i++) {
- const FileDescriptor* file = parsed_files[i];
-
- string error;
- bool succeeded = generator.Generate(
- file, request.parameter(), &context, &error);
-
- if (!succeeded && error.empty()) {
- error = "Code generator returned false but provided no error "
- "description.";
- }
- if (!error.empty()) {
- response->set_error(file->name() + ": " + error);
- break;
- }
- }
+ string error;
+ bool succeeded = generator.GenerateAll(
+ parsed_files, request.parameter(), &context, &error);
+
+ if (!succeeded && error.empty()) {
+ error = "Code generator returned false but provided no error "
+ "description.";
+ }
+ if (!error.empty()) {
+ response->set_error(error);
}
return true;
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 5247f9a2..1c19d46a 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -52,14 +52,13 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
CodeGeneratorRequest_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
CodeGeneratorRequest_descriptor_,
- CodeGeneratorRequest::default_instance_,
+ CodeGeneratorRequest::internal_default_instance(),
CodeGeneratorRequest_offsets_,
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_),
-1,
-1,
sizeof(CodeGeneratorRequest),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_),
- -1);
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _internal_metadata_));
CodeGeneratorResponse_descriptor_ = file->message_type(1);
static const int CodeGeneratorResponse_offsets_[2] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_),
@@ -68,14 +67,13 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
CodeGeneratorResponse_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
CodeGeneratorResponse_descriptor_,
- CodeGeneratorResponse::default_instance_,
+ CodeGeneratorResponse::internal_default_instance(),
CodeGeneratorResponse_offsets_,
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_),
-1,
-1,
sizeof(CodeGeneratorResponse),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_),
- -1);
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _internal_metadata_));
CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0);
static const int CodeGeneratorResponse_File_offsets_[3] = {
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_),
@@ -85,20 +83,19 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
CodeGeneratorResponse_File_reflection_ =
::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection(
CodeGeneratorResponse_File_descriptor_,
- CodeGeneratorResponse_File::default_instance_,
+ CodeGeneratorResponse_File::internal_default_instance(),
CodeGeneratorResponse_File_offsets_,
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_),
-1,
-1,
sizeof(CodeGeneratorResponse_File),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_),
- -1);
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_));
}
namespace {
GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
-inline void protobuf_AssignDescriptorsOnce() {
+void protobuf_AssignDescriptorsOnce() {
::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
&protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
}
@@ -107,32 +104,45 @@ void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
void protobuf_RegisterTypes(const ::std::string&) {
protobuf_AssignDescriptorsOnce();
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance());
+ CodeGeneratorRequest_descriptor_, CodeGeneratorRequest::internal_default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance());
+ CodeGeneratorResponse_descriptor_, CodeGeneratorResponse::internal_default_instance());
::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
- CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance());
+ CodeGeneratorResponse_File_descriptor_, CodeGeneratorResponse_File::internal_default_instance());
}
} // namespace
void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
- delete CodeGeneratorRequest::default_instance_;
delete CodeGeneratorRequest_reflection_;
- delete CodeGeneratorResponse::default_instance_;
delete CodeGeneratorResponse_reflection_;
- delete CodeGeneratorResponse_File::default_instance_;
delete CodeGeneratorResponse_File_reflection_;
}
-void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() GOOGLE_ATTRIBUTE_COLD;
-void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
- static bool already_here = false;
- if (already_here) return;
- already_here = true;
+void protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto_impl() {
GOOGLE_PROTOBUF_VERIFY_VERSION;
- ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+ ::google::protobuf::protobuf_InitDefaults_google_2fprotobuf_2fdescriptor_2eproto();
+ ::google::protobuf::internal::GetEmptyString();
+ CodeGeneratorRequest::default_instance_.DefaultConstruct();
+ ::google::protobuf::internal::GetEmptyString();
+ CodeGeneratorResponse::default_instance_.DefaultConstruct();
+ ::google::protobuf::internal::GetEmptyString();
+ CodeGeneratorResponse_File::default_instance_.DefaultConstruct();
+ CodeGeneratorRequest::default_instance_.get_mutable()->InitAsDefaultInstance();
+ CodeGeneratorResponse::default_instance_.get_mutable()->InitAsDefaultInstance();
+ CodeGeneratorResponse_File::default_instance_.get_mutable()->InitAsDefaultInstance();
+}
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once_);
+void protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once_,
+ &protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto_impl);
+}
+void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto_impl() {
+ GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+ protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
"\n%google/protobuf/compiler/plugin.proto\022"
"\030google.protobuf.compiler\032 google/protob"
@@ -148,15 +158,15 @@ void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
"rotosZ\tplugin_go", 456);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
- CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest();
- CodeGeneratorResponse::default_instance_ = new CodeGeneratorResponse();
- CodeGeneratorResponse_File::default_instance_ = new CodeGeneratorResponse_File();
- CodeGeneratorRequest::default_instance_->InitAsDefaultInstance();
- CodeGeneratorResponse::default_instance_->InitAsDefaultInstance();
- CodeGeneratorResponse_File::default_instance_->InitAsDefaultInstance();
+ ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
}
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once_);
+void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+ ::google::protobuf::GoogleOnceInit(&protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once_,
+ &protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto_impl);
+}
// Force AddDescriptors() to be called at static initialization time.
struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
@@ -164,6 +174,16 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto
}
} static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
+namespace {
+
+static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD GOOGLE_ATTRIBUTE_NORETURN;
+static void MergeFromFail(int line) {
+ ::google::protobuf::internal::MergeFromFail(__FILE__, line);
+}
+
+} // namespace
+
+
// ===================================================================
#if !defined(_MSC_VER) || _MSC_VER >= 1900
@@ -174,6 +194,7 @@ const int CodeGeneratorRequest::kProtoFileFieldNumber;
CodeGeneratorRequest::CodeGeneratorRequest()
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ if (this != internal_default_instance()) protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
}
@@ -185,15 +206,13 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
: ::google::protobuf::Message(),
_internal_metadata_(NULL) {
SharedCtor();
- MergeFrom(from);
+ UnsafeMergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest)
}
void CodeGeneratorRequest::SharedCtor() {
- ::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
parameter_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
}
CodeGeneratorRequest::~CodeGeneratorRequest() {
@@ -203,8 +222,6 @@ CodeGeneratorRequest::~CodeGeneratorRequest() {
void CodeGeneratorRequest::SharedDtor() {
parameter_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- if (this != default_instance_) {
- }
}
void CodeGeneratorRequest::SetCachedSize(int size) const {
@@ -218,11 +235,11 @@ const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() {
}
const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
- if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
- return *default_instance_;
+ protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ return *internal_default_instance();
}
-CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
+::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorRequest> CodeGeneratorRequest::default_instance_;
CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const {
CodeGeneratorRequest* n = new CodeGeneratorRequest;
@@ -239,7 +256,7 @@ void CodeGeneratorRequest::Clear() {
}
file_to_generate_.Clear();
proto_file_.Clear();
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ _has_bits_.Clear();
if (_internal_metadata_.have_unknown_fields()) {
mutable_unknown_fields()->Clear();
}
@@ -406,9 +423,9 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
return target;
}
-int CodeGeneratorRequest::ByteSize() const {
+size_t CodeGeneratorRequest::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest)
- int total_size = 0;
+ size_t total_size = 0;
// optional string parameter = 2;
if (has_parameter()) {
@@ -418,18 +435,22 @@ int CodeGeneratorRequest::ByteSize() const {
}
// repeated string file_to_generate = 1;
- total_size += 1 * this->file_to_generate_size();
+ total_size += 1 *
+ ::google::protobuf::internal::FromIntSize(this->file_to_generate_size());
for (int i = 0; i < this->file_to_generate_size(); i++) {
total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
this->file_to_generate(i));
}
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
- total_size += 1 * this->proto_file_size();
- for (int i = 0; i < this->proto_file_size(); i++) {
- total_size +=
- ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
- this->proto_file(i));
+ {
+ unsigned int count = this->proto_file_size();
+ total_size += 1UL * count;
+ for (unsigned int i = 0; i < count; i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->proto_file(i));
+ }
}
if (_internal_metadata_.have_unknown_fields()) {
@@ -437,18 +458,17 @@ int CodeGeneratorRequest::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
- _cached_size_ = total_size;
+ _cached_size_ = cached_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
- if (GOOGLE_PREDICT_FALSE(&from == this)) {
- ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
- }
- const CodeGeneratorRequest* source =
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const CodeGeneratorRequest* source =
::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>(
&from);
if (source == NULL) {
@@ -456,16 +476,22 @@ void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorRequest)
- MergeFrom(*source);
+ UnsafeMergeFrom(*source);
}
}
void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
- if (GOOGLE_PREDICT_FALSE(&from == this)) {
- ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ if (GOOGLE_PREDICT_TRUE(&from != this)) {
+ UnsafeMergeFrom(from);
+ } else {
+ MergeFromFail(__LINE__);
}
- file_to_generate_.MergeFrom(from.file_to_generate_);
+}
+
+void CodeGeneratorRequest::UnsafeMergeFrom(const CodeGeneratorRequest& from) {
+ GOOGLE_DCHECK(&from != this);
+ file_to_generate_.UnsafeMergeFrom(from.file_to_generate_);
proto_file_.MergeFrom(from.proto_file_);
if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
if (from.has_parameter()) {
@@ -474,7 +500,8 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
}
}
if (from._internal_metadata_.have_unknown_fields()) {
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ ::google::protobuf::UnknownFieldSet::MergeToInternalMetdata(
+ from.unknown_fields(), &_internal_metadata_);
}
}
@@ -489,7 +516,7 @@ void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorRequest)
if (&from == this) return;
Clear();
- MergeFrom(from);
+ UnsafeMergeFrom(from);
}
bool CodeGeneratorRequest::IsInitialized() const {
@@ -529,49 +556,49 @@ int CodeGeneratorRequest::file_to_generate_size() const {
void CodeGeneratorRequest::clear_file_to_generate() {
file_to_generate_.Clear();
}
- const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
+const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
return file_to_generate_.Get(index);
}
- ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
+::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
return file_to_generate_.Mutable(index);
}
- void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
+void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
file_to_generate_.Mutable(index)->assign(value);
}
- void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
+void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
file_to_generate_.Mutable(index)->assign(value);
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
}
- void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
+void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
file_to_generate_.Mutable(index)->assign(
reinterpret_cast<const char*>(value), size);
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
}
- ::std::string* CodeGeneratorRequest::add_file_to_generate() {
+::std::string* CodeGeneratorRequest::add_file_to_generate() {
// @@protoc_insertion_point(field_add_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
return file_to_generate_.Add();
}
- void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
+void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
file_to_generate_.Add()->assign(value);
// @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
}
- void CodeGeneratorRequest::add_file_to_generate(const char* value) {
+void CodeGeneratorRequest::add_file_to_generate(const char* value) {
file_to_generate_.Add()->assign(value);
// @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
}
- void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
+void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
// @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
}
- const ::google::protobuf::RepeatedPtrField< ::std::string>&
+const ::google::protobuf::RepeatedPtrField< ::std::string>&
CodeGeneratorRequest::file_to_generate() const {
// @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
return file_to_generate_;
}
- ::google::protobuf::RepeatedPtrField< ::std::string>*
+::google::protobuf::RepeatedPtrField< ::std::string>*
CodeGeneratorRequest::mutable_file_to_generate() {
// @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
return &file_to_generate_;
@@ -591,37 +618,37 @@ void CodeGeneratorRequest::clear_parameter() {
parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_parameter();
}
- const ::std::string& CodeGeneratorRequest::parameter() const {
+const ::std::string& CodeGeneratorRequest::parameter() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
+void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
set_has_parameter();
parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
}
- void CodeGeneratorRequest::set_parameter(const char* value) {
+void CodeGeneratorRequest::set_parameter(const char* value) {
set_has_parameter();
parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
}
- void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
+void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
set_has_parameter();
parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
}
- ::std::string* CodeGeneratorRequest::mutable_parameter() {
+::std::string* CodeGeneratorRequest::mutable_parameter() {
set_has_parameter();
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- ::std::string* CodeGeneratorRequest::release_parameter() {
+::std::string* CodeGeneratorRequest::release_parameter() {
// @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
clear_has_parameter();
return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
+void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
if (parameter != NULL) {
set_has_parameter();
} else {
@@ -673,6 +700,7 @@ const int CodeGeneratorResponse_File::kContentFieldNumber;
CodeGeneratorResponse_File::CodeGeneratorResponse_File()
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ if (this != internal_default_instance()) protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
}
@@ -684,17 +712,15 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon
: ::google::protobuf::Message(),
_internal_metadata_(NULL) {
SharedCtor();
- MergeFrom(from);
+ UnsafeMergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
}
void CodeGeneratorResponse_File::SharedCtor() {
- ::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
insertion_point_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
content_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
}
CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
@@ -706,8 +732,6 @@ void CodeGeneratorResponse_File::SharedDtor() {
name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
insertion_point_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
content_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- if (this != default_instance_) {
- }
}
void CodeGeneratorResponse_File::SetCachedSize(int size) const {
@@ -721,11 +745,11 @@ const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() {
}
const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
- if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
- return *default_instance_;
+ protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ return *internal_default_instance();
}
-CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
+::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse_File> CodeGeneratorResponse_File::default_instance_;
CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const {
CodeGeneratorResponse_File* n = new CodeGeneratorResponse_File;
@@ -748,7 +772,7 @@ void CodeGeneratorResponse_File::Clear() {
content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
}
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ _has_bits_.Clear();
if (_internal_metadata_.have_unknown_fields()) {
mutable_unknown_fields()->Clear();
}
@@ -921,9 +945,9 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
return target;
}
-int CodeGeneratorResponse_File::ByteSize() const {
+size_t CodeGeneratorResponse_File::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File)
- int total_size = 0;
+ size_t total_size = 0;
if (_has_bits_[0 / 32] & 7u) {
// optional string name = 1;
@@ -953,18 +977,17 @@ int CodeGeneratorResponse_File::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
- _cached_size_ = total_size;
+ _cached_size_ = cached_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
- if (GOOGLE_PREDICT_FALSE(&from == this)) {
- ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
- }
- const CodeGeneratorResponse_File* source =
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const CodeGeneratorResponse_File* source =
::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>(
&from);
if (source == NULL) {
@@ -972,15 +995,21 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse.File)
- MergeFrom(*source);
+ UnsafeMergeFrom(*source);
}
}
void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
- if (GOOGLE_PREDICT_FALSE(&from == this)) {
- ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ if (GOOGLE_PREDICT_TRUE(&from != this)) {
+ UnsafeMergeFrom(from);
+ } else {
+ MergeFromFail(__LINE__);
}
+}
+
+void CodeGeneratorResponse_File::UnsafeMergeFrom(const CodeGeneratorResponse_File& from) {
+ GOOGLE_DCHECK(&from != this);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_name()) {
set_has_name();
@@ -996,7 +1025,8 @@ void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& fro
}
}
if (from._internal_metadata_.have_unknown_fields()) {
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ ::google::protobuf::UnknownFieldSet::MergeToInternalMetdata(
+ from.unknown_fields(), &_internal_metadata_);
}
}
@@ -1011,7 +1041,7 @@ void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
if (&from == this) return;
Clear();
- MergeFrom(from);
+ UnsafeMergeFrom(from);
}
bool CodeGeneratorResponse_File::IsInitialized() const {
@@ -1050,6 +1080,7 @@ const int CodeGeneratorResponse::kFileFieldNumber;
CodeGeneratorResponse::CodeGeneratorResponse()
: ::google::protobuf::Message(), _internal_metadata_(NULL) {
+ if (this != internal_default_instance()) protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
}
@@ -1061,15 +1092,13 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
: ::google::protobuf::Message(),
_internal_metadata_(NULL) {
SharedCtor();
- MergeFrom(from);
+ UnsafeMergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse)
}
void CodeGeneratorResponse::SharedCtor() {
- ::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
error_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
}
CodeGeneratorResponse::~CodeGeneratorResponse() {
@@ -1079,8 +1108,6 @@ CodeGeneratorResponse::~CodeGeneratorResponse() {
void CodeGeneratorResponse::SharedDtor() {
error_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- if (this != default_instance_) {
- }
}
void CodeGeneratorResponse::SetCachedSize(int size) const {
@@ -1094,11 +1121,11 @@ const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() {
}
const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
- if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
- return *default_instance_;
+ protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ return *internal_default_instance();
}
-CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
+::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse> CodeGeneratorResponse::default_instance_;
CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const {
CodeGeneratorResponse* n = new CodeGeneratorResponse;
@@ -1114,7 +1141,7 @@ void CodeGeneratorResponse::Clear() {
error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
file_.Clear();
- ::memset(_has_bits_, 0, sizeof(_has_bits_));
+ _has_bits_.Clear();
if (_internal_metadata_.have_unknown_fields()) {
mutable_unknown_fields()->Clear();
}
@@ -1241,9 +1268,9 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
return target;
}
-int CodeGeneratorResponse::ByteSize() const {
+size_t CodeGeneratorResponse::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse)
- int total_size = 0;
+ size_t total_size = 0;
// optional string error = 1;
if (has_error()) {
@@ -1253,11 +1280,14 @@ int CodeGeneratorResponse::ByteSize() const {
}
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
- total_size += 1 * this->file_size();
- for (int i = 0; i < this->file_size(); i++) {
- total_size +=
- ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
- this->file(i));
+ {
+ unsigned int count = this->file_size();
+ total_size += 1UL * count;
+ for (unsigned int i = 0; i < count; i++) {
+ total_size +=
+ ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+ this->file(i));
+ }
}
if (_internal_metadata_.have_unknown_fields()) {
@@ -1265,18 +1295,17 @@ int CodeGeneratorResponse::ByteSize() const {
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
}
+ int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
- _cached_size_ = total_size;
+ _cached_size_ = cached_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) {
- ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
- }
- const CodeGeneratorResponse* source =
+ if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+ const CodeGeneratorResponse* source =
::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>(
&from);
if (source == NULL) {
@@ -1284,15 +1313,21 @@ void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
::google::protobuf::internal::ReflectionOps::Merge(from, this);
} else {
// @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.CodeGeneratorResponse)
- MergeFrom(*source);
+ UnsafeMergeFrom(*source);
}
}
void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
- if (GOOGLE_PREDICT_FALSE(&from == this)) {
- ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);
+ if (GOOGLE_PREDICT_TRUE(&from != this)) {
+ UnsafeMergeFrom(from);
+ } else {
+ MergeFromFail(__LINE__);
}
+}
+
+void CodeGeneratorResponse::UnsafeMergeFrom(const CodeGeneratorResponse& from) {
+ GOOGLE_DCHECK(&from != this);
file_.MergeFrom(from.file_);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_error()) {
@@ -1301,7 +1336,8 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
}
}
if (from._internal_metadata_.have_unknown_fields()) {
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ ::google::protobuf::UnknownFieldSet::MergeToInternalMetdata(
+ from.unknown_fields(), &_internal_metadata_);
}
}
@@ -1316,7 +1352,7 @@ void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.CodeGeneratorResponse)
if (&from == this) return;
Clear();
- MergeFrom(from);
+ UnsafeMergeFrom(from);
}
bool CodeGeneratorResponse::IsInitialized() const {
@@ -1361,37 +1397,37 @@ void CodeGeneratorResponse_File::clear_name() {
name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_name();
}
- const ::std::string& CodeGeneratorResponse_File::name() const {
+const ::std::string& CodeGeneratorResponse_File::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
+void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
set_has_name();
name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
}
- void CodeGeneratorResponse_File::set_name(const char* value) {
+void CodeGeneratorResponse_File::set_name(const char* value) {
set_has_name();
name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
}
- void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
+void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
set_has_name();
name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
}
- ::std::string* CodeGeneratorResponse_File::mutable_name() {
+::std::string* CodeGeneratorResponse_File::mutable_name() {
set_has_name();
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- ::std::string* CodeGeneratorResponse_File::release_name() {
+::std::string* CodeGeneratorResponse_File::release_name() {
// @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
clear_has_name();
return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
+void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
if (name != NULL) {
set_has_name();
} else {
@@ -1415,37 +1451,37 @@ void CodeGeneratorResponse_File::clear_insertion_point() {
insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_insertion_point();
}
- const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
+const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
+void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
set_has_insertion_point();
insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
}
- void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
+void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
set_has_insertion_point();
insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
}
- void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
+void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
set_has_insertion_point();
insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
}
- ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
+::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
set_has_insertion_point();
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
+::std::string* CodeGeneratorResponse_File::release_insertion_point() {
// @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
clear_has_insertion_point();
return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
+void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
if (insertion_point != NULL) {
set_has_insertion_point();
} else {
@@ -1469,37 +1505,37 @@ void CodeGeneratorResponse_File::clear_content() {
content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_content();
}
- const ::std::string& CodeGeneratorResponse_File::content() const {
+const ::std::string& CodeGeneratorResponse_File::content() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
+void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
set_has_content();
content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
- void CodeGeneratorResponse_File::set_content(const char* value) {
+void CodeGeneratorResponse_File::set_content(const char* value) {
set_has_content();
content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
- void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
+void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
set_has_content();
content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
- ::std::string* CodeGeneratorResponse_File::mutable_content() {
+::std::string* CodeGeneratorResponse_File::mutable_content() {
set_has_content();
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- ::std::string* CodeGeneratorResponse_File::release_content() {
+::std::string* CodeGeneratorResponse_File::release_content() {
// @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
clear_has_content();
return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
+void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
if (content != NULL) {
set_has_content();
} else {
@@ -1527,37 +1563,37 @@ void CodeGeneratorResponse::clear_error() {
error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
clear_has_error();
}
- const ::std::string& CodeGeneratorResponse::error() const {
+const ::std::string& CodeGeneratorResponse::error() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- void CodeGeneratorResponse::set_error(const ::std::string& value) {
+void CodeGeneratorResponse::set_error(const ::std::string& value) {
set_has_error();
error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
}
- void CodeGeneratorResponse::set_error(const char* value) {
+void CodeGeneratorResponse::set_error(const char* value) {
set_has_error();
error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
}
- void CodeGeneratorResponse::set_error(const char* value, size_t size) {
+void CodeGeneratorResponse::set_error(const char* value, size_t size) {
set_has_error();
error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
::std::string(reinterpret_cast<const char*>(value), size));
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
}
- ::std::string* CodeGeneratorResponse::mutable_error() {
+::std::string* CodeGeneratorResponse::mutable_error() {
set_has_error();
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- ::std::string* CodeGeneratorResponse::release_error() {
+::std::string* CodeGeneratorResponse::release_error() {
// @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error)
clear_has_error();
return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
- void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
+void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
if (error != NULL) {
set_has_error();
} else {
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 282c977d..709ab6ba 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -36,6 +36,7 @@ namespace compiler {
// Internal implementation detail -- do not call these.
void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+void LIBPROTOC_EXPORT protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
@@ -68,6 +69,10 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorRequest& default_instance();
+ static inline const CodeGeneratorRequest* internal_default_instance() {
+ return &default_instance_.get();
+ }
+
void Swap(CodeGeneratorRequest* other);
// implements Message ----------------------------------------------
@@ -82,7 +87,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ size_t ByteSizeLong() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
@@ -98,6 +103,7 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
void SharedDtor();
void SetCachedSize(int size) const;
void InternalSwap(CodeGeneratorRequest* other);
+ void UnsafeMergeFrom(const CodeGeneratorRequest& from);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return _internal_metadata_.arena();
@@ -159,17 +165,18 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
inline void clear_has_parameter();
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
- ::google::protobuf::uint32 _has_bits_[1];
+ ::google::protobuf::internal::HasBits<1> _has_bits_;
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
- ::google::protobuf::internal::ArenaStringPtr parameter_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
- friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ ::google::protobuf::internal::ArenaStringPtr parameter_;
+ friend void LIBPROTOC_EXPORT protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto_impl();
+ friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto_impl();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
void InitAsDefaultInstance();
- static CodeGeneratorRequest* default_instance_;
+ static ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorRequest> default_instance_;
};
// -------------------------------------------------------------------
@@ -196,6 +203,10 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorResponse_File& default_instance();
+ static inline const CodeGeneratorResponse_File* internal_default_instance() {
+ return &default_instance_.get();
+ }
+
void Swap(CodeGeneratorResponse_File* other);
// implements Message ----------------------------------------------
@@ -210,7 +221,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ size_t ByteSizeLong() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
@@ -226,6 +237,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
void SharedDtor();
void SetCachedSize(int size) const;
void InternalSwap(CodeGeneratorResponse_File* other);
+ void UnsafeMergeFrom(const CodeGeneratorResponse_File& from);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return _internal_metadata_.arena();
@@ -287,17 +299,18 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
inline void clear_has_content();
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
- ::google::protobuf::uint32 _has_bits_[1];
+ ::google::protobuf::internal::HasBits<1> _has_bits_;
mutable int _cached_size_;
::google::protobuf::internal::ArenaStringPtr name_;
::google::protobuf::internal::ArenaStringPtr insertion_point_;
::google::protobuf::internal::ArenaStringPtr content_;
- friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ friend void LIBPROTOC_EXPORT protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto_impl();
+ friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto_impl();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
void InitAsDefaultInstance();
- static CodeGeneratorResponse_File* default_instance_;
+ static ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse_File> default_instance_;
};
// -------------------------------------------------------------------
@@ -324,6 +337,10 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorResponse& default_instance();
+ static inline const CodeGeneratorResponse* internal_default_instance() {
+ return &default_instance_.get();
+ }
+
void Swap(CodeGeneratorResponse* other);
// implements Message ----------------------------------------------
@@ -338,7 +355,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
void Clear();
bool IsInitialized() const;
- int ByteSize() const;
+ size_t ByteSizeLong() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
@@ -354,6 +371,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
void SharedDtor();
void SetCachedSize(int size) const;
void InternalSwap(CodeGeneratorResponse* other);
+ void UnsafeMergeFrom(const CodeGeneratorResponse& from);
private:
inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
return _internal_metadata_.arena();
@@ -401,16 +419,17 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
inline void clear_has_error();
::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
- ::google::protobuf::uint32 _has_bits_[1];
+ ::google::protobuf::internal::HasBits<1> _has_bits_;
mutable int _cached_size_;
- ::google::protobuf::internal::ArenaStringPtr error_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
- friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+ ::google::protobuf::internal::ArenaStringPtr error_;
+ friend void LIBPROTOC_EXPORT protobuf_InitDefaults_google_2fprotobuf_2fcompiler_2fplugin_2eproto_impl();
+ friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto_impl();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
void InitAsDefaultInstance();
- static CodeGeneratorResponse* default_instance_;
+ static ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse> default_instance_;
};
// ===================================================================
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index d5468a0c..3b1b0d1d 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -88,8 +88,8 @@ string StripProto(const string& filename) {
// Returns the Python module name expected for a given .proto filename.
string ModuleName(const string& filename) {
string basename = StripProto(filename);
- StripString(&basename, "-", '_');
- StripString(&basename, "/", '.');
+ ReplaceCharacters(&basename, "-", '_');
+ ReplaceCharacters(&basename, "/", '.');
return basename + "_pb2";
}
@@ -320,7 +320,7 @@ bool Generator::Generate(const FileDescriptor* file,
file_ = file;
string module_name = ModuleName(file->name());
string filename = module_name;
- StripString(&filename, ".", '/');
+ ReplaceCharacters(&filename, ".", '/');
filename += ".py";
FileDescriptorProto fdp;
@@ -430,6 +430,15 @@ void Generator::PrintFileDescriptor() const {
}
printer_->Print("]");
}
+ if (file_->public_dependency_count() > 0) {
+ printer_->Print(",\npublic_dependencies=[");
+ for (int i = 0; i < file_->public_dependency_count(); ++i) {
+ string module_alias = ModuleAlias(file_->public_dependency(i)->name());
+ printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
+ module_alias);
+ }
+ printer_->Print("]");
+ }
// TODO(falk): Also print options and fix the message_type, enum_type,
// service and extension later in the generation.
@@ -1094,6 +1103,8 @@ void Generator::PrintFieldDescriptor(
m["default_value"] = StringifyDefaultValue(field);
m["is_extension"] = is_extension ? "True" : "False";
m["options"] = OptionsValue("FieldOptions", options_string);
+ m["json_name"] = field.has_json_name() ?
+ ", json_name='" + field.json_name() + "'": "";
// We always set message_type and enum_type to None at this point, and then
// these fields in correctly after all referenced descriptors have been
// defined and/or imported (see FixForeignFieldsInDescriptors()).
@@ -1104,7 +1115,7 @@ void Generator::PrintFieldDescriptor(
" has_default_value=$has_default_value$, default_value=$default_value$,\n"
" message_type=None, enum_type=None, containing_type=None,\n"
" is_extension=$is_extension$, extension_scope=None,\n"
- " options=$options$)";
+ " options=$options$$json_name$)";
printer_->Print(m, field_descriptor_decl);
}