aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler
diff options
context:
space:
mode:
authorGravatar Feng Xiao <xfxyjwf@gmail.com>2014-11-10 17:34:54 -0800
committerGravatar Feng Xiao <xfxyjwf@gmail.com>2014-11-10 17:34:54 -0800
commit6ef984af4b0c63c1c33127a12dcfc8e6359f0c9e (patch)
treed17c61ff9f3ae28224fbddac6d26bfc59e2cf755 /src/google/protobuf/compiler
parentbaca1a8a1aa180c42de6278d3b8286c4496c6a10 (diff)
Down-integrate from internal code base.
Diffstat (limited to 'src/google/protobuf/compiler')
-rw-r--r--src/google/protobuf/compiler/command_line_interface.cc3
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc13
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum.cc9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_enum_field.cc118
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.cc17
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_field.h13
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.cc17
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_file.h3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_generator.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc21
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h33
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc1014
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.h9
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message_field.cc369
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc128
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_primitive_field.cc8
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc538
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.h1
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto20
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/importer.cc3
-rw-r--r--src/google/protobuf/compiler/importer_unittest.cc124
-rw-r--r--src/google/protobuf/compiler/java/java_context.h3
-rw-r--r--src/google/protobuf/compiler/java/java_enum.cc32
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc354
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.h2
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc18
-rw-r--r--src/google/protobuf/compiler/java/java_field.h3
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc27
-rw-r--r--src/google/protobuf/compiler/java/java_file.h3
-rw-r--r--src/google/protobuf/compiler/java/java_generator.cc7
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.cc20
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h26
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.cc455
-rw-r--r--src/google/protobuf/compiler/java/java_map_field.h82
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc399
-rw-r--r--src/google/protobuf/compiler/java/java_message.h1
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc54
-rw-r--r--src/google/protobuf/compiler/java/java_plugin_unittest.cc3
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc20
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.cc6
-rw-r--r--src/google/protobuf/compiler/java/java_shared_code_generator.h4
-rw-r--r--src/google/protobuf/compiler/java/java_string_field.cc27
-rw-r--r--src/google/protobuf/compiler/mock_code_generator.cc3
-rw-r--r--src/google/protobuf/compiler/parser.cc149
-rw-r--r--src/google/protobuf/compiler/parser.h24
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc251
-rw-r--r--src/google/protobuf/compiler/plugin.pb.cc333
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h455
-rw-r--r--src/google/protobuf/compiler/plugin.proto1
-rw-r--r--src/google/protobuf/compiler/python/python_generator.cc116
-rw-r--r--src/google/protobuf/compiler/python/python_generator.h3
-rw-r--r--src/google/protobuf/compiler/python/python_plugin_unittest.cc3
53 files changed, 3990 insertions, 1361 deletions
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index f9f27bd8..fc7df414 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -50,6 +50,9 @@
#include <google/protobuf/stubs/hash.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/stringprintf.h>
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 5bc1fea9..6e1a204d 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -41,6 +41,9 @@
#include <unistd.h>
#endif
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <google/protobuf/descriptor.pb.h>
@@ -48,6 +51,7 @@
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/compiler/command_line_interface.h>
#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/compiler/mock_code_generator.h>
#include <google/protobuf/compiler/subprocess.h>
#include <google/protobuf/io/printer.h>
@@ -59,6 +63,7 @@
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
+
namespace google {
namespace protobuf {
namespace compiler {
@@ -77,6 +82,10 @@ namespace compiler {
namespace {
+bool FileExists(const string& path) {
+ return File::Exists(path);
+}
+
class CommandLineInterfaceTest : public testing::Test {
protected:
virtual void SetUp();
@@ -226,7 +235,7 @@ void CommandLineInterfaceTest::SetUp() {
// If the temp directory already exists, it must be left over from a
// previous run. Delete it.
- if (File::Exists(temp_directory_)) {
+ if (FileExists(temp_directory_)) {
File::DeleteRecursively(temp_directory_, NULL, NULL);
}
@@ -335,7 +344,7 @@ void CommandLineInterfaceTest::CreateTempFile(
string::size_type slash_pos = name.find_last_of('/');
if (slash_pos != string::npos) {
string dir = name.substr(0, slash_pos);
- if (!File::Exists(temp_directory_ + "/" + dir)) {
+ if (!FileExists(temp_directory_ + "/" + dir)) {
GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + dir,
0777));
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index c31cb5b3..32d5516e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -101,6 +101,15 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) {
}
}
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ // For new enum semantics: generate min and max sentinel values equal to
+ // INT32_MIN and INT32_MAX
+ if (descriptor_->value_count() > 0) printer->Print(",\n");
+ printer->Print(vars,
+ "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = INT32_MIN,\n"
+ "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = INT32_MAX");
+ }
+
printer->Outdent();
printer->Print("\n};\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index 20b18ade..17926135 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -87,9 +87,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" // @@protoc_insertion_point(field_get:$full_name$)\n"
" return static_cast< $type$ >($name$_);\n"
"}\n"
- "inline void $classname$::set_$name$($type$ value) {\n"
- " assert($type$_IsValid(value));\n"
- " set_has_$name$();\n"
+ "inline void $classname$::set_$name$($type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " assert($type$_IsValid(value));\n");
+ }
+ printer->Print(variables_,
+ " $set_hasbit$\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
@@ -121,21 +125,27 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"int value;\n"
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
- " input, &value)));\n"
- "if ($type$_IsValid(value)) {\n"
- " set_$name$(static_cast< $type$ >(value));\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
+ " input, &value)));\n");
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables_,
- "} else {\n"
- " mutable_unknown_fields()->AddVarint($number$, value);\n");
+ "set_$name$(static_cast< $type$ >(value));\n");
} else {
- printer->Print(
- "} else {\n"
- " unknown_fields_stream.WriteVarint32(tag);\n"
- " unknown_fields_stream.WriteVarint32(value);\n");
+ printer->Print(variables_,
+ "if ($type$_IsValid(value)) {\n"
+ " set_$name$(static_cast< $type$ >(value));\n");
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(variables_,
+ "} else {\n"
+ " mutable_unknown_fields()->AddVarint($number$, value);\n");
+ } else {
+ printer->Print(
+ "} else {\n"
+ " unknown_fields_stream.WriteVarint32(tag);\n"
+ " unknown_fields_stream.WriteVarint32(value);\n");
+ }
+ printer->Print(variables_,
+ "}\n");
}
- printer->Print(variables_,
- "}\n");
}
void EnumFieldGenerator::
@@ -174,18 +184,24 @@ void EnumOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"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"
- " assert($type$_IsValid(value));\n"
+ "inline void $classname$::set_$name$($type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " assert($type$_IsValid(value));\n");
+ }
+ printer->Print(variables_,
" if (!has_$name$()) {\n"
" clear_$oneof_name$();\n"
" set_has_$name$();\n"
" }\n"
" $oneof_prefix$$name$_ = value;\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
@@ -245,13 +261,21 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" // @@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"
- " assert($type$_IsValid(value));\n"
+ "inline void $classname$::set_$name$(int index, $type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " assert($type$_IsValid(value));\n");
+ }
+ printer->Print(variables_,
" $name$_.Set(index, value);\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n"
- "inline void $classname$::add_$name$($type$ value) {\n"
- " assert($type$_IsValid(value));\n"
+ "inline void $classname$::add_$name$($type$ value) {\n");
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " assert($type$_IsValid(value));\n");
+ }
+ printer->Print(variables_,
" $name$_.Add(value);\n"
" // @@protoc_insertion_point(field_add:$full_name$)\n"
"}\n");
@@ -280,7 +304,7 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+ printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
void RepeatedEnumFieldGenerator::
@@ -295,20 +319,26 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"int value;\n"
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
- " input, &value)));\n"
- "if ($type$_IsValid(value)) {\n"
- " add_$name$(static_cast< $type$ >(value));\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
+ " input, &value)));\n");
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
printer->Print(variables_,
- "} else {\n"
- " mutable_unknown_fields()->AddVarint($number$, value);\n");
+ "add_$name$(static_cast< $type$ >(value));\n");
} else {
- printer->Print(
- "} else {\n"
- " unknown_fields_stream.WriteVarint32(tag);\n"
- " unknown_fields_stream.WriteVarint32(value);\n");
+ printer->Print(variables_,
+ "if ($type$_IsValid(value)) {\n"
+ " add_$name$(static_cast< $type$ >(value));\n");
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(variables_,
+ "} else {\n"
+ " mutable_unknown_fields()->AddVarint($number$, value);\n");
+ } else {
+ printer->Print(
+ "} else {\n"
+ " unknown_fields_stream.WriteVarint32(tag);\n"
+ " unknown_fields_stream.WriteVarint32(value);\n");
+ }
+ printer->Print("}\n");
}
- printer->Print("}\n");
}
void RepeatedEnumFieldGenerator::
@@ -318,8 +348,15 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
// rarely be executed.
printer->Print(variables_,
"DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n"
- " input,\n"
- " &$type$_IsValid,\n"
+ " input,\n");
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " NULL,\n");
+ } else {
+ printer->Print(variables_,
+ " &$type$_IsValid,\n");
+ }
+ printer->Print(variables_,
" this->mutable_$name$())));\n");
} else {
printer->Print(variables_,
@@ -331,10 +368,17 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const {
" int value;\n"
" DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(\n"
- " input, &value)));\n"
+ " input, &value)));\n");
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ printer->Print(variables_,
+ " add_$name$(static_cast< $type$ >(value));\n");
+ } else {
+ printer->Print(variables_,
" if ($type$_IsValid(value)) {\n"
" add_$name$(static_cast< $type$ >(value));\n"
- " }\n"
+ " }\n");
+ }
+ printer->Print(variables_,
"}\n"
"input->PopLimit(limit);\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index 1e9a40ac..85838ac3 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -34,6 +34,9 @@
#include <google/protobuf/compiler/cpp/cpp_field.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/cpp/cpp_helpers.h>
#include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
@@ -68,6 +71,20 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor,
? " PROTOBUF_DEPRECATED" : "";
(*variables)["cppget"] = "Get";
+
+ if (HasFieldPresence(descriptor->file())) {
+ (*variables)["set_hasbit"] =
+ "set_has_" + FieldName(descriptor) + "();";
+ (*variables)["clear_hasbit"] =
+ "clear_has_" + FieldName(descriptor) + "();";
+ } else {
+ (*variables)["set_hasbit"] = "";
+ (*variables)["clear_hasbit"] = "";
+ }
+
+ // By default, empty string, so that generic code used for both oneofs and
+ // singular fields can be written.
+ (*variables)["oneof_prefix"] = "";
}
void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 0342c35e..088e5063 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -37,6 +37,9 @@
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <google/protobuf/descriptor.h>
@@ -124,6 +127,16 @@ class FieldGenerator {
// Most field types don't need this, so the default implementation is empty.
virtual void GenerateDestructorCode(io::Printer* /*printer*/) const {}
+ // Generate a manual destructor invocation for use when the message is on an
+ // arena. The code that this method generates will be executed inside a
+ // shared-for-the-whole-message-class method registered with OwnDestructor().
+ // The method should return |true| if it generated any code that requires a
+ // call; this allows the message generator to eliminate the OwnDestructor()
+ // registration if no fields require it.
+ virtual bool GenerateArenaDestructorCode(io::Printer* printer) const {
+ return false;
+ }
+
// Generate code that allocates the fields's default instance.
virtual void GenerateDefaultInstanceAllocator(io::Printer* /*printer*/)
const {}
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index fa194273..dc8bf613 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -34,6 +34,9 @@
#include <google/protobuf/compiler/cpp/cpp_file.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <set>
#include <google/protobuf/compiler/cpp/cpp_enum.h>
@@ -102,6 +105,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"#define PROTOBUF_$filename_identifier$__INCLUDED\n"
"\n"
"#include <string>\n"
+ "#include <stdint.h>\n" // INT32_MIN, INT32_MAX
"\n",
"filename", file_->name(),
"filename_identifier", filename_identifier);
@@ -131,7 +135,10 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
// OK, it's now safe to #include other files.
printer->Print(
- "#include <google/protobuf/generated_message_util.h>\n");
+ "#include <google/protobuf/arena.h>\n"
+ "#include <google/protobuf/arenastring.h>\n"
+ "#include <google/protobuf/generated_message_util.h>\n"
+ "#include <google/protobuf/metadata.h>\n");
if (file_->message_type_count() > 0) {
if (HasDescriptorMethods(file_)) {
printer->Print(
@@ -181,6 +188,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
"// @@protoc_insertion_point(includes)\n");
+
// Open namespace.
GenerateNamespaceOpeners(printer);
@@ -189,9 +197,10 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
printer->Print(
"\n"
"// Internal implementation detail -- do not call these.\n"
- "void $dllexport_decl$ $adddescriptorsname$();\n",
+ "void $dllexport_decl$$adddescriptorsname$();\n",
"adddescriptorsname", GlobalAddDescriptorsName(file_->name()),
- "dllexport_decl", options_.dllexport_decl);
+ "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
@@ -295,7 +304,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) {
}
printer->Print(
"\n"
- "} // namespace google\n} // namespace protobuf\n"
+ "} // namespace protobuf\n} // namespace google\n"
"#endif // SWIG\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
index 4e4d8b6a..13d06f98 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.h
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -36,6 +36,9 @@
#define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index 75d558ea..a2fb7162 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -36,6 +36,9 @@
#include <vector>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <utility>
#include <google/protobuf/compiler/cpp/cpp_file.h>
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index b7a47acb..63b0265e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -60,16 +60,17 @@ string DotsToColons(const string& name) {
}
const char* const kKeywordList[] = {
- "and", "and_eq", "asm", "auto", "bitand", "bitor", "bool", "break", "case",
- "catch", "char", "class", "compl", "const", "const_cast", "continue",
- "default", "delete", "do", "double", "dynamic_cast", "else", "enum",
- "explicit", "extern", "false", "float", "for", "friend", "goto", "if",
- "inline", "int", "long", "mutable", "namespace", "new", "not", "not_eq",
- "operator", "or", "or_eq", "private", "protected", "public", "register",
- "reinterpret_cast", "return", "short", "signed", "sizeof", "static",
- "static_cast", "struct", "switch", "template", "this", "throw", "true", "try",
- "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual",
- "void", "volatile", "wchar_t", "while", "xor", "xor_eq"
+ "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor",
+ "bool", "break", "case", "catch", "char", "class", "compl", "const",
+ "constexpr", "const_cast", "continue", "decltype", "default", "delete", "do",
+ "double", "dynamic_cast", "else", "enum", "explicit", "extern", "false",
+ "float", "for", "friend", "goto", "if", "inline", "int", "long", "mutable",
+ "namespace", "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or",
+ "or_eq", "private", "protected", "public", "register", "reinterpret_cast",
+ "return", "short", "signed", "sizeof", "static", "static_assert",
+ "static_cast", "struct", "switch", "template", "this", "thread_local",
+ "throw", "true", "try", "typedef", "typeid", "typename", "union", "unsigned",
+ "using", "virtual", "void", "volatile", "wchar_t", "while", "xor", "xor_eq"
};
hash_set<string> MakeKeywordsMap() {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 5d30240c..1cff17c8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -135,8 +135,15 @@ string SafeFunctionName(const Descriptor* descriptor,
const FieldDescriptor* field,
const string& prefix);
-// Do message classes in this file use UnknownFieldSet?
-// Otherwise, messages will store unknown fields in a string
+// Returns true if unknown fields are preseved after parsing.
+inline bool PreserveUnknownFields(const Descriptor* message) {
+ return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// If PreserveUnknownFields() is true, determines whether unknown
+// fields will be stored in an UnknownFieldSet or a string.
+// If PreserveUnknownFields() is false, this method will not be
+// used.
inline bool UseUnknownFieldSet(const FileDescriptor* file) {
return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
}
@@ -198,6 +205,28 @@ bool IsStringOrMessage(const FieldDescriptor* field);
string UnderscoresToCamelCase(const string& input, bool cap_next_letter);
+inline bool HasFieldPresence(const FileDescriptor* file) {
+ return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Returns true if 'enum' semantics are such that unknown values are preserved
+// in the enum field itself, rather than going to the UnknownFieldSet.
+inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
+ return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool SupportsArenas(const FileDescriptor* file) {
+ return true;
+}
+
+inline bool SupportsArenas(const Descriptor* desc) {
+ return SupportsArenas(desc->file());
+}
+
+inline bool SupportsArenas(const FieldDescriptor* field) {
+ return SupportsArenas(field->file());
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 3a9d2639..54a92ae4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -36,6 +36,9 @@
#include <google/protobuf/stubs/hash.h>
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <set>
#include <utility>
#include <vector>
@@ -281,8 +284,67 @@ string MessageTypeProtoName(const FieldDescriptor* field) {
return field->message_type()->full_name();
}
+// Emits an if-statement with a condition that evaluates to true if |field| is
+// considered non-default (will be sent over the wire), for message types
+// without true field presence. Should only be called if
+// !HasFieldPresence(message_descriptor).
+bool EmitFieldNonDefaultCondition(io::Printer* printer,
+ const string& prefix,
+ const FieldDescriptor* field) {
+ // Merge and serialize semantics: primitive fields are merged/serialized only
+ // if non-zero (numeric) or non-empty (string).
+ if (!field->is_repeated() && !field->containing_oneof()) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ printer->Print(
+ "if ($prefix$$name$().size() > 0) {\n",
+ "prefix", prefix,
+ "name", FieldName(field));
+ } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ // Message fields still have has_$name$() methods.
+ printer->Print(
+ "if ($prefix$has_$name$()) {\n",
+ "prefix", prefix,
+ "name", FieldName(field));
+ } else {
+ printer->Print(
+ "if ($prefix$$name$() != 0) {\n",
+ "prefix", prefix,
+ "name", FieldName(field));
+ }
+ printer->Indent();
+ return true;
+ } else if (field->containing_oneof()) {
+ printer->Print(
+ "if (has_$name$()) {\n",
+ "name", FieldName(field));
+ printer->Indent();
+ return true;
+ }
+ return false;
+}
+
+// Does the given field have a has_$name$() method?
+bool HasHasMethod(const FieldDescriptor* field) {
+ if (HasFieldPresence(field->file())) {
+ // In proto1/proto2, every field has a has_$name$() method.
+ return true;
+ }
+ // For message types without true field presence, only fields with a message
+ // type have a has_$name$() method.
+ return field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
}
+// Does the given field have a private (internal helper only) has_$name$()
+// method?
+bool HasPrivateHasMethod(const FieldDescriptor* field) {
+ // Only for oneofs in message types with no field presence. has_$name$(),
+ // based on the oneof case, is still useful internally for generated code.
+ return (!HasFieldPresence(field->file()) &&
+ field->containing_oneof() != NULL);
+}
+
+} // anonymous namespace
+
// ===================================================================
MessageGenerator::MessageGenerator(const Descriptor* descriptor,
@@ -312,6 +374,13 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor,
extension_generators_[i].reset(
new ExtensionGenerator(descriptor->extension(i), options));
}
+
+ num_required_fields_ = 0;
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ if (descriptor->field(i)->is_required()) {
+ ++num_required_fields_;
+ }
+ }
}
MessageGenerator::~MessageGenerator() {}
@@ -360,8 +429,13 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) {
if (field->is_repeated()) {
printer->Print(vars, "inline int $name$_size() const$deprecation$;\n");
- } else {
+ } else if (HasHasMethod(field)) {
printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n");
+ } else if (HasPrivateHasMethod(field)) {
+ printer->Print(vars,
+ "private:\n"
+ "inline bool has_$name$() const$deprecation$;\n"
+ "public:\n");
}
printer->Print(vars, "inline void clear_$name$()$deprecation$;\n");
@@ -410,32 +484,59 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
"}\n");
} else if (field->containing_oneof()) {
// Singular field in a oneof
+ // N.B.: Without field presence, we do not use has-bits or generate
+ // has_$name$() methods, but oneofs still have set_has_$name$().
+ // Oneofs also have has_$name$() but only as a private helper
+ // method, so that generated code is slightly cleaner (vs. comparing
+ // _oneof_case_[index] against a constant everywhere).
vars["field_name"] = UnderscoresToCamelCase(field->name(), true);
vars["oneof_name"] = field->containing_oneof()->name();
vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index());
printer->Print(vars,
"inline bool $classname$::has_$name$() const {\n"
" return $oneof_name$_case() == k$field_name$;\n"
- "}\n"
+ "}\n");
+ printer->Print(vars,
"inline void $classname$::set_has_$name$() {\n"
" _oneof_case_[$oneof_index$] = k$field_name$;\n"
"}\n");
} else {
// Singular field.
- char buffer[kFastToBufferSize];
- vars["has_array_index"] = SimpleItoa(field->index() / 32);
- vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer);
- printer->Print(vars,
- "inline bool $classname$::has_$name$() const {\n"
- " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
- "}\n"
- "inline void $classname$::set_has_$name$() {\n"
- " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
- "}\n"
- "inline void $classname$::clear_has_$name$() {\n"
- " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
- "}\n"
- );
+ if (HasFieldPresence(descriptor_->file())) {
+ // N.B.: without field presence, we do not use has-bits or generate
+ // has_$name$() methods.
+ char buffer[kFastToBufferSize];
+ vars["has_array_index"] = SimpleItoa(field->index() / 32);
+ vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32),
+ buffer);
+ printer->Print(vars,
+ "inline bool $classname$::has_$name$() const {\n"
+ " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n"
+ "}\n"
+ "inline void $classname$::set_has_$name$() {\n"
+ " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n"
+ "}\n"
+ "inline void $classname$::clear_has_$name$() {\n"
+ " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n"
+ "}\n"
+ );
+ } else {
+ // Message fields have a has_$name$() method.
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ bool is_lazy = false;
+ if (is_lazy) {
+ printer->Print(vars,
+ "inline bool $classname$::has_$name$() const {\n"
+ " return !$name$_.IsCleared();\n"
+ "}\n");
+ } else {
+ printer->Print(vars,
+ "inline bool $classname$::has_$name$() const {\n"
+ " return $name$_ != NULL;\n"
+ "}\n");
+ }
+ }
+ }
}
// Generate clear_$name$()
@@ -457,9 +558,11 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) {
printer->Print("}\n");
} else {
field_generators_.get(field).GenerateClearingCode(printer);
- if (!field->is_repeated()) {
- printer->Print(vars,
- "clear_has_$name$();\n");
+ if (HasFieldPresence(descriptor_->file())) {
+ if (!field->is_repeated()) {
+ printer->Print(vars,
+ "clear_has_$name$();\n");
+ }
}
}
@@ -553,26 +656,41 @@ GenerateClassDefinition(io::Printer* printer) {
"}\n"
"\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print(
- "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
- " return _unknown_fields_;\n"
- "}\n"
- "\n"
- "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
- " return &_unknown_fields_;\n"
- "}\n"
- "\n");
- } else {
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n"
+ " return _internal_metadata_.unknown_fields();\n"
+ "}\n"
+ "\n"
+ "inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {\n"
+ " return _internal_metadata_.mutable_unknown_fields();\n"
+ "}\n"
+ "\n");
+ } else {
+ printer->Print(
+ "inline const ::std::string& unknown_fields() const {\n"
+ " return _unknown_fields_;\n"
+ "}\n"
+ "\n"
+ "inline ::std::string* mutable_unknown_fields() {\n"
+ " return &_unknown_fields_;\n"
+ "}\n"
+ "\n");
+ }
+ }
+
+ // N.B.: We exclude GetArena() when arena support is disabled, falling back on
+ // MessageLite's implementation which returns NULL rather than generating our
+ // own method which returns NULL, in order to reduce code size.
+ if (SupportsArenas(descriptor_)) {
+ // virtual method version of GetArenaNoVirtual(), required for generic dispatch given a
+ // MessageLite* (e.g., in RepeatedField::AddAllocated()).
printer->Print(
- "inline const ::std::string& unknown_fields() const {\n"
- " return _unknown_fields_;\n"
- "}\n"
- "\n"
- "inline ::std::string* mutable_unknown_fields() {\n"
- " return &_unknown_fields_;\n"
- "}\n"
- "\n");
+ "inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }\n"
+ "inline void* GetMaybeArenaPointer() const {\n"
+ " return MaybeArenaPtr();\n"
+ "}\n");
}
// Only generate this member if it's not disabled.
@@ -628,12 +746,18 @@ GenerateClassDefinition(io::Printer* printer) {
}
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(vars,
+ "void UnsafeArenaSwap($classname$* other);\n");
+ }
printer->Print(vars,
"void Swap($classname$* other);\n"
"\n"
"// implements Message ----------------------------------------------\n"
"\n"
- "$classname$* New() const;\n");
+ "inline $classname$* New() const { return New(NULL); }\n"
+ "\n"
+ "$classname$* New(::google::protobuf::Arena* arena) const;\n");
if (HasGeneratedMethods(descriptor_->file())) {
if (HasDescriptorMethods(descriptor_->file())) {
@@ -699,7 +823,41 @@ GenerateClassDefinition(io::Printer* printer) {
"void SharedCtor();\n"
"void SharedDtor();\n"
"void SetCachedSize(int size) const;\n"
- "public:\n");
+ "void InternalSwap($classname$* other);\n",
+ "classname", classname_);
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "protected:\n"
+ "explicit $classname$(::google::protobuf::Arena* arena);\n"
+ "private:\n"
+ "static void ArenaDtor(void* object);\n"
+ "inline void RegisterArenaDtor(::google::protobuf::Arena* arena);\n",
+ "classname", classname_);
+ }
+
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "private:\n"
+ "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
+ " return _internal_metadata_.arena();\n"
+ "}\n"
+ "inline void* MaybeArenaPtr() const {\n"
+ " return _internal_metadata_.raw_arena_ptr();\n"
+ "}\n"
+ "public:\n"
+ "\n");
+ } else {
+ printer->Print(
+ "private:\n"
+ "inline ::google::protobuf::Arena* GetArenaNoVirtual() const {\n"
+ " return _arena_ptr_;\n"
+ "}\n"
+ "inline ::google::protobuf::Arena* MaybeArenaPtr() const {\n"
+ " return _arena_ptr_;\n"
+ "}\n"
+ "public:\n"
+ "\n");
+ }
if (HasDescriptorMethods(descriptor_->file())) {
printer->Print(
@@ -759,10 +917,18 @@ GenerateClassDefinition(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->is_repeated()) {
- printer->Print(
- "inline void set_has_$name$();\n",
- "name", FieldName(descriptor_->field(i)));
- if (!descriptor_->field(i)->containing_oneof()) {
+ // set_has_***() generated in all proto1/2 code and in oneofs (only) for
+ // messages without true field presence.
+ if (HasFieldPresence(descriptor_->file()) ||
+ descriptor_->field(i)->containing_oneof()) {
+ printer->Print(
+ "inline void set_has_$name$();\n",
+ "name", FieldName(descriptor_->field(i)));
+ }
+ // clear_has_***() generated only for non-oneof fields
+ // in proto1/2.
+ if (!descriptor_->field(i)->containing_oneof() &&
+ HasFieldPresence(descriptor_->file())) {
printer->Print(
"inline void clear_has_$name$();\n",
"name", FieldName(descriptor_->field(i)));
@@ -780,6 +946,14 @@ GenerateClassDefinition(io::Printer* printer) {
"oneof_name", descriptor_->oneof_decl(i)->name());
}
+ if (HasGeneratedMethods(descriptor_->file()) &&
+ !descriptor_->options().message_set_wire_format() &&
+ num_required_fields_ > 1) {
+ printer->Print(
+ "// helper for ByteSize()\n"
+ "int RequiredFieldsByteSizeFallback() const;\n\n");
+ }
+
// Prepare decls for _cached_size_ and _has_bits_. Their position in the
// output will be determined later.
@@ -816,23 +990,32 @@ GenerateClassDefinition(io::Printer* printer) {
if (UseUnknownFieldSet(descriptor_->file())) {
printer->Print(
- "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"
- "\n");
+ "::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;\n");
} else {
printer->Print(
"::std::string _unknown_fields_;\n"
+ "::google::protobuf::Arena* _arena_ptr_;\n"
"\n");
}
- // _has_bits_ is frequently accessed, so to reduce code size and improve
- // speed, it should be close to the start of the object. But, try not to
- // waste space:_has_bits_ by itself always makes sense if its size is a
- // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together
- // will work well.
- printer->Print(has_bits_decl.c_str());
- if ((sizeof_has_bits % 8) != 0) {
- printer->Print(cached_size_decl.c_str());
- need_to_emit_cached_size = false;
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "friend class ::google::protobuf::Arena;\n"
+ "typedef void InternalArenaConstructable_;\n"
+ "typedef void DestructorSkippable_;\n");
+ }
+
+ if (HasFieldPresence(descriptor_->file())) {
+ // _has_bits_ is frequently accessed, so to reduce code size and improve
+ // speed, it should be close to the start of the object. But, try not to
+ // waste space:_has_bits_ by itself always makes sense if its size is a
+ // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together
+ // will work well.
+ printer->Print(has_bits_decl.c_str());
+ if ((sizeof_has_bits % 8) != 0) {
+ printer->Print(cached_size_decl.c_str());
+ need_to_emit_cached_size = false;
+ }
}
// Field members:
@@ -871,7 +1054,10 @@ GenerateClassDefinition(io::Printer* printer) {
// For each oneof generate a union
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
printer->Print(
- "union $camel_oneof_name$Union {\n",
+ "union $camel_oneof_name$Union {\n"
+ // explicit empty constructor is needed when union contains
+ // ArenaStringPtr members for string fields.
+ " $camel_oneof_name$Union() {}\n",
"camel_oneof_name",
UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true));
printer->Indent();
@@ -1029,10 +1215,28 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
" new ::google::protobuf::internal::GeneratedMessageReflection(\n"
" $classname$_descriptor_,\n"
" $classname$::default_instance_,\n"
- " $classname$_offsets_,\n"
- " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n"
+ " $classname$_offsets_,\n");
+ if (!HasFieldPresence(descriptor_->file())) {
+ // If we don't have field presence, then _has_bits_ does not exist.
+ printer->Print(vars,
+ " -1,\n");
+ } else {
+ printer->Print(vars,
+ " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, _has_bits_[0]),\n");
+ }
+
+ // Unknown field offset: either points to the unknown field set if embedded
+ // directly, or indicates that the unknown field set is stored as part of the
+ // internal metadata if not.
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(vars,
+ " -1,\n");
+ } else {
+ printer->Print(vars,
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
"$classname$, _unknown_fields_),\n");
+ }
+
if (descriptor_->extension_range_count() > 0) {
printer->Print(vars,
" GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
@@ -1054,8 +1258,23 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) {
" ::google::protobuf::DescriptorPool::generated_pool(),\n");
printer->Print(vars,
" ::google::protobuf::MessageFactory::generated_factory(),\n");
+
printer->Print(vars,
- " sizeof($classname$));\n");
+ " sizeof($classname$),\n");
+
+ // Arena offset: either an offset to the metadata struct that contains the
+ // arena pointer and unknown field set (in a space-efficient way) if we use
+ // that implementation strategy, or an offset directly to the arena pointer if
+ // not (because e.g. we don't have an unknown field set).
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(vars,
+ " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+ "$classname$, _internal_metadata_));\n");
+ } else {
+ printer->Print(vars,
+ " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+ "$classname$, _arena_));\n");
+ }
// Handle nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
@@ -1100,7 +1319,7 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) {
if ((descriptor_->oneof_decl_count() > 0) &&
HasDescriptorMethods(descriptor_->file())) {
printer->Print(
- "$classname$_default_oneof_instance_ = new $classname$OneofInstance;\n",
+ "$classname$_default_oneof_instance_ = new $classname$OneofInstance();\n",
"classname", classname_);
}
@@ -1312,8 +1531,10 @@ GenerateSharedConstructorCode(io::Printer* printer) {
}
}
- printer->Print(
- "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+ }
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
printer->Print(
@@ -1331,6 +1552,14 @@ GenerateSharedDestructorCode(io::Printer* printer) {
"void $classname$::SharedDtor() {\n",
"classname", classname_);
printer->Indent();
+ if (SupportsArenas(descriptor_)) {
+ // Do nothing when the message is allocated in an arena.
+ printer->Print(
+ "if (GetArenaNoVirtual() != NULL) {\n"
+ " return;\n"
+ "}\n"
+ "\n");
+ }
// Write the destructors for each field except oneof members.
for (int i = 0; i < descriptor_->field_count(); i++) {
if (!descriptor_->field(i)->containing_oneof()) {
@@ -1381,19 +1610,107 @@ GenerateSharedDestructorCode(io::Printer* printer) {
}
void MessageGenerator::
+GenerateArenaDestructorCode(io::Printer* printer) {
+ // Generate the ArenaDtor() method. Track whether any fields actually produced
+ // code that needs to be called.
+ printer->Print(
+ "void $classname$::ArenaDtor(void* object) {\n",
+ "classname", classname_);
+ printer->Indent();
+
+ // This code is placed inside a static method, rather than an ordinary one,
+ // since that simplifies Arena's destructor list (ordinary function pointers
+ // rather than member function pointers). _this is the object being
+ // destructed.
+ printer->Print(
+ "$classname$* _this = reinterpret_cast< $classname$* >(object);\n"
+ // avoid an "unused variable" warning in case no fields have dtor code.
+ "(void)_this;\n",
+ "classname", classname_);
+
+ bool need_registration = false;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (field_generators_.get(descriptor_->field(i))
+ .GenerateArenaDestructorCode(printer)) {
+ need_registration = true;
+ }
+ }
+ printer->Outdent();
+ printer->Print(
+ "}\n");
+
+ if (need_registration) {
+ printer->Print(
+ "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n"
+ " if (arena != NULL) {"
+ " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n"
+ " }\n"
+ "}\n",
+ "classname", classname_);
+ } else {
+ printer->Print(
+ "void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n"
+ "}\n",
+ "classname", classname_);
+ }
+}
+
+void MessageGenerator::
GenerateStructors(io::Printer* printer) {
string superclass = SuperClassName(descriptor_);
+ string initializer_with_arena;
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ initializer_with_arena = "_internal_metadata_(arena)";
+ } else {
+ initializer_with_arena = "_arena_ptr_(arena)";
+ }
+ if (descriptor_->extension_range_count() > 0) {
+ initializer_with_arena = string("\n _extensions_(arena)") +
+ (!initializer_with_arena.empty() ? ", " : "") + initializer_with_arena;
+ } else {
+ initializer_with_arena = "\n " + initializer_with_arena;
+ }
+
+ // Initialize member variables with arena constructor.
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ bool has_arena_constructor = descriptor_->field(i)->is_repeated();
+ if (has_arena_constructor) {
+ initializer_with_arena += string(",\n ") +
+ FieldName(descriptor_->field(i)) + string("_(arena)");
+ }
+ }
+ initializer_with_arena = superclass + "()" +
+ (!initializer_with_arena.empty() ? "," : " ") + initializer_with_arena;
+
+ string initializer_null;
+ initializer_null = (UseUnknownFieldSet(descriptor_->file()) ?
+ ", _internal_metadata_(NULL) " : ", _arena_ptr_(NULL)");
- // Generate the default constructor.
printer->Print(
- "$classname$::$classname$()\n"
- " : $superclass$() {\n"
- " SharedCtor();\n"
- " // @@protoc_insertion_point(constructor:$full_name$)\n"
- "}\n",
- "classname", classname_,
- "superclass", superclass,
- "full_name", descriptor_->full_name());
+ "$classname$::$classname$()\n"
+ " : $superclass$() $initializer$ {\n"
+ " SharedCtor();\n"
+ " // @@protoc_insertion_point(constructor:$full_name$)\n"
+ "}\n",
+ "classname", classname_,
+ "superclass", superclass,
+ "full_name", descriptor_->full_name(),
+ "initializer", initializer_null);
+
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "\n"
+ "$classname$::$classname$(::google::protobuf::Arena* arena)\n"
+ " : $initializer$ {\n"
+ " SharedCtor();\n"
+ " RegisterArenaDtor(arena);\n"
+ " // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
+ "}\n",
+ "initializer", initializer_with_arena,
+ "classname", classname_,
+ "superclass", superclass,
+ "full_name", descriptor_->full_name());
+ }
printer->Print(
"\n"
@@ -1441,7 +1758,17 @@ GenerateStructors(io::Printer* printer) {
// Generate the copy constructor.
printer->Print(
"$classname$::$classname$(const $classname$& from)\n"
- " : $superclass$() {\n"
+ " : $superclass$()",
+ "classname", classname_,
+ "superclass", superclass,
+ "full_name", descriptor_->full_name());
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ ",\n _internal_metadata_(NULL) {\n");
+ } else if (!UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(",\n _arena_ptr_(NULL) {\n");
+ }
+ printer->Print(
" SharedCtor();\n"
" MergeFrom(from);\n"
" // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
@@ -1467,6 +1794,11 @@ GenerateStructors(io::Printer* printer) {
// Generate the shared destructor code.
GenerateSharedDestructorCode(printer);
+ // Generate the arena-specific destructor code.
+ if (SupportsArenas(descriptor_)) {
+ GenerateArenaDestructorCode(printer);
+ }
+
// Generate SetCachedSize.
printer->Print(
"void $classname$::SetCachedSize(int size) const {\n"
@@ -1512,11 +1844,23 @@ GenerateStructors(io::Printer* printer) {
"\n",
"classname", classname_);
- printer->Print(
- "$classname$* $classname$::New() const {\n"
- " return new $classname$;\n"
- "}\n",
- "classname", classname_);
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(
+ "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
+ " return ::google::protobuf::Arena::CreateMessage<$classname$>(arena);\n"
+ "}\n",
+ "classname", classname_);
+ } else {
+ printer->Print(
+ "$classname$* $classname$::New(::google::protobuf::Arena* arena) const {\n"
+ " $classname$* n = new $classname$;\n"
+ " if (arena != NULL) {\n"
+ " arena->Own(n);\n"
+ " }\n"
+ " return n;\n"
+ "}\n",
+ "classname", classname_);
+ }
}
@@ -1616,16 +1960,19 @@ GenerateClear(io::Printer* printer) {
const string& memsets = memsets_for_chunk[i / 8];
uint32 mask = fields_mask_for_chunk[i / 8];
int count = popcnt(mask);
+ GOOGLE_DCHECK_GE(count, 1);
if (count == 1 ||
(count <= 4 && count == memset_field_count_for_chunk[i / 8])) {
// No "if" here because the chunk is trivial.
} else {
- printer->Print(
- "if (_has_bits_[$index$ / 32] & $mask$) {\n",
- "index", SimpleItoa(i / 8 * 8),
- "mask", SimpleItoa(mask));
- printer->Indent();
- chunk_block_in_progress = true;
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ "if (_has_bits_[$index$ / 32] & $mask$) {\n",
+ "index", SimpleItoa(i / 8 * 8),
+ "mask", SimpleItoa(mask));
+ printer->Indent();
+ chunk_block_in_progress = true;
+ }
}
printer->Print(memsets.c_str());
}
@@ -1639,14 +1986,18 @@ GenerateClear(io::Printer* printer) {
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
field->cpp_type() == FieldDescriptor::CPPTYPE_STRING;
- if (should_check_bit) {
+ bool have_enclosing_if = false;
+ if (should_check_bit &&
+ // If no field presence, then always clear strings/messages as well.
+ HasFieldPresence(descriptor_->file())) {
printer->Print("if (has_$name$()) {\n", "name", fieldname);
printer->Indent();
+ have_enclosing_if = true;
}
field_generators_.get(field).GenerateClearingCode(printer);
- if (should_check_bit) {
+ if (have_enclosing_if) {
printer->Outdent();
printer->Print("}\n");
}
@@ -1678,16 +2029,22 @@ GenerateClear(io::Printer* printer) {
"oneof_name", descriptor_->oneof_decl(i)->name());
}
- // Step 5: Everything else.
- printer->Print(
- "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
-
- if (UseUnknownFieldSet(descriptor_->file())) {
+ if (HasFieldPresence(descriptor_->file())) {
+ // Step 5: Everything else.
printer->Print(
- "mutable_unknown_fields()->Clear();\n");
- } else {
- printer->Print(
- "mutable_unknown_fields()->clear();\n");
+ "::memset(_has_bits_, 0, sizeof(_has_bits_));\n");
+ }
+
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "if (_internal_metadata_.have_unknown_fields()) {\n"
+ " mutable_unknown_fields()->Clear();\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "mutable_unknown_fields()->clear();\n");
+ }
}
printer->Outdent();
@@ -1748,12 +2105,42 @@ GenerateOneofClear(io::Printer* printer) {
void MessageGenerator::
GenerateSwap(io::Printer* printer) {
- // Generate the Swap member function.
- printer->Print("void $classname$::Swap($classname$* other) {\n",
+ if (SupportsArenas(descriptor_)) {
+ // Generate the Swap member function. This is a lightweight wrapper around
+ // UnsafeArenaSwap() / MergeFrom() with temporaries, depending on the memory
+ // ownership situation: swapping across arenas or between an arena and a
+ // heap requires copying.
+ printer->Print(
+ "void $classname$::Swap($classname$* other) {\n"
+ " if (other == this) return;\n"
+ " if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {\n"
+ " InternalSwap(other);\n"
+ " } else {\n"
+ " $classname$ temp;\n"
+ " temp.MergeFrom(*this);\n"
+ " CopyFrom(*other);\n"
+ " other->CopyFrom(temp);\n"
+ " }\n"
+ "}\n"
+ "void $classname$::UnsafeArenaSwap($classname$* other) {\n"
+ " if (other == this) return;\n"
+ " GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());\n"
+ " InternalSwap(other);\n"
+ "}\n",
+ "classname", classname_);
+ } else {
+ printer->Print(
+ "void $classname$::Swap($classname$* other) {\n"
+ " if (other == this) return;\n"
+ " InternalSwap(other);\n"
+ "}\n",
+ "classname", classname_);
+ }
+
+ // Generate the UnsafeArenaSwap member function.
+ printer->Print("void $classname$::InternalSwap($classname$* other) {\n",
"classname", classname_);
printer->Indent();
- printer->Print("if (other != this) {\n");
- printer->Indent();
if (HasGeneratedMethods(descriptor_->file())) {
for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -1769,15 +2156,25 @@ GenerateSwap(io::Printer* printer) {
"i", SimpleItoa(i));
}
- for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) {
- printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
- "i", SimpleItoa(i));
+ if (HasFieldPresence(descriptor_->file())) {
+ for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) {
+ printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
+ "i", SimpleItoa(i));
+ }
}
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
+ } else {
+ printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n");
+ }
} else {
- printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n");
+ // Still swap internal_metadata as it may contain more than just
+ // unknown fields.
+ printer->Print(
+ "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
}
printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
if (descriptor_->extension_range_count() > 0) {
@@ -1789,8 +2186,6 @@ GenerateSwap(io::Printer* printer) {
printer->Outdent();
printer->Print("}\n");
- printer->Outdent();
- printer->Print("}\n");
}
void MessageGenerator::
@@ -1886,33 +2281,48 @@ GenerateMergeFrom(io::Printer* printer) {
const FieldDescriptor* field = descriptor_->field(i);
if (!field->is_repeated() && !field->containing_oneof()) {
- // See above in GenerateClear for an explanation of this.
- if (i / 8 != last_index / 8 || last_index < 0) {
- if (last_index >= 0) {
- printer->Outdent();
- printer->Print("}\n");
+ if (HasFieldPresence(descriptor_->file())) {
+ // See above in GenerateClear for an explanation of this.
+ if (i / 8 != last_index / 8 || last_index < 0) {
+ if (last_index >= 0) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ printer->Print(
+ "if (from._has_bits_[$index$ / 32] & "
+ "(0xffu << ($index$ % 32))) {\n",
+ "index", SimpleItoa(field->index()));
+ printer->Indent();
}
- printer->Print(
- "if (from._has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
- "index", SimpleItoa(field->index()));
- printer->Indent();
}
last_index = i;
- printer->Print(
- "if (from.has_$name$()) {\n",
- "name", FieldName(field));
- printer->Indent();
+ bool have_enclosing_if = false;
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ "if (from.has_$name$()) {\n",
+ "name", FieldName(field));
+ printer->Indent();
+ have_enclosing_if = true;
+ } else {
+ // Merge semantics without true field presence: primitive fields are
+ // merged only if non-zero (numeric) or non-empty (string).
+ have_enclosing_if = EmitFieldNonDefaultCondition(
+ printer, "from.", field);
+ }
field_generators_.get(field).GenerateMergingCode(printer);
- printer->Outdent();
- printer->Print("}\n");
+ if (have_enclosing_if) {
+ printer->Outdent();
+ printer->Print("}\n");
+ }
}
}
- if (last_index >= 0) {
+ if (HasFieldPresence(descriptor_->file()) &&
+ last_index >= 0) {
printer->Outdent();
printer->Print("}\n");
}
@@ -1921,12 +2331,16 @@ GenerateMergeFrom(io::Printer* printer) {
printer->Print("_extensions_.MergeFrom(from._extensions_);\n");
}
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print(
- "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n");
- } else {
- printer->Print(
- "mutable_unknown_fields()->append(from.unknown_fields());\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "if (from._internal_metadata_.have_unknown_fields()) {\n"
+ " mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "mutable_unknown_fields()->append(from.unknown_fields());\n");
+ }
}
printer->Outdent();
@@ -2171,24 +2585,33 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
}
printer->Print(") {\n");
- if (UseUnknownFieldSet(descriptor_->file())) {
- PrintHandlingOptionalStaticInitializers(
- descriptor_->file(), printer,
- // With static initializers.
- " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
- " mutable_unknown_fields()));\n",
- // Without.
- " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
- " mutable_unknown_fields()));\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ PrintHandlingOptionalStaticInitializers(
+ descriptor_->file(), printer,
+ // With static initializers.
+ " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+ " mutable_unknown_fields()));\n",
+ // Without.
+ " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
+ " mutable_unknown_fields()));\n");
+ } else {
+ PrintHandlingOptionalStaticInitializers(
+ descriptor_->file(), printer,
+ // With static initializers.
+ " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
+ " &unknown_fields_stream));\n",
+ // Without.
+ " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
+ " &unknown_fields_stream));\n");
+ }
} else {
PrintHandlingOptionalStaticInitializers(
descriptor_->file(), printer,
// With static initializers.
- " DO_(_extensions_.ParseField(tag, input, default_instance_,\n"
- " &unknown_fields_stream));\n",
+ " DO_(_extensions_.ParseField(tag, input, default_instance_);\n",
// Without.
- " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n"
- " &unknown_fields_stream));\n");
+ " DO_(_extensions_.ParseField(tag, input, &default_instance());\n");
}
printer->Print(
" continue;\n"
@@ -2196,14 +2619,19 @@ GenerateMergeFromCodedStream(io::Printer* printer) {
}
// We really don't recognize this tag. Skip it.
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print(
- "DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
- " input, tag, mutable_unknown_fields()));\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
+ " input, tag, mutable_unknown_fields()));\n");
+ } else {
+ printer->Print(
+ "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n"
+ " input, tag, &unknown_fields_stream));\n");
+ }
} else {
printer->Print(
- "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n"
- " input, tag, &unknown_fields_stream));\n");
+ "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n");
}
if (descriptor_->field_count() > 0) {
@@ -2232,11 +2660,15 @@ void MessageGenerator::GenerateSerializeOneField(
io::Printer* printer, const FieldDescriptor* field, bool to_array) {
PrintFieldComment(printer, field);
- if (!field->is_repeated()) {
+ bool have_enclosing_if = false;
+ if (!field->is_repeated() && HasFieldPresence(descriptor_->file())) {
printer->Print(
"if (has_$name$()) {\n",
"name", FieldName(field));
printer->Indent();
+ have_enclosing_if = true;
+ } else if (!HasFieldPresence(descriptor_->file())) {
+ have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field);
}
if (to_array) {
@@ -2246,7 +2678,7 @@ void MessageGenerator::GenerateSerializeOneField(
field_generators_.get(field).GenerateSerializeWithCachedSizes(printer);
}
- if (!field->is_repeated()) {
+ if (have_enclosing_if) {
printer->Outdent();
printer->Print("}\n");
}
@@ -2386,28 +2818,69 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) {
}
}
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print("if (!unknown_fields().empty()) {\n");
- printer->Indent();
- if (to_array) {
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n");
+ printer->Indent();
+ if (to_array) {
+ printer->Print(
+ "target = "
+ "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
+ " unknown_fields(), target);\n");
+ } else {
+ printer->Print(
+ "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
+ " unknown_fields(), output);\n");
+ }
+ printer->Outdent();
+
printer->Print(
- "target = "
- "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
- " unknown_fields(), target);\n");
+ "}\n");
} else {
printer->Print(
- "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
- " unknown_fields(), output);\n");
+ "output->WriteRaw(unknown_fields().data(),\n"
+ " unknown_fields().size());\n");
}
- printer->Outdent();
+ }
+}
- printer->Print(
- "}\n");
- } else {
- printer->Print(
- "output->WriteRaw(unknown_fields().data(),\n"
- " unknown_fields().size());\n");
+static vector<uint32> RequiredFieldsBitMask(const Descriptor* desc) {
+ vector<uint32> result;
+ uint32 mask = 0;
+ for (int i = 0; i < desc->field_count(); i++) {
+ if (i > 0 && i % 32 == 0) {
+ result.push_back(mask);
+ mask = 0;
+ }
+ if (desc->field(i)->is_required()) {
+ mask |= (1 << (i & 31));
+ }
+ }
+ if (mask != 0) {
+ result.push_back(mask);
}
+ return result;
+}
+
+// Create an expression that evaluates to
+// "for all i, (_has_bits_[i] & masks[i]) == masks[i]"
+// masks is allowed to be shorter than _has_bits_, but at least one element of
+// masks must be non-zero.
+static string ConditionalToCheckBitmasks(const vector<uint32>& masks) {
+ vector<string> parts;
+ for (int i = 0; i < masks.size(); i++) {
+ if (masks[i] == 0) continue;
+ char buffer[kFastToBufferSize];
+ FastHex32ToBuffer(masks[i], buffer);
+ string m = StrCat("0x", buffer);
+ // Each xor evaluates to 0 if the expected bits are present.
+ parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")"));
+ }
+ GOOGLE_CHECK(!parts.empty());
+ // If we have multiple parts, each expected to be 0, then bitwise-or them.
+ string result = parts.size() == 1 ? parts[0] :
+ StrCat("(", Join(parts, "\n | "), ")");
+ return result + " == 0";
}
void MessageGenerator::
@@ -2420,8 +2893,10 @@ GenerateByteSize(io::Printer* printer) {
"classname", classname_);
GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
printer->Print(
+ "if (_internal_metadata_.have_unknown_fields()) {\n"
" total_size += ::google::protobuf::internal::WireFormat::\n"
- " ComputeUnknownMessageSetItemsSize(unknown_fields());\n");
+ " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"
+ "}\n");
printer->Print(
" GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
" _cached_size_ = total_size;\n"
@@ -2431,6 +2906,33 @@ GenerateByteSize(io::Printer* printer) {
return;
}
+ if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) {
+ // Emit a function (rarely used, we hope) that handles the required fields
+ // by checking for each one individually.
+ printer->Print(
+ "int $classname$::RequiredFieldsByteSizeFallback() const {\n",
+ "classname", classname_);
+ printer->Indent();
+ printer->Print("int total_size = 0;\n");
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->is_required()) {
+ printer->Print("\n"
+ "if (has_$name$()) {\n",
+ "name", FieldName(field));
+ printer->Indent();
+ PrintFieldComment(printer, field);
+ field_generators_.get(field).GenerateByteSize(printer);
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ }
+ printer->Print("\n"
+ "return total_size;\n");
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+
printer->Print(
"int $classname$::ByteSize() const {\n",
"classname", classname_);
@@ -2439,45 +2941,121 @@ GenerateByteSize(io::Printer* printer) {
"int total_size = 0;\n"
"\n");
- int last_index = -1;
+ // Handle required fields (if any). We expect all of them to be
+ // present, so emit one conditional that checks for that. If they are all
+ // present then the fast path executes; otherwise the slow path executes.
+ if (num_required_fields_ > 1 && HasFieldPresence(descriptor_->file())) {
+ // The fast path works if all required fields are present.
+ vector<uint32> masks_for_has_bits = RequiredFieldsBitMask(descriptor_);
+ printer->Print((string("if (") +
+ ConditionalToCheckBitmasks(masks_for_has_bits) +
+ ") { // All required fields are present.\n").c_str());
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (!field->is_required()) continue;
+ PrintFieldComment(printer, field);
+ field_generators_.get(field).GenerateByteSize(printer);
+ printer->Print("\n");
+ }
+ printer->Outdent();
+ printer->Print("} else {\n" // the slow path
+ " total_size += RequiredFieldsByteSizeFallback();\n"
+ "}\n");
+ } else {
+ // num_required_fields_ <= 1: no need to be tricky
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (!field->is_required()) continue;
+ PrintFieldComment(printer, field);
+ printer->Print("if (has_$name$()) {\n",
+ "name", FieldName(field));
+ printer->Indent();
+ field_generators_.get(field).GenerateByteSize(printer);
+ printer->Outdent();
+ printer->Print("}\n");
+ }
+ }
+ // Handle optional fields (worry below about repeateds, oneofs, etc.).
+ // These are handled in chunks of 8. The first chunk is
+ // the non-requireds-non-repeateds-non-unions-non-extensions in
+ // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7),
+ // and the second chunk is the same for
+ // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15),
+ // etc.
+ hash_map<int, uint32> fields_mask_for_chunk;
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
+ if (!field->is_required() && !field->is_repeated() &&
+ !field->containing_oneof()) {
+ fields_mask_for_chunk[i / 8] |= static_cast<uint32>(1) << (i % 32);
+ }
+ }
- if (!field->is_repeated() && !field->containing_oneof()) {
+ int last_index = -1;
+ bool chunk_block_in_progress = false;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (!field->is_required() && !field->is_repeated() &&
+ !field->containing_oneof()) {
// See above in GenerateClear for an explanation of this.
// TODO(kenton): Share code? Unclear how to do so without
// over-engineering.
- if ((i / 8) != (last_index / 8) ||
- last_index < 0) {
- if (last_index >= 0) {
+ if (i / 8 != last_index / 8 || last_index < 0) {
+ // End previous chunk, if there was one.
+ if (chunk_block_in_progress) {
printer->Outdent();
printer->Print("}\n");
+ chunk_block_in_progress = false;
+ }
+ // Start chunk.
+ uint32 mask = fields_mask_for_chunk[i / 8];
+ int count = popcnt(mask);
+ GOOGLE_DCHECK_GE(count, 1);
+ if (count == 1) {
+ // No "if" here because the chunk is trivial.
+ } else {
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ "if (_has_bits_[$index$ / 32] & $mask$) {\n",
+ "index", SimpleItoa(i),
+ "mask", SimpleItoa(mask));
+ printer->Indent();
+ chunk_block_in_progress = true;
+ }
}
- printer->Print(
- "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n",
- "index", SimpleItoa(field->index()));
- printer->Indent();
}
last_index = i;
PrintFieldComment(printer, field);
- printer->Print(
- "if (has_$name$()) {\n",
- "name", FieldName(field));
- printer->Indent();
+ bool have_enclosing_if = false;
+ if (HasFieldPresence(descriptor_->file())) {
+ printer->Print(
+ "if (has_$name$()) {\n",
+ "name", FieldName(field));
+ printer->Indent();
+ have_enclosing_if = true;
+ } else {
+ // Without field presence: field is serialized only if it has a
+ // non-default value.
+ have_enclosing_if = EmitFieldNonDefaultCondition(
+ printer, "this->", field);
+ }
field_generators_.get(field).GenerateByteSize(printer);
- printer->Outdent();
- printer->Print(
- "}\n"
- "\n");
+ if (have_enclosing_if) {
+ printer->Outdent();
+ printer->Print(
+ "}\n"
+ "\n");
+ }
}
}
- if (last_index >= 0) {
+ if (chunk_block_in_progress) {
printer->Outdent();
printer->Print("}\n");
}
@@ -2532,19 +3110,19 @@ GenerateByteSize(io::Printer* printer) {
"\n");
}
- if (UseUnknownFieldSet(descriptor_->file())) {
- printer->Print("if (!unknown_fields().empty()) {\n");
- printer->Indent();
- printer->Print(
- "total_size +=\n"
- " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
- " unknown_fields());\n");
- printer->Outdent();
- printer->Print("}\n");
- } else {
- printer->Print(
- "total_size += unknown_fields().size();\n"
- "\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (UseUnknownFieldSet(descriptor_->file())) {
+ printer->Print(
+ "if (_internal_metadata_.have_unknown_fields()) {\n"
+ " total_size +=\n"
+ " ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
+ " unknown_fields());\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "total_size += unknown_fields().size();\n"
+ "\n");
+ }
}
// We update _cached_size_ even though this is a const method. In theory,
@@ -2569,27 +3147,29 @@ GenerateIsInitialized(io::Printer* printer) {
"classname", classname_);
printer->Indent();
- // Check that all required fields in this message are set. We can do this
- // most efficiently by checking 32 "has bits" at a time.
- int has_bits_array_size = (descriptor_->field_count() + 31) / 32;
- for (int i = 0; i < has_bits_array_size; i++) {
- uint32 mask = 0;
- for (int bit = 0; bit < 32; bit++) {
- int index = i * 32 + bit;
- if (index >= descriptor_->field_count()) break;
- const FieldDescriptor* field = descriptor_->field(index);
-
- if (field->is_required()) {
- mask |= 1 << bit;
+ if (HasFieldPresence(descriptor_->file())) {
+ // Check that all required fields in this message are set. We can do this
+ // most efficiently by checking 32 "has bits" at a time.
+ int has_bits_array_size = (descriptor_->field_count() + 31) / 32;
+ for (int i = 0; i < has_bits_array_size; i++) {
+ uint32 mask = 0;
+ for (int bit = 0; bit < 32; bit++) {
+ int index = i * 32 + bit;
+ if (index >= descriptor_->field_count()) break;
+ const FieldDescriptor* field = descriptor_->field(index);
+
+ if (field->is_required()) {
+ mask |= 1 << bit;
+ }
}
- }
- if (mask != 0) {
- char buffer[kFastToBufferSize];
- printer->Print(
- "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
- "i", SimpleItoa(i),
- "mask", FastHex32ToBuffer(mask, buffer));
+ if (mask != 0) {
+ char buffer[kFastToBufferSize];
+ printer->Print(
+ "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n",
+ "i", SimpleItoa(i),
+ "mask", FastHex32ToBuffer(mask, buffer));
+ }
}
}
@@ -2607,7 +3187,7 @@ GenerateIsInitialized(io::Printer* printer) {
"name", FieldName(field));
} else {
if (field->options().weak()) {
- // For weak fields, use the data member (google::protobuf::Message*) instead
+ // For weak fields, use the data member (::google::protobuf::Message*) instead
// of the getter to avoid a link dependency on the weak message type
// which is only forward declared.
printer->Print(
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index bfd3cec1..a781c234 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -36,6 +36,9 @@
#define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <vector>
#include <google/protobuf/compiler/cpp/cpp_field.h>
@@ -58,8 +61,7 @@ class ExtensionGenerator; // extension.h
class MessageGenerator {
public:
// See generator.cc for the meaning of dllexport_decl.
- explicit MessageGenerator(const Descriptor* descriptor,
- const Options& options);
+ MessageGenerator(const Descriptor* descriptor, const Options& options);
~MessageGenerator();
// Header stuff.
@@ -130,6 +132,8 @@ class MessageGenerator {
void GenerateSharedConstructorCode(io::Printer* printer);
// Generate the shared destructor code.
void GenerateSharedDestructorCode(io::Printer* printer);
+ // Generate the arena-specific destructor code.
+ void GenerateArenaDestructorCode(io::Printer* printer);
// Generate standard Message methods.
void GenerateClear(io::Printer* printer);
@@ -162,6 +166,7 @@ class MessageGenerator {
scoped_array<scoped_ptr<MessageGenerator> > nested_generators_;
scoped_array<scoped_ptr<EnumGenerator> > enum_generators_;
scoped_array<scoped_ptr<ExtensionGenerator> > extension_generators_;
+ int num_required_fields_;
bool uses_string_;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index 6ac15a5a..da1ec60b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -86,6 +86,12 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"inline $type$* mutable_$name$()$deprecation$;\n"
"inline $type$* $release_name$()$deprecation$;\n"
"inline void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "inline $type$* unsafe_arena_release_$name$()$deprecation$;\n"
+ "inline void unsafe_arena_set_allocated_$name$(\n"
+ " $type$* $name$)$deprecation$;\n");
+ }
}
void MessageFieldGenerator::
@@ -101,36 +107,157 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
// Without.
" return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n");
- printer->Print(variables_,
- "}\n"
- "inline $type$* $classname$::mutable_$name$() {\n"
- " set_has_$name$();\n"
- " if ($name$_ == NULL) $name$_ = new $type$;\n"
- " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $name$_;\n"
- "}\n"
- "inline $type$* $classname$::$release_name$() {\n"
- " clear_has_$name$();\n"
- " $type$* temp = $name$_;\n"
- " $name$_ = NULL;\n"
- " return temp;\n"
- "}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " delete $name$_;\n"
- " $name$_ = $name$;\n"
- " if ($name$) {\n"
- " set_has_$name$();\n"
- " } else {\n"
- " clear_has_$name$();\n"
- " }\n"
- " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
- "}\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "}\n"
+ "inline $type$* $classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " if ($name$_ == NULL) {\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ }
+ printer->Print(variables_, " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline $type$* $classname$::$release_name$() {\n"
+ " $clear_hasbit$\n"
+ " if (GetArenaNoVirtual() != NULL) {\n"
+ " if ($name$_ == NULL) {\n"
+ " return NULL;\n"
+ " } else {\n"
+ " $type$* temp = new $type$;\n"
+ " temp->MergeFrom(*$name$_);\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ " } else {\n"
+ " $type$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ "}\n"
+ "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ " $clear_hasbit$\n"
+ " $type$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " if (GetArenaNoVirtual() == NULL) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " if ($name$ != NULL) {\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ // If we're on an arena and the incoming message is not, simply Own() it
+ // rather than copy to the arena -- either way we need a heap dealloc,
+ // so we might as well defer it. Otherwise, if incoming message is on a
+ // different ownership domain (specific arena, or the heap) than we are,
+ // copy to our arena (or heap, as the case may be).
+ printer->Print(variables_,
+ " if (GetArenaNoVirtual() != NULL && \n"
+ " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
+ " GetArenaNoVirtual()->Own($name$);\n"
+ " } else if (GetArenaNoVirtual() !=\n"
+ " ::google::protobuf::Arena::GetArena($name$)) {\n"
+ " $type$* new_$name$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ } else {
+ printer->Print(variables_,
+ " if (GetArenaNoVirtual() != NULL) {\n"
+ " GetArenaNoVirtual()->Own($name$);\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
+ " }\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+ " $type$* $name$) {\n"
+ // If we're not on an arena, free whatever we were holding before.
+ // (If we are on arena, we can just forget the earlier pointer.)
+ " if (GetArenaNoVirtual() == NULL) {\n"
+ " delete $name$_;\n"
+ " }\n"
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_set_allocated"
+ ":$full_name$)\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "}\n"
+ "inline $type$* $classname$::mutable_$name$() {\n"
+ " $set_hasbit$\n"
+ " if ($name$_ == NULL) {\n"
+ " $name$_ = new $type$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $name$_;\n"
+ "}\n"
+ "inline $type$* $classname$::$release_name$() {\n"
+ " $clear_hasbit$\n"
+ " $type$* temp = $name$_;\n"
+ " $name$_ = NULL;\n"
+ " return temp;\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " delete $name$_;\n");
+
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ " if ($name$ != NULL && $name$->GetArena() != NULL) {\n"
+ " $type$* new_$name$ = new $type$;\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
+ " $name$_ = $name$;\n"
+ " if ($name$) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+ }
}
void MessageFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
+ if (!HasFieldPresence(descriptor_->file())) {
+ // If we don't have has-bits, message presence is indicated only by ptr !=
+ // NULL. Thus on clear, we need to delete the object.
+ printer->Print(variables_,
+ "if ($name$_ != NULL) delete $name$_;\n"
+ "$name$_ = NULL;\n");
+ } else {
+ printer->Print(variables_,
+ "if ($name$_ != NULL) $name$_->$type$::Clear();\n");
+ }
}
void MessageFieldGenerator::
@@ -198,43 +325,165 @@ MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {}
void MessageOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const $type$& $classname$::$name$() const {\n"
- " return has_$name$() ? *$oneof_prefix$$name$_\n"
- " : $type$::default_instance();\n"
- "}\n"
- "inline $type$* $classname$::mutable_$name$() {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = new $type$;\n"
- " }\n"
- " return $oneof_prefix$$name$_;\n"
- "}\n"
- "inline $type$* $classname$::$release_name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " $type$* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
- " return temp;\n"
- " } else {\n"
- " return NULL;\n"
- " }\n"
- "}\n"
- "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
- " clear_$oneof_name$();\n"
- " if ($name$) {\n"
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = $name$;\n"
- " }\n"
- "}\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "inline const $type$& $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return has_$name$() ? *$oneof_prefix$$name$_\n"
+ " : $type$::default_instance();\n"
+ "}\n"
+ "inline $type$* $classname$::mutable_$name$() {\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ " $oneof_prefix$$name$_ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ " $oneof_prefix$$name$_ = \n"
+ " ::google::protobuf::Arena::Create< $type$ >(\n"
+ " GetArenaNoVirtual());\n");
+ }
+ printer->Print(variables_,
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $oneof_prefix$$name$_;\n"
+ "}\n"
+ "inline $type$* $classname$::$release_name$() {\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " if (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).
+ " $type$* temp = new $type$;\n"
+ " temp->MergeFrom(*$oneof_prefix$$name$_);\n"
+ " $oneof_prefix$$name$_ = NULL;\n"
+ " return temp;\n"
+ " } else {\n"
+ " $type$* temp = $oneof_prefix$$name$_;\n"
+ " $oneof_prefix$$name$_ = NULL;\n"
+ " return temp;\n"
+ " }\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "inline $type$* $classname$::unsafe_arena_release_$name$() {\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " $type$* temp = $oneof_prefix$$name$_;\n"
+ " $oneof_prefix$$name$_ = NULL;\n"
+ " return temp;\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " clear_$oneof_name$();\n"
+ " if ($name$) {\n");
+
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ // If incoming message is on the heap and we are on an arena, just Own()
+ // it (see above). If it's on a different arena than we are or one of us
+ // is on the heap, we make a copy to our arena/heap.
+ " if (GetArenaNoVirtual() != NULL &&\n"
+ " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n"
+ " GetArenaNoVirtual()->Own($name$);\n"
+ " } else if (GetArenaNoVirtual() !=\n"
+ " ::google::protobuf::Arena::GetArena($name$)) {\n"
+ " $type$* new_$name$ = \n"
+ " ::google::protobuf::Arena::CreateMessage< $type$ >(\n"
+ " GetArenaNoVirtual());\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ } else {
+ printer->Print(variables_,
+ " if (GetArenaNoVirtual() != NULL) {\n"
+ " GetArenaNoVirtual()->Own($name$);\n"
+ " }\n");
+ }
+
+ printer->Print(variables_,
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_ = $name$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::unsafe_arena_set_allocated_$name$("
+ "$type$* $name$) {\n"
+ // We rely on the oneof clear method to free the earlier contents of this
+ // oneof. We can directly use the pointer we're given to set the new
+ // value.
+ " clear_$oneof_name$();\n"
+ " if ($name$) {\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_ = $name$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_unsafe_arena_set_allocated:"
+ "$full_name$)\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "inline const $type$& $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
+ " return has_$name$() ? *$oneof_prefix$$name$_\n"
+ " : $type$::default_instance();\n"
+ "}\n"
+ "inline $type$* $classname$::mutable_$name$() {\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_ = new $type$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $oneof_prefix$$name$_;\n"
+ "}\n"
+ "inline $type$* $classname$::$release_name$() {\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " $type$* temp = $oneof_prefix$$name$_;\n"
+ " $oneof_prefix$$name$_ = NULL;\n"
+ " return temp;\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$($type$* $name$) {\n"
+ " clear_$oneof_name$();\n"
+ " if ($name$) {\n");
+ if (SupportsArenas(descriptor_->message_type())) {
+ printer->Print(variables_,
+ " if ($name$->GetArena() != NULL) {\n"
+ " $type$* new_$name$ = new $type$;\n"
+ " new_$name$->CopyFrom(*$name$);\n"
+ " $name$ = new_$name$;\n"
+ " }\n");
+ }
+ printer->Print(variables_,
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_ = $name$;\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
+ }
}
void MessageOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- // if it is the active field, it cannot be NULL.
- printer->Print(variables_,
- "delete $oneof_prefix$$name$_;\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "if (GetArenaNoVirtual() == NULL) {\n"
+ " delete $oneof_prefix$$name$_;\n"
+ "}\n");
+ } else {
+ printer->Print(variables_,
+ "delete $oneof_prefix$$name$_;\n");
+ }
}
void MessageOneofFieldGenerator::
@@ -318,7 +567,7 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+ printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
void RepeatedMessageFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
index 2dbf14ce..26cefb2e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -35,6 +35,9 @@
// worth.
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/cpp/cpp_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
@@ -69,6 +72,100 @@ class TestGenerator : public CodeGenerator {
TryInsert("test.pb.cc", "includes", context);
TryInsert("test.pb.cc", "namespace_scope", context);
TryInsert("test.pb.cc", "global_scope", context);
+
+ // Check field accessors for an optional int32:
+ TryInsert("test.pb.h", "field_get:foo.Bar.optInt", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.optInt", context);
+
+ // Check field accessors for a repeated int32:
+ TryInsert("test.pb.h", "field_get:foo.Bar.repeatedInt", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.repeatedInt", context);
+
+ // Check field accessors for a required string:
+ TryInsert("test.pb.h", "field_get:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set_allocated:foo.Bar.requiredString",
+ context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
+
+ // Check field accessors for a repeated string:
+ TryInsert("test.pb.h", "field_get:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.repeatedString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.repeatedString", context);
+
+ // Check field accessors for an int inside oneof{}:
+ TryInsert("test.pb.h", "field_get:foo.Bar.oneOfInt", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.oneOfInt", context);
+
+ // Check field accessors for a string inside oneof{}:
+ TryInsert("test.pb.h", "field_get:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
+ TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
+
+ // Check field accessors for an optional message:
+ TryInsert("test.pb.h", "field_get:foo.Bar.optMessage", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.optMessage", context);
+ TryInsert("test.pb.h", "field_set_allocated:foo.Bar.optMessage", context);
+
+ // Check field accessors for a repeated message:
+ TryInsert("test.pb.h", "field_add:foo.Bar.repeatedMessage", context);
+ TryInsert("test.pb.h", "field_get:foo.Bar.repeatedMessage", context);
+ TryInsert("test.pb.h", "field_list:foo.Bar.repeatedMessage", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedMessage", context);
+ TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedMessage",
+ context);
+
+ // Check field accessors for a message inside oneof{}:
+ TryInsert("test.pb.h", "field_get:foo.Bar.oneOfMessage", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfMessage", context);
+ TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfMessage", context);
+
+ // Check field accessors for an optional enum:
+ TryInsert("test.pb.h", "field_get:foo.Bar.optEnum", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.optEnum", context);
+
+ // Check field accessors for a repeated enum:
+ TryInsert("test.pb.h", "field_get:foo.Bar.repeatedEnum", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.repeatedEnum", context);
+ TryInsert("test.pb.h", "field_add:foo.Bar.repeatedEnum", context);
+ TryInsert("test.pb.h", "field_list:foo.Bar.repeatedEnum", context);
+ TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedEnum", context);
+
+ // Check field accessors for an enum inside oneof{}:
+ TryInsert("test.pb.h", "field_get:foo.Bar.oneOfEnum", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.oneOfEnum", context);
+
+ // Check field accessors for a required cord:
+ TryInsert("test.pb.h", "field_get:foo.Bar.requiredCord", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.requiredCord", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredCord", context);
+
+ // Check field accessors for a repeated cord:
+ TryInsert("test.pb.h", "field_get:foo.Bar.repeatedCord", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.repeatedCord", context);
+ TryInsert("test.pb.h", "field_add:foo.Bar.repeatedCord", context);
+ TryInsert("test.pb.h", "field_list:foo.Bar.repeatedCord", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.repeatedCord", context);
+ TryInsert("test.pb.h", "field_mutable_list:foo.Bar.repeatedCord", context);
+
+ // Check field accessors for a cord inside oneof{}:
+ TryInsert("test.pb.h", "field_get:foo.Bar.oneOfCord", context);
+ TryInsert("test.pb.h", "field_set:foo.Bar.oneOfCord", context);
+ TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfCord", context);
+
return true;
}
@@ -88,8 +185,39 @@ TEST(CppPluginTest, PluginTest) {
GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto",
"syntax = \"proto2\";\n"
"package foo;\n"
+ "\n"
+ "enum Thud { VALUE = 0; }\n"
+ "\n"
"message Bar {\n"
" message Baz {}\n"
+ " optional int32 optInt = 1;\n"
+ " repeated int32 repeatedInt = 2;\n"
+ "\n"
+ " required string requiredString = 3;\n"
+ " repeated string repeatedString = 4;\n"
+ "\n"
+ " optional Baz optMessage = 6;\n"
+ " repeated Baz repeatedMessage = 7;\n"
+ "\n"
+ " optional Thud optEnum = 8;\n"
+ " repeated Thud repeatedEnum = 9;\n"
+ "\n"
+ " required string requiredCord = 10 [\n"
+ " ctype = CORD\n"
+ " ];\n"
+ " repeated string repeatedCord = 11 [\n"
+ " ctype = CORD\n"
+ " ];\n"
+ "\n"
+ " oneof Qux {\n"
+ " int64 oneOfInt = 20;\n"
+ " string oneOfString = 21;\n"
+ " Baz oneOfMessage = 22;\n"
+ " Thud oneOfEnum = 23;"
+ " string oneOfCord = 24 [\n"
+ " ctype = CORD\n"
+ " ];\n"
+ " }\n"
"}\n",
true));
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 44290a31..9a2c930e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -129,7 +129,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" return $name$_;\n"
"}\n"
"inline void $classname$::set_$name$($type$ value) {\n"
- " set_has_$name$();\n"
+ " $set_hasbit$\n"
" $name$_ = value;\n"
" // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
@@ -161,7 +161,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
" $type$, $wire_format_field_type$>(\n"
" input, &$name$_)));\n"
- "set_has_$name$();\n");
+ "$set_hasbit$\n");
}
void PrimitiveFieldGenerator::
@@ -207,6 +207,7 @@ void PrimitiveOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
printer->Print(variables_,
"inline $type$ $classname$::$name$() const {\n"
+ " // @@protoc_insertion_point(field_get:$full_name$)\n"
" if (has_$name$()) {\n"
" return $oneof_prefix$$name$_;\n"
" }\n"
@@ -218,6 +219,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const {
" set_has_$name$();\n"
" }\n"
" $oneof_prefix$$name$_ = value;\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
"}\n");
}
@@ -330,7 +332,7 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+ printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
void RepeatedPrimitiveFieldGenerator::
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 180d236b..a2a8c81c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -52,9 +52,14 @@ void SetStringVariables(const FieldDescriptor* descriptor,
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["default_length"] =
SimpleItoa(descriptor->default_value_string().length());
- (*variables)["default_variable"] = descriptor->default_value_string().empty()
- ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()"
- : "_default_" + FieldName(descriptor) + "_";
+ string default_variable_string =
+ descriptor->default_value_string().empty()
+ ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()"
+ : "_default_" + FieldName(descriptor) + "_";
+ (*variables)["default_variable"] = default_variable_string;
+ (*variables)["default_value_init"] =
+ descriptor->default_value_string().empty()
+ ? "" : "*" + default_variable_string;
(*variables)["pointer_type"] =
descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
// NOTE: Escaped here to unblock proto1->proto2 migration.
@@ -63,6 +68,8 @@ void SetStringVariables(const FieldDescriptor* descriptor,
SafeFunctionName(descriptor->containing_type(),
descriptor, "release_");
(*variables)["full_name"] = descriptor->full_name();
+
+ (*variables)["string_piece"] = "::std::string";
}
} // namespace
@@ -80,7 +87,19 @@ StringFieldGenerator::~StringFieldGenerator() {}
void StringFieldGenerator::
GeneratePrivateMembers(io::Printer* printer) const {
- printer->Print(variables_, "::std::string* $name$_;\n");
+ // N.B. that we continue to use |ArenaStringPtr| instead of |string*| for
+ // string fields, even when SupportArenas(descriptor_) == false. Why?
+ // The simple answer is to avoid unmaintainable complexity. The reflection
+ // code assumes ArenaStringPtrs. These are *almost* in-memory-compatible with
+ // string*, except for the pointer tags and related ownership semantics. We
+ // could modify the runtime code to use string* for the not-supporting-arenas
+ // case, but this would require a way to detect which type of class was
+ // generated (adding overhead and complexity to GeneratedMessageReflection)
+ // and littering the runtime code paths with conditionals. It's simpler to
+ // stick with this but use lightweight accessors that assume arena == NULL.
+ // There should be very little overhead anyway because it's just a tagged
+ // pointer in-memory.
+ printer->Print(variables_, "::google::protobuf::internal::ArenaStringPtr $name$_;\n");
}
void StringFieldGenerator::
@@ -125,6 +144,12 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
"inline ::std::string* mutable_$name$()$deprecation$;\n"
"inline ::std::string* $release_name$()$deprecation$;\n"
"inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "inline ::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
+ "inline void unsafe_arena_set_allocated_$name$(\n"
+ " ::std::string* $name$)$deprecation$;\n");
+ }
if (descriptor_->options().ctype() != FieldOptions::STRING) {
@@ -136,74 +161,113 @@ GenerateAccessorDeclarations(io::Printer* printer) const {
void StringFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
- " // @@protoc_insertion_point(field_get:$full_name$)\n"
- " return *$name$_;\n"
- "}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
- " set_has_$name$();\n"
- " if ($name$_ == $default_variable$) {\n"
- " $name$_ = new ::std::string;\n"
- " }\n"
- " $name$_->assign(value);\n"
- " // @@protoc_insertion_point(field_set:$full_name$)\n"
- "}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
- " set_has_$name$();\n"
- " if ($name$_ == $default_variable$) {\n"
- " $name$_ = new ::std::string;\n"
- " }\n"
- " $name$_->assign(value);\n"
- " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
- "}\n"
- "inline "
- "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
- " set_has_$name$();\n"
- " if ($name$_ == $default_variable$) {\n"
- " $name$_ = new ::std::string;\n"
- " }\n"
- " $name$_->assign(reinterpret_cast<const char*>(value), size);\n"
- " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
- "}\n"
- "inline ::std::string* $classname$::mutable_$name$() {\n"
- " set_has_$name$();\n"
- " if ($name$_ == $default_variable$) {\n");
- if (descriptor_->default_value_string().empty()) {
+ if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- " $name$_ = new ::std::string;\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"
+ " $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"
+ " $set_hasbit$\n"
+ " $name$_.Set($default_variable$, $string_piece$(value),\n"
+ " GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+ "}\n"
+ "inline "
+ "void $classname$::set_$name$(const $pointer_type$* value,\n"
+ " size_t size) {\n"
+ " $set_hasbit$\n"
+ " $name$_.Set($default_variable$, $string_piece$(\n"
+ " 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"
+ " $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"
+ " $clear_hasbit$\n"
+ " return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
+ "}\n"
+ "inline ::std::string* $classname$::unsafe_arena_release_$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"
+ " if ($name$ != NULL) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " $name$_.SetAllocated($default_variable$, $name$,\n"
+ " GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::unsafe_arena_set_allocated_$name$(\n"
+ " ::std::string* $name$) {\n"
+ " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+ " if ($name$ != NULL) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " $set_hasbit$\n"
+ " $name$_.UnsafeArenaSetAllocated($default_variable$,\n"
+ " $name$, GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
} else {
+ // No-arena case.
printer->Print(variables_,
- " $name$_ = new ::std::string(*$default_variable$);\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"
+ " $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"
+ " $set_hasbit$\n"
+ " $name$_.SetNoArena($default_variable$, $string_piece$(value));\n"
+ " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+ "}\n"
+ "inline "
+ "void $classname$::set_$name$(const $pointer_type$* value, "
+ "size_t size) {\n"
+ " $set_hasbit$\n"
+ " $name$_.SetNoArena($default_variable$,\n"
+ " $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"
+ " $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"
+ " $clear_hasbit$\n"
+ " return $name$_.ReleaseNoArena($default_variable$);\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ " if ($name$ != NULL) {\n"
+ " $set_hasbit$\n"
+ " } else {\n"
+ " $clear_hasbit$\n"
+ " }\n"
+ " $name$_.SetAllocatedNoArena($default_variable$, $name$);\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
}
- printer->Print(variables_,
- " }\n"
- " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
- " return $name$_;\n"
- "}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
- " clear_has_$name$();\n"
- " if ($name$_ == $default_variable$) {\n"
- " return NULL;\n"
- " } else {\n"
- " ::std::string* temp = $name$_;\n"
- " $name$_ = const_cast< ::std::string*>($default_variable$);\n"
- " return temp;\n"
- " }\n"
- "}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
- " if ($name$_ != $default_variable$) {\n"
- " delete $name$_;\n"
- " }\n"
- " if ($name$) {\n"
- " set_has_$name$();\n"
- " $name$_ = $name$;\n"
- " } else {\n"
- " clear_has_$name$();\n"
- " $name$_ = const_cast< ::std::string*>($default_variable$);\n"
- " }\n"
- " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
- "}\n");
}
void StringFieldGenerator::
@@ -217,16 +281,26 @@ GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {
void StringFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
- if (descriptor_->default_value_string().empty()) {
- printer->Print(variables_,
- "if ($name$_ != $default_variable$) {\n"
- " $name$_->clear();\n"
- "}\n");
+ // Two-dimension specialization here: supporting arenas or not, and default
+ // value is the empty string or not. Complexity here ensures the minimal
+ // number of branches / amount of extraneous code at runtime (given that the
+ // below methods are inlined one-liners)!
+ if (SupportsArenas(descriptor_)) {
+ if (descriptor_->default_value_string().empty()) {
+ printer->Print(variables_,
+ "$name$_.ClearToEmpty($default_variable$, GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.ClearToDefault($default_variable$, GetArenaNoVirtual());\n");
+ }
} else {
- printer->Print(variables_,
- "if ($name$_ != $default_variable$) {\n"
- " $name$_->assign(*$default_variable$);\n"
- "}\n");
+ if (descriptor_->default_value_string().empty()) {
+ printer->Print(variables_,
+ "$name$_.ClearToEmptyNoArena($default_variable$);\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.ClearToDefaultNoArena($default_variable$);\n");
+ }
}
}
@@ -237,21 +311,24 @@ GenerateMergingCode(io::Printer* printer) const {
void StringFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
- printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+ printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
}
void StringFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_,
- "$name$_ = const_cast< ::std::string*>($default_variable$);\n");
+ "$name$_.UnsafeSetDefault($default_variable$);\n");
}
void StringFieldGenerator::
GenerateDestructorCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if ($name$_ != $default_variable$) {\n"
- " delete $name$_;\n"
- "}\n");
+ if (SupportsArenas(descriptor_)) {
+ printer->Print(variables_,
+ "$name$_.Destroy($default_variable$, GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ "$name$_.DestroyNoArena($default_variable$);\n");
+ }
}
void StringFieldGenerator::
@@ -276,13 +353,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n");
+
if (HasUtf8Verification(descriptor_->file()) &&
descriptor_->type() == FieldDescriptor::TYPE_STRING) {
printer->Print(variables_,
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$().data(), this->$name$().length(),\n"
" ::google::protobuf::internal::WireFormat::PARSE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
}
@@ -294,7 +372,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$().data(), this->$name$().length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
printer->Print(variables_,
"::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n"
@@ -309,7 +387,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$().data(), this->$name$().length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
printer->Print(variables_,
"target =\n"
@@ -338,84 +416,186 @@ StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
void StringOneofFieldGenerator::
GenerateInlineAccessorDefinitions(io::Printer* printer) const {
- printer->Print(variables_,
- "inline const ::std::string& $classname$::$name$() const {\n"
- " if (has_$name$()) {\n"
- " return *$oneof_prefix$$name$_;\n"
- " }\n");
- if (descriptor_->default_value_string().empty()) {
- printer->Print(variables_,
- " return ::google::protobuf::internal::GetEmptyStringAlreadyInited();\n");
- } else {
- printer->Print(variables_,
- " return *$default_variable$;\n");
- }
- printer->Print(variables_,
- "}\n"
- "inline void $classname$::set_$name$(const ::std::string& value) {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = new ::std::string;\n"
- " }\n"
- " $oneof_prefix$$name$_->assign(value);\n"
- "}\n"
- "inline void $classname$::set_$name$(const char* value) {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = new ::std::string;\n"
- " }\n"
- " $oneof_prefix$$name$_->assign(value);\n"
- "}\n"
- "inline "
- "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = new ::std::string;\n"
- " }\n"
- " $oneof_prefix$$name$_->assign(\n"
- " reinterpret_cast<const char*>(value), size);\n"
- "}\n"
- "inline ::std::string* $classname$::mutable_$name$() {\n"
- " if (!has_$name$()) {\n"
- " clear_$oneof_name$();\n"
- " set_has_$name$();\n");
- if (descriptor_->default_value_string().empty()) {
+ if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- " $oneof_prefix$$name$_ = new ::std::string;\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"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.Set($default_variable$, value,\n"
+ " GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::set_$name$(const char* value) {\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.Set($default_variable$,\n"
+ " $string_piece$(value), GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+ "}\n"
+ "inline "
+ "void $classname$::set_$name$(const $pointer_type$* value,\n"
+ " size_t size) {\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.Set($default_variable$, $string_piece$(\n"
+ " reinterpret_cast<const char*>(value), size),\n"
+ " GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+ "}\n"
+ "inline ::std::string* $classname$::mutable_$name$() {\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " return $oneof_prefix$$name$_.Mutable($default_variable$,\n"
+ " GetArenaNoVirtual());\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ "}\n"
+ "inline ::std::string* $classname$::$release_name$() {\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " return $oneof_prefix$$name$_.Release($default_variable$,\n"
+ " GetArenaNoVirtual());\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n"
+ " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " return $oneof_prefix$$name$_.UnsafeArenaRelease(\n"
+ " $default_variable$, GetArenaNoVirtual());\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ " if (!has_$name$()) {\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " clear_$oneof_name$();\n"
+ " if ($name$ != NULL) {\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.SetAllocated($default_variable$, $name$,\n"
+ " GetArenaNoVirtual());\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n"
+ "inline void $classname$::unsafe_arena_set_allocated_$name$("
+ "::std::string* $name$) {\n"
+ " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n"
+ " if (!has_$name$()) {\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " clear_$oneof_name$();\n"
+ " if ($name$) {\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeArenaSetAllocated($default_variable$, "
+ "$name$, GetArenaNoVirtual());\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
} else {
+ // No-arena case.
printer->Print(variables_,
- " $oneof_prefix$$name$_ = new ::std::string(*$default_variable$);\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"
+ " // @@protoc_insertion_point(field_set:$full_name$)\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $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"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.SetNoArena($default_variable$,\n"
+ " $string_piece$(value));\n"
+ " // @@protoc_insertion_point(field_set_char:$full_name$)\n"
+ "}\n"
+ "inline "
+ "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " $oneof_prefix$$name$_.SetNoArena($default_variable$, $string_piece$(\n"
+ " reinterpret_cast<const char*>(value), size));\n"
+ " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
+ "}\n"
+ "inline ::std::string* $classname$::mutable_$name$() {\n"
+ " if (!has_$name$()) {\n"
+ " clear_$oneof_name$();\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_mutable:$full_name$)\n"
+ " return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n"
+ "}\n"
+ "inline ::std::string* $classname$::$release_name$() {\n"
+ " if (has_$name$()) {\n"
+ " clear_has_$oneof_name$();\n"
+ " return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n"
+ " } else {\n"
+ " return NULL;\n"
+ " }\n"
+ "}\n"
+ "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
+ " if (!has_$name$()) {\n"
+ " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+ " }\n"
+ " clear_$oneof_name$();\n"
+ " if ($name$ != NULL) {\n"
+ " set_has_$name$();\n"
+ " $oneof_prefix$$name$_.SetAllocatedNoArena($default_variable$,\n"
+ " $name$);\n"
+ " }\n"
+ " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
+ "}\n");
}
- printer->Print(variables_,
- " }\n"
- " return $oneof_prefix$$name$_;\n"
- "}\n"
- "inline ::std::string* $classname$::$release_name$() {\n"
- " if (has_$name$()) {\n"
- " clear_has_$oneof_name$();\n"
- " ::std::string* temp = $oneof_prefix$$name$_;\n"
- " $oneof_prefix$$name$_ = NULL;\n"
- " return temp;\n"
- " } else {\n"
- " return NULL;\n"
- " }\n"
- "}\n"
- "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n"
- " clear_$oneof_name$();\n"
- " if ($name$) {\n"
- " set_has_$name$();\n"
- " $oneof_prefix$$name$_ = $name$;\n"
- " }\n"
- "}\n");
}
void StringOneofFieldGenerator::
GenerateClearingCode(io::Printer* printer) const {
+ if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- "delete $oneof_prefix$$name$_;\n");
+ "$oneof_prefix$$name$_.Destroy($default_variable$,\n"
+ " GetArenaNoVirtual());\n");
+ } else {
+ printer->Print(variables_,
+ "$oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n");
+ }
}
void StringOneofFieldGenerator::
@@ -425,25 +605,45 @@ GenerateSwappingCode(io::Printer* printer) const {
void StringOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
- if (!descriptor_->default_value_string().empty()) {
+ printer->Print(variables_,
+ " const_cast< ::google::protobuf::internal::ArenaStringPtr*>("
+ "&$classname$_default_oneof_instance_->$name$_)->UnsafeSetDefault("
+ "$default_variable$);\n");
+}
+
+void StringOneofFieldGenerator::
+GenerateDestructorCode(io::Printer* printer) const {
+ if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
- " $classname$_default_oneof_instance_->$name$_ = "
- "$classname$::$default_variable$;\n");
+ "if (has_$name$()) {\n"
+ " $oneof_prefix$$name$_.Destroy($default_variable$,\n"
+ " GetArenaNoVirtual());\n"
+ "}\n");
} else {
printer->Print(variables_,
- " $classname$_default_oneof_instance_->$name$_ = "
- "$default_variable$;\n");
+ "if (has_$name$()) {\n"
+ " $oneof_prefix$$name$_.DestroyNoArena($default_variable$);\n"
+ "}\n");
}
}
void StringOneofFieldGenerator::
-GenerateDestructorCode(io::Printer* printer) const {
- printer->Print(variables_,
- "if (has_$name$()) {\n"
- " delete $oneof_prefix$$name$_;\n"
- "}\n");
+GenerateMergeFromCodedStream(io::Printer* printer) const {
+ printer->Print(variables_,
+ "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
+ " input, this->mutable_$name$()));\n");
+
+ if (HasUtf8Verification(descriptor_->file()) &&
+ descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ printer->Print(variables_,
+ "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
+ " this->$name$().data(), this->$name$().length(),\n"
+ " ::google::protobuf::internal::WireFormat::PARSE,\n"
+ " \"$full_name$\");\n");
+ }
}
+
// ===================================================================
RepeatedStringFieldGenerator::
@@ -566,7 +766,7 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedStringFieldGenerator::
GenerateSwappingCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_.Swap(&other->$name$_);\n");
+ printer->Print(variables_, "$name$_.UnsafeArenaSwap(&other->$name$_);\n");
}
void RepeatedStringFieldGenerator::
@@ -586,7 +786,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
" this->$name$(this->$name$_size() - 1).data(),\n"
" this->$name$(this->$name$_size() - 1).length(),\n"
" ::google::protobuf::internal::WireFormat::PARSE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
}
@@ -600,7 +800,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
"::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$(i).data(), this->$name$(i).length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
@@ -618,7 +818,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
" ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
" this->$name$(i).data(), this->$name$(i).length(),\n"
" ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$name$\");\n");
+ " \"$full_name$\");\n");
}
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index 86da38f2..0a5ca440 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -88,6 +88,7 @@ class StringOneofFieldGenerator : public StringFieldGenerator {
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateDestructorCode(io::Printer* printer) const;
+ void GenerateMergeFromCodedStream(io::Printer* printer) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);
diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
index 6b7f8308..4fa3c144 100644
--- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
@@ -35,6 +35,7 @@
// This file tests that various identifiers work as field and type names even
// though the same identifiers are used internally by the C++ code generator.
+syntax = "proto2";
// Some generic_services option(s) added automatically.
// See: http://go/proto2-generic-services-default
@@ -58,7 +59,7 @@ message TestConflictingSymbolNames {
optional int32 total_size = 6;
optional int32 tag = 7;
- enum TestEnum { FOO = 1; }
+ enum TestEnum { FOO = 0; }
message Data1 { repeated int32 data = 1; }
message Data2 { repeated TestEnum data = 1; }
message Data3 { repeated string data = 1; }
@@ -99,6 +100,8 @@ message TestConflictingSymbolNames {
optional uint32 int = 30;
optional uint32 friend = 31;
optional uint32 class = 37;
+ optional uint32 typedecl = 39;
+ optional uint32 auto = 40;
// The generator used to #define a macro called "DO" inside the .cc file.
message DO {}
@@ -116,15 +119,18 @@ message TestConflictingSymbolNames {
// names.
optional DO release_do = 36;
- extensions 1000 to max;
-}
+ // For clashing local variables in Serialize and ByteSize calculation.
+ optional string target = 38;
-message TestConflictingSymbolNamesExtension {
- extend TestConflictingSymbolNames {
- repeated int32 repeated_int32_ext = 20423638 [packed=true];
- }
+ extensions 1000 to max; // NO_PROTO3
}
+message TestConflictingSymbolNamesExtension { // NO_PROTO3
+ extend TestConflictingSymbolNames { // NO_PROTO3
+ repeated int32 repeated_int32_ext = 20423638 [packed=true]; // NO_PROTO3
+ } // NO_PROTO3
+} // NO_PROTO3
+
message DummyMessage {}
service TestConflictingMethodNames {
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 93e1c3f1..c509a6a9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -47,6 +47,9 @@
#include <google/protobuf/compiler/cpp/cpp_unittest.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <google/protobuf/unittest.pb.h>
diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
index e6c446af..678823cd 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -44,6 +44,9 @@
#include <algorithm>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/importer.h>
diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc
index 8cc5d882..81c636c6 100644
--- a/src/google/protobuf/compiler/importer_unittest.cc
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -34,9 +34,13 @@
#include <google/protobuf/stubs/hash.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/testing/file.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/map_util.h>
@@ -53,6 +57,10 @@ namespace compiler {
namespace {
+bool FileExists(const string& path) {
+ return File::Exists(path);
+}
+
#define EXPECT_SUBSTRING(needle, haystack) \
EXPECT_PRED_FORMAT2(testing::IsSubstring, (needle), (haystack))
@@ -215,120 +223,6 @@ TEST_F(ImporterTest, RecursiveImport) {
error_collector_.text_);
}
-// TODO(sanjay): The MapField tests below more properly belong in
-// descriptor_unittest, but are more convenient to test here.
-TEST_F(ImporterTest, MapFieldValid) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Item {\n"
- " required string key = 1;\n"
- "}\n"
- "message Map {\n"
- " repeated Item items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- const FileDescriptor* file = importer_.Import("map.proto");
- ASSERT_TRUE(file != NULL) << error_collector_.text_;
- EXPECT_EQ("", error_collector_.text_);
-
- // Check that Map::items points to Item::key
- const Descriptor* item_type = file->FindMessageTypeByName("Item");
- ASSERT_TRUE(item_type != NULL);
- const Descriptor* map_type = file->FindMessageTypeByName("Map");
- ASSERT_TRUE(map_type != NULL);
- const FieldDescriptor* key_field = item_type->FindFieldByName("key");
- ASSERT_TRUE(key_field != NULL);
- const FieldDescriptor* items_field = map_type->FindFieldByName("items");
- ASSERT_TRUE(items_field != NULL);
- EXPECT_EQ(items_field->experimental_map_key(), key_field);
-}
-
-TEST_F(ImporterTest, MapFieldNotRepeated) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Item {\n"
- " required string key = 1;\n"
- "}\n"
- "message Map {\n"
- " required Item items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("only allowed for repeated fields", error());
-}
-
-TEST_F(ImporterTest, MapFieldNotMessageType) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Map {\n"
- " repeated int32 items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("only allowed for fields with a message type", error());
-}
-
-TEST_F(ImporterTest, MapFieldTypeNotFound) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Map {\n"
- " repeated Unknown items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("not defined", error());
-}
-
-TEST_F(ImporterTest, MapFieldKeyNotFound) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Item {\n"
- " required string key = 1;\n"
- "}\n"
- "message Map {\n"
- " repeated Item items = 1 [experimental_map_key = \"badkey\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("Could not find field", error());
-}
-
-TEST_F(ImporterTest, MapFieldKeyRepeated) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message Item {\n"
- " repeated string key = 1;\n"
- "}\n"
- "message Map {\n"
- " repeated Item items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("must not name a repeated field", error());
-}
-
-TEST_F(ImporterTest, MapFieldKeyNotScalar) {
- AddFile(
- "map.proto",
- "syntax = \"proto2\";\n"
- "message ItemKey { }\n"
- "message Item {\n"
- " required ItemKey key = 1;\n"
- "}\n"
- "message Map {\n"
- " repeated Item items = 1 [experimental_map_key = \"key\"];\n"
- "}\n"
- );
- EXPECT_TRUE(importer_.Import("map.proto") == NULL);
- EXPECT_SUBSTRING("must name a scalar or string", error());
-}
-
// ===================================================================
@@ -339,7 +233,7 @@ class DiskSourceTreeTest : public testing::Test {
dirnames_.push_back(TestTempDir() + "/test_proto2_import_path_2");
for (int i = 0; i < dirnames_.size(); i++) {
- if (File::Exists(dirnames_[i])) {
+ if (FileExists(dirnames_[i])) {
File::DeleteRecursively(dirnames_[i], NULL, NULL);
}
GOOGLE_CHECK_OK(File::CreateDir(dirnames_[i], 0777));
diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h
index 57914450..7f1ce1f9 100644
--- a/src/google/protobuf/compiler/java/java_context.h
+++ b/src/google/protobuf/compiler/java/java_context.h
@@ -33,6 +33,9 @@
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 668377a3..0353b607 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -111,6 +111,10 @@ void EnumGenerator::Generate(io::Printer* printer) {
"$name$($index$, $number$),\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print("UNRECOGNIZED(-1, -1),\n");
+ }
+
printer->Print(
";\n"
"\n");
@@ -141,7 +145,17 @@ void EnumGenerator::Generate(io::Printer* printer) {
printer->Print(
"\n"
- "public final int getNumber() { return value; }\n"
+ "public final int getNumber() {\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ " if (index == -1) {\n"
+ " throw new java.lang.IllegalArgumentException(\n"
+ " \"Can't get the number of an unknown enum value.\");\n"
+ " }\n");
+ }
+ printer->Print(
+ " return value;\n"
+ "}\n"
"\n"
"public static $classname$ valueOf(int value) {\n"
" switch (value) {\n",
@@ -231,11 +245,12 @@ void EnumGenerator::Generate(io::Printer* printer) {
"index", SimpleItoa(descriptor_->index()));
}
printer->Print(
- "return $immutable_package$.$descriptor_class$.getDescriptor()\n"
+ "return $immutable_package$.$descriptor_class$.$descriptor$\n"
" .getEnumTypes().get($index$);\n",
"immutable_package", FileJavaPackage(descriptor_->file(), true),
"descriptor_class",
name_resolver_->GetDescriptorClassName(descriptor_->file()),
+ "descriptor", "getDescriptor()",
"index", SimpleItoa(descriptor_->index()));
printer->Outdent();
}
@@ -283,11 +298,18 @@ void EnumGenerator::Generate(io::Printer* printer) {
" if (desc.getType() != getDescriptor()) {\n"
" throw new java.lang.IllegalArgumentException(\n"
" \"EnumValueDescriptor is not for this type.\");\n"
- " }\n"
+ " }\n",
+ "classname", descriptor_->name());
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(
+ " if (desc.getIndex() == -1) {\n"
+ " return UNRECOGNIZED;\n"
+ " }\n");
+ }
+ printer->Print(
" return VALUES[desc.getIndex()];\n"
"}\n"
- "\n",
- "classname", descriptor_->name());
+ "\n");
// index is only used for reflection; lite implementation does not need it
printer->Print("private final int index;\n");
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 1f0c4af0..71a2ba4b 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -65,6 +65,8 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["mutable_type"] =
name_resolver->GetMutableClassName(descriptor->enum_type());
(*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+ (*variables)["default_number"] = SimpleItoa(
+ descriptor->default_value_enum()->number());
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
@@ -95,7 +97,8 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["clear_has_field_bit_builder"] = "";
(*variables)["is_field_present_message"] =
- (*variables)["name"] + "_ != " + (*variables)["default"];
+ (*variables)["name"] + "_ != " +
+ (*variables)["default"] + ".getNumber()";
}
// For repated builders, one bit is used for whether the array is immutable.
@@ -114,6 +117,12 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
GenerateGetBitFromLocal(builderBitIndex);
(*variables)["set_has_field_bit_to_local"] =
GenerateSetBitToLocal(messageBitIndex);
+
+ if (SupportUnknownEnumValue(descriptor->file())) {
+ (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
+ } else {
+ (*variables)["unknown"] = (*variables)["default"];
+ }
}
} // namespace
@@ -150,6 +159,11 @@ GenerateInterfaceMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$boolean has$capitalized_name$();\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Value();\n");
+ }
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$();\n");
@@ -158,7 +172,7 @@ GenerateInterfaceMembers(io::Printer* printer) const {
void ImmutableEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private $type$ $name$_;\n");
+ "private int $name$_;\n");
PrintExtraFieldInfo(variables_, printer);
if (SupportFieldPresence(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
@@ -167,17 +181,25 @@ GenerateMembers(io::Printer* printer) const {
" return $get_has_field_bit_message$;\n"
"}\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " return $name$_;\n"
+ "}\n");
+ }
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
- " return $name$_;\n"
+ " $type$ result = $type$.valueOf($name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
"}\n");
}
void ImmutableEnumFieldGenerator::
GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private $type$ $name$_ = $default$;\n");
+ "private int $name$_ = $default_number$;\n");
if (SupportFieldPresence(descriptor_->file())) {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -185,10 +207,25 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return $get_has_field_bit_builder$;\n"
"}\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " return $name$_;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+ " $name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ }
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
- " return $name$_;\n"
+ " $type$ result = $type$.valueOf($name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -197,7 +234,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" throw new NullPointerException();\n"
" }\n"
" $set_has_field_bit_builder$\n"
- " $name$_ = value;\n"
+ " $name$_ = value.getNumber();\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -205,7 +242,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public Builder clear$capitalized_name$() {\n"
" $clear_has_field_bit_builder$\n"
- " $name$_ = $default$;\n"
+ " $name$_ = $default_number$;\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -218,13 +255,13 @@ GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
void ImmutableEnumFieldGenerator::
GenerateInitializationCode(io::Printer* printer) const {
- printer->Print(variables_, "$name$_ = $default$;\n");
+ printer->Print(variables_, "$name$_ = $default_number$;\n");
}
void ImmutableEnumFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
printer->Print(variables_,
- "$name$_ = $default$;\n"
+ "$name$_ = $default_number$;\n"
"$clear_has_field_bit_builder$\n");
}
@@ -235,11 +272,13 @@ GenerateMergingCode(io::Printer* printer) const {
"if (other.has$capitalized_name$()) {\n"
" set$capitalized_name$(other.get$capitalized_name$());\n"
"}\n");
- } else {
+ } else if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print(variables_,
- "if (other.get$capitalized_name$() != $default$) {\n"
- " set$capitalized_name$(other.get$capitalized_name$());\n"
+ "if (other.$name$_ != $default_number$) {\n"
+ " set$capitalized_name$Value(other.get$capitalized_name$Value());\n"
"}\n");
+ } else {
+ GOOGLE_LOG(FATAL) << "Can't reach here.";
}
}
@@ -257,23 +296,26 @@ GenerateBuildingCode(io::Printer* printer) const {
void ImmutableEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "int rawValue = input.readEnum();\n"
- "$type$ value = $type$.valueOf(rawValue);\n"
- "if (value == null) {\n");
- if (UseUnknownFieldSet(descriptor_->containing_type())) {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print(variables_,
- " unknownFields.mergeVarintField($number$, rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = rawValue;\n");
} else {
printer->Print(variables_,
- " unknownFieldsCodedOutput.writeRawVarint32(tag);\n"
- " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "$type$ value = $type$.valueOf(rawValue);\n"
+ "if (value == null) {\n");
+ if (PreserveUnknownFields(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ " unknownFields.mergeVarintField($number$, rawValue);\n");
+ }
+ printer->Print(variables_,
+ "} else {\n"
+ " $set_has_field_bit_message$\n"
+ " $name$_ = rawValue;\n"
+ "}\n");
}
- printer->Print(variables_,
- "} else {\n"
- " $set_has_field_bit_message$\n"
- " $name$_ = value;\n"
- "}\n");
}
void ImmutableEnumFieldGenerator::
@@ -285,7 +327,7 @@ void ImmutableEnumFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
- " output.writeEnum($number$, $name$_.getNumber());\n"
+ " output.writeEnum($number$, $name$_);\n"
"}\n");
}
@@ -294,23 +336,21 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
- " .computeEnumSize($number$, $name$_.getNumber());\n"
+ " .computeEnumSize($number$, $name$_);\n"
"}\n");
}
void ImmutableEnumFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
- "result = result &&\n"
- " (get$capitalized_name$() == other.get$capitalized_name$());\n");
+ "result = result && $name$_ == other.$name$_;\n");
}
void ImmutableEnumFieldGenerator::
GenerateHashCode(io::Printer* printer) const {
printer->Print(variables_,
"hash = (37 * hash) + $constant_name$;\n"
- "hash = (53 * hash) + com.google.protobuf.Internal.hashEnum(\n"
- " get$capitalized_name$());\n");
+ "hash = (53 * hash) + $name$_;\n");
}
string ImmutableEnumFieldGenerator::GetBoxedType() const {
@@ -344,11 +384,22 @@ GenerateMembers(io::Printer* printer) const {
" return $has_oneof_case_message$;\n"
"}\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return (java.lang.Integer) $oneof_name$_;\n"
+ " }\n"
+ " return $default_number$;\n"
+ "}\n");
+ }
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" if ($has_oneof_case_message$) {\n"
- " return ($type$) $oneof_name$_;\n"
+ " $type$ result = $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
" }\n"
" return $default$;\n"
"}\n");
@@ -363,11 +414,30 @@ GenerateBuilderMembers(io::Printer* printer) const {
" return $has_oneof_case_message$;\n"
"}\n");
}
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value() {\n"
+ " if ($has_oneof_case_message$) {\n"
+ " return ((java.lang.Integer) $oneof_name$_).intValue();\n"
+ " }\n"
+ " return $default_number$;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = value;\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ }
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
" if ($has_oneof_case_message$) {\n"
- " return ($type$) $oneof_name$_;\n"
+ " $type$ result = $type$.valueOf((java.lang.Integer) $oneof_name$_);\n"
+ " return result == null ? $unknown$ : result;\n"
" }\n"
" return $default$;\n"
"}\n");
@@ -378,7 +448,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" throw new NullPointerException();\n"
" }\n"
" $set_oneof_case_message$;\n"
- " $oneof_name$_ = value;\n"
+ " $oneof_name$_ = value.getNumber();\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -404,36 +474,44 @@ GenerateBuildingCode(io::Printer* printer) const {
void ImmutableEnumOneofFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "set$capitalized_name$(other.get$capitalized_name$());\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "set$capitalized_name$Value(other.get$capitalized_name$Value());\n");
+ } else {
+ printer->Print(variables_,
+ "set$capitalized_name$(other.get$capitalized_name$());\n");
+ }
}
void ImmutableEnumOneofFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- printer->Print(variables_,
- "int rawValue = input.readEnum();\n"
- "$type$ value = $type$.valueOf(rawValue);\n"
- "if (value == null) {\n");
- if (UseUnknownFieldSet(descriptor_->containing_type())) {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print(variables_,
- " unknownFields.mergeVarintField($number$, rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = rawValue;\n");
} else {
printer->Print(variables_,
- " unknownFieldsCodedOutput.writeRawVarint32(tag);\n"
- " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "$type$ value = $type$.valueOf(rawValue);\n"
+ "if (value == null) {\n");
+ if (PreserveUnknownFields(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ " unknownFields.mergeVarintField($number$, rawValue);\n");
+ }
+ printer->Print(variables_,
+ "} else {\n"
+ " $set_oneof_case_message$;\n"
+ " $oneof_name$_ = rawValue;\n"
+ "}\n");
}
- printer->Print(variables_,
- "} else {\n"
- " $set_oneof_case_message$;\n"
- " $oneof_name$_ = value;\n"
- "}\n");
}
void ImmutableEnumOneofFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($has_oneof_case_message$) {\n"
- " output.writeEnum($number$, (($type$) $oneof_name$_).getNumber());\n"
+ " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n"
"}\n");
}
@@ -442,10 +520,36 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($has_oneof_case_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
- " .computeEnumSize($number$, (($type$) $oneof_name$_).getNumber());\n"
+ " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n"
"}\n");
}
+void ImmutableEnumOneofFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$Value()\n"
+ " == other.get$capitalized_name$Value();\n");
+ } else {
+ printer->Print(variables_,
+ "result = result && get$capitalized_name$()\n"
+ " .equals(other.get$capitalized_name$());\n");
+ }
+}
+
+void ImmutableEnumOneofFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$Value();\n");
+ } else {
+ printer->Print(variables_,
+ "hash = (37 * hash) + $constant_name$;\n"
+ "hash = (53 * hash) + get$capitalized_name$().getNumber();\n");
+ }
+}
+
// ===================================================================
RepeatedImmutableEnumFieldGenerator::
@@ -482,17 +586,36 @@ GenerateInterfaceMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$$type$ get$capitalized_name$(int index);\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList();\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$int get$capitalized_name$Value(int index);\n");
+ }
}
void RepeatedImmutableEnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
- "private java.util.List<$type$> $name$_;\n");
+ "private java.util.List<java.lang.Integer> $name$_;\n"
+ "private static final com.google.protobuf.Internal.ListAdapter.Converter<\n"
+ " java.lang.Integer, $type$> $name$_converter_ =\n"
+ " new com.google.protobuf.Internal.ListAdapter.Converter<\n"
+ " java.lang.Integer, $type$>() {\n"
+ " public $type$ convert(java.lang.Integer from) {\n"
+ " $type$ result = $type$.valueOf(from);\n"
+ " return result == null ? $unknown$ : result;\n"
+ " }\n"
+ " };\n");
PrintExtraFieldInfo(variables_, printer);
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
- " return $name$_;\n" // note: unmodifiable list
+ " return new com.google.protobuf.Internal.ListAdapter<\n"
+ " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -502,8 +625,21 @@ GenerateMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
- " return $name$_.get(index);\n"
+ " return $name$_converter_.convert($name$_.get(index));\n"
"}\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList() {\n"
+ " return $name$_;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ }
if (descriptor_->options().packed() &&
HasGeneratedMethods(descriptor_->containing_type())) {
@@ -524,12 +660,12 @@ GenerateBuilderMembers(io::Printer* printer) const {
// memory allocations. Note, immutable is a strong guarantee here -- not
// just that the list cannot be modified via the reference but that the
// list can never be modified.
- "private java.util.List<$type$> $name$_ =\n"
+ "private java.util.List<java.lang.Integer> $name$_ =\n"
" java.util.Collections.emptyList();\n"
"private void ensure$capitalized_name$IsMutable() {\n"
" if (!$get_mutable_bit_builder$) {\n"
- " $name$_ = new java.util.ArrayList<$type$>($name$_);\n"
+ " $name$_ = new java.util.ArrayList<java.lang.Integer>($name$_);\n"
" $set_mutable_bit_builder$;\n"
" }\n"
"}\n");
@@ -541,7 +677,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
// has been built, thus mutating the message which is supposed to be
// immutable.
"$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
- " return java.util.Collections.unmodifiableList($name$_);\n"
+ " return new com.google.protobuf.Internal.ListAdapter<\n"
+ " java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -551,7 +688,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$(int index) {\n"
- " return $name$_.get(index);\n"
+ " return $name$_converter_.convert($name$_.get(index));\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
@@ -561,7 +698,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" throw new NullPointerException();\n"
" }\n"
" ensure$capitalized_name$IsMutable();\n"
- " $name$_.set(index, value);\n"
+ " $name$_.set(index, value.getNumber());\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -572,7 +709,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
" throw new NullPointerException();\n"
" }\n"
" ensure$capitalized_name$IsMutable();\n"
- " $name$_.add(value);\n"
+ " $name$_.add(value.getNumber());\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -581,8 +718,9 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$public Builder addAll$capitalized_name$(\n"
" java.lang.Iterable<? extends $type$> values) {\n"
" ensure$capitalized_name$IsMutable();\n"
- " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
- " values, $name$_);\n"
+ " for ($type$ value : values) {\n"
+ " $name$_.add(value.getNumber());\n"
+ " }\n"
" $on_changed$\n"
" return this;\n"
"}\n");
@@ -594,6 +732,48 @@ GenerateBuilderMembers(io::Printer* printer) const {
" $on_changed$\n"
" return this;\n"
"}\n");
+
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public java.util.List<java.lang.Integer>\n"
+ "get$capitalized_name$ValueList() {\n"
+ " return java.util.Collections.unmodifiableList($name$_);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+ " return $name$_.get(index);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder set$capitalized_name$Value(\n"
+ " int index, int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.set(index, value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " $name$_.add(value);\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(variables_,
+ "$deprecation$public Builder addAll$capitalized_name$Value(\n"
+ " java.lang.Iterable<java.lang.Integer> values) {\n"
+ " ensure$capitalized_name$IsMutable();\n"
+ " for (int value : values) {\n"
+ " $name$_.add(value);\n"
+ " }\n"
+ " $on_changed$\n"
+ " return this;\n"
+ "}\n");
+ }
}
void RepeatedImmutableEnumFieldGenerator::
@@ -648,26 +828,32 @@ GenerateBuildingCode(io::Printer* printer) const {
void RepeatedImmutableEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
// Read and store the enum
- printer->Print(variables_,
- "int rawValue = input.readEnum();\n"
- "$type$ value = $type$.valueOf(rawValue);\n"
- "if (value == null) {\n");
- if (UseUnknownFieldSet(descriptor_->containing_type())) {
+ if (SupportUnknownEnumValue(descriptor_->file())) {
printer->Print(variables_,
- " unknownFields.mergeVarintField($number$, rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n"
+ "$name$_.add(rawValue);\n");
} else {
printer->Print(variables_,
- " unknownFieldsCodedOutput.writeRawVarint32(tag);\n"
- " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n");
+ "int rawValue = input.readEnum();\n"
+ "$type$ value = $type$.valueOf(rawValue);\n"
+ "if (value == null) {\n");
+ if (PreserveUnknownFields(descriptor_->containing_type())) {
+ printer->Print(variables_,
+ " unknownFields.mergeVarintField($number$, rawValue);\n");
+ }
+ printer->Print(variables_,
+ "} else {\n"
+ " if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
+ " $set_mutable_bit_parser$;\n"
+ " }\n"
+ " $name$_.add(rawValue);\n"
+ "}\n");
}
- printer->Print(variables_,
- " } else {\n"
- " if (!$get_mutable_bit_parser$) {\n"
- " $name$_ = new java.util.ArrayList<$type$>();\n"
- " $set_mutable_bit_parser$;\n"
- " }\n"
- " $name$_.add(value);\n"
- "}\n");
}
void RepeatedImmutableEnumFieldGenerator::
@@ -705,12 +891,12 @@ GenerateSerializationCode(io::Printer* printer) const {
" output.writeRawVarint32($name$MemoizedSerializedSize);\n"
"}\n"
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.writeEnumNoTag($name$_.get(i).getNumber());\n"
+ " output.writeEnumNoTag($name$_.get(i));\n"
"}\n");
} else {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
- " output.writeEnum($number$, $name$_.get(i).getNumber());\n"
+ " output.writeEnum($number$, $name$_.get(i));\n"
"}\n");
}
}
@@ -725,7 +911,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < $name$_.size(); i++) {\n"
" dataSize += com.google.protobuf.CodedOutputStream\n"
- " .computeEnumSizeNoTag($name$_.get(i).getNumber());\n"
+ " .computeEnumSizeNoTag($name$_.get(i));\n"
"}\n");
printer->Print(
"size += dataSize;\n");
@@ -754,8 +940,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
void RepeatedImmutableEnumFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
- "result = result && get$capitalized_name$List()\n"
- " .equals(other.get$capitalized_name$List());\n");
+ "result = result && $name$_.equals(other.$name$_);\n");
}
void RepeatedImmutableEnumFieldGenerator::
@@ -763,8 +948,7 @@ GenerateHashCode(io::Printer* printer) const {
printer->Print(variables_,
"if (get$capitalized_name$Count() > 0) {\n"
" hash = (37 * hash) + $constant_name$;\n"
- " hash = (53 * hash) + com.google.protobuf.Internal.hashEnumList(\n"
- " get$capitalized_name$List());\n"
+ " hash = (53 * hash) + $name$_.hashCode();\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h
index 6a9535aa..b8ff7343 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/src/google/protobuf/compiler/java/java_enum_field.h
@@ -106,6 +106,8 @@ class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator {
void GenerateParsingCode(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator);
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index d7b0f3fc..49635bb4 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -35,12 +35,16 @@
#include <google/protobuf/compiler/java/java_field.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum_field.h>
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_lazy_message_field.h>
+#include <google/protobuf/compiler/java/java_map_field.h>
#include <google/protobuf/compiler/java/java_message_field.h>
#include <google/protobuf/compiler/java/java_primitive_field.h>
#include <google/protobuf/compiler/java/java_string_field.h>
@@ -48,6 +52,7 @@
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
+
namespace google {
namespace protobuf {
namespace compiler {
@@ -61,12 +66,17 @@ ImmutableFieldGenerator* MakeImmutableGenerator(
if (field->is_repeated()) {
switch (GetJavaType(field)) {
case JAVATYPE_MESSAGE:
- if (IsLazy(field)) {
- return new RepeatedImmutableLazyMessageFieldGenerator(
+ if (IsMapEntry(field->message_type())) {
+ return new ImmutableMapFieldGenerator(
field, messageBitIndex, builderBitIndex, context);
} else {
- return new RepeatedImmutableMessageFieldGenerator(
- field, messageBitIndex, builderBitIndex, context);
+ if (IsLazy(field)) {
+ return new RepeatedImmutableLazyMessageFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ } else {
+ return new RepeatedImmutableMessageFieldGenerator(
+ field, messageBitIndex, builderBitIndex, context);
+ }
}
case JAVATYPE_ENUM:
return new RepeatedImmutableEnumFieldGenerator(
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index db339d5b..5bc5634e 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -37,6 +37,9 @@
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 231b1445..1ac945cd 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -35,6 +35,9 @@
#include <google/protobuf/compiler/java/java_file.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/java/java_context.h>
#include <google/protobuf/compiler/java/java_enum.h>
@@ -180,29 +183,6 @@ bool FileGenerator::Validate(string* error) {
"option to specify a different outer class name for the .proto file.");
return false;
}
- // If java_outer_classname option is not set and the default outer class name
- // conflicts with a type defined in the message, we will append a suffix to
- // avoid the conflict. This allows proto1 API protos to be dual-compiled into
- // proto2 API without code change. When this happens we'd like to issue an
- // warning to let the user know that the outer class name has been changed.
- // Although we only do this automatic naming fix for immutable API, mutable
- // outer class name will also be affected as it's contructed from immutable
- // outer class name with an additional "Mutable" prefix. Since the naming
- // change in mutable API is not caused by a naming conflict, we generate the
- // warning for immutable API only.
- if (immutable_api_ && !file_->options().has_java_outer_classname()) {
- string default_classname =
- name_resolver_->GetFileDefaultImmutableClassName(file_);
- if (default_classname != classname_) {
- GOOGLE_LOG(WARNING) << file_->name() << ": The default outer class name, \""
- << default_classname << "\", conflicts with a type "
- << "declared in the proto file and an alternative outer "
- << "class name is used: \"" << classname_ << "\". To avoid "
- << "this warning, please use the java_outer_classname "
- << "option to specify a different outer class name for "
- << "the .proto file.";
- }
- }
return true;
}
@@ -323,6 +303,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
SharedCodeGenerator shared_code_generator(file_);
shared_code_generator.GenerateDescriptors(printer);
+
for (int i = 0; i < file_->message_type_count(); i++) {
message_generators_[i]->GenerateStaticVariableInitializers(printer);
}
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index c805b9a6..0b2230a0 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -36,6 +36,9 @@
#define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <vector>
#include <google/protobuf/stubs/common.h>
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index c3a47e3e..a743ce22 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -35,6 +35,9 @@
#include <google/protobuf/compiler/java/java_generator.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/java/java_file.h>
#include <google/protobuf/compiler/java/java_generator_factory.h>
@@ -99,10 +102,14 @@ bool JavaGenerator::Generate(const FileDescriptor* file,
vector<string> all_files;
+
vector<FileGenerator*> file_generators;
if (generate_immutable_code) {
file_generators.push_back(new FileGenerator(file, /* immutable = */ true));
}
+ if (generate_mutable_code) {
+ file_generators.push_back(new FileGenerator(file, /* mutable = */ false));
+ }
for (int i = 0; i < file_generators.size(); ++i) {
if (!file_generators[i]->Validate(error)) {
for (int j = 0; j < file_generators.size(); ++j) {
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index 3efd7edb..23685385 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -306,6 +306,26 @@ JavaType GetJavaType(const FieldDescriptor* field) {
return JAVATYPE_INT;
}
+const char* PrimitiveTypeName(JavaType type) {
+ switch (type) {
+ case JAVATYPE_INT : return "int";
+ case JAVATYPE_LONG : return "long";
+ case JAVATYPE_FLOAT : return "float";
+ case JAVATYPE_DOUBLE : return "double";
+ case JAVATYPE_BOOLEAN: return "boolean";
+ case JAVATYPE_STRING : return "java.lang.String";
+ case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
+ case JAVATYPE_ENUM : return NULL;
+ case JAVATYPE_MESSAGE: return NULL;
+
+ // No default because we want the compiler to complain if any new
+ // JavaTypes are added.
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
const char* BoxedPrimitiveTypeName(JavaType type) {
switch (type) {
case JAVATYPE_INT : return "java.lang.Integer";
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 93f23a93..2707fa0a 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -149,6 +149,8 @@ enum JavaType {
JavaType GetJavaType(const FieldDescriptor* field);
+const char* PrimitiveTypeName(JavaType type);
+
// Get the fully-qualified class name for a boxed primitive type, e.g.
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
// types.
@@ -168,13 +170,6 @@ inline string ImmutableDefaultValue(const FieldDescriptor* field,
}
bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
-// Does this message class use UnknownFieldSet?
-// Otherwise, unknown fields will be stored in a ByteString object
-inline bool UseUnknownFieldSet(const Descriptor* descriptor) {
- return descriptor->file()->options().optimize_for() !=
- FileOptions::LITE_RUNTIME;
-}
-
// Does this message class have generated parsing, serialization, and other
// standard methods for which reflection-based fallback implementations exist?
inline bool HasGeneratedMethods(const Descriptor* descriptor) {
@@ -308,12 +303,27 @@ bool HasRequiredFields(const Descriptor* descriptor);
// Whether a .proto file supports field presence test for non-message types.
inline bool SupportFieldPresence(const FileDescriptor* descriptor) {
- return true;
+ return descriptor->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Whether unknown enum values are kept (i.e., not stored in UnknownFieldSet
+// but in the message and can be queried using additional getters that return
+// ints.
+inline bool SupportUnknownEnumValue(const FileDescriptor* descriptor) {
+ return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
}
// Check whether a mesasge has repeated fields.
bool HasRepeatedFields(const Descriptor* descriptor);
+inline bool IsMapEntry(const Descriptor* descriptor) {
+ return descriptor->options().map_entry();
+}
+
+inline bool PreserveUnknownFields(const Descriptor* descriptor) {
+ return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
new file mode 100644
index 00000000..2986f51f
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -0,0 +1,455 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <google/protobuf/compiler/java/java_map_field.h>
+
+#include <google/protobuf/compiler/java/java_context.h>
+#include <google/protobuf/compiler/java/java_doc_comment.h>
+#include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("key");
+}
+
+const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) {
+ GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type());
+ const Descriptor* message = descriptor->message_type();
+ GOOGLE_CHECK(message->options().map_entry());
+ return message->FindFieldByName("value");
+}
+
+string TypeName(const FieldDescriptor* field,
+ ClassNameResolver* name_resolver,
+ bool boxed) {
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
+ return name_resolver->GetImmutableClassName(field->message_type());
+ } else if (GetJavaType(field) == JAVATYPE_ENUM) {
+ return name_resolver->GetImmutableClassName(field->enum_type());
+ } else {
+ return boxed ? BoxedPrimitiveTypeName(GetJavaType(field))
+ : PrimitiveTypeName(GetJavaType(field));
+ }
+}
+
+string WireType(const FieldDescriptor* field) {
+ return "com.google.protobuf.WireFormat.FieldType." +
+ string(FieldTypeName(field->type()));
+}
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ const FieldGeneratorInfo* info,
+ ClassNameResolver* name_resolver,
+ map<string, string>* variables) {
+ SetCommonFieldVariables(descriptor, info, variables);
+
+ (*variables)["type"] =
+ name_resolver->GetImmutableClassName(descriptor->message_type());
+ const FieldDescriptor* key = KeyField(descriptor);
+ const FieldDescriptor* value = ValueField(descriptor);
+ (*variables)["key_type"] = TypeName(key, name_resolver, false);
+ (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true);
+ (*variables)["key_wire_type"] = WireType(key);
+ (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
+ if (GetJavaType(value) == JAVATYPE_ENUM) {
+ // We store enums as Integers internally.
+ (*variables)["value_type"] = "int";
+ (*variables)["boxed_value_type"] = "java.lang.Integer";
+ (*variables)["value_wire_type"] = WireType(value);
+ (*variables)["value_default_value"] =
+ DefaultValue(value, true, name_resolver) + ".getNumber()";
+
+ (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
+
+ if (SupportUnknownEnumValue(descriptor->file())) {
+ // Map unknown values to a special UNRECOGNIZED value if supported.
+ (*variables)["unrecognized_value"] =
+ (*variables)["value_enum_type"] + ".UNRECOGNIZED";
+ } else {
+ // Map unknown values to the default value if we don't have UNRECOGNIZED.
+ (*variables)["unrecognized_value"] =
+ DefaultValue(value, true, name_resolver);
+ }
+ } else {
+ (*variables)["value_type"] = TypeName(value, name_resolver, false);
+ (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
+ (*variables)["value_wire_type"] = WireType(value);
+ (*variables)["value_default_value"] =
+ DefaultValue(value, true, name_resolver);
+ }
+ (*variables)["type_parameters"] =
+ (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+ // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
+ // by the proto compiler
+ (*variables)["deprecation"] = descriptor->options().deprecated()
+ ? "@java.lang.Deprecated " : "";
+ (*variables)["on_changed"] =
+ HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+ // For repeated fields, one bit is used for whether the array is immutable
+ // in the parsing constructor.
+ (*variables)["get_mutable_bit_parser"] =
+ GenerateGetBitMutableLocal(builderBitIndex);
+ (*variables)["set_mutable_bit_parser"] =
+ GenerateSetBitMutableLocal(builderBitIndex);
+
+ if (HasDescriptorMethods(descriptor->file())) {
+ (*variables)["lite"] = "";
+ (*variables)["map_field_parameter"] = (*variables)["name"] + "DefaultEntry";
+ (*variables)["descriptor"] =
+ name_resolver->GetImmutableClassName(descriptor->file()) +
+ ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
+ "_descriptor, ";
+ } else {
+ (*variables)["lite"] = "Lite";
+ (*variables)["map_field_parameter"] = "";
+ (*variables)["descriptor"] = "";
+ }
+}
+
+} // namespace
+
+ImmutableMapFieldGenerator::
+ImmutableMapFieldGenerator(const FieldDescriptor* descriptor,
+ int messageBitIndex,
+ int builderBitIndex,
+ Context* context)
+ : descriptor_(descriptor), messageBitIndex_(messageBitIndex),
+ builderBitIndex_(builderBitIndex), context_(context),
+ name_resolver_(context->GetNameResolver()) {
+ SetMessageVariables(descriptor, messageBitIndex, builderBitIndex,
+ context->GetFieldGeneratorInfo(descriptor),
+ name_resolver_, &variables_);
+}
+
+ImmutableMapFieldGenerator::
+~ImmutableMapFieldGenerator() {}
+
+int ImmutableMapFieldGenerator::GetNumBitsForMessage() const {
+ return 0;
+}
+
+int ImmutableMapFieldGenerator::GetNumBitsForBuilder() const {
+ return 1;
+}
+
+void ImmutableMapFieldGenerator::
+GenerateInterfaceMembers(io::Printer* printer) const {
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "get$capitalized_name$();\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$type_parameters$>\n"
+ "get$capitalized_name$Value();\n");
+ }
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$java.util.Map<$type_parameters$>\n"
+ "get$capitalized_name$();\n");
+ }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateMembers(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private static final com.google.protobuf.MapEntry$lite$<\n"
+ " $type_parameters$> $name$DefaultEntry =\n"
+ " com.google.protobuf.MapEntry$lite$\n"
+ " .<$type_parameters$>newDefaultInstance(\n"
+ " $descriptor$\n"
+ " $key_wire_type$,\n"
+ " $key_default_value$,\n"
+ " $value_wire_type$,\n"
+ " $value_default_value$);\n");
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.MapField$lite$<\n"
+ " $type_parameters$> $name$_ =\n"
+ " com.google.protobuf.MapField$lite$.emptyMapField(\n"
+ " $map_field_parameter$);\n"
+ "\n");
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(
+ variables_,
+ "private static final\n"
+ "com.google.protobuf.Internal.MapAdapter.Converter<\n"
+ " java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n"
+ " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
+ " $value_enum_type$.internalGetValueMap(),\n"
+ " $unrecognized_value$);\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "get$capitalized_name$Value() {\n"
+ " return $name$_.getMap();\n"
+ "}\n");
+ }
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "get$capitalized_name$() {\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " $name$_.getMap(), $name$ValueConverter);\n"
+ "}\n");
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+ " return $name$_.getMap();\n"
+ "}\n");
+ }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateBuilderMembers(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "private com.google.protobuf.MapField$lite$<\n"
+ " $type_parameters$> $name$_ =\n"
+ " com.google.protobuf.MapField$lite$.newMapField(\n"
+ " $map_field_parameter$);\n"
+ "\n");
+ if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "get$capitalized_name$() {\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " $name$_.getMap(), $name$ValueConverter);\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " $on_changed$\n"
+ " return new com.google.protobuf.Internal.MapAdapter<\n"
+ " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
+ " $name$_.getMutableMap(), $name$ValueConverter);\n"
+ "}\n");
+ if (SupportUnknownEnumValue(descriptor_->file())) {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "get$capitalized_name$Value() {\n"
+ " return $name$_.getMap();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "$deprecation$\n"
+ "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+ "getMutable$capitalized_name$Value() {\n"
+ " $on_changed$\n"
+ " return $name$_.getMutableMap();\n"
+ "}\n");
+ }
+ } else {
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+ " return $name$_.getMap();\n"
+ "}\n");
+ WriteFieldDocComment(printer, descriptor_);
+ printer->Print(
+ variables_,
+ "public java.util.Map<$type_parameters$>\n"
+ "getMutable$capitalized_name$() {\n"
+ " $on_changed$\n"
+ " return $name$_.getMutableMap();\n"
+ "}\n");
+ }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+void ImmutableMapFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Nothing to initialize.
+}
+
+void ImmutableMapFieldGenerator::
+GenerateBuilderClearCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "$name$_.clear();\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateMergingCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "$name$_.mergeFrom(other.$name$_);\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateBuildingCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ // We do a copy of the map field to ensure that the built result is
+ // immutable. Implementation of this copy() method can do copy-on-write
+ // to defer this copy until further modifications are made on the field.
+ "result.$name$_ = $name$_.copy();\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!$get_mutable_bit_parser$) {\n"
+ " $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n"
+ " $map_field_parameter$);\n"
+ " $set_mutable_bit_parser$;\n"
+ "}\n");
+ if (!SupportUnknownEnumValue(descriptor_->file()) &&
+ GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
+ printer->Print(
+ variables_,
+ "com.google.protobuf.ByteString bytes = input.readBytes();\n"
+ "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ "$name$ = $name$DefaultEntry.getParserForType().parseFrom(bytes);\n");
+ printer->Print(
+ variables_,
+ "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n"
+ " unknownFields.mergeLengthDelimitedField($number$, bytes);\n"
+ "} else {\n"
+ " $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"
+ "}\n");
+ } else {
+ printer->Print(
+ variables_,
+ "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ "$name$ = input.readMessage(\n"
+ " $name$DefaultEntry.getParserForType(), extensionRegistry);\n"
+ "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n");
+ }
+}
+
+void ImmutableMapFieldGenerator::
+GenerateParsingDoneCode(io::Printer* printer) const {
+ // Nothing to do here.
+}
+
+void ImmutableMapFieldGenerator::
+GenerateSerializationCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "for (java.util.Map.Entry<$type_parameters$> entry\n"
+ " : $name$_.getMap().entrySet()) {\n"
+ " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ " $name$ = $name$DefaultEntry.newBuilderForType()\n"
+ " .setKey(entry.getKey())\n"
+ " .setValue(entry.getValue())\n"
+ " .build();\n"
+ " output.writeMessage($number$, $name$);\n"
+ "}\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateSerializedSizeCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "for (java.util.Map.Entry<$type_parameters$> entry\n"
+ " : $name$_.getMap().entrySet()) {\n"
+ " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n"
+ " $name$ = $name$DefaultEntry.newBuilderForType()\n"
+ " .setKey(entry.getKey())\n"
+ " .setValue(entry.getValue())\n"
+ " .build();\n"
+ " size += com.google.protobuf.CodedOutputStream\n"
+ " .computeMessageSize($number$, $name$);\n"
+ "}\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateEqualsCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "result = result && $name$_.equals(other.$name$_);\n");
+}
+
+void ImmutableMapFieldGenerator::
+GenerateHashCode(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "if (!$name$_.getMap().isEmpty()) {\n"
+ " hash = (37 * hash) + $constant_name$;\n"
+ " hash = (53 * hash) + $name$_.hashCode();\n"
+ "}\n");
+}
+
+string ImmutableMapFieldGenerator::GetBoxedType() const {
+ return name_resolver_->GetImmutableClassName(descriptor_->message_type());
+}
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h
new file mode 100644
index 00000000..80a94f45
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_map_field.h
@@ -0,0 +1,82 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
+
+#include <google/protobuf/compiler/java/java_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+class ImmutableMapFieldGenerator : public ImmutableFieldGenerator {
+ public:
+ explicit ImmutableMapFieldGenerator(
+ const FieldDescriptor* descriptor, int messageBitIndex,
+ int builderBitIndex, Context* context);
+ ~ImmutableMapFieldGenerator();
+
+ // implements ImmutableFieldGenerator ---------------------------------------
+ int GetNumBitsForMessage() const;
+ int GetNumBitsForBuilder() const;
+ void GenerateInterfaceMembers(io::Printer* printer) const;
+ void GenerateMembers(io::Printer* printer) const;
+ void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
+ void GenerateBuilderClearCode(io::Printer* printer) const;
+ void GenerateMergingCode(io::Printer* printer) const;
+ void GenerateBuildingCode(io::Printer* printer) const;
+ void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingDoneCode(io::Printer* printer) const;
+ void GenerateSerializationCode(io::Printer* printer) const;
+ void GenerateSerializedSizeCode(io::Printer* printer) const;
+ void GenerateFieldBuilderInitializationCode(io::Printer* printer) const;
+ void GenerateEqualsCode(io::Printer* printer) const;
+ void GenerateHashCode(io::Printer* printer) const;
+
+ string GetBoxedType() const;
+
+ private:
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+ const int messageBitIndex_;
+ const int builderBitIndex_;
+ Context* context_;
+ ClassNameResolver* name_resolver_;
+};
+
+} // namespace java
+} // namespace compiler
+} // namespace protobuf
+
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_H__
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 8aa89ac7..dd1ad6a6 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -38,6 +38,9 @@
#include <google/protobuf/stubs/hash.h>
#include <map>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <google/protobuf/compiler/java/java_context.h>
@@ -264,60 +267,36 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
descriptor_->containing_type() == NULL &&
MultipleJavaFiles(descriptor_->file(), /* immutable = */ true);
+ map<string, string> variables;
+ variables["static"] = is_own_file ? " " : " static ";
+ variables["classname"] = descriptor_->name();
+ variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
+ variables["lite"] = HasDescriptorMethods(descriptor_) ? "" : "Lite";
+
WriteMessageDocComment(printer, descriptor_);
// The builder_type stores the super type name of the nested Builder class.
string builder_type;
if (descriptor_->extension_range_count() > 0) {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public$static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n"
- " $classname$> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "static", is_own_file ? " " : " static ",
- "classname", descriptor_->name(),
- "extra_interfaces", ExtraMessageInterfaces(descriptor_));
- builder_type = strings::Substitute(
- "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>",
- name_resolver_->GetImmutableClassName(descriptor_));
- } else {
- printer->Print(
- "public$static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
- " $classname$> implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "static", is_own_file ? " " : " static ",
- "classname", descriptor_->name(),
- "extra_interfaces", ExtraMessageInterfaces(descriptor_));
- builder_type = strings::Substitute(
- "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>",
- name_resolver_->GetImmutableClassName(descriptor_));
- }
+ printer->Print(variables,
+ "public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage<\n"
+ " $classname$> implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
+ name_resolver_->GetImmutableClassName(descriptor_),
+ variables["lite"]);
} else {
- if (HasDescriptorMethods(descriptor_)) {
- printer->Print(
- "public$static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessage implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "static", is_own_file ? " " : " static ",
- "classname", descriptor_->name(),
- "extra_interfaces", ExtraMessageInterfaces(descriptor_));
- builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>";
- } else {
- printer->Print(
- "public$static$final class $classname$ extends\n"
- " com.google.protobuf.GeneratedMessageLite implements\n"
- " $extra_interfaces$\n"
- " $classname$OrBuilder {\n",
- "static", is_own_file ? " " : " static ",
- "classname", descriptor_->name(),
- "extra_interfaces", ExtraMessageInterfaces(descriptor_));
- builder_type = "com.google.protobuf.GeneratedMessageLite.Builder";
- }
+ printer->Print(variables,
+ "public $static$final class $classname$ extends\n"
+ " com.google.protobuf.GeneratedMessage$lite$ implements\n"
+ " $extra_interfaces$\n"
+ " $classname$OrBuilder {\n");
+ builder_type = strings::Substitute(
+ "com.google.protobuf.GeneratedMessage$0.Builder",
+ variables["lite"]);
}
printer->Indent();
// Using builder_type, instead of Builder, prevents the Builder class from
@@ -328,16 +307,22 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
"// Use $classname$.newBuilder() to construct.\n"
"private $classname$($buildertype$ builder) {\n"
" super(builder);\n"
- "$set_unknown_fields$\n"
"}\n",
"classname", descriptor_->name(),
- "buildertype", builder_type,
- "set_unknown_fields",
- " this.unknownFields = builder.getUnknownFields();");
+ "buildertype", builder_type);
printer->Print(
- // Used when constructing the default instance, which cannot be initialized
- // immediately because it may cyclically refer to other default instances.
- "private $classname$(boolean noInit) {$set_default_unknown_fields$}\n"
+ "private $classname$() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ if (!descriptor_->field(i)->containing_oneof()) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInitializationCode(printer);
+ }
+ }
+ printer->Outdent();
+ printer->Print(
+ "}\n"
"\n"
"private static final $classname$ defaultInstance;\n"
"public static $classname$ getDefaultInstance() {\n"
@@ -349,23 +334,22 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
"}\n"
"\n",
"classname", descriptor_->name(),
- "set_default_unknown_fields", UseUnknownFieldSet(descriptor_)
- ? " this.unknownFields ="
- " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); "
- : " this.unknownFields = com.google.protobuf.ByteString.EMPTY;");
+ "lite", variables["lite"]);
- if (UseUnknownFieldSet(descriptor_)) {
+ if (HasDescriptorMethods(descriptor_)) {
printer->Print(
- "private final com.google.protobuf.UnknownFieldSet unknownFields;\n"
- ""
- "@java.lang.Override\n"
- "public final com.google.protobuf.UnknownFieldSet\n"
- " getUnknownFields() {\n"
- " return this.unknownFields;\n"
- "}\n");
- } else {
+ "@java.lang.Override\n"
+ "public final com.google.protobuf.UnknownFieldSet\n"
+ "getUnknownFields() {\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ " return this.unknownFields;\n");
+ } else {
+ printer->Print(
+ " return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n");
+ }
printer->Print(
- "private final com.google.protobuf.ByteString unknownFields;\n");
+ "}\n");
}
if (HasGeneratedMethods(descriptor_)) {
@@ -382,6 +366,8 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
}
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ // Don't generate Java classes for map entry messages.
+ if (IsMapEntry(descriptor_->nested_type(i))) continue;
ImmutableMessageGenerator messageGenerator(
descriptor_->nested_type(i), context_);
messageGenerator.GenerateInterface(printer);
@@ -480,20 +466,6 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
printer->Print("\n");
}
- // Called by the constructor, except in the case of the default instance,
- // in which case this is called by static init code later on.
- printer->Print("private void initFields() {\n");
- printer->Indent();
- for (int i = 0; i < descriptor_->field_count(); i++) {
- if (!descriptor_->field(i)->containing_oneof()) {
- field_generators_.get(descriptor_->field(i))
- .GenerateInitializationCode(printer);
- }
- }
-
- printer->Outdent();
- printer->Print("}\n");
-
if (HasGeneratedMethods(descriptor_)) {
GenerateIsInitialized(printer, MEMOIZE);
GenerateMessageSerializationMethods(printer);
@@ -512,8 +484,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) {
printer->Print(
"\n"
"static {\n"
- " defaultInstance = new $classname$(true);\n"
- " defaultInstance.initFields();\n"
+ " defaultInstance = new $classname$();\n"
"}\n"
"\n"
"// @@protoc_insertion_point(class_scope:$full_name$)\n",
@@ -593,17 +564,15 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
}
}
- if (UseUnknownFieldSet(descriptor_)) {
- if (descriptor_->options().message_set_wire_format()) {
+ if (PreserveUnknownFields(descriptor_)) {
+ if (descriptor_->options().message_set_wire_format()
+ && HasDescriptorMethods(descriptor_)) {
printer->Print(
- "getUnknownFields().writeAsMessageSetTo(output);\n");
+ "unknownFields.writeAsMessageSetTo(output);\n");
} else {
printer->Print(
- "getUnknownFields().writeTo(output);\n");
+ "unknownFields.writeTo(output);\n");
}
- } else {
- printer->Print(
- "output.writeRawBytes(unknownFields);\n");
}
printer->Outdent();
@@ -632,17 +601,15 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
}
}
- if (UseUnknownFieldSet(descriptor_)) {
- if (descriptor_->options().message_set_wire_format()) {
+ if (PreserveUnknownFields(descriptor_)) {
+ if (descriptor_->options().message_set_wire_format()
+ && HasDescriptorMethods(descriptor_)) {
printer->Print(
- "size += getUnknownFields().getSerializedSizeAsMessageSet();\n");
+ "size += unknownFields.getSerializedSizeAsMessageSet();\n");
} else {
printer->Print(
- "size += getUnknownFields().getSerializedSize();\n");
+ "size += unknownFields.getSerializedSize();\n");
}
- } else {
- printer->Print(
- "size += unknownFields.size();\n");
}
printer->Outdent();
@@ -653,13 +620,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) {
"\n");
printer->Print(
- "private static final long serialVersionUID = 0L;\n"
- "@java.lang.Override\n"
- "protected java.lang.Object writeReplace()\n"
- " throws java.io.ObjectStreamException {\n"
- " return super.writeReplace();\n"
- "}\n"
- "\n");
+ "private static final long serialVersionUID = 0L;\n");
}
void ImmutableMessageGenerator::
@@ -740,7 +701,7 @@ void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
printer->Print(
- "public static Builder newBuilder() { return Builder.create(); }\n"
+ "public static Builder newBuilder() { return new Builder(); }\n"
"public Builder newBuilderForType() { return newBuilder(); }\n"
"public static Builder newBuilder($classname$ prototype) {\n"
" return newBuilder().mergeFrom(prototype);\n"
@@ -809,7 +770,6 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
if (HasGeneratedMethods(descriptor_)) {
GenerateIsInitialized(printer, DONT_MEMOIZE);
- GenerateBuilderParsingMethods(printer);
}
// oneof
@@ -864,6 +824,20 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
.GenerateBuilderMembers(printer);
}
+ if (!PreserveUnknownFields(descriptor_)) {
+ printer->Print(
+ "public final Builder setUnknownFields(\n"
+ " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+ " return this;\n"
+ "}\n"
+ "\n"
+ "public final Builder mergeUnknownFields(\n"
+ " final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+ " return this;\n"
+ "}\n"
+ "\n");
+ }
+
printer->Print(
"\n"
"// @@protoc_insertion_point(builder_scope:$full_name$)\n",
@@ -886,6 +860,41 @@ GenerateDescriptorMethods(io::Printer* printer) {
"fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()),
"identifier", UniqueFileScopeIdentifier(descriptor_));
}
+ vector<const FieldDescriptor*> map_fields;
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
+ IsMapEntry(field->message_type())) {
+ map_fields.push_back(field);
+ }
+ }
+ if (!map_fields.empty()) {
+ printer->Print(
+ "@SuppressWarnings({\"rawtypes\"})\n"
+ "protected com.google.protobuf.MapField internalGetMapField(\n"
+ " int number) {\n"
+ " switch (number) {\n");
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < map_fields.size(); ++i) {
+ const FieldDescriptor* field = map_fields[i];
+ const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ printer->Print(
+ "case $number$:\n"
+ " return $name$_;\n",
+ "number", SimpleItoa(field->number()),
+ "name", info->name);
+ }
+ printer->Print(
+ "default:\n"
+ " throw new RuntimeException(\n"
+ " \"Invalid map field number: \" + number);\n");
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " }\n"
+ "}\n");
+ }
printer->Print(
"protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
" internalGetFieldAccessorTable() {\n"
@@ -949,13 +958,8 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
}
printer->Print(
- "private static Builder create() {\n"
- " return new Builder();\n"
- "}\n"
- "\n"
"public Builder clear() {\n"
- " super.clear();\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ " super.clear();\n");
printer->Indent();
@@ -979,12 +983,8 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
printer->Print(
" return this;\n"
"}\n"
- "\n"
- "public Builder clone() {\n"
- " return create().mergeFrom(buildPartial());\n"
- "}\n"
- "\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
+ "\n");
+
if (HasDescriptorMethods(descriptor_)) {
printer->Print(
"public com.google.protobuf.Descriptors.Descriptor\n"
@@ -1153,13 +1153,13 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
" this.mergeExtensionFields(other);\n");
}
- if (UseUnknownFieldSet(descriptor_)) {
+ if (PreserveUnknownFields(descriptor_)) {
printer->Print(
- " this.mergeUnknownFields(other.getUnknownFields());\n");
- } else {
- printer->Print(
- " setUnknownFields(\n"
- " getUnknownFields().concat(other.unknownFields));\n");
+ " this.mergeUnknownFields(other.unknownFields);\n");
+ }
+
+ if (HasDescriptorMethods(descriptor_)) {
+ printer->Print(" onChanged();\n");
}
printer->Print(
@@ -1171,31 +1171,6 @@ GenerateCommonBuilderMethods(io::Printer* printer) {
// ===================================================================
-void ImmutableMessageGenerator::
-GenerateBuilderParsingMethods(io::Printer* printer) {
- printer->Print(
- "public Builder mergeFrom(\n"
- " com.google.protobuf.CodedInputStream input,\n"
- " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
- " throws java.io.IOException {\n"
- " $classname$ parsedMessage = null;\n"
- " try {\n"
- " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n"
- " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n"
- " parsedMessage = ($classname$) e.getUnfinishedMessage();\n"
- " throw e;\n"
- " } finally {\n"
- " if (parsedMessage != null) {\n"
- " mergeFrom(parsedMessage);\n"
- " }\n"
- " }\n"
- " return this;\n"
- "}\n",
- "classname", name_resolver_->GetImmutableClassName(descriptor_));
-}
-
-// ===================================================================
-
void ImmutableMessageGenerator::GenerateIsInitialized(
io::Printer* printer, UseMemoization useMemoization) {
bool memoization = useMemoization == MEMOIZE;
@@ -1256,15 +1231,26 @@ void ImmutableMessageGenerator::GenerateIsInitialized(
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
break;
case FieldDescriptor::LABEL_OPTIONAL:
+ if (!SupportFieldPresence(descriptor_->file()) &&
+ field->containing_oneof() != NULL) {
+ const OneofDescriptor* oneof = field->containing_oneof();
+ const OneofGeneratorInfo* oneof_info =
+ context_->GetOneofGeneratorInfo(oneof);
+ printer->Print(
+ "if ($oneof_name$Case_ == $field_number$) {\n",
+ "oneof_name", oneof_info->name,
+ "field_number", SimpleItoa(field->number()));
+ } else {
+ printer->Print(
+ "if (has$name$()) {\n",
+ "name", info->capitalized_name);
+ }
printer->Print(
- "if (has$name$()) {\n"
" if (!get$name$().isInitialized()) {\n"
" $memoize$\n"
" return false;\n"
" }\n"
"}\n",
- "type", name_resolver_->GetImmutableClassName(
- field->message_type()),
"name", info->capitalized_name,
"memoize", memoization ? "memoizedIsInitialized = 0;" : "");
break;
@@ -1358,10 +1344,14 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
"}\n");
}
}
- if (HasDescriptorMethods(descriptor_)) {
+ if (PreserveUnknownFields(descriptor_)) {
+ // Always consider unknown fields for equality. This will sometimes return
+ // false for non-canonical ordering when running in LITE_RUNTIME but it's
+ // the best we can do.
printer->Print(
- "result = result &&\n"
- " getUnknownFields().equals(other.getUnknownFields());\n");
+ "result = result && unknownFields.equals(other.unknownFields);\n");
+ }
+ if (HasDescriptorMethods(descriptor_)) {
if (descriptor_->extension_range_count() > 0) {
printer->Print(
"result = result &&\n"
@@ -1421,13 +1411,8 @@ GenerateEqualsAndHashCode(io::Printer* printer) {
}
}
- if (UseUnknownFieldSet(descriptor_)) {
- printer->Print(
- "hash = (29 * hash) + getUnknownFields().hashCode();\n");
- } else {
- printer->Print(
- "hash = (29 * hash) + unknownFields.hashCode();\n");
- }
+ printer->Print(
+ "hash = (29 * hash) + unknownFields.hashCode();\n");
printer->Print(
"memoizedHashCode = hash;\n"
"return hash;\n");
@@ -1468,7 +1453,7 @@ GenerateParsingConstructor(io::Printer* printer) {
// Initialize all fields to default.
printer->Print(
- "initFields();\n");
+ "this();\n");
// Use builder bits to track mutable repeated fields.
int totalBuilderBits = 0;
@@ -1483,17 +1468,16 @@ GenerateParsingConstructor(io::Printer* printer) {
"bit_field_name", GetBitFieldName(i));
}
- if (UseUnknownFieldSet(descriptor_)) {
- printer->Print(
- "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
- " com.google.protobuf.UnknownFieldSet.newBuilder();\n");
- } else {
- printer->Print(
- "com.google.protobuf.ByteString.Output unknownFieldsOutput =\n"
- " com.google.protobuf.ByteString.newOutput();\n"
- "com.google.protobuf.CodedOutputStream unknownFieldsCodedOutput =\n"
- " com.google.protobuf.CodedOutputStream.newInstance(\n"
- " unknownFieldsOutput);\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ if (HasDescriptorMethods(descriptor_)) {
+ printer->Print(
+ "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
+ " com.google.protobuf.UnknownFieldSet.newBuilder();\n");
+ } else {
+ printer->Print(
+ "com.google.protobuf.UnknownFieldSetLite.Builder unknownFields =\n"
+ " com.google.protobuf.UnknownFieldSetLite.newBuilder();\n");
+ }
}
printer->Print(
@@ -1513,16 +1497,41 @@ GenerateParsingConstructor(io::Printer* printer) {
printer->Print(
"case 0:\n" // zero signals EOF / limit reached
" done = true;\n"
- " break;\n"
- "default: {\n"
- " if (!parseUnknownField(input,$unknown_fields$\n"
- " extensionRegistry, tag)) {\n"
- " done = true;\n" // it's an endgroup tag
- " }\n"
- " break;\n"
- "}\n",
- "unknown_fields", UseUnknownFieldSet(descriptor_)
- ? " unknownFields," : " unknownFieldsCodedOutput,");
+ " break;\n");
+
+ if (PreserveUnknownFields(descriptor_)) {
+ if (!HasDescriptorMethods(descriptor_)
+ && descriptor_->extension_range_count() > 0) {
+ // Lite runtime directly invokes parseUnknownField to reduce method
+ // counts.
+ printer->Print(
+ "default: {\n"
+ " if (!parseUnknownField(extensions, getDefaultInstanceForType(),\n"
+ " input, unknownFields,\n"
+ " extensionRegistry, tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ } else {
+ printer->Print(
+ "default: {\n"
+ " if (!parseUnknownField(input, unknownFields,\n"
+ " extensionRegistry, tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ }
+ } else {
+ printer->Print(
+ "default: {\n"
+ " if (!input.skipField(tag)) {\n"
+ " done = true;\n" // it's an endgroup tag
+ " }\n"
+ " break;\n"
+ "}\n");
+ }
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = sorted_fields[i];
@@ -1582,19 +1591,9 @@ GenerateParsingConstructor(io::Printer* printer) {
field_generators_.get(field).GenerateParsingDoneCode(printer);
}
- // Make unknown fields immutable.
- if (UseUnknownFieldSet(descriptor_)) {
- printer->Print(
- "this.unknownFields = unknownFields.build();\n");
- } else {
- printer->Print(
- "try {\n"
- " unknownFieldsCodedOutput.flush();\n"
- "} catch (java.io.IOException e) {\n"
- "// Should not happen\n"
- "} finally {\n"
- " unknownFields = unknownFieldsOutput.toByteString();\n"
- "}\n");
+ if (PreserveUnknownFields(descriptor_)) {
+ // Make unknown fields immutable.
+ printer->Print("this.unknownFields = unknownFields.build();\n");
}
// Make extensions immutable.
@@ -1611,7 +1610,7 @@ GenerateParsingConstructor(io::Printer* printer) {
// ===================================================================
void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) {
printer->Print(
- "public static com.google.protobuf.Parser<$classname$> PARSER =\n"
+ "public static final com.google.protobuf.Parser<$classname$> PARSER =\n"
" new com.google.protobuf.AbstractParser<$classname$>() {\n",
"classname", descriptor_->name());
printer->Indent();
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index fece1c21..2703016e 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -118,7 +118,6 @@ class ImmutableMessageGenerator : public MessageGenerator {
void GenerateBuilder(io::Printer* printer);
void GenerateCommonBuilderMethods(io::Printer* printer);
void GenerateDescriptorMethods(io::Printer* printer);
- void GenerateBuilderParsingMethods(io::Printer* printer);
void GenerateIsInitialized(io::Printer* printer,
UseMemoization useMemoization);
void GenerateEqualsAndHashCode(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index e681314e..538f1248 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -179,7 +179,7 @@ GenerateMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
printer->Print(variables_,
"$deprecation$public $type$ get$capitalized_name$() {\n"
- " return $name$_;\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
if (HasNestedBuilders(descriptor_->containing_type())) {
@@ -187,7 +187,7 @@ GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"$deprecation$public $type$OrBuilder "
"get$capitalized_name$OrBuilder() {\n"
- " return $name$_;\n"
+ " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
"}\n");
}
} else {
@@ -257,14 +257,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
bool support_field_presence = SupportFieldPresence(descriptor_->file());
- if (support_field_presence) {
- printer->Print(variables_,
- // Used when the builder is null.
- "private $type$ $name$_ = $type$.getDefaultInstance();\n");
- } else {
- printer->Print(variables_,
- "private $type$ $name$_ = null;\n");
- }
+ printer->Print(variables_,
+ "private $type$ $name$_ = null;\n");
if (HasNestedBuilders(descriptor_->containing_type())) {
printer->Print(variables_,
@@ -296,13 +290,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
WriteFieldDocComment(printer, descriptor_);
PrintNestedBuilderFunction(printer,
"$deprecation$public $type$ get$capitalized_name$()",
-
- support_field_presence
- ? "return $name$_;\n"
- : "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
-
+ "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
"return $name$Builder_.getMessage();\n",
-
NULL);
// Field.Builder setField(Field value)
@@ -342,6 +331,7 @@ GenerateBuilderMembers(io::Printer* printer) const {
support_field_presence
? "if ($get_has_field_bit_builder$ &&\n"
+ " $name$_ != null &&\n"
" $name$_ != $type$.getDefaultInstance()) {\n"
" $name$_ =\n"
" $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n"
@@ -367,11 +357,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
PrintNestedBuilderFunction(printer,
"$deprecation$public Builder clear$capitalized_name$()",
- support_field_presence
- ? "$name$_ = $type$.getDefaultInstance();\n"
- "$on_changed$\n"
- : "$name$_ = null;\n"
- "$on_changed$\n",
+ "$name$_ = null;\n"
+ "$on_changed$\n",
support_field_presence
? "$name$Builder_.clear();\n"
@@ -394,16 +381,9 @@ GenerateBuilderMembers(io::Printer* printer) const {
"$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
" if ($name$Builder_ != null) {\n"
" return $name$Builder_.getMessageOrBuilder();\n"
- " } else {\n");
- if (support_field_presence) {
- printer->Print(variables_,
- " return $name$_;\n");
- } else {
- printer->Print(variables_,
- " return $name$_ == null ?\n"
- " $type$.getDefaultInstance() : $name$_;\n");
- }
- printer->Print(variables_,
+ " } else {\n"
+ " return $name$_ == null ?\n"
+ " $type$.getDefaultInstance() : $name$_;\n"
" }\n"
"}\n");
WriteFieldDocComment(printer, descriptor_);
@@ -434,17 +414,13 @@ GenerateFieldBuilderInitializationCode(io::Printer* printer) const {
void ImmutableMessageFieldGenerator::
-GenerateInitializationCode(io::Printer* printer) const {
- if (SupportFieldPresence(descriptor_->file())) {
- printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
- }
-}
+GenerateInitializationCode(io::Printer* printer) const {}
void ImmutableMessageFieldGenerator::
GenerateBuilderClearCode(io::Printer* printer) const {
if (SupportFieldPresence(descriptor_->file())) {
PrintNestedBuilderCondition(printer,
- "$name$_ = $type$.getDefaultInstance();\n",
+ "$name$_ = null;\n",
"$name$Builder_.clear();\n");
printer->Print(variables_, "$clear_has_field_bit_builder$\n");
@@ -514,7 +490,7 @@ void ImmutableMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
- " output.write$group_or_message$($number$, $name$_);\n"
+ " output.write$group_or_message$($number$, get$capitalized_name$());\n"
"}\n");
}
@@ -523,7 +499,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
"if ($is_field_present_message$) {\n"
" size += com.google.protobuf.CodedOutputStream\n"
- " .compute$group_or_message$Size($number$, $name$_);\n"
+ " .compute$group_or_message$Size($number$, get$capitalized_name$());\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
index c4d6995d..45aa8ffe 100644
--- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
@@ -35,6 +35,9 @@
// worth.
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/java/java_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 6713d29a..e331d7a4 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -55,26 +55,6 @@ using internal::WireFormatLite;
namespace {
-const char* PrimitiveTypeName(JavaType type) {
- switch (type) {
- case JAVATYPE_INT : return "int";
- case JAVATYPE_LONG : return "long";
- case JAVATYPE_FLOAT : return "float";
- case JAVATYPE_DOUBLE : return "double";
- case JAVATYPE_BOOLEAN: return "boolean";
- case JAVATYPE_STRING : return "java.lang.String";
- case JAVATYPE_BYTES : return "com.google.protobuf.ByteString";
- case JAVATYPE_ENUM : return NULL;
- case JAVATYPE_MESSAGE: return NULL;
-
- // No default because we want the compiler to complain if any new
- // JavaTypes are added.
- }
-
- GOOGLE_LOG(FATAL) << "Can't get here.";
- return NULL;
-}
-
void SetPrimitiveVariables(const FieldDescriptor* descriptor,
int messageBitIndex,
int builderBitIndex,
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 ea77f792..f8723f2a 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -33,6 +33,9 @@
#include <google/protobuf/compiler/java/java_shared_code_generator.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/java/java_helpers.h>
#include <google/protobuf/compiler/java/java_name_resolver.h>
@@ -176,7 +179,8 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) {
// Invoke internalBuildGeneratedFileFrom() to build the file.
printer->Print(
"com.google.protobuf.Descriptors.FileDescriptor\n"
- " .internalBuildGeneratedFileFrom(descriptorData,\n"
+ " .internalBuildGeneratedFileFrom(descriptorData,\n");
+ printer->Print(
" new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
for (int i = 0; i < dependencies.size(); i++) {
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h
index 1bb2f3dc..fdbe2ce8 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.h
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.h
@@ -36,6 +36,9 @@
#define GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
#include <vector>
@@ -68,6 +71,7 @@ class SharedCodeGenerator {
void Generate(GeneratorContext* generator_context,
vector<string>* file_list);
+
void GenerateDescriptors(io::Printer* printer);
private:
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 8889a744..1c9302af 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -407,6 +407,15 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readStringRequireUtf8();\n"
"$set_has_field_bit_message$\n"
"$name$_ = s;\n");
+ } else if (!HasDescriptorMethods(descriptor_->file())) {
+ // Lite runtime should attempt to reduce allocations by attempting to
+ // construct the string directly from the input stream buffer. This avoids
+ // spurious intermediary ByteString allocations, cutting overall allocations
+ // in half.
+ printer->Print(variables_,
+ "String s = input.readString();\n"
+ "$set_has_field_bit_message$\n"
+ "$name$_ = s;\n");
} else {
printer->Print(variables_,
"com.google.protobuf.ByteString bs = input.readBytes();\n"
@@ -659,6 +668,15 @@ GenerateParsingCode(io::Printer* printer) const {
"String s = input.readStringRequireUtf8();\n"
"$set_oneof_case_message$;\n"
"$oneof_name$_ = s;\n}\n");
+ } else if (!HasDescriptorMethods(descriptor_->file())) {
+ // Lite runtime should attempt to reduce allocations by attempting to
+ // construct the string directly from the input stream buffer. This avoids
+ // spurious intermediary ByteString allocations, cutting overall allocations
+ // in half.
+ printer->Print(variables_,
+ "String s = input.readString();\n"
+ "$set_oneof_case_message$;\n"
+ "$oneof_name$_ = s;\n");
} else {
printer->Print(variables_,
"com.google.protobuf.ByteString bs = input.readBytes();\n"
@@ -923,6 +941,13 @@ GenerateParsingCode(io::Printer* printer) const {
if (CheckUtf8(descriptor_)) {
printer->Print(variables_,
"String s = input.readStringRequireUtf8();\n");
+ } else if (!HasDescriptorMethods(descriptor_->file())) {
+ // Lite runtime should attempt to reduce allocations by attempting to
+ // construct the string directly from the input stream buffer. This avoids
+ // spurious intermediary ByteString allocations, cutting overall allocations
+ // in half.
+ printer->Print(variables_,
+ "String s = input.readString();\n");
} else {
printer->Print(variables_,
"com.google.protobuf.ByteString bs = input.readBytes();\n");
@@ -932,7 +957,7 @@ GenerateParsingCode(io::Printer* printer) const {
" $name$_ = new com.google.protobuf.LazyStringArrayList();\n"
" $set_mutable_bit_parser$;\n"
"}\n");
- if (CheckUtf8(descriptor_)) {
+ if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
printer->Print(variables_,
"$name$_.add(s);\n");
} else {
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 916b0ccd..70373c8e 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -33,6 +33,9 @@
#include <google/protobuf/compiler/mock_code_generator.h>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/testing/file.h>
#include <google/protobuf/descriptor.pb.h>
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 474a8f80..0ed80d54 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -84,6 +84,32 @@ TypeNameMap MakeTypeNameTable() {
const TypeNameMap kTypeNames = MakeTypeNameTable();
+// Camel-case the field name and append "Entry" for generated map entry name.
+// e.g. map<KeyType, ValueType> foo_map => FooMapEntry
+string MapEntryName(const string& field_name) {
+ string result;
+ static const char kSuffix[] = "Entry";
+ result.reserve(field_name.size() + sizeof(kSuffix));
+ bool cap_next = true;
+ for (int i = 0; i < field_name.size(); ++i) {
+ if (field_name[i] == '_') {
+ cap_next = true;
+ } else if (cap_next) {
+ // Note: Do not use ctype.h due to locales.
+ if ('a' <= field_name[i] && field_name[i] <= 'z') {
+ result.push_back(field_name[i] - 'a' + 'A');
+ } else {
+ result.push_back(field_name[i]);
+ }
+ cap_next = false;
+ } else {
+ result.push_back(field_name[i]);
+ }
+ }
+ result.append(kSuffix);
+ return result;
+}
+
} // anonymous namespace
// Makes code slightly more readable. The meaning of "DO(foo)" is
@@ -439,6 +465,8 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
// identifier.
return false;
}
+ // Store the syntax into the file.
+ if (file != NULL) file->set_syntax(syntax_identifier_);
} else if (!stop_after_syntax_identifier_) {
syntax_identifier_ = "proto2";
}
@@ -467,7 +495,9 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) {
}
bool Parser::ParseSyntaxIdentifier() {
- DO(Consume("syntax", "File must begin with 'syntax = \"proto2\";'."));
+ DO(Consume(
+ "syntax",
+ "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'."));
DO(Consume("="));
io::Tokenizer::Token syntax_token = input_->current();
string syntax;
@@ -476,10 +506,11 @@ bool Parser::ParseSyntaxIdentifier() {
syntax_identifier_ = syntax;
- if (syntax != "proto2" && !stop_after_syntax_identifier_) {
+ if (syntax != "proto2" && syntax != "proto3" &&
+ !stop_after_syntax_identifier_) {
AddError(syntax_token.line, syntax_token.column,
"Unrecognized syntax identifier \"" + syntax + "\". This parser "
- "only recognizes \"proto2\".");
+ "only recognizes \"proto2\" and \"proto3\".");
return false;
}
@@ -673,8 +704,9 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field,
LocationRecorder location(field_location,
FieldDescriptorProto::kLabelFieldNumber);
FieldDescriptorProto::Label label;
- DO(ParseLabel(&label, containing_file));
- field->set_label(label);
+ if (ParseLabel(&label, containing_file)) {
+ field->set_label(label);
+ }
}
return ParseMessageFieldNoLabel(field, messages, parent_location,
@@ -690,20 +722,75 @@ bool Parser::ParseMessageFieldNoLabel(
int location_field_number_for_nested_type,
const LocationRecorder& field_location,
const FileDescriptorProto* containing_file) {
+ MapField map_field;
// Parse type.
{
LocationRecorder location(field_location); // add path later
location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE);
+ bool type_parsed = false;
FieldDescriptorProto::Type type = FieldDescriptorProto::TYPE_INT32;
string type_name;
- DO(ParseType(&type, &type_name));
- if (type_name.empty()) {
- location.AddPath(FieldDescriptorProto::kTypeFieldNumber);
- field->set_type(type);
- } else {
+
+ // Special case map field. We only treat the field as a map field if the
+ // field type name starts with the word "map" with a following "<".
+ if (TryConsume("map")) {
+ if (LookingAt("<")) {
+ map_field.is_map_field = true;
+ } else {
+ // False positive
+ type_parsed = true;
+ type_name = "map";
+ }
+ }
+ if (map_field.is_map_field) {
+ if (field->has_oneof_index()) {
+ AddError("Map fields are not allowed in oneofs.");
+ return false;
+ }
+ if (field->has_label()) {
+ AddError(
+ "Field labels (required/optional/repeated) are not allowed on "
+ "map fields.");
+ return false;
+ }
+ if (field->has_extendee()) {
+ AddError("Map fields are not allowed to be extensions.");
+ return false;
+ }
+ field->set_label(FieldDescriptorProto::LABEL_REPEATED);
+ DO(Consume("<"));
+ DO(ParseType(&map_field.key_type, &map_field.key_type_name));
+ DO(Consume(","));
+ DO(ParseType(&map_field.value_type, &map_field.value_type_name));
+ DO(Consume(">"));
+ // Defer setting of the type name of the map field until the
+ // field name is parsed. Add the source location though.
location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
- field->set_type_name(type_name);
+ } else {
+ // Handle the case where no explicit label is given for a non-map field.
+ if (!field->has_label() && DefaultToOptionalFields()) {
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ }
+ if (!field->has_label()) {
+ AddError("Expected \"required\", \"optional\", or \"repeated\".");
+ // We can actually reasonably recover here by just assuming the user
+ // forgot the label altogether.
+ field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ }
+
+ // Handle the case where the actual type is a message or enum named "map",
+ // which we already consumed in the code above.
+ if (!type_parsed) {
+ DO(ParseType(&type, &type_name));
+ }
+ if (type_name.empty()) {
+ location.AddPath(FieldDescriptorProto::kTypeFieldNumber);
+ field->set_type(type);
+ } else {
+ location.AddPath(FieldDescriptorProto::kTypeNameFieldNumber);
+ field->set_type_name(type_name);
+ }
}
}
@@ -781,9 +868,42 @@ bool Parser::ParseMessageFieldNoLabel(
DO(ConsumeEndOfDeclaration(";", &field_location));
}
+ // Create a map entry type if this is a map field.
+ if (map_field.is_map_field) {
+ GenerateMapEntry(map_field, field, messages);
+ }
+
return true;
}
+void Parser::GenerateMapEntry(const MapField& map_field,
+ FieldDescriptorProto* field,
+ RepeatedPtrField<DescriptorProto>* messages) {
+ DescriptorProto* entry = messages->Add();
+ string entry_name = MapEntryName(field->name());
+ field->set_type_name(entry_name);
+ entry->set_name(entry_name);
+ entry->mutable_options()->set_map_entry(true);
+ FieldDescriptorProto* key_field = entry->add_field();
+ key_field->set_name("key");
+ key_field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ key_field->set_number(1);
+ if (map_field.key_type_name.empty()) {
+ key_field->set_type(map_field.key_type);
+ } else {
+ key_field->set_type_name(map_field.key_type_name);
+ }
+ FieldDescriptorProto* value_field = entry->add_field();
+ value_field->set_name("value");
+ value_field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
+ value_field->set_number(2);
+ if (map_field.value_type_name.empty()) {
+ value_field->set_type(map_field.value_type);
+ } else {
+ value_field->set_type_name(map_field.value_type_name);
+ }
+}
+
bool Parser::ParseFieldOptions(FieldDescriptorProto* field,
const LocationRecorder& field_location,
const FileDescriptorProto* containing_file) {
@@ -1588,13 +1708,8 @@ bool Parser::ParseLabel(FieldDescriptorProto::Label* label,
} else if (TryConsume("required")) {
*label = FieldDescriptorProto::LABEL_REQUIRED;
return true;
- } else {
- AddError("Expected \"required\", \"optional\", or \"repeated\".");
- // We can actually reasonably recover here by just assuming the user
- // forgot the label altogether.
- *label = FieldDescriptorProto::LABEL_OPTIONAL;
- return true;
}
+ return false;
}
bool Parser::ParseType(FieldDescriptorProto::Type* type,
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index d0a2359b..a15cc705 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -403,7 +403,7 @@ class LIBPROTOBUF_EXPORT Parser {
Message* mutable_options);
// Parse "required", "optional", or "repeated" and fill in "label"
- // with the value.
+ // with the value. Returns true if shuch a label is consumed.
bool ParseLabel(FieldDescriptorProto::Label* label,
const FileDescriptorProto* containing_file);
@@ -460,6 +460,28 @@ class LIBPROTOBUF_EXPORT Parser {
// the ending brace.
bool ParseUninterpretedBlock(string* value);
+ struct MapField {
+ // Whether the field is a map field.
+ bool is_map_field;
+ // The types of the key and value if they are primitive types.
+ FieldDescriptorProto::Type key_type;
+ FieldDescriptorProto::Type value_type;
+ // Or the type names string if the types are customized types.
+ string key_type_name;
+ string value_type_name;
+
+ MapField() : is_map_field(false) {}
+ };
+ // Desugar the map syntax to generate a nested map entry message.
+ void GenerateMapEntry(const MapField& map_field, FieldDescriptorProto* field,
+ RepeatedPtrField<DescriptorProto>* messages);
+
+ // Whether fields without label default to optional fields.
+ bool DefaultToOptionalFields() const {
+ return syntax_identifier_ == "proto3";
+ }
+
+
// =================================================================
io::Tokenizer* input_;
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 9ec29a48..c2206ade 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -33,6 +33,9 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <vector>
#include <algorithm>
#include <map>
@@ -250,6 +253,7 @@ TEST_F(ParseMessageTest, ExplicitSyntaxIdentifier) {
" required int32 foo = 1;\n"
"}\n",
+ "syntax: 'proto2' "
"message_type {"
" name: \"TestMessage\""
" field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
@@ -265,6 +269,7 @@ TEST_F(ParseMessageTest, ExplicitRequiredSyntaxIdentifier) {
" required int32 foo = 1;\n"
"}\n",
+ "syntax: 'proto2' "
"message_type {"
" name: \"TestMessage\""
" field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }"
@@ -500,6 +505,54 @@ TEST_F(ParseMessageTest, MultipleOneofs) {
"}");
}
+TEST_F(ParseMessageTest, Maps) {
+ ExpectParsesTo(
+ "message TestMessage {\n"
+ " map<int32, string> primitive_type_map = 1;\n"
+ " map<KeyType, ValueType> composite_type_map = 2;\n"
+ "}\n",
+
+ "message_type {"
+ " name: \"TestMessage\""
+ " nested_type {"
+ " name: \"PrimitiveTypeMapEntry\""
+ " field { "
+ " name: \"key\" number: 1 label:LABEL_OPTIONAL"
+ " type:TYPE_INT32"
+ " }"
+ " field { "
+ " name: \"value\" number: 2 label:LABEL_OPTIONAL"
+ " type:TYPE_STRING"
+ " }"
+ " options { map_entry: true }"
+ " }"
+ " nested_type {"
+ " name: \"CompositeTypeMapEntry\""
+ " field { "
+ " name: \"key\" number: 1 label:LABEL_OPTIONAL"
+ " type_name: \"KeyType\""
+ " }"
+ " field { "
+ " name: \"value\" number: 2 label:LABEL_OPTIONAL"
+ " type_name: \"ValueType\""
+ " }"
+ " options { map_entry: true }"
+ " }"
+ " field {"
+ " name: \"primitive_type_map\""
+ " label: LABEL_REPEATED"
+ " type_name: \"PrimitiveTypeMapEntry\""
+ " number: 1"
+ " }"
+ " field {"
+ " name: \"composite_type_map\""
+ " label: LABEL_REPEATED"
+ " type_name: \"CompositeTypeMapEntry\""
+ " number: 2"
+ " }"
+ "}");
+}
+
TEST_F(ParseMessageTest, Group) {
ExpectParsesTo(
"message TestMessage {\n"
@@ -639,6 +692,20 @@ TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) {
" type_name:\"TestMessage\" extendee: \"Extendee1\" }");
}
+TEST_F(ParseMessageTest, OptionalOptionalLabelProto3) {
+ ExpectParsesTo(
+ "syntax = \"proto3\";\n"
+ "message TestMessage {\n"
+ " int32 foo = 1;\n"
+ " optional int32 bar = 2;\n"
+ "}\n",
+
+ "syntax: \"proto3\" "
+ "message_type {"
+ " name: \"TestMessage\""
+ " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }"
+ " field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:2 } }");
+}
// ===================================================================
@@ -828,9 +895,9 @@ typedef ParserTest ParseErrorTest;
TEST_F(ParseErrorTest, MissingSyntaxIdentifier) {
require_syntax_identifier_ = true;
- ExpectHasEarlyExitErrors(
- "message TestMessage {}",
- "0:0: File must begin with 'syntax = \"proto2\";'.\n");
+ ExpectHasEarlyExitErrors("message TestMessage {}",
+ "0:0: File must begin with a syntax statement, e.g. "
+ "'syntax = \"proto2\";'.\n");
EXPECT_EQ("", parser_->GetSyntaxIdentifier());
}
@@ -838,7 +905,7 @@ TEST_F(ParseErrorTest, UnknownSyntaxIdentifier) {
ExpectHasEarlyExitErrors(
"syntax = \"no_such_syntax\";",
"0:9: Unrecognized syntax identifier \"no_such_syntax\". This parser "
- "only recognizes \"proto2\".\n");
+ "only recognizes \"proto2\" and \"proto3\".\n");
EXPECT_EQ("no_such_syntax", parser_->GetSyntaxIdentifier());
}
@@ -1041,6 +1108,55 @@ TEST_F(ParseErrorTest, LabelInOneof) {
"/ repeated).\n");
}
+TEST_F(ParseErrorTest, MapInOneof) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " oneof foo {\n"
+ " map<int32, int32> foo_map = 1;\n"
+ " map message_field = 2;\n" // a normal message field is OK
+ " }\n"
+ "}\n",
+ "2:7: Map fields are not allowed in oneofs.\n");
+}
+
+TEST_F(ParseErrorTest, LabelForMap) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " optional map<int32, int32> int_map = 1;\n"
+ " required map<int32, int32> int_map2 = 2;\n"
+ " repeated map<int32, int32> int_map3 = 3;\n"
+ " optional map map_message = 4;\n" // a normal message field is OK
+ "}\n",
+ "1:14: Field labels (required/optional/repeated) are not allowed on map "
+ "fields.\n"
+ "2:14: Field labels (required/optional/repeated) are not allowed on map "
+ "fields.\n"
+ "3:14: Field labels (required/optional/repeated) are not allowed on map "
+ "fields.\n");
+}
+
+TEST_F(ParseErrorTest, MalformedMaps) {
+ ExpectHasErrors(
+ "message TestMessage {\n"
+ " map map_message = 1;\n" // a normal message field lacking label
+ " map<string> str_map = 2;\n"
+ " map<string,> str_map2 = 3;\n"
+ " map<,string> str_map3 = 4;\n"
+ " map<> empty_map = 5;\n"
+ " map<string,string str_map6 = 6;\n"
+ "}"
+ "extend SomeMessage {\n"
+ " map<int32, int32> int_map = 1;\n"
+ "}",
+ "1:6: Expected \"required\", \"optional\", or \"repeated\".\n"
+ "2:12: Expected \",\".\n"
+ "3:13: Expected type name.\n"
+ "4:6: Expected type name.\n"
+ "5:6: Expected type name.\n"
+ "6:20: Expected \">\".\n"
+ "8:5: Map fields are not allowed to be extensions.\n");
+}
+
TEST_F(ParseErrorTest, GroupNotCapitalized) {
ExpectHasErrors(
"message TestMessage {\n"
@@ -1413,7 +1529,7 @@ TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) {
// definitions again afoter parsing (note, however, that the order of messages
// cannot be guaranteed to be the same)
-typedef ParserTest ParseDecriptorDebugTest;
+typedef ParserTest ParseDescriptorDebugTest;
class CompareDescriptorNames {
public:
@@ -1447,7 +1563,28 @@ void SortMessages(FileDescriptorProto *file_descriptor_proto) {
sort(data, data + size, CompareDescriptorNames());
}
-TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) {
+// Strips the message and enum field type names for comparison purpose only.
+void StripFieldTypeName(DescriptorProto* proto) {
+ for (int i = 0; i < proto->field_size(); ++i) {
+ string type_name = proto->field(i).type_name();
+ string::size_type pos = type_name.find_last_of(".");
+ if (pos != string::npos) {
+ proto->mutable_field(i)->mutable_type_name()->assign(
+ type_name.begin() + pos + 1, type_name.end());
+ }
+ }
+ for (int i = 0; i < proto->nested_type_size(); ++i) {
+ StripFieldTypeName(proto->mutable_nested_type(i));
+ }
+}
+
+void StripFieldTypeName(FileDescriptorProto* file_proto) {
+ for (int i = 0; i < file_proto->message_type_size(); ++i) {
+ StripFieldTypeName(file_proto->mutable_message_type(i));
+ }
+}
+
+TEST_F(ParseDescriptorDebugTest, TestAllDescriptorTypes) {
const FileDescriptor* original_file =
protobuf_unittest::TestAllTypes::descriptor()->file();
FileDescriptorProto expected;
@@ -1499,7 +1636,7 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) {
EXPECT_EQ(expected.DebugString(), parsed.DebugString());
}
-TEST_F(ParseDecriptorDebugTest, TestCustomOptions) {
+TEST_F(ParseDescriptorDebugTest, TestCustomOptions) {
const FileDescriptor* original_file =
protobuf_unittest::AggregateMessage::descriptor()->file();
FileDescriptorProto expected;
@@ -1538,6 +1675,106 @@ TEST_F(ParseDecriptorDebugTest, TestCustomOptions) {
EXPECT_EQ(expected.DebugString(), parsed.DebugString());
}
+// Ensure that DebugStringWithOptions(), with |include_comments| set to true,
+// includes comments from the original parser input in all of the appropriate
+// places.
+TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) {
+ SetupParser(
+ "// Message comment.\n"
+ "message TestMessage1 {\n"
+ " // Field comment.\n"
+ " optional int32 foo = 1;\n"
+ "\n"
+ " // Nested-message comment.\n"
+ " message NestedMessage {\n"
+ " optional int32 bar = 1;\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "// Enum comment.\n"
+ "enum MyEnumType {\n"
+ " // Enum-value comment.\n"
+ " ASDF = 1;\n"
+ "}\n"
+ "\n"
+ "// Service comment.\n"
+ "service MyService {\n"
+ " // RPC comment.\n"
+ " rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n"
+ "}\n");
+
+ FileDescriptorProto parsed_desc;
+ parsed_desc.set_name("foo.proto");
+ SourceLocationTable source_locations;
+ parser_->RecordSourceLocationsTo(&source_locations);
+ parser_->Parse(input_.get(), &parsed_desc);
+ EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+ ASSERT_EQ("", error_collector_.text_);
+
+ // We need to import the FileDescriptorProto to get a FileDescriptor.
+ MockValidationErrorCollector collector(source_locations, &error_collector_);
+ const FileDescriptor* descriptor =
+ pool_.BuildFileCollectingErrors(parsed_desc, &collector);
+ ASSERT_TRUE(descriptor != NULL);
+
+ DebugStringOptions debug_string_options;
+ debug_string_options.include_comments = true;
+ const string debug_string =
+ descriptor->DebugStringWithOptions(debug_string_options);
+
+ // Ensure that each of the comments appears somewhere in the DebugString(),
+ // and that these comments appear in order. We don't test the exact comment
+ // placement or formatting, because we do not want to be too fragile here.
+ const char* expected_comments[] = {
+ "Message comment.",
+ "Field comment",
+ "Nested-message comment",
+ "Enum comment",
+ "Enum-value comment",
+ "Service comment",
+ "RPC comment",
+ };
+
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) {
+ string::size_type found_pos = debug_string.find(expected_comments[i]);
+ ASSERT_TRUE(found_pos != string::npos);
+ }
+}
+
+TEST_F(ParseDescriptorDebugTest, TestMaps) {
+ SetupParser(
+ "syntax = \"proto3\"; "
+ "message Foo { "
+ " message Bar { } "
+ " map<int32, Bar> enum_message_map = 1; "
+ " map<string, float> primitive_map = 2; "
+ "} ");
+ FileDescriptorProto original;
+ EXPECT_TRUE(parser_->Parse(input_.get(), &original));
+ original.set_name("foo.proto");
+ const FileDescriptor* file = pool_.BuildFile(original);
+ ASSERT_TRUE(file != NULL);
+
+ // Make sure the debug string uses map syntax and does not have the auto
+ // generated entry.
+ string debug_string = file->DebugString();
+ EXPECT_TRUE(debug_string.find("map<") != string::npos);
+ EXPECT_TRUE(debug_string.find("option map_entry") == string::npos);
+ EXPECT_TRUE(debug_string.find("MapEntry") == string::npos);
+
+ // Make sure the descriptor debug string is parsable.
+ FileDescriptorProto parsed;
+ SetupParser(debug_string.c_str());
+ parsed.set_name("foo.proto");
+ ASSERT_TRUE(parser_->Parse(input_.get(), &parsed));
+
+ original.clear_source_code_info();
+ parsed.clear_source_code_info();
+ StripFieldTypeName(&original);
+ StripFieldTypeName(&parsed);
+ EXPECT_EQ(original.DebugString(), parsed.DebugString());
+}
+
// ===================================================================
// SourceCodeInfo tests.
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index b5cd01b5..efa64f3d 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -53,11 +53,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
CodeGeneratorRequest::default_instance_,
CodeGeneratorRequest_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(CodeGeneratorRequest));
+ sizeof(CodeGeneratorRequest),
+ 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_),
@@ -69,11 +70,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
CodeGeneratorResponse::default_instance_,
CodeGeneratorResponse_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(CodeGeneratorResponse));
+ sizeof(CodeGeneratorResponse),
+ 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_),
@@ -86,11 +88,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
CodeGeneratorResponse_File::default_instance_,
CodeGeneratorResponse_File_offsets_,
GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]),
- GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _unknown_fields_),
+ -1,
-1,
::google::protobuf::DescriptorPool::generated_pool(),
::google::protobuf::MessageFactory::generated_factory(),
- sizeof(CodeGeneratorResponse_File));
+ sizeof(CodeGeneratorResponse_File),
+ GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _internal_metadata_));
}
namespace {
@@ -169,16 +172,27 @@ const int CodeGeneratorRequest::kProtoFileFieldNumber;
#endif // !_MSC_VER
CodeGeneratorRequest::CodeGeneratorRequest()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest)
}
+CodeGeneratorRequest::CodeGeneratorRequest(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ file_to_generate_(arena),
+ proto_file_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorRequest)
+}
+
void CodeGeneratorRequest::InitAsDefaultInstance() {
}
CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest)
@@ -187,7 +201,7 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
void CodeGeneratorRequest::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ parameter_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -197,13 +211,21 @@ CodeGeneratorRequest::~CodeGeneratorRequest() {
}
void CodeGeneratorRequest::SharedDtor() {
- if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete parameter_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ parameter_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void CodeGeneratorRequest::ArenaDtor(void* object) {
+ CodeGeneratorRequest* _this = reinterpret_cast< CodeGeneratorRequest* >(object);
+ (void)_this;
+}
+void CodeGeneratorRequest::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void CodeGeneratorRequest::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -221,20 +243,20 @@ const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
-CodeGeneratorRequest* CodeGeneratorRequest::New() const {
- return new CodeGeneratorRequest;
+CodeGeneratorRequest* CodeGeneratorRequest::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<CodeGeneratorRequest>(arena);
}
void CodeGeneratorRequest::Clear() {
if (has_parameter()) {
- if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- parameter_->clear();
- }
+ parameter_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
file_to_generate_.Clear();
proto_file_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool CodeGeneratorRequest::MergePartialFromCodedStream(
@@ -257,7 +279,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
this->file_to_generate(this->file_to_generate_size() - 1).data(),
this->file_to_generate(this->file_to_generate_size() - 1).length(),
::google::protobuf::internal::WireFormat::PARSE,
- "file_to_generate");
+ "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
} else {
goto handle_unusual;
}
@@ -275,7 +297,7 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->parameter().data(), this->parameter().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "parameter");
+ "google.protobuf.compiler.CodeGeneratorRequest.parameter");
} else {
goto handle_unusual;
}
@@ -327,7 +349,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->file_to_generate(i).data(), this->file_to_generate(i).length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "file_to_generate");
+ "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
::google::protobuf::internal::WireFormatLite::WriteString(
1, this->file_to_generate(i), output);
}
@@ -337,7 +359,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->parameter().data(), this->parameter().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "parameter");
+ "google.protobuf.compiler.CodeGeneratorRequest.parameter");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
2, this->parameter(), output);
}
@@ -348,7 +370,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
15, this->proto_file(i), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -363,7 +385,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->file_to_generate(i).data(), this->file_to_generate(i).length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "file_to_generate");
+ "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
target = ::google::protobuf::internal::WireFormatLite::
WriteStringToArray(1, this->file_to_generate(i), target);
}
@@ -373,7 +395,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->parameter().data(), this->parameter().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "parameter");
+ "google.protobuf.compiler.CodeGeneratorRequest.parameter");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->parameter(), target);
@@ -386,7 +408,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
15, this->proto_file(i), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -397,15 +419,13 @@ void CodeGeneratorRequest::SerializeWithCachedSizes(
int CodeGeneratorRequest::ByteSize() const {
int total_size = 0;
- if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
- // optional string parameter = 2;
- if (has_parameter()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::StringSize(
- this->parameter());
- }
-
+ // optional string parameter = 2;
+ if (has_parameter()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->parameter());
}
+
// repeated string file_to_generate = 1;
total_size += 1 * this->file_to_generate_size();
for (int i = 0; i < this->file_to_generate_size(); i++) {
@@ -421,7 +441,7 @@ int CodeGeneratorRequest::ByteSize() const {
this->proto_file(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -453,7 +473,9 @@ void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
set_parameter(from.parameter());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void CodeGeneratorRequest::CopyFrom(const ::google::protobuf::Message& from) {
@@ -475,15 +497,29 @@ bool CodeGeneratorRequest::IsInitialized() const {
}
void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) {
- if (other != this) {
- file_to_generate_.Swap(&other->file_to_generate_);
- std::swap(parameter_, other->parameter_);
- proto_file_.Swap(&other->proto_file_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ CodeGeneratorRequest temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void CodeGeneratorRequest::UnsafeArenaSwap(CodeGeneratorRequest* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
+ file_to_generate_.UnsafeArenaSwap(&other->file_to_generate_);
+ parameter_.Swap(&other->parameter_);
+ proto_file_.UnsafeArenaSwap(&other->proto_file_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -503,16 +539,25 @@ const int CodeGeneratorResponse_File::kContentFieldNumber;
#endif // !_MSC_VER
CodeGeneratorResponse_File::CodeGeneratorResponse_File()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
}
+CodeGeneratorResponse_File::CodeGeneratorResponse_File(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
+}
+
void CodeGeneratorResponse_File::InitAsDefaultInstance() {
}
CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
@@ -521,9 +566,9 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon
void CodeGeneratorResponse_File::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ 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_));
}
@@ -533,19 +578,23 @@ CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
}
void CodeGeneratorResponse_File::SharedDtor() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
- }
- if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete insertion_point_;
- }
- if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete content_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ insertion_point_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+ content_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void CodeGeneratorResponse_File::ArenaDtor(void* object) {
+ CodeGeneratorResponse_File* _this = reinterpret_cast< CodeGeneratorResponse_File* >(object);
+ (void)_this;
+}
+void CodeGeneratorResponse_File::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void CodeGeneratorResponse_File::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -563,30 +612,26 @@ const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance()
CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
-CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const {
- return new CodeGeneratorResponse_File;
+CodeGeneratorResponse_File* CodeGeneratorResponse_File::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<CodeGeneratorResponse_File>(arena);
}
void CodeGeneratorResponse_File::Clear() {
if (_has_bits_[0 / 32] & 7) {
if (has_name()) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_insertion_point()) {
- if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- insertion_point_->clear();
- }
+ insertion_point_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
if (has_content()) {
- if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- content_->clear();
- }
+ content_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
@@ -607,7 +652,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "name");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.name");
} else {
goto handle_unusual;
}
@@ -624,7 +669,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->insertion_point().data(), this->insertion_point().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "insertion_point");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
} else {
goto handle_unusual;
}
@@ -641,7 +686,7 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->content().data(), this->content().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "content");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.content");
} else {
goto handle_unusual;
}
@@ -679,7 +724,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.name");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->name(), output);
}
@@ -689,7 +734,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->insertion_point().data(), this->insertion_point().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "insertion_point");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
2, this->insertion_point(), output);
}
@@ -699,12 +744,12 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->content().data(), this->content().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "content");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.content");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
15, this->content(), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -719,7 +764,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->name().data(), this->name().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "name");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.name");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->name(), target);
@@ -730,7 +775,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->insertion_point().data(), this->insertion_point().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "insertion_point");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
2, this->insertion_point(), target);
@@ -741,13 +786,13 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->content().data(), this->content().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "content");
+ "google.protobuf.compiler.CodeGeneratorResponse.File.content");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
15, this->content(), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -758,7 +803,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes(
int CodeGeneratorResponse_File::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+ if (_has_bits_[0 / 32] & 7) {
// optional string name = 1;
if (has_name()) {
total_size += 1 +
@@ -781,7 +826,7 @@ int CodeGeneratorResponse_File::ByteSize() const {
}
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -817,7 +862,9 @@ void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& fro
set_content(from.content());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void CodeGeneratorResponse_File::CopyFrom(const ::google::protobuf::Message& from) {
@@ -838,15 +885,29 @@ bool CodeGeneratorResponse_File::IsInitialized() const {
}
void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) {
- if (other != this) {
- std::swap(name_, other->name_);
- std::swap(insertion_point_, other->insertion_point_);
- std::swap(content_, other->content_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ CodeGeneratorResponse_File temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void CodeGeneratorResponse_File::UnsafeArenaSwap(CodeGeneratorResponse_File* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
+ name_.Swap(&other->name_);
+ insertion_point_.Swap(&other->insertion_point_);
+ content_.Swap(&other->content_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
@@ -865,16 +926,26 @@ const int CodeGeneratorResponse::kFileFieldNumber;
#endif // !_MSC_VER
CodeGeneratorResponse::CodeGeneratorResponse()
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message() , _internal_metadata_(NULL) {
SharedCtor();
// @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse)
}
+CodeGeneratorResponse::CodeGeneratorResponse(::google::protobuf::Arena* arena)
+ : ::google::protobuf::Message(),
+ _internal_metadata_(arena),
+ file_(arena) {
+ SharedCtor();
+ RegisterArenaDtor(arena);
+ // @@protoc_insertion_point(arena_constructor:google.protobuf.compiler.CodeGeneratorResponse)
+}
+
void CodeGeneratorResponse::InitAsDefaultInstance() {
}
CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
- : ::google::protobuf::Message() {
+ : ::google::protobuf::Message(),
+ _internal_metadata_(NULL) {
SharedCtor();
MergeFrom(from);
// @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse)
@@ -883,7 +954,7 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
void CodeGeneratorResponse::SharedCtor() {
::google::protobuf::internal::GetEmptyString();
_cached_size_ = 0;
- error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+ error_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@@ -893,13 +964,21 @@ CodeGeneratorResponse::~CodeGeneratorResponse() {
}
void CodeGeneratorResponse::SharedDtor() {
- if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete error_;
+ if (GetArenaNoVirtual() != NULL) {
+ return;
}
+
+ error_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
if (this != default_instance_) {
}
}
+void CodeGeneratorResponse::ArenaDtor(void* object) {
+ CodeGeneratorResponse* _this = reinterpret_cast< CodeGeneratorResponse* >(object);
+ (void)_this;
+}
+void CodeGeneratorResponse::RegisterArenaDtor(::google::protobuf::Arena* arena) {
+}
void CodeGeneratorResponse::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
@@ -917,19 +996,19 @@ const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
-CodeGeneratorResponse* CodeGeneratorResponse::New() const {
- return new CodeGeneratorResponse;
+CodeGeneratorResponse* CodeGeneratorResponse::New(::google::protobuf::Arena* arena) const {
+ return ::google::protobuf::Arena::CreateMessage<CodeGeneratorResponse>(arena);
}
void CodeGeneratorResponse::Clear() {
if (has_error()) {
- if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- error_->clear();
- }
+ error_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
file_.Clear();
::memset(_has_bits_, 0, sizeof(_has_bits_));
- mutable_unknown_fields()->Clear();
+ if (_internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->Clear();
+ }
}
bool CodeGeneratorResponse::MergePartialFromCodedStream(
@@ -950,7 +1029,7 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->error().data(), this->error().length(),
::google::protobuf::internal::WireFormat::PARSE,
- "error");
+ "google.protobuf.compiler.CodeGeneratorResponse.error");
} else {
goto handle_unusual;
}
@@ -1002,7 +1081,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->error().data(), this->error().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "error");
+ "google.protobuf.compiler.CodeGeneratorResponse.error");
::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
1, this->error(), output);
}
@@ -1013,7 +1092,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
15, this->file(i), output);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
::google::protobuf::internal::WireFormat::SerializeUnknownFields(
unknown_fields(), output);
}
@@ -1028,7 +1107,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
this->error().data(), this->error().length(),
::google::protobuf::internal::WireFormat::SERIALIZE,
- "error");
+ "google.protobuf.compiler.CodeGeneratorResponse.error");
target =
::google::protobuf::internal::WireFormatLite::WriteStringToArray(
1, this->error(), target);
@@ -1041,7 +1120,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
15, this->file(i), target);
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
unknown_fields(), target);
}
@@ -1052,15 +1131,13 @@ void CodeGeneratorResponse::SerializeWithCachedSizes(
int CodeGeneratorResponse::ByteSize() const {
int total_size = 0;
- if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
- // optional string error = 1;
- if (has_error()) {
- total_size += 1 +
- ::google::protobuf::internal::WireFormatLite::StringSize(
- this->error());
- }
-
+ // optional string error = 1;
+ if (has_error()) {
+ total_size += 1 +
+ ::google::protobuf::internal::WireFormatLite::StringSize(
+ this->error());
}
+
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
total_size += 1 * this->file_size();
for (int i = 0; i < this->file_size(); i++) {
@@ -1069,7 +1146,7 @@ int CodeGeneratorResponse::ByteSize() const {
this->file(i));
}
- if (!unknown_fields().empty()) {
+ if (_internal_metadata_.have_unknown_fields()) {
total_size +=
::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
unknown_fields());
@@ -1100,7 +1177,9 @@ void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
set_error(from.error());
}
}
- mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ if (from._internal_metadata_.have_unknown_fields()) {
+ mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+ }
}
void CodeGeneratorResponse::CopyFrom(const ::google::protobuf::Message& from) {
@@ -1121,14 +1200,28 @@ bool CodeGeneratorResponse::IsInitialized() const {
}
void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) {
- if (other != this) {
- std::swap(error_, other->error_);
- file_.Swap(&other->file_);
- std::swap(_has_bits_[0], other->_has_bits_[0]);
- _unknown_fields_.Swap(&other->_unknown_fields_);
- std::swap(_cached_size_, other->_cached_size_);
+ if (other == this) return;
+ if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) {
+ InternalSwap(other);
+ } else {
+ CodeGeneratorResponse temp;
+ temp.MergeFrom(*this);
+ CopyFrom(*other);
+ other->CopyFrom(temp);
}
}
+void CodeGeneratorResponse::UnsafeArenaSwap(CodeGeneratorResponse* other) {
+ if (other == this) return;
+ GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual());
+ InternalSwap(other);
+}
+void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
+ error_.Swap(&other->error_);
+ file_.UnsafeArenaSwap(&other->file_);
+ std::swap(_has_bits_[0], other->_has_bits_[0]);
+ _internal_metadata_.Swap(&other->_internal_metadata_);
+ std::swap(_cached_size_, other->_cached_size_);
+}
::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const {
protobuf_AssignDescriptorsOnce();
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 567b30ef..636992a6 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -5,6 +5,7 @@
#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
#include <string>
+#include <stdint.h>
#include <google/protobuf/stubs/common.h>
@@ -19,7 +20,10 @@
#error regenerate this file with a newer version of protoc.
#endif
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>
#include <google/protobuf/extension_set.h>
@@ -55,21 +59,28 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorRequest& default_instance();
+ void UnsafeArenaSwap(CodeGeneratorRequest* other);
void Swap(CodeGeneratorRequest* other);
// implements Message ----------------------------------------------
- CodeGeneratorRequest* New() const;
+ inline CodeGeneratorRequest* New() const { return New(NULL); }
+
+ CodeGeneratorRequest* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const CodeGeneratorRequest& from);
@@ -88,7 +99,21 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(CodeGeneratorRequest* other);
+ protected:
+ explicit CodeGeneratorRequest(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -122,6 +147,9 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
inline ::std::string* mutable_parameter();
inline ::std::string* release_parameter();
inline void set_allocated_parameter(::std::string* parameter);
+ inline ::std::string* unsafe_arena_release_parameter();
+ inline void unsafe_arena_set_allocated_parameter(
+ ::std::string* parameter);
// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
inline int proto_file_size() const;
@@ -140,12 +168,14 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message
inline void set_has_parameter();
inline void clear_has_parameter();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
- ::std::string* parameter_;
+ ::google::protobuf::internal::ArenaStringPtr parameter_;
::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
@@ -169,21 +199,28 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorResponse_File& default_instance();
+ void UnsafeArenaSwap(CodeGeneratorResponse_File* other);
void Swap(CodeGeneratorResponse_File* other);
// implements Message ----------------------------------------------
- CodeGeneratorResponse_File* New() const;
+ inline CodeGeneratorResponse_File* New() const { return New(NULL); }
+
+ CodeGeneratorResponse_File* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const CodeGeneratorResponse_File& from);
@@ -202,7 +239,21 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(CodeGeneratorResponse_File* other);
+ protected:
+ explicit CodeGeneratorResponse_File(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -220,6 +271,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
inline ::std::string* mutable_name();
inline ::std::string* release_name();
inline void set_allocated_name(::std::string* name);
+ inline ::std::string* unsafe_arena_release_name();
+ inline void unsafe_arena_set_allocated_name(
+ ::std::string* name);
// optional string insertion_point = 2;
inline bool has_insertion_point() const;
@@ -232,6 +286,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
inline ::std::string* mutable_insertion_point();
inline ::std::string* release_insertion_point();
inline void set_allocated_insertion_point(::std::string* insertion_point);
+ inline ::std::string* unsafe_arena_release_insertion_point();
+ inline void unsafe_arena_set_allocated_insertion_point(
+ ::std::string* insertion_point);
// optional string content = 15;
inline bool has_content() const;
@@ -244,6 +301,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
inline ::std::string* mutable_content();
inline ::std::string* release_content();
inline void set_allocated_content(::std::string* content);
+ inline ::std::string* unsafe_arena_release_content();
+ inline void unsafe_arena_set_allocated_content(
+ ::std::string* content);
// @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
private:
@@ -254,13 +314,15 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M
inline void set_has_content();
inline void clear_has_content();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* name_;
- ::std::string* insertion_point_;
- ::std::string* content_;
+ ::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 protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
@@ -283,21 +345,28 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
}
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
- return _unknown_fields_;
+ return _internal_metadata_.unknown_fields();
}
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
- return &_unknown_fields_;
+ return _internal_metadata_.mutable_unknown_fields();
}
+ inline ::google::protobuf::Arena* GetArena() const { return GetArenaNoVirtual(); }
+ inline void* GetMaybeArenaPointer() const {
+ return MaybeArenaPtr();
+ }
static const ::google::protobuf::Descriptor* descriptor();
static const CodeGeneratorResponse& default_instance();
+ void UnsafeArenaSwap(CodeGeneratorResponse* other);
void Swap(CodeGeneratorResponse* other);
// implements Message ----------------------------------------------
- CodeGeneratorResponse* New() const;
+ inline CodeGeneratorResponse* New() const { return New(NULL); }
+
+ CodeGeneratorResponse* New(::google::protobuf::Arena* arena) const;
void CopyFrom(const ::google::protobuf::Message& from);
void MergeFrom(const ::google::protobuf::Message& from);
void CopyFrom(const CodeGeneratorResponse& from);
@@ -316,7 +385,21 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
+ void InternalSwap(CodeGeneratorResponse* other);
+ protected:
+ explicit CodeGeneratorResponse(::google::protobuf::Arena* arena);
+ private:
+ static void ArenaDtor(void* object);
+ inline void RegisterArenaDtor(::google::protobuf::Arena* arena);
+ private:
+ inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+ return _internal_metadata_.arena();
+ }
+ inline void* MaybeArenaPtr() const {
+ return _internal_metadata_.raw_arena_ptr();
+ }
public:
+
::google::protobuf::Metadata GetMetadata() const;
// nested types ----------------------------------------------------
@@ -336,6 +419,9 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
inline ::std::string* mutable_error();
inline ::std::string* release_error();
inline void set_allocated_error(::std::string* error);
+ inline ::std::string* unsafe_arena_release_error();
+ inline void unsafe_arena_set_allocated_error(
+ ::std::string* error);
// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
inline int file_size() const;
@@ -354,11 +440,13 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag
inline void set_has_error();
inline void clear_has_error();
- ::google::protobuf::UnknownFieldSet _unknown_fields_;
-
+ ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+ friend class ::google::protobuf::Arena;
+ typedef void InternalArenaConstructable_;
+ typedef void DestructorSkippable_;
::google::protobuf::uint32 _has_bits_[1];
mutable int _cached_size_;
- ::std::string* error_;
+ ::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();
friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
@@ -439,68 +527,67 @@ inline void CodeGeneratorRequest::clear_has_parameter() {
_has_bits_[0] &= ~0x00000002u;
}
inline void CodeGeneratorRequest::clear_parameter() {
- if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- parameter_->clear();
- }
+ parameter_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_parameter();
}
inline const ::std::string& CodeGeneratorRequest::parameter() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
- return *parameter_;
+ return parameter_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
set_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- parameter_ = new ::std::string;
- }
- parameter_->assign(value);
+ parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
}
inline void CodeGeneratorRequest::set_parameter(const char* value) {
set_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- parameter_ = new ::std::string;
- }
- parameter_->assign(value);
+ parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
}
-inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
+inline void CodeGeneratorRequest::set_parameter(const char* value,
+ size_t size) {
set_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- parameter_ = new ::std::string;
- }
- parameter_->assign(reinterpret_cast<const char*>(value), size);
+ parameter_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
}
inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
set_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- parameter_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter)
- return parameter_;
+ return parameter_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* CodeGeneratorRequest::release_parameter() {
clear_has_parameter();
- if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = parameter_;
- parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return parameter_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* CodeGeneratorRequest::unsafe_arena_release_parameter() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_parameter();
+ return parameter_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) {
- if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete parameter_;
+ if (parameter != NULL) {
+ set_has_parameter();
+ } else {
+ clear_has_parameter();
}
- if (parameter) {
+ parameter_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
+}
+inline void CodeGeneratorRequest::unsafe_arena_set_allocated_parameter(
+ ::std::string* parameter) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (parameter != NULL) {
set_has_parameter();
- parameter_ = parameter;
} else {
clear_has_parameter();
- parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_parameter();
+ parameter_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ parameter, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter)
}
@@ -549,68 +636,67 @@ inline void CodeGeneratorResponse_File::clear_has_name() {
_has_bits_[0] &= ~0x00000001u;
}
inline void CodeGeneratorResponse_File::clear_name() {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_->clear();
- }
+ name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_name();
}
inline const ::std::string& CodeGeneratorResponse_File::name() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
- return *name_;
+ return name_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
}
inline void CodeGeneratorResponse_File::set_name(const char* value) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(value);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
}
-inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
+inline void CodeGeneratorResponse_File::set_name(const char* value,
+ size_t size) {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
- name_->assign(reinterpret_cast<const char*>(value), size);
+ name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
}
inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
set_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- name_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name)
- return name_;
+ return name_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* CodeGeneratorResponse_File::release_name() {
clear_has_name();
- if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = name_;
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return name_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_name() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_name();
+ return name_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) {
- if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete name_;
+ if (name != NULL) {
+ set_has_name();
+ } else {
+ clear_has_name();
}
- if (name) {
+ name_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
+}
+inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_name(
+ ::std::string* name) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (name != NULL) {
set_has_name();
- name_ = name;
} else {
clear_has_name();
- name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_name();
+ name_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ name, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name)
}
@@ -625,68 +711,67 @@ inline void CodeGeneratorResponse_File::clear_has_insertion_point() {
_has_bits_[0] &= ~0x00000002u;
}
inline void CodeGeneratorResponse_File::clear_insertion_point() {
- if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- insertion_point_->clear();
- }
+ insertion_point_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_insertion_point();
}
inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
- return *insertion_point_;
+ return insertion_point_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
set_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- insertion_point_ = new ::std::string;
- }
- insertion_point_->assign(value);
+ insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
}
inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
set_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- insertion_point_ = new ::std::string;
- }
- insertion_point_->assign(value);
+ insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
}
-inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
+inline void CodeGeneratorResponse_File::set_insertion_point(const char* value,
+ size_t size) {
set_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- insertion_point_ = new ::std::string;
- }
- insertion_point_->assign(reinterpret_cast<const char*>(value), size);
+ insertion_point_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
}
inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
set_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- insertion_point_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
- return insertion_point_;
+ return insertion_point_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() {
clear_has_insertion_point();
- if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = insertion_point_;
- insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return insertion_point_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_insertion_point() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_insertion_point();
+ return insertion_point_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) {
- if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete insertion_point_;
+ if (insertion_point != NULL) {
+ set_has_insertion_point();
+ } else {
+ clear_has_insertion_point();
}
- if (insertion_point) {
+ insertion_point_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
+}
+inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_insertion_point(
+ ::std::string* insertion_point) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (insertion_point != NULL) {
set_has_insertion_point();
- insertion_point_ = insertion_point;
} else {
clear_has_insertion_point();
- insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_insertion_point();
+ insertion_point_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ insertion_point, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
}
@@ -701,68 +786,67 @@ inline void CodeGeneratorResponse_File::clear_has_content() {
_has_bits_[0] &= ~0x00000004u;
}
inline void CodeGeneratorResponse_File::clear_content() {
- if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- content_->clear();
- }
+ content_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_content();
}
inline const ::std::string& CodeGeneratorResponse_File::content() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
- return *content_;
+ return content_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
set_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- content_ = new ::std::string;
- }
- content_->assign(value);
+ content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
inline void CodeGeneratorResponse_File::set_content(const char* value) {
set_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- content_ = new ::std::string;
- }
- content_->assign(value);
+ content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
-inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
+inline void CodeGeneratorResponse_File::set_content(const char* value,
+ size_t size) {
set_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- content_ = new ::std::string;
- }
- content_->assign(reinterpret_cast<const char*>(value), size);
+ content_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
set_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- content_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content)
- return content_;
+ return content_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* CodeGeneratorResponse_File::release_content() {
clear_has_content();
- if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = content_;
- content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return content_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* CodeGeneratorResponse_File::unsafe_arena_release_content() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_content();
+ return content_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) {
- if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete content_;
+ if (content != NULL) {
+ set_has_content();
+ } else {
+ clear_has_content();
}
- if (content) {
+ content_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
+}
+inline void CodeGeneratorResponse_File::unsafe_arena_set_allocated_content(
+ ::std::string* content) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (content != NULL) {
set_has_content();
- content_ = content;
} else {
clear_has_content();
- content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_content();
+ content_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ content, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content)
}
@@ -781,68 +865,67 @@ inline void CodeGeneratorResponse::clear_has_error() {
_has_bits_[0] &= ~0x00000001u;
}
inline void CodeGeneratorResponse::clear_error() {
- if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- error_->clear();
- }
+ error_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
clear_has_error();
}
inline const ::std::string& CodeGeneratorResponse::error() const {
// @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
- return *error_;
+ return error_.Get(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
set_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- error_ = new ::std::string;
- }
- error_->assign(value);
+ error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
}
inline void CodeGeneratorResponse::set_error(const char* value) {
set_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- error_ = new ::std::string;
- }
- error_->assign(value);
+ error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value),
+ GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
}
-inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
+inline void CodeGeneratorResponse::set_error(const char* value,
+ size_t size) {
set_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- error_ = new ::std::string;
- }
- error_->assign(reinterpret_cast<const char*>(value), size);
+ error_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(
+ reinterpret_cast<const char*>(value), size), GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
}
inline ::std::string* CodeGeneratorResponse::mutable_error() {
set_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- error_ = new ::std::string;
- }
// @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error)
- return error_;
+ return error_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
}
inline ::std::string* CodeGeneratorResponse::release_error() {
clear_has_error();
- if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- return NULL;
- } else {
- ::std::string* temp = error_;
- error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
- return temp;
- }
+ return error_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* CodeGeneratorResponse::unsafe_arena_release_error() {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ clear_has_error();
+ return error_.UnsafeArenaRelease(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ GetArenaNoVirtual());
}
inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) {
- if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
- delete error_;
+ if (error != NULL) {
+ set_has_error();
+ } else {
+ clear_has_error();
}
- if (error) {
+ error_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error,
+ GetArenaNoVirtual());
+ // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
+}
+inline void CodeGeneratorResponse::unsafe_arena_set_allocated_error(
+ ::std::string* error) {
+ GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);
+ if (error != NULL) {
set_has_error();
- error_ = error;
} else {
clear_has_error();
- error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
+ set_has_error();
+ error_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+ error, GetArenaNoVirtual());
// @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error)
}
@@ -888,8 +971,8 @@ namespace google {
namespace protobuf {
-} // namespace google
} // namespace protobuf
+} // namespace google
#endif // SWIG
// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index b65379d7..e627289b 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -44,6 +44,7 @@
// plugin should be named "protoc-gen-$NAME", and will then be used when the
// flag "--${NAME}_out" is passed to protoc.
+syntax = "proto2";
package google.protobuf.compiler;
option java_package = "com.google.protobuf.compiler";
option java_outer_classname = "PluginProtos";
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 15e05da9..d72ca207 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -44,11 +44,15 @@
// performance-minded Python code leverage the fast C++ implementation
// directly.
+#include <google/protobuf/stubs/hash.h>
#include <limits>
#include <map>
-#include <utility>
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <string>
+#include <utility>
#include <vector>
#include <google/protobuf/compiler/python/python_generator.h>
@@ -69,6 +73,41 @@ namespace python {
namespace {
+const char* const kKeywordList[] = {
+ "and", "as", "break", "class", "continue", "def", "elif", "else", "except",
+ "False", "for", "from", "if", "import", "not", "or", "raise", "return",
+ "True", "try", "with", "while", "yield"
+};
+
+hash_set<string> MakeKeywordsMap() {
+ hash_set<string> result;
+ for (int i = 0; i < GOOGLE_ARRAYSIZE(kKeywordList); ++i) {
+ result.insert(kKeywordList[i]);
+ }
+ return result;
+}
+
+hash_set<string>* keywords_ = NULL;
+GOOGLE_PROTOBUF_DECLARE_ONCE(keywords_once_);
+
+void InitKeywords() {
+ keywords_ = new hash_set<string>();
+ *keywords_ = MakeKeywordsMap();
+}
+
+hash_set<string>& GetKeywords() {
+ ::google::protobuf::GoogleOnceInit(&keywords_once_, &InitKeywords);
+ return *keywords_;
+}
+
+string FieldName(const FieldDescriptor& field) {
+ string result = field.name();
+ if (GetKeywords().count(result) > 0) {
+ result.append("_");
+ }
+ return result;
+}
+
// Returns a copy of |filename| with any trailing ".protodevel" or ".proto
// suffix stripped.
// TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
@@ -88,6 +127,37 @@ string ModuleName(const string& filename) {
}
+// Returns the alias we assign to the module of the given .proto filename
+// when importing. See testPackageInitializationImport in
+// google/protobuf/python/reflection_test.py
+// to see why we need the alias.
+string ModuleAlias(const string& filename) {
+ string module_name = ModuleName(filename);
+ // We can't have dots in the module name, so we replace each with _dot_.
+ // But that could lead to a collision between a.b and a_dot_b, so we also
+ // duplicate each underscore.
+ GlobalReplaceSubstring("_", "__", &module_name);
+ GlobalReplaceSubstring(".", "_dot_", &module_name);
+ return module_name;
+}
+
+
+// Returns an import statement of form "from X.Y.Z import T" for the given
+// .proto filename.
+string ModuleImportStatement(const string& filename) {
+ string module_name = ModuleName(filename);
+ int last_dot_pos = module_name.rfind('.');
+ if (last_dot_pos == string::npos) {
+ // NOTE(petya): this is not tested as it would require a protocol buffer
+ // outside of any package, and I don't think that is easily achievable.
+ return "import " + module_name;
+ } else {
+ return "from " + module_name.substr(0, last_dot_pos) + " import " +
+ module_name.substr(last_dot_pos + 1);
+ }
+}
+
+
// Returns the name of all containing types for descriptor,
// in order from outermost to innermost, followed by descriptor's
// own name. Each name is separated by |separator|.
@@ -309,9 +379,12 @@ bool Generator::Generate(const FileDescriptor* file,
// Prints Python imports for all modules imported by |file|.
void Generator::PrintImports() const {
for (int i = 0; i < file_->dependency_count(); ++i) {
- string module_name = ModuleName(file_->dependency(i)->name());
- printer_->Print("import $module$\n", "module",
- module_name);
+ const string& filename = file_->dependency(i)->name();
+ string import_statement = ModuleImportStatement(filename);
+ string module_alias = ModuleAlias(filename);
+ printer_->Print("$statement$ as $alias$\n", "statement",
+ import_statement, "alias", module_alias);
+ CopyPublicDependenciesAliases(module_alias, file_->dependency(i));
}
printer_->Print("\n");
@@ -342,8 +415,9 @@ void Generator::PrintFileDescriptor() const {
if (file_->dependency_count() != 0) {
printer_->Print(",\ndependencies=[");
for (int i = 0; i < file_->dependency_count(); ++i) {
- string module_name = ModuleName(file_->dependency(i)->name());
- printer_->Print("$module_name$.DESCRIPTOR,", "module_name", module_name);
+ string module_alias = ModuleAlias(file_->dependency(i)->name());
+ printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
+ module_alias);
}
printer_->Print("]");
}
@@ -457,7 +531,7 @@ void Generator::PrintTopLevelExtensions() const {
printer_->Print("$constant_name$ = $number$\n",
"constant_name", constant_name,
"number", SimpleItoa(extension_field.number()));
- printer_->Print("$name$ = ", "name", extension_field.name());
+ printer_->Print("$name$ = ", "name", FieldName(extension_field));
PrintFieldDescriptor(extension_field, is_extension);
printer_->Print("\n");
}
@@ -804,7 +878,7 @@ void Generator::AddExtensionToFileDescriptor(
const FieldDescriptor& descriptor) const {
map<string, string> m;
m["descriptor_name"] = kDescriptorKey;
- m["field_name"] = descriptor.name();
+ m["field_name"] = FieldName(descriptor);
const char file_descriptor_template[] =
"$descriptor_name$.extensions_by_name['$field_name$'] = "
"$field_name$\n";
@@ -857,12 +931,12 @@ string Generator::FieldReferencingExpression(
GOOGLE_CHECK_EQ(field.file(), file_) << field.file()->name() << " vs. "
<< file_->name();
if (!containing_type) {
- return field.name();
+ return FieldName(field);
}
return strings::Substitute(
"$0.$1['$2']",
ModuleLevelDescriptorName(*containing_type),
- python_dict_name, field.name());
+ python_dict_name, FieldName(field));
}
// Prints containing_type for nested descriptors or enum descriptors.
@@ -991,7 +1065,7 @@ void Generator::PrintFieldDescriptor(
string options_string;
field.options().SerializeToString(&options_string);
map<string, string> m;
- m["name"] = field.name();
+ m["name"] = FieldName(field);
m["full_name"] = field.full_name();
m["index"] = SimpleItoa(field.index());
m["number"] = SimpleItoa(field.number());
@@ -1084,7 +1158,7 @@ string Generator::ModuleLevelDescriptorName(
// We now have the name relative to its own module. Also qualify with
// the module name iff this descriptor is from a different .proto file.
if (descriptor.file() != file_) {
- name = ModuleName(descriptor.file()->name()) + "." + name;
+ name = ModuleAlias(descriptor.file()->name()) + "." + name;
}
return name;
}
@@ -1096,7 +1170,7 @@ string Generator::ModuleLevelDescriptorName(
string Generator::ModuleLevelMessageName(const Descriptor& descriptor) const {
string name = NamePrefixedWithNestedTypes(descriptor, ".");
if (descriptor.file() != file_) {
- name = ModuleName(descriptor.file()->name()) + "." + name;
+ name = ModuleAlias(descriptor.file()->name()) + "." + name;
}
return name;
}
@@ -1109,7 +1183,7 @@ string Generator::ModuleLevelServiceDescriptorName(
UpperString(&name);
name = "_" + name;
if (descriptor.file() != file_) {
- name = ModuleName(descriptor.file()->name()) + "." + name;
+ name = ModuleAlias(descriptor.file()->name()) + "." + name;
}
return name;
}
@@ -1211,7 +1285,7 @@ void Generator::FixOptionsForField(
if (field.is_extension()) {
if (field.extension_scope() == NULL) {
// Top level extensions.
- field_name = field.name();
+ field_name = FieldName(field);
} else {
field_name = FieldReferencingExpression(
field.extension_scope(), field, "extensions_by_name");
@@ -1256,6 +1330,18 @@ void Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
}
}
+// If a dependency forwards other files through public dependencies, let's
+// copy over the corresponding module aliases.
+void Generator::CopyPublicDependenciesAliases(
+ const string& copy_from, const FileDescriptor* file) const {
+ for (int i = 0; i < file->public_dependency_count(); ++i) {
+ string module_alias = ModuleAlias(file->public_dependency(i)->name());
+ printer_->Print("$alias$ = $copy_from$.$alias$\n", "alias", module_alias,
+ "copy_from", copy_from);
+ CopyPublicDependenciesAliases(copy_from, file->public_dependency(i));
+ }
+}
+
} // namespace python
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index f86e9ea2..7e8f58e5 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -148,6 +148,9 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator {
void FixOptionsForEnum(const EnumDescriptor& descriptor) const;
void FixOptionsForMessage(const Descriptor& descriptor) const;
+ void CopyPublicDependenciesAliases(
+ const string& copy_from, const FileDescriptor* file) const;
+
// Very coarse-grained lock to ensure that Generate() is reentrant.
// Guards file_, printer_ and file_descriptor_serialized_.
mutable Mutex mutex_;
diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
index 09dbc654..24c2f971 100644
--- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -35,6 +35,9 @@
// worth.
#include <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
#include <google/protobuf/compiler/python/python_generator.h>
#include <google/protobuf/compiler/command_line_interface.h>