diff options
author | kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2009-07-29 01:13:20 +0000 |
---|---|---|
committer | kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2009-07-29 01:13:20 +0000 |
commit | 80b1d62bfcea65c59e2160da71dad84b1bd19cef (patch) | |
tree | 5423b830c53174fec83a7ea01ff0877e11c1ddb6 /src/google/protobuf/compiler | |
parent | d2fd0638c309113ccae3731a58e30419f522269a (diff) | |
download | protobuf-80b1d62bfcea65c59e2160da71dad84b1bd19cef.tar.gz protobuf-80b1d62bfcea65c59e2160da71dad84b1bd19cef.tar.bz2 protobuf-80b1d62bfcea65c59e2160da71dad84b1bd19cef.zip |
Submit recent changes from internal branch, including "lite mode" for
C++ and Java. See CHANGES.txt for more details.
Diffstat (limited to 'src/google/protobuf/compiler')
30 files changed, 1604 insertions, 983 deletions
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 149d34af..0def84d8 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -34,6 +34,8 @@ #include <google/protobuf/compiler/code_generator.h> +#include <google/protobuf/stubs/strutil.h> + namespace google { namespace protobuf { namespace compiler { @@ -41,6 +43,26 @@ namespace compiler { CodeGenerator::~CodeGenerator() {} OutputDirectory::~OutputDirectory() {} +// Parses a set of comma-delimited name/value pairs. +void ParseGeneratorParameter(const string& text, + vector<pair<string, string> >* output) { + vector<string> parts; + SplitStringUsing(text, ",", &parts); + + for (int i = 0; i < parts.size(); i++) { + string::size_type equals_pos = parts[i].find_first_of('='); + pair<string, string> value; + if (equals_pos == string::npos) { + value.first = parts[i]; + value.second = ""; + } else { + value.first = parts[i].substr(0, equals_pos); + value.second = parts[i].substr(equals_pos + 1); + } + output->push_back(value); + } +} + } // namespace compiler } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index d22974e9..8a7081f7 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -40,6 +40,8 @@ #include <google/protobuf/stubs/common.h> #include <string> +#include <vector> +#include <utility> namespace google { namespace protobuf { @@ -105,6 +107,15 @@ class LIBPROTOC_EXPORT OutputDirectory { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OutputDirectory); }; +// Several code generators treat the parameter argument as holding a +// list of options separated by commas. This helper function parses +// a set of comma-delimited name/value pairs: e.g., +// "foo=bar,baz,qux=corge" +// parses to the pairs: +// ("foo", "bar"), ("baz", ""), ("qux", "corge") +extern void ParseGeneratorParameter(const string&, + vector<pair<string, string> >*); + } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 875cbef8..90e9172a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -95,24 +95,39 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { } printer->Print(vars, - "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n" "$dllexport$bool $classname$_IsValid(int value);\n" "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n" "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n" "\n"); - // The _Name and _Parse methods - printer->Print(vars, - "inline const ::std::string& $classname$_Name($classname$ value) {\n" - " return ::google::protobuf::internal::NameOfEnum(\n" - " $classname$_descriptor(), value);\n" - "}\n"); - printer->Print(vars, - "inline bool $classname$_Parse(\n" - " const ::std::string& name, $classname$* value) {\n" - " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n" - " $classname$_descriptor(), name, value);\n" - "}\n"); + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "$dllexport$const ::google::protobuf::EnumDescriptor* $classname$_descriptor();\n"); + // The _Name and _Parse methods + printer->Print(vars, + "inline const ::std::string& $classname$_Name($classname$ value) {\n" + " return ::google::protobuf::internal::NameOfEnum(\n" + " $classname$_descriptor(), value);\n" + "}\n"); + printer->Print(vars, + "inline bool $classname$_Parse(\n" + " const ::std::string& name, $classname$* value) {\n" + " return ::google::protobuf::internal::ParseNamedEnum<$classname$>(\n" + " $classname$_descriptor(), name, value);\n" + "}\n"); + } +} + +void EnumGenerator:: +GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "template <>\n" + "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" + " return $classname$_descriptor();\n" + "}\n", + "classname", ClassName(descriptor_, true)); + } } void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { @@ -128,24 +143,28 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { } printer->Print(vars, - "static inline const ::google::protobuf::EnumDescriptor*\n" - "$nested_name$_descriptor() {\n" - " return $classname$_descriptor();\n" - "}\n" "static inline bool $nested_name$_IsValid(int value) {\n" " return $classname$_IsValid(value);\n" "}\n" - "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n" - " return $classname$_Name(value);\n" - "}\n" - "static inline bool $nested_name$_Parse(const ::std::string& name,\n" - " $nested_name$* value) {\n" - " return $classname$_Parse(name, value);\n" - "}\n" "static const $nested_name$ $nested_name$_MIN =\n" " $classname$_$nested_name$_MIN;\n" "static const $nested_name$ $nested_name$_MAX =\n" " $classname$_$nested_name$_MAX;\n"); + + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "static inline const ::google::protobuf::EnumDescriptor*\n" + "$nested_name$_descriptor() {\n" + " return $classname$_descriptor();\n" + "}\n" + "static inline const ::std::string& $nested_name$_Name($nested_name$ value) {\n" + " return $classname$_Name(value);\n" + "}\n" + "static inline bool $nested_name$_Parse(const ::std::string& name,\n" + " $nested_name$* value) {\n" + " return $classname$_Parse(name, value);\n" + "}\n"); + } } void EnumGenerator::GenerateDescriptorInitializer( @@ -168,11 +187,15 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { map<string, string> vars; vars["classname"] = classname_; + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n" + " protobuf_AssignDescriptorsOnce();\n" + " return $classname$_descriptor_;\n" + "}\n"); + } + printer->Print(vars, - "const ::google::protobuf::EnumDescriptor* $classname$_descriptor() {\n" - " protobuf_AssignDescriptorsOnce();\n" - " return $classname$_descriptor_;\n" - "}\n" "bool $classname$_IsValid(int value) {\n" " switch(value) {\n"); diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h index 9f2e5fee..58f7721e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -63,6 +63,10 @@ class EnumGenerator { // nested enums. void GenerateDefinition(io::Printer* printer); + // Generate specialization of GetEnumDescriptor<MyEnum>(). + // Precondition: in ::google::protobuf namespace. + void GenerateGetEnumDescriptorSpecializations(io::Printer* printer); + // For enums nested within a message, generate code to import all the enum's // symbols (e.g. the enum type name, all its values, etc.) into the class's // namespace. This should be placed inside the class definition in the diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index b90eb372..7ca11c8c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -35,7 +35,7 @@ #include <google/protobuf/compiler/cpp/cpp_enum_field.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format_inl.h> +#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/strutil.h> namespace google { @@ -43,24 +43,14 @@ namespace protobuf { namespace compiler { namespace cpp { -using internal::WireFormat; - namespace { -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetEnumVariables(const FieldDescriptor* descriptor, map<string, string>* variables) { + SetCommonFieldVariables(descriptor, variables); const EnumValueDescriptor* default_value = descriptor->default_value_enum(); - - (*variables)["name"] = FieldName(descriptor); (*variables)["type"] = ClassName(descriptor->enum_type(), true); (*variables)["default"] = SimpleItoa(default_value->number()); - (*variables)["index"] = SimpleItoa(descriptor->index()); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["classname"] = ClassName(FieldScope(descriptor), false); - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); } } // namespace @@ -83,8 +73,8 @@ GeneratePrivateMembers(io::Printer* printer) const { void EnumFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$() const;\n" - "inline void set_$name$($type$ value);\n"); + "inline $type$ $name$() const$deprecation$;\n" + "inline void set_$name$($type$ value)$deprecation$;\n"); } void EnumFieldGenerator:: @@ -124,33 +114,37 @@ void EnumFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, "int value;\n" - "DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n" + "DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n" "if ($type$_IsValid(value)) {\n" - " set_$name$(static_cast< $type$ >(value));\n" - "} else {\n" - " mutable_unknown_fields()->AddVarint($number$, value);\n" + " set_$name$(static_cast< $type$ >(value));\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print(variables_, + "} else {\n" + " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } + printer->Print(variables_, "}\n"); } void EnumFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::WriteEnum(" - "$number$, this->$name$(), output);\n"); + "::google::protobuf::internal::WireFormatLite::WriteEnum(\n" + " $number$, this->$name$(), output);\n"); } void EnumFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(" - "$number$, this->$name$(), target);\n"); + "target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n" + " $number$, this->$name$(), target);\n"); } void EnumFieldGenerator:: GenerateByteSize(io::Printer* printer) const { printer->Print(variables_, "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormat::EnumSize(this->$name$());\n"); + " ::google::protobuf::internal::WireFormatLite::EnumSize(this->$name$());\n"); } // =================================================================== @@ -167,8 +161,7 @@ void RepeatedEnumFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField<int> $name$_;\n"); - if (descriptor_->options().packed() && - descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); } @@ -177,11 +170,11 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField<int>& $name$() const;\n" - "inline ::google::protobuf::RepeatedField<int>* mutable_$name$();\n" - "inline $type$ $name$(int index) const;\n" - "inline void set_$name$(int index, $type$ value);\n" - "inline void add_$name$($type$ value);\n"); + "inline const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n" + "inline ::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\n" + "inline $type$ $name$(int index) const$deprecation$;\n" + "inline void set_$name$(int index, $type$ value)$deprecation$;\n" + "inline void add_$name$($type$ value)$deprecation$;\n"); } void RepeatedEnumFieldGenerator:: @@ -238,7 +231,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { "input->PushLimit(length);\n" "while (input->BytesUntilLimit() > 0) {\n" " int value;\n" - " DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n" + " DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n" " if ($type$_IsValid(value)) {\n" " add_$name$(static_cast< $type$ >(value));\n" " }\n" @@ -247,11 +240,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { } else { printer->Print(variables_, "int value;\n" - "DO_(::google::protobuf::internal::WireFormat::ReadEnum(input, &value));\n" + "DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));\n" "if ($type$_IsValid(value)) {\n" - " add_$name$(static_cast< $type$ >(value));\n" - "} else {\n" - " mutable_unknown_fields()->AddVarint($number$, value);\n" + " add_$name$(static_cast< $type$ >(value));\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print(variables_, + "} else {\n" + " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } + printer->Print(variables_, "}\n"); } } @@ -262,10 +259,10 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" - " ::google::protobuf::internal::WireFormat::WriteTag(" - "$number$, " - "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, " - "output);\n" + " ::google::protobuf::internal::WireFormatLite::WriteTag(\n" + " $number$,\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " output);\n" " output->WriteVarint32(_$name$_cached_byte_size_);\n" "}\n"); } @@ -273,12 +270,12 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { "for (int i = 0; i < this->$name$_size(); i++) {\n"); if (descriptor_->options().packed()) { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::WriteEnumNoTag(" - "this->$name$(i), output);\n"); + " ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n" + " this->$name$(i), output);\n"); } else { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::WriteEnum(" - "$number$, this->$name$(i), output);\n"); + " ::google::protobuf::internal::WireFormatLite::WriteEnum(\n" + " $number$, this->$name$(i), output);\n"); } printer->Print("}\n"); } @@ -289,24 +286,24 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" - " target = ::google::protobuf::internal::WireFormat::WriteTagToArray(" - "$number$, " - "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, " - "target);\n" + " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" + " $number$,\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " target);\n" " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(" - "_$name$_cached_byte_size_, target);\n" + " _$name$_cached_byte_size_, target);\n" "}\n"); } printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n"); if (descriptor_->options().packed()) { printer->Print(variables_, - " target = ::google::protobuf::internal::WireFormat::WriteEnumNoTagToArray(" - "this->$name$(i), target);\n"); + " target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n" + " this->$name$(i), target);\n"); } else { printer->Print(variables_, - " target = ::google::protobuf::internal::WireFormat::WriteEnumToArray(" - "$number$, this->$name$(i), target);\n"); + " target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(\n" + " $number$, this->$name$(i), target);\n"); } printer->Print("}\n"); } @@ -319,15 +316,15 @@ GenerateByteSize(io::Printer* printer) const { printer->Indent(); printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n" - " data_size += ::google::protobuf::internal::WireFormat::EnumSize(\n" + " data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n" " this->$name$(i));\n" "}\n"); if (descriptor_->options().packed()) { printer->Print(variables_, "if (data_size > 0) {\n" - " total_size += $tag_size$ + " - "::google::protobuf::internal::WireFormat::Int32Size(data_size);\n" + " total_size += $tag_size$ +\n" + " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" "}\n" "_$name$_cached_byte_size_ = data_size;\n" "total_size += data_size;\n"); diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc index cd4806ba..7208ed3a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_extension.cc +++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc @@ -133,6 +133,7 @@ void ExtensionGenerator::GenerateDefinition(io::Printer* printer) { vars["global_name"] = global_name; printer->Print(vars, "const ::std::string $global_name$_default($default$);\n"); + // Update the default to refer to the string global. vars["default"] = global_name + "_default"; } diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc index 47daac7a..c546e964 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -33,18 +33,37 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <google/protobuf/compiler/cpp/cpp_field.h> +#include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/compiler/cpp/cpp_primitive_field.h> #include <google/protobuf/compiler/cpp/cpp_string_field.h> #include <google/protobuf/compiler/cpp/cpp_enum_field.h> #include <google/protobuf/compiler/cpp/cpp_message_field.h> #include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/wire_format.h> #include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/strutil.h> namespace google { namespace protobuf { namespace compiler { namespace cpp { +using internal::WireFormat; + +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + map<string, string>* variables) { + (*variables)["name"] = FieldName(descriptor); + (*variables)["index"] = SimpleItoa(descriptor->index()); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["classname"] = ClassName(FieldScope(descriptor), false); + (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); + + (*variables)["tag_size"] = SimpleItoa( + WireFormat::TagSize(descriptor->number(), descriptor->type())); + (*variables)["deprecation"] = descriptor->options().deprecated() + ? " DEPRECATED_PROTOBUF_FIELD" : ""; +} + FieldGenerator::~FieldGenerator() {} FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index 7e7c7f83..00ec2c7c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -35,6 +35,9 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ +#include <map> +#include <string> + #include <google/protobuf/stubs/common.h> #include <google/protobuf/descriptor.h> @@ -49,6 +52,13 @@ namespace protobuf { namespace compiler { namespace cpp { +// Helper function: set variables in the map that are the same for all +// field code generators. +// ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size', +// 'deprecation']. +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + map<string, string>* variables); + class FieldGenerator { public: FieldGenerator() {} diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index f056ed57..51859bb3 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -125,13 +125,18 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { // OK, it's now safe to #include other files. printer->Print( - "#include <google/protobuf/generated_message_reflection.h>\n" + "#include <google/protobuf/generated_message_util.h>\n" "#include <google/protobuf/repeated_field.h>\n" "#include <google/protobuf/extension_set.h>\n"); - if (file_->service_count() > 0) { + if (HasDescriptorMethods(file_)) { printer->Print( - "#include <google/protobuf/service.h>\n"); + "#include <google/protobuf/generated_message_reflection.h>\n"); + + if (file_->service_count() > 0) { + printer->Print( + "#include <google/protobuf/service.h>\n"); + } } for (int i = 0; i < file_->dependency_count(); i++) { @@ -193,19 +198,21 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { printer->Print(kThickSeparator); printer->Print("\n"); - // Generate service definitions. - for (int i = 0; i < file_->service_count(); i++) { - if (i > 0) { - printer->Print("\n"); - printer->Print(kThinSeparator); - printer->Print("\n"); + if (HasDescriptorMethods(file_)) { + // Generate service definitions. + for (int i = 0; i < file_->service_count(); i++) { + if (i > 0) { + printer->Print("\n"); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + service_generators_[i]->GenerateDeclarations(printer); } - service_generators_[i]->GenerateDeclarations(printer); - } - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); + printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + } // Declare extension identifiers. for (int i = 0; i < file_->extension_count(); i++) { @@ -228,6 +235,30 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { // Close up namespace. GenerateNamespaceClosers(printer); + // Emit GetEnumDescriptor specializations into google::protobuf namespace: + if (HasDescriptorMethods(file_)) { + // The SWIG conditional is to avoid a null-pointer dereference + // (bug 1984964) in swig-1.3.21 resulting from the following syntax: + // namespace X { void Y<Z::W>(); } + // which appears in GetEnumDescriptor() specializations. + printer->Print( + "\n" + "#ifndef SWIG\n" + "namespace google {\nnamespace protobuf {\n" + "\n"); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + printer->Print( + "\n" + "} // namespace google\n} // namespace protobuf\n" + "#endif // SWIG\n" + "\n"); + } + printer->Print( "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n", "filename_identifier", filename_identifier); @@ -237,40 +268,52 @@ void FileGenerator::GenerateSource(io::Printer* printer) { printer->Print( "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" "\n" + // The generated code calls accessors that might be deprecated. We don't + // want the compiler to warn in generated code. + "#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION\n" "#include \"$basename$.pb.h\"\n" + "#include <google/protobuf/stubs/once.h>\n" - "#include <google/protobuf/descriptor.h>\n" "#include <google/protobuf/io/coded_stream.h>\n" - "#include <google/protobuf/reflection_ops.h>\n" - "#include <google/protobuf/wire_format_inl.h>\n", + "#include <google/protobuf/wire_format_lite_inl.h>\n", "basename", StripProto(file_->name())); + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include <google/protobuf/descriptor.h>\n" + "#include <google/protobuf/reflection_ops.h>\n" + "#include <google/protobuf/wire_format.h>\n"); + } + GenerateNamespaceOpeners(printer); - printer->Print( - "\n" - "namespace {\n" - "\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateDescriptorDeclarations(printer); - } - for (int i = 0; i < file_->enum_type_count(); i++) { + if (HasDescriptorMethods(file_)) { printer->Print( - "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n", - "name", ClassName(file_->enum_type(i), false)); - } - for (int i = 0; i < file_->service_count(); i++) { + "\n" + "namespace {\n" + "\n"); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateDescriptorDeclarations(printer); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + printer->Print( + "const ::google::protobuf::EnumDescriptor* $name$_descriptor_ = NULL;\n", + "name", ClassName(file_->enum_type(i), false)); + } + for (int i = 0; i < file_->service_count(); i++) { + printer->Print( + "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n", + "name", file_->service(i)->name()); + } + printer->Print( - "const ::google::protobuf::ServiceDescriptor* $name$_descriptor_ = NULL;\n", - "name", file_->service(i)->name()); + "\n" + "} // namespace\n" + "\n"); } - printer->Print( - "\n" - "} // namespace\n" - "\n"); - - // Define our externally-visible BuildDescriptors() function. + // Define our externally-visible BuildDescriptors() function. (For the lite + // library, all this does is initialize default instances.) GenerateBuildDescriptors(printer); // Generate enums. @@ -286,12 +329,14 @@ void FileGenerator::GenerateSource(io::Printer* printer) { message_generators_[i]->GenerateClassMethods(printer); } - // Generate services. - for (int i = 0; i < file_->service_count(); i++) { - if (i == 0) printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); - service_generators_[i]->GenerateImplementation(printer); + if (HasDescriptorMethods(file_)) { + // Generate services. + for (int i = 0; i < file_->service_count(); i++) { + if (i == 0) printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + service_generators_[i]->GenerateImplementation(printer); + } } // Define extensions. @@ -317,80 +362,84 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // anyone calls descriptor() or GetReflection() on one of the types defined // in the file. - printer->Print( - "\n" - "void $assigndescriptorsname$() {\n", - "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); - printer->Indent(); - - // Make sure the file has found its way into the pool. If a descriptor - // is requested *during* static init then AddDescriptors() may not have - // been called yet, so we call it manually. Note that it's fine if - // AddDescriptors() is called multiple times. - printer->Print( - "$adddescriptorsname$();\n", - "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); + // In optimize_for = LITE_RUNTIME mode, we don't generate AssignDescriptors() + // and we only use AddDescriptors() to allocate default instances. + if (HasDescriptorMethods(file_)) { + printer->Print( + "\n" + "void $assigndescriptorsname$() {\n", + "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); + printer->Indent(); + + // Make sure the file has found its way into the pool. If a descriptor + // is requested *during* static init then AddDescriptors() may not have + // been called yet, so we call it manually. Note that it's fine if + // AddDescriptors() is called multiple times. + printer->Print( + "$adddescriptorsname$();\n", + "adddescriptorsname", GlobalAddDescriptorsName(file_->name())); - // Get the file's descriptor from the pool. - printer->Print( - "const ::google::protobuf::FileDescriptor* file =\n" - " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n" - " \"$filename$\");\n" - // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file" - // being unused when compiling an empty .proto file. - "GOOGLE_CHECK(file != NULL);\n", - "filename", file_->name()); - - // Go through all the stuff defined in this file and generated code to - // assign the global descriptor pointers based on the file descriptor. - for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateDescriptorInitializer(printer, i); - } - for (int i = 0; i < file_->enum_type_count(); i++) { - enum_generators_[i]->GenerateDescriptorInitializer(printer, i); - } - for (int i = 0; i < file_->service_count(); i++) { - service_generators_[i]->GenerateDescriptorInitializer(printer, i); - } + // Get the file's descriptor from the pool. + printer->Print( + "const ::google::protobuf::FileDescriptor* file =\n" + " ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(\n" + " \"$filename$\");\n" + // Note that this GOOGLE_CHECK is necessary to prevent a warning about "file" + // being unused when compiling an empty .proto file. + "GOOGLE_CHECK(file != NULL);\n", + "filename", file_->name()); + + // Go through all the stuff defined in this file and generated code to + // assign the global descriptor pointers based on the file descriptor. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateDescriptorInitializer(printer, i); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDescriptorInitializer(printer, i); + } + for (int i = 0; i < file_->service_count(); i++) { + service_generators_[i]->GenerateDescriptorInitializer(printer, i); + } - printer->Outdent(); - printer->Print( - "}\n" - "\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); - // ----------------------------------------------------------------- + // --------------------------------------------------------------- - // protobuf_AssignDescriptorsOnce(): The first time it is called, calls - // AssignDescriptors(). All later times, waits for the first call to - // complete and then returns. - printer->Print( - "namespace {\n" - "\n" - "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n" - "inline void protobuf_AssignDescriptorsOnce() {\n" - " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n" - " &$assigndescriptorsname$);\n" - "}\n" - "\n", - "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); + // protobuf_AssignDescriptorsOnce(): The first time it is called, calls + // AssignDescriptors(). All later times, waits for the first call to + // complete and then returns. + printer->Print( + "namespace {\n" + "\n" + "GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);\n" + "inline void protobuf_AssignDescriptorsOnce() {\n" + " ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,\n" + " &$assigndescriptorsname$);\n" + "}\n" + "\n", + "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); + + // protobuf_RegisterTypes(): Calls + // MessageFactory::InternalRegisterGeneratedType() for each message type. + printer->Print( + "void protobuf_RegisterTypes(const ::std::string&) {\n" + " protobuf_AssignDescriptorsOnce();\n"); + printer->Indent(); - // protobuf_RegisterTypes(): Calls - // MessageFactory::InternalRegisterGeneratedType() for each message type. - printer->Print( - "void protobuf_RegisterTypes() {\n" - " protobuf_AssignDescriptorsOnce();\n"); - printer->Indent(); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateTypeRegistrations(printer); + } - for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateTypeRegistrations(printer); + printer->Outdent(); + printer->Print( + "}\n" + "\n" + "} // namespace\n"); } - printer->Outdent(); - printer->Print( - "}\n" - "\n" - "} // namespace\n"); - // ----------------------------------------------------------------- // ShutdownFile(): Deletes descriptors, default instances, etc. on shutdown. @@ -442,32 +491,34 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { "name", GlobalAddDescriptorsName(dependency->name())); } - // Embed the descriptor. We simply serialize the entire FileDescriptorProto - // and embed it as a string literal, which is parsed and built into real - // descriptors at initialization time. - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); - string file_data; - file_proto.SerializeToString(&file_data); + if (HasDescriptorMethods(file_)) { + // Embed the descriptor. We simply serialize the entire FileDescriptorProto + // and embed it as a string literal, which is parsed and built into real + // descriptors at initialization time. + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + string file_data; + file_proto.SerializeToString(&file_data); - printer->Print( - "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); + printer->Print( + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); - // Only write 40 bytes per line. - static const int kBytesPerLine = 40; - for (int i = 0; i < file_data.size(); i += kBytesPerLine) { - printer->Print("\n \"$data$\"", - "data", CEscape(file_data.substr(i, kBytesPerLine))); - } - printer->Print( - ", $size$);\n", - "size", SimpleItoa(file_data.size())); + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + printer->Print("\n \"$data$\"", + "data", CEscape(file_data.substr(i, kBytesPerLine))); + } + printer->Print( + ", $size$);\n", + "size", SimpleItoa(file_data.size())); - // Call MessageFactory::InternalRegisterGeneratedFile(). - printer->Print( - "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n" - " \"$filename$\", &protobuf_RegisterTypes);\n", - "filename", file_->name()); + // Call MessageFactory::InternalRegisterGeneratedFile(). + printer->Print( + "::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(\n" + " \"$filename$\", &protobuf_RegisterTypes);\n", + "filename", file_->name()); + } // Allocate and initialize default instances. This can't be done lazily // since default instances are returned by simple accessors and are used with diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index f3515255..d67d3504 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -42,39 +42,12 @@ #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/descriptor.pb.h> -#include <google/protobuf/stubs/strutil.h> namespace google { namespace protobuf { namespace compiler { namespace cpp { -namespace { - -// Parses a set of comma-delimited name/value pairs, e.g.: -// "foo=bar,baz,qux=corge" -// parses to the pairs: -// ("foo", "bar"), ("baz", ""), ("qux", "corge") -void ParseOptions(const string& text, vector<pair<string, string> >* output) { - vector<string> parts; - SplitStringUsing(text, ",", &parts); - - for (int i = 0; i < parts.size(); i++) { - string::size_type equals_pos = parts[i].find_first_of('='); - pair<string, string> value; - if (equals_pos == string::npos) { - value.first = parts[i]; - value.second = ""; - } else { - value.first = parts[i].substr(0, equals_pos); - value.second = parts[i].substr(equals_pos + 1); - } - output->push_back(value); - } -} - -} // namespace - CppGenerator::CppGenerator() {} CppGenerator::~CppGenerator() {} @@ -83,7 +56,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, OutputDirectory* output_directory, string* error) const { vector<pair<string, string> > options; - ParseOptions(parameter, &options); + ParseGeneratorParameter(parameter, &options); // ----------------------------------------------------------------- // parse generator options diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 595aeaeb..723a8b45 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -152,7 +152,18 @@ string FieldName(const FieldDescriptor* field) { string FieldConstantName(const FieldDescriptor *field) { string field_name = UnderscoresToCamelCase(field->name(), true); - return "k" + field_name + "FieldNumber"; + string result = "k" + field_name + "FieldNumber"; + + if (!field->is_extension() && + field->containing_type()->FindFieldByCamelcaseName( + field->camelcase_name()) != field) { + // This field's camelcase name is not unique. As a hack, add the field + // number to the constant name. This makes the constant rather useless, + // but what can we do? + result += "_" + SimpleItoa(field->number()); + } + + return result; } string StripProto(const string& filename) { diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 55fd7e29..83e12501 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -37,6 +37,7 @@ #include <string> #include <google/protobuf/descriptor.h> +#include <google/protobuf/descriptor.pb.h> namespace google { namespace protobuf { @@ -105,6 +106,34 @@ string GlobalAssignDescriptorsName(const string& filename); // Return the name of the ShutdownFile() function for a given file. string GlobalShutdownFileName(const string& filename); +// Do message classes in this file keep track of unknown fields? +inline const bool HasUnknownFields(const FileDescriptor *file) { + return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +} + +// Does this file have generated parsing, serialization, and other +// standard methods for which reflection-based fallback implementations exist? +inline const bool HasGeneratedMethods(const FileDescriptor *file) { + return file->options().optimize_for() != FileOptions::CODE_SIZE; +} + +// Do message classes in this file have descriptor and refelction methods? +inline const bool HasDescriptorMethods(const FileDescriptor *file) { + return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +} + +// Should string fields in this file verify that their contents are UTF-8? +inline const bool HasUtf8Verification(const FileDescriptor* file) { + return file->options().optimize_for() != FileOptions::LITE_RUNTIME; +} + +// Should we generate a separate, super-optimized code path for serializing to +// flat arrays? We don't do this in Lite mode because we'd rather reduce code +// size. +inline const bool HasFastArraySerialization(const FileDescriptor* file) { + return file->options().optimize_for() == FileOptions::SPEED; +} + } // 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 9852ee91..ae243dd9 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -34,14 +34,17 @@ #include <algorithm> #include <google/protobuf/stubs/hash.h> +#include <map> +#include <vector> #include <google/protobuf/compiler/cpp/cpp_message.h> +#include <google/protobuf/compiler/cpp/cpp_field.h> #include <google/protobuf/compiler/cpp/cpp_enum.h> #include <google/protobuf/compiler/cpp/cpp_extension.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/wire_format_inl.h> +#include <google/protobuf/wire_format.h> #include <google/protobuf/descriptor.pb.h> namespace google { @@ -50,6 +53,7 @@ namespace compiler { namespace cpp { using internal::WireFormat; +using internal::WireFormatLite; namespace { @@ -196,6 +200,16 @@ GenerateEnumDefinitions(io::Printer* printer) { } void MessageGenerator:: +GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } +} + +void MessageGenerator:: GenerateFieldAccessorDeclarations(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); @@ -203,17 +217,16 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { PrintFieldComment(printer, field); map<string, string> vars; - vars["name"] = FieldName(field); + SetCommonFieldVariables(field, &vars); vars["constant_name"] = FieldConstantName(field); - vars["number"] = SimpleItoa(field->number()); if (field->is_repeated()) { - printer->Print(vars, "inline int $name$_size() const;\n"); + printer->Print(vars, "inline int $name$_size() const$deprecation$;\n"); } else { - printer->Print(vars, "inline bool has_$name$() const;\n"); + printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n"); } - printer->Print(vars, "inline void clear_$name$();\n"); + printer->Print(vars, "inline void clear_$name$()$deprecation$;\n"); printer->Print(vars, "static const int $constant_name$ = $number$;\n"); // Generate type-specific accessor declarations. @@ -241,9 +254,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { PrintFieldComment(printer, field); map<string, string> vars; - vars["name"] = FieldName(field); - vars["index"] = SimpleItoa(field->index()); - vars["classname"] = classname_; + SetCommonFieldVariables(field, &vars); // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { @@ -297,9 +308,11 @@ GenerateClassDefinition(io::Printer* printer) { } else { vars["dllexport"] = dllexport_decl_ + " "; } + vars["superclass"] = HasDescriptorMethods(descriptor_->file()) ? + "Message" : "MessageLite"; printer->Print(vars, - "class $dllexport$$classname$ : public ::google::protobuf::Message {\n" + "class $dllexport$$classname$ : public ::google::protobuf::$superclass$ {\n" " public:\n"); printer->Indent(); @@ -313,16 +326,28 @@ GenerateClassDefinition(io::Printer* printer) { " CopyFrom(from);\n" " return *this;\n" "}\n" - "\n" - "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" - "static const ::google::protobuf::Descriptor* descriptor();\n" + "\n"); + + if (HasUnknownFields(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"); + } + + // Only generate this member if it's not disabled. + if (HasDescriptorMethods(descriptor_->file()) && + !descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print(vars, + "static const ::google::protobuf::Descriptor* descriptor();\n"); + } + + printer->Print(vars, "static const $classname$& default_instance();\n" "void Swap($classname$* other);\n" "\n" @@ -330,28 +355,29 @@ GenerateClassDefinition(io::Printer* printer) { "\n" "$classname$* New() const;\n"); - if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (HasGeneratedMethods(descriptor_->file())) { + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(vars, + "void CopyFrom(const ::google::protobuf::Message& from);\n" + "void MergeFrom(const ::google::protobuf::Message& from);\n"); + } else { + printer->Print(vars, + "void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);\n"); + } + printer->Print(vars, - "void CopyFrom(const ::google::protobuf::Message& from);\n" - "void MergeFrom(const ::google::protobuf::Message& from);\n" "void CopyFrom(const $classname$& from);\n" "void MergeFrom(const $classname$& from);\n" "void Clear();\n" - "bool IsInitialized() const;\n"); - - if (!descriptor_->options().message_set_wire_format()) { - // For message_set_wire_format, we don't generate parsing or - // serialization code even if optimize_for = SPEED, since MessageSet - // encoding is somewhat more complicated than normal extension encoding - // and we'd like to avoid having to implement it in multiple places. - // WireFormat's implementation is probably good enough. - printer->Print(vars, - "\n" - "int ByteSize() const;\n" - "bool MergePartialFromCodedStream(\n" - " ::google::protobuf::io::CodedInputStream* input);\n" - "void SerializeWithCachedSizes(\n" - " ::google::protobuf::io::CodedOutputStream* output) const;\n" + "bool IsInitialized() const;\n" + "\n" + "int ByteSize() const;\n" + "bool MergePartialFromCodedStream(\n" + " ::google::protobuf::io::CodedInputStream* input);\n" + "void SerializeWithCachedSizes(\n" + " ::google::protobuf::io::CodedOutputStream* output) const;\n"); + if (HasFastArraySerialization(descriptor_->file())) { + printer->Print( "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n"); } } @@ -363,10 +389,19 @@ GenerateClassDefinition(io::Printer* printer) { "void SharedDtor();\n" "void SetCachedSize(int size) const { _cached_size_ = size; }\n" "public:\n" - "\n" - "const ::google::protobuf::Descriptor* GetDescriptor() const;\n" - "const ::google::protobuf::Reflection* GetReflection() const;\n" - "\n" + "\n"); + + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "::google::protobuf::Metadata GetMetadata() const;\n" + "\n"); + } else { + printer->Print( + "::std::string GetTypeName() const;\n" + "\n"); + } + + printer->Print( "// nested types ----------------------------------------------------\n" "\n"); @@ -411,9 +446,13 @@ GenerateClassDefinition(io::Printer* printer) { "::google::protobuf::internal::ExtensionSet _extensions_;\n"); } + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "::google::protobuf::UnknownFieldSet _unknown_fields_;\n"); + } + // TODO(kenton): Make _cached_size_ an atomic<int> when C++ supports it. printer->Print( - "::google::protobuf::UnknownFieldSet _unknown_fields_;\n" "mutable int _cached_size_;\n" "\n"); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -431,7 +470,8 @@ GenerateClassDefinition(io::Printer* printer) { GlobalAddDescriptorsName(descriptor_->file()->name())); printer->Print( "friend void $assigndescriptorsname$();\n" - "friend void $shutdownfilename$();\n", + "friend void $shutdownfilename$();\n" + "\n", "assigndescriptorsname", GlobalAssignDescriptorsName(descriptor_->file()->name()), "shutdownfilename", GlobalShutdownFileName(descriptor_->file()->name())); @@ -605,10 +645,15 @@ GenerateDefaultInstanceInitializer(io::Printer* printer) { void MessageGenerator:: GenerateShutdownCode(io::Printer* printer) { printer->Print( - "delete $classname$::default_instance_;\n" - "delete $classname$_reflection_;\n", + "delete $classname$::default_instance_;\n", "classname", classname_); + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "delete $classname$_reflection_;\n", + "classname", classname_); + } + // Handle nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateShutdownCode(printer); @@ -655,29 +700,24 @@ GenerateClassMethods(io::Printer* printer) { GenerateStructors(printer); printer->Print("\n"); - if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (HasGeneratedMethods(descriptor_->file())) { GenerateClear(printer); printer->Print("\n"); - if (!descriptor_->options().message_set_wire_format()) { - // For message_set_wire_format, we don't generate parsing or - // serialization code even if optimize_for = SPEED, since MessageSet - // encoding is somewhat more complicated than normal extension encoding - // and we'd like to avoid having to implement it in multiple places. - // WireFormat's implementation is probably good enough. - GenerateMergeFromCodedStream(printer); - printer->Print("\n"); + GenerateMergeFromCodedStream(printer); + printer->Print("\n"); - GenerateSerializeWithCachedSizes(printer); - printer->Print("\n"); + GenerateSerializeWithCachedSizes(printer); + printer->Print("\n"); + if (HasFastArraySerialization(descriptor_->file())) { GenerateSerializeWithCachedSizesToArray(printer); printer->Print("\n"); - - GenerateByteSize(printer); - printer->Print("\n"); } + GenerateByteSize(printer); + printer->Print("\n"); + GenerateMergeFrom(printer); printer->Print("\n"); @@ -691,16 +731,26 @@ GenerateClassMethods(io::Printer* printer) { GenerateSwap(printer); printer->Print("\n"); - printer->Print( - "const ::google::protobuf::Descriptor* $classname$::GetDescriptor() const {\n" - " return descriptor();\n" - "}\n" - "\n" - "const ::google::protobuf::Reflection* $classname$::GetReflection() const {\n" - " protobuf_AssignDescriptorsOnce();\n" - " return $classname$_reflection_;\n" - "}\n", - "classname", classname_); + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "::google::protobuf::Metadata $classname$::GetMetadata() const {\n" + " protobuf_AssignDescriptorsOnce();\n" + " ::google::protobuf::Metadata metadata;\n" + " metadata.descriptor = $classname$_descriptor_;\n" + " metadata.reflection = $classname$_reflection_;\n" + " return metadata;\n" + "}\n" + "\n", + "classname", classname_); + } else { + printer->Print( + "::std::string $classname$::GetTypeName() const {\n" + " return \"$type_name$\";\n" + "}\n" + "\n", + "classname", classname_, + "type_name", descriptor_->full_name()); + } } void MessageGenerator:: @@ -724,18 +774,6 @@ GenerateOffsets(io::Printer* printer) { } void MessageGenerator:: -GenerateInitializerList(io::Printer* printer) { - printer->Indent(); - printer->Indent(); - - printer->Print( - "::google::protobuf::Message()"); - - printer->Outdent(); - printer->Outdent(); -} - -void MessageGenerator:: GenerateSharedConstructorCode(io::Printer* printer) { printer->Print( "void $classname$::SharedCtor() {\n", @@ -797,17 +835,14 @@ void MessageGenerator:: GenerateStructors(io::Printer* printer) { // Generate the default constructor. printer->Print( - "$classname$::$classname$()\n" - " : ", - "classname", classname_); - GenerateInitializerList(printer); - printer->Print(" {\n" + "$classname$::$classname$() {\n" " SharedCtor();\n" - "}\n"); + "}\n", + "classname", classname_); printer->Print( "\n" - "void $classname$::InitAsDefaultInstance() {", + "void $classname$::InitAsDefaultInstance() {\n", "classname", classname_); // The default instance needs all of its embedded message pointers @@ -833,15 +868,12 @@ GenerateStructors(io::Printer* printer) { // Generate the copy constructor. printer->Print( - "$classname$::$classname$(const $classname$& from)\n" - " : ", - "classname", classname_); - GenerateInitializerList(printer); - printer->Print(" {\n" + "$classname$::$classname$(const $classname$& from) {\n" " SharedCtor();\n" " MergeFrom(from);\n" "}\n" - "\n"); + "\n", + "classname", classname_); // Generate the shared constructor code. GenerateSharedConstructorCode(printer); @@ -857,12 +889,21 @@ GenerateStructors(io::Printer* printer) { // Generate the shared destructor code. GenerateSharedDestructorCode(printer); + // Only generate this member if it's not disabled. + if (HasDescriptorMethods(descriptor_->file()) && + !descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print( + "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" + " protobuf_AssignDescriptorsOnce();\n" + " return $classname$_descriptor_;\n" + "}\n" + "\n", + "classname", classname_, + "adddescriptorsname", + GlobalAddDescriptorsName(descriptor_->file()->name())); + } + printer->Print( - "const ::google::protobuf::Descriptor* $classname$::descriptor() {\n" - " protobuf_AssignDescriptorsOnce();\n" - " return $classname$_descriptor_;\n" - "}\n" - "\n" "const $classname$& $classname$::default_instance() {\n" " if (default_instance_ == NULL) $adddescriptorsname$();" " return *default_instance_;\n" @@ -951,8 +992,12 @@ GenerateClear(io::Printer* printer) { } printer->Print( - "::memset(_has_bits_, 0, sizeof(_has_bits_));\n" - "mutable_unknown_fields()->Clear();\n"); + "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); + + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "mutable_unknown_fields()->Clear();\n"); + } printer->Outdent(); printer->Print("}\n"); @@ -967,7 +1012,7 @@ GenerateSwap(io::Printer* printer) { printer->Print("if (other != this) {\n"); printer->Indent(); - if ( descriptor_->file()->options().optimize_for() == FileOptions::SPEED ) { + if (HasGeneratedMethods(descriptor_->file())) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); field_generators_.get(field).GenerateSwappingCode(printer); @@ -978,7 +1023,9 @@ GenerateSwap(io::Printer* printer) { "i", SimpleItoa(i)); } - printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); + } printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); if (descriptor_->extension_range_count() > 0) { printer->Print("_extensions_.Swap(&other->_extensions_);\n"); @@ -987,7 +1034,6 @@ GenerateSwap(io::Printer* printer) { printer->Print("GetReflection()->Swap(this, other);"); } - printer->Outdent(); printer->Print("}\n"); printer->Outdent(); @@ -996,31 +1042,42 @@ GenerateSwap(io::Printer* printer) { void MessageGenerator:: GenerateMergeFrom(io::Printer* printer) { - // Generate the generalized MergeFrom (aka that which takes in the Message - // base class as a parameter). - printer->Print( - "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n" - " GOOGLE_CHECK_NE(&from, this);\n", - "classname", classname_); - printer->Indent(); + if (HasDescriptorMethods(descriptor_->file())) { + // Generate the generalized MergeFrom (aka that which takes in the Message + // base class as a parameter). + printer->Print( + "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n" + " GOOGLE_CHECK_NE(&from, this);\n", + "classname", classname_); + printer->Indent(); - // Cast the message to the proper type. If we find that the message is - // *not* of the proper type, we can still call Merge via the reflection - // system, as the GOOGLE_CHECK above ensured that we have the same descriptor - // for each message. - printer->Print( - "const $classname$* source =\n" - " ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n" - " &from);\n" - "if (source == NULL) {\n" - " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" - "} else {\n" - " MergeFrom(*source);\n" - "}\n", - "classname", classname_); + // Cast the message to the proper type. If we find that the message is + // *not* of the proper type, we can still call Merge via the reflection + // system, as the GOOGLE_CHECK above ensured that we have the same descriptor + // for each message. + printer->Print( + "const $classname$* source =\n" + " ::google::protobuf::internal::dynamic_cast_if_available<const $classname$*>(\n" + " &from);\n" + "if (source == NULL) {\n" + " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" + "} else {\n" + " MergeFrom(*source);\n" + "}\n", + "classname", classname_); - printer->Outdent(); - printer->Print("}\n\n"); + printer->Outdent(); + printer->Print("}\n\n"); + } else { + // Generate CheckTypeAndMergeFrom(). + printer->Print( + "void $classname$::CheckTypeAndMergeFrom(\n" + " const ::google::protobuf::MessageLite& from) {\n" + " MergeFrom(*::google::protobuf::down_cast<const $classname$*>(&from));\n" + "}\n" + "\n", + "classname", classname_); + } // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast. printer->Print( @@ -1082,8 +1139,10 @@ GenerateMergeFrom(io::Printer* printer) { printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); } - printer->Print( - "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"); + } printer->Outdent(); printer->Print("}\n"); @@ -1091,20 +1150,22 @@ GenerateMergeFrom(io::Printer* printer) { void MessageGenerator:: GenerateCopyFrom(io::Printer* printer) { - // Generate the generalized CopyFrom (aka that which takes in the Message - // base class as a parameter). - printer->Print( - "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n", - "classname", classname_); - printer->Indent(); + if (HasDescriptorMethods(descriptor_->file())) { + // Generate the generalized CopyFrom (aka that which takes in the Message + // base class as a parameter). + printer->Print( + "void $classname$::CopyFrom(const ::google::protobuf::Message& from) {\n", + "classname", classname_); + printer->Indent(); - printer->Print( - "if (&from == this) return;\n" - "Clear();\n" - "MergeFrom(from);\n"); + printer->Print( + "if (&from == this) return;\n" + "Clear();\n" + "MergeFrom(from);\n"); - printer->Outdent(); - printer->Print("}\n\n"); + printer->Outdent(); + printer->Print("}\n\n"); + } // Generate the class-specific CopyFrom. printer->Print( @@ -1123,6 +1184,18 @@ GenerateCopyFrom(io::Printer* printer) { void MessageGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "bool $classname$::MergePartialFromCodedStream(\n" + " ::google::protobuf::io::CodedInputStream* input) {\n" + " return _extensions_.ParseMessageSet(input, default_instance_,\n" + " mutable_unknown_fields());\n" + "}\n", + "classname", classname_); + return; + } + printer->Print( "bool $classname$::MergePartialFromCodedStream(\n" " ::google::protobuf::io::CodedInputStream* input) {\n" @@ -1144,7 +1217,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // creates a jump table that is 8x larger and sparser, and meanwhile the // if()s are highly predictable. printer->Print( - "switch (::google::protobuf::internal::WireFormat::GetTagFieldNumber(tag)) {\n"); + "switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n"); printer->Indent(); @@ -1158,8 +1231,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print( "case $number$: {\n" - " if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) !=\n" - " ::google::protobuf::internal::WireFormat::WIRETYPE_$wiretype$) {\n" + " if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n" " goto handle_uninterpreted;\n" " }\n", "number", SimpleItoa(field->number()), @@ -1214,8 +1287,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // Is this an end-group tag? If so, this must be the end of the message. printer->Print( - "if (::google::protobuf::internal::WireFormat::GetTagWireType(tag) ==\n" - " ::google::protobuf::internal::WireFormat::WIRETYPE_END_GROUP) {\n" + "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n" " return true;\n" "}\n"); @@ -1228,10 +1301,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) { descriptor_->extension_range(i); if (i > 0) printer->Print(" ||\n "); - uint32 start_tag = WireFormat::MakeTag( - range->start, static_cast<WireFormat::WireType>(0)); - uint32 end_tag = WireFormat::MakeTag( - range->end, static_cast<WireFormat::WireType>(0)); + uint32 start_tag = WireFormatLite::MakeTag( + range->start, static_cast<WireFormatLite::WireType>(0)); + uint32 end_tag = WireFormatLite::MakeTag( + range->end, static_cast<WireFormatLite::WireType>(0)); if (range->end > FieldDescriptor::kMaxNumber) { printer->Print( @@ -1244,17 +1317,29 @@ GenerateMergeFromCodedStream(io::Printer* printer) { "end", SimpleItoa(end_tag)); } } - printer->Print(") {\n" - " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" - " mutable_unknown_fields()));\n" + printer->Print(") {\n"); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" + " mutable_unknown_fields()));\n"); + } else { + printer->Print( + " DO_(_extensions_.ParseField(tag, input, default_instance_));\n"); + } + printer->Print( " continue;\n" "}\n"); } // We really don't recognize this tag. Skip it. - printer->Print( - "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" - " input, tag, mutable_unknown_fields()));\n"); + if (HasUnknownFields(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(input, tag));\n"); + } if (descriptor_->field_count() > 0) { printer->Print("break;\n"); @@ -1319,21 +1404,41 @@ void MessageGenerator::GenerateSerializeOneExtensionRange( void MessageGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "void $classname$::SerializeWithCachedSizes(\n" + " ::google::protobuf::io::CodedOutputStream* output) const {\n" + " _extensions_.SerializeMessageSetWithCachedSizes(output);\n", + "classname", classname_); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" + " unknown_fields(), output);\n"); + } + printer->Print( + "}\n"); + return; + } + printer->Print( "void $classname$::SerializeWithCachedSizes(\n" " ::google::protobuf::io::CodedOutputStream* output) const {\n", "classname", classname_); printer->Indent(); - printer->Print( - "::google::protobuf::uint8* raw_buffer = " - "output->GetDirectBufferForNBytesAndAdvance(_cached_size_);\n" - "if (raw_buffer != NULL) {\n" - " $classname$::SerializeWithCachedSizesToArray(raw_buffer);\n" - " return;\n" - "}\n" - "\n", - "classname", classname_); + if (HasFastArraySerialization(descriptor_->file())) { + printer->Print( + "::google::protobuf::uint8* raw_buffer = " + "output->GetDirectBufferForNBytesAndAdvance(_cached_size_);\n" + "if (raw_buffer != NULL) {\n" + " $classname$::SerializeWithCachedSizesToArray(raw_buffer);\n" + " return;\n" + "}\n" + "\n", + "classname", classname_); + } + GenerateSerializeWithCachedSizesBody(printer, false); printer->Outdent(); @@ -1343,6 +1448,26 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) { void MessageGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n" + " ::google::protobuf::uint8* target) const {\n" + " target =\n" + " _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n", + "classname", classname_); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " target = ::google::protobuf::internal::WireFormat::\n" + " SerializeUnknownMessageSetItemsToArray(\n" + " unknown_fields(), target);\n"); + } + printer->Print( + " return target;\n" + "}\n"); + return; + } + printer->Print( "::google::protobuf::uint8* $classname$::SerializeWithCachedSizesToArray(\n" " ::google::protobuf::uint8* target) const {\n", @@ -1389,26 +1514,46 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { } } - printer->Print("if (!unknown_fields().empty()) {\n"); - printer->Indent(); - if (to_array) { - printer->Print( - "target = " - "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n" - " unknown_fields(), target);\n"); - } else { + if (HasUnknownFields(descriptor_->file())) { + printer->Print("if (!unknown_fields().empty()) {\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( - "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n" - " unknown_fields(), output);\n"); + "}\n"); } - printer->Outdent(); - - printer->Print( - "}\n"); } void MessageGenerator:: GenerateByteSize(io::Printer* printer) { + if (descriptor_->options().message_set_wire_format()) { + // Special-case MessageSet. + printer->Print( + "int $classname$::ByteSize() const {\n" + " int total_size = _extensions_.MessageSetByteSize();\n", + "classname", classname_); + if (HasUnknownFields(descriptor_->file())) { + printer->Print( + " total_size += ::google::protobuf::internal::WireFormat::\n" + " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"); + } + printer->Print( + " _cached_size_ = total_size;\n" + " return total_size;\n" + "}\n"); + return; + } + printer->Print( "int $classname$::ByteSize() const {\n", "classname", classname_); @@ -1478,14 +1623,16 @@ GenerateByteSize(io::Printer* printer) { "\n"); } - 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"); + if (HasUnknownFields(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"); + } // We update _cached_size_ even though this is a const method. In theory, // this is not thread-compatible, because concurrent writes have undefined diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index 105574a7..f1c57141 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -69,6 +69,10 @@ class MessageGenerator { // definitions because those classes use the enums definitions). void GenerateEnumDefinitions(io::Printer* printer); + // Generate specializations of GetEnumDescriptor<MyEnum>(). + // Precondition: in ::google::protobuf namespace. + void GenerateGetEnumDescriptorSpecializations(io::Printer* printer); + // Generate definitions for this class and all its nested types. void GenerateClassDefinition(io::Printer* printer); @@ -125,11 +129,6 @@ class MessageGenerator { // Generate the shared destructor code. void GenerateSharedDestructorCode(io::Printer* printer); - // Generate the member initializer list for the constructors. The member - // initializer list is shared between the default constructor and the copy - // constructor. - void GenerateInitializerList(io::Printer* printer); - // Generate standard Message methods. void GenerateClear(io::Printer* printer); void GenerateMergeFromCodedStream(io::Printer* printer); diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index 2a7eb3f8..059fba6e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -35,7 +35,6 @@ #include <google/protobuf/compiler/cpp/cpp_message_field.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format_inl.h> #include <google/protobuf/stubs/strutil.h> namespace google { @@ -43,22 +42,12 @@ namespace protobuf { namespace compiler { namespace cpp { -using internal::WireFormat; - namespace { -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetMessageVariables(const FieldDescriptor* descriptor, map<string, string>* variables) { - (*variables)["name"] = FieldName(descriptor); + SetCommonFieldVariables(descriptor, variables); (*variables)["type"] = ClassName(descriptor->message_type(), true); - (*variables)["index"] = SimpleItoa(descriptor->index()); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["classname"] = ClassName(FieldScope(descriptor), false); - (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); } } // namespace @@ -81,8 +70,8 @@ GeneratePrivateMembers(io::Printer* printer) const { void MessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const $type$& $name$() const;\n" - "inline $type$* mutable_$name$();\n"); + "inline const $type$& $name$() const$deprecation$;\n" + "inline $type$* mutable_$name$()$deprecation$;\n"); } void MessageFieldGenerator:: @@ -124,35 +113,35 @@ void MessageFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n" + "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" " input, mutable_$name$()));\n"); } else { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::ReadGroupNoVirtual(" - "$number$, input, mutable_$name$()));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" + " $number$, input, mutable_$name$()));\n"); } } void MessageFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual(" - "$number$, this->$name$(), output);\n"); + "::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n" + " $number$, this->$name$(), output);\n"); } void MessageFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormat::" - "Write$declared_type$NoVirtualToArray(" - "$number$, this->$name$(), target);\n"); + "target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$NoVirtualToArray(\n" + " $number$, this->$name$(), target);\n"); } void MessageFieldGenerator:: GenerateByteSize(io::Printer* printer) const { printer->Print(variables_, "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n" + " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" " this->$name$());\n"); } @@ -175,11 +164,13 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedMessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< $type$ >& $name$() const;\n" - "inline ::google::protobuf::RepeatedPtrField< $type$ >* mutable_$name$();\n" - "inline const $type$& $name$(int index) const;\n" - "inline $type$* mutable_$name$(int index);\n" - "inline $type$* add_$name$();\n"); + "inline const ::google::protobuf::RepeatedPtrField< $type$ >& $name$() const" + "$deprecation$;\n" + "inline ::google::protobuf::RepeatedPtrField< $type$ >* mutable_$name$()" + "$deprecation$;\n" + "inline const $type$& $name$(int index) const$deprecation$;\n" + "inline $type$* mutable_$name$(int index)$deprecation$;\n" + "inline $type$* add_$name$()$deprecation$;\n"); } void RepeatedMessageFieldGenerator:: @@ -228,12 +219,12 @@ void RepeatedMessageFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::ReadMessageNoVirtual(\n" - " input, add_$name$()));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" + " input, add_$name$()));\n"); } else { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::ReadGroupNoVirtual(" - "$number$, input, add_$name$()));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" + " $number$, input, add_$name$()));\n"); } } @@ -241,8 +232,8 @@ void RepeatedMessageFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n" - " ::google::protobuf::internal::WireFormat::Write$declared_type$NoVirtual(" - "$number$, this->$name$(i), output);\n" + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoVirtual(\n" + " $number$, this->$name$(i), output);\n" "}\n"); } @@ -250,9 +241,9 @@ void RepeatedMessageFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n" - " target = ::google::protobuf::internal::WireFormat::" - "Write$declared_type$NoVirtualToArray(" - "$number$, this->$name$(i), target);\n" + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$NoVirtualToArray(\n" + " $number$, this->$name$(i), target);\n" "}\n"); } @@ -262,7 +253,7 @@ GenerateByteSize(io::Printer* printer) const { "total_size += $tag_size$ * this->$name$_size();\n" "for (int i = 0; i < this->$name$_size(); i++) {\n" " total_size +=\n" - " ::google::protobuf::internal::WireFormat::$declared_type$SizeNoVirtual(\n" + " ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n" " this->$name$(i));\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index 44d0b97c..81f5ce07 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -35,7 +35,7 @@ #include <google/protobuf/compiler/cpp/cpp_primitive_field.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format_inl.h> +#include <google/protobuf/wire_format.h> #include <google/protobuf/stubs/strutil.h> namespace google { @@ -43,7 +43,7 @@ namespace protobuf { namespace compiler { namespace cpp { -using internal::WireFormat; +using internal::WireFormatLite; namespace { @@ -57,14 +57,14 @@ int FixedSize(FieldDescriptor::Type type) { case FieldDescriptor::TYPE_UINT64 : return -1; case FieldDescriptor::TYPE_SINT32 : return -1; case FieldDescriptor::TYPE_SINT64 : return -1; - case FieldDescriptor::TYPE_FIXED32 : return WireFormat::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64 : return WireFormat::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: return WireFormat::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: return WireFormat::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT : return WireFormat::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE : return WireFormat::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL : return WireFormat::kBoolSize; + case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; case FieldDescriptor::TYPE_ENUM : return -1; case FieldDescriptor::TYPE_STRING : return -1; @@ -79,20 +79,11 @@ int FixedSize(FieldDescriptor::Type type) { return -1; } -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetPrimitiveVariables(const FieldDescriptor* descriptor, map<string, string>* variables) { - (*variables)["name"] = FieldName(descriptor); + SetCommonFieldVariables(descriptor, variables); (*variables)["type"] = PrimitiveTypeName(descriptor->cpp_type()); (*variables)["default"] = DefaultValue(descriptor); - (*variables)["index"] = SimpleItoa(descriptor->index()); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["classname"] = ClassName(FieldScope(descriptor), false); - (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); - int fixed_size = FixedSize(descriptor->type()); if (fixed_size != -1) { (*variables)["fixed_size"] = SimpleItoa(fixed_size); @@ -119,8 +110,8 @@ GeneratePrivateMembers(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$() const;\n" - "inline void set_$name$($type$ value);\n"); + "inline $type$ $name$() const$deprecation$;\n" + "inline void set_$name$($type$ value)$deprecation$;\n"); } void PrimitiveFieldGenerator:: @@ -158,7 +149,7 @@ GenerateConstructorCode(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n" + "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" " input, &$name$_));\n" "_set_bit($index$);\n"); } @@ -166,14 +157,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::Write$declared_type$(" + "::google::protobuf::internal::WireFormatLite::Write$declared_type$(" "$number$, this->$name$(), output);\n"); } void PrimitiveFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray(" + "target = ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(" "$number$, this->$name$(), target);\n"); } @@ -183,7 +174,7 @@ GenerateByteSize(io::Printer* printer) const { if (fixed_size == -1) { printer->Print(variables_, "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormat::$declared_type$Size(\n" + " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" " this->$name$());\n"); } else { printer->Print(variables_, @@ -205,8 +196,7 @@ void RepeatedPrimitiveFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField< $type$ > $name$_;\n"); - if (descriptor_->options().packed() && - descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); } @@ -215,11 +205,12 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField< $type$ >& $name$() const;\n" - "inline ::google::protobuf::RepeatedField< $type$ >* mutable_$name$();\n" - "inline $type$ $name$(int index) const;\n" - "inline void set_$name$(int index, $type$ value);\n" - "inline void add_$name$($type$ value);\n"); + "inline const ::google::protobuf::RepeatedField< $type$ >& $name$() const\n" + " $deprecation$;\n" + "inline ::google::protobuf::RepeatedField< $type$ >* mutable_$name$()$deprecation$;\n" + "inline $type$ $name$(int index) const$deprecation$;\n" + "inline void set_$name$(int index, $type$ value)$deprecation$;\n" + "inline void add_$name$($type$ value)$deprecation$;\n"); } void RepeatedPrimitiveFieldGenerator:: @@ -272,12 +263,12 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::uint32 length;\n" "DO_(input->ReadVarint32(&length));\n" - "::google::protobuf::io::CodedInputStream::Limit limit = " - "input->PushLimit(length);\n" + "::google::protobuf::io::CodedInputStream::Limit limit =\n" + " input->PushLimit(length);\n" "while (input->BytesUntilLimit() > 0) {\n" " $type$ value;\n" - " DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(" - "input, &value));\n" + " DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" + " input, &value));\n" " add_$name$(value);\n" "}\n" "input->PopLimit(limit);\n"); @@ -286,8 +277,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { } else { printer->Print(variables_, "$type$ value;\n" - "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(" - "input, &value));\n" + "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" + " input, &value));\n" "add_$name$(value);\n"); } } @@ -298,9 +289,9 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" - " ::google::protobuf::internal::WireFormat::WriteTag(" + " ::google::protobuf::internal::WireFormatLite::WriteTag(" "$number$, " - "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, " + "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, " "output);\n" " output->WriteVarint32(_$name$_cached_byte_size_);\n" "}\n"); @@ -309,12 +300,12 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { "for (int i = 0; i < this->$name$_size(); i++) {\n"); if (descriptor_->options().packed()) { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::Write$declared_type$NoTag(" - "this->$name$(i), output);\n"); + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n" + " this->$name$(i), output);\n"); } else { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::Write$declared_type$(" - "$number$, this->$name$(i), output);\n"); + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(i), output);\n"); } printer->Print("}\n"); } @@ -325,26 +316,24 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" - " target = ::google::protobuf::internal::WireFormat::WriteTagToArray(" - "$number$, " - "::google::protobuf::internal::WireFormat::WIRETYPE_LENGTH_DELIMITED, " - "target);\n" - " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(" - "_$name$_cached_byte_size_, target);\n" + " target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray(\n" + " $number$,\n" + " ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n" + " target);\n" + " target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n" + " _$name$_cached_byte_size_, target);\n" "}\n"); } printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n"); if (descriptor_->options().packed()) { printer->Print(variables_, - " target = ::google::protobuf::internal::WireFormat::" - "Write$declared_type$NoTagToArray(" - "this->$name$(i), target);\n"); + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$NoTagToArray(this->$name$(i), target);\n"); } else { printer->Print(variables_, - " target = ::google::protobuf::internal::WireFormat::" - "Write$declared_type$ToArray(" - "$number$, this->$name$(i), target);\n"); + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$ToArray($number$, this->$name$(i), target);\n"); } printer->Print("}\n"); } @@ -359,8 +348,8 @@ GenerateByteSize(io::Printer* printer) const { if (fixed_size == -1) { printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n" - " data_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n" - " this->$name$(i));\n" + " data_size += ::google::protobuf::internal::WireFormatLite::\n" + " $declared_type$Size(this->$name$(i));\n" "}\n"); } else { printer->Print(variables_, @@ -370,8 +359,8 @@ GenerateByteSize(io::Printer* printer) const { if (descriptor_->options().packed()) { printer->Print(variables_, "if (data_size > 0) {\n" - " total_size += $tag_size$ + " - "::google::protobuf::internal::WireFormat::Int32Size(data_size);\n" + " total_size += $tag_size$ +\n" + " ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n" "}\n" "_$name$_cached_byte_size_ = data_size;\n" "total_size += data_size;\n"); diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc index 7689fa13..c2825683 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.cc +++ b/src/google/protobuf/compiler/cpp/cpp_service.cc @@ -249,7 +249,7 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { sub_vars["input_type"] = ClassName(method->input_type(), true); sub_vars["output_type"] = ClassName(method->output_type(), true); - // Note: ::google::protobuf::down_cast does not work here because it only works on pointers, + // Note: down_cast does not work here because it only works on pointers, // not references. printer->Print(sub_vars, " case $index$:\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 05858da4..72258e89 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -35,7 +35,6 @@ #include <google/protobuf/compiler/cpp/cpp_string_field.h> #include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format_inl.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/strutil.h> @@ -44,23 +43,13 @@ namespace protobuf { namespace compiler { namespace cpp { -using internal::WireFormat; - namespace { -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetStringVariables(const FieldDescriptor* descriptor, map<string, string>* variables) { - (*variables)["name"] = FieldName(descriptor); + SetCommonFieldVariables(descriptor, variables); (*variables)["default"] = "\"" + CEscape(descriptor->default_value_string()) + "\""; - (*variables)["index"] = SimpleItoa(descriptor->index()); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["classname"] = ClassName(FieldScope(descriptor), false); - (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type()); - (*variables)["tag_size"] = SimpleItoa( - WireFormat::TagSize(descriptor->number(), descriptor->type())); (*variables)["pointer_type"] = descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; } @@ -111,11 +100,12 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } printer->Print(variables_, - "inline const ::std::string& $name$() const;\n" - "inline void set_$name$(const ::std::string& value);\n" - "inline void set_$name$(const char* value);\n" - "inline void set_$name$(const $pointer_type$* value, size_t size);\n" - "inline ::std::string* mutable_$name$();\n"); + "inline const ::std::string& $name$() const$deprecation$;\n" + "inline void set_$name$(const ::std::string& value)$deprecation$;\n" + "inline void set_$name$(const char* value)$deprecation$;\n" + "inline void set_$name$(const $pointer_type$* value, size_t size)" + "$deprecation$;\n" + "inline ::std::string* mutable_$name$()$deprecation$;\n"); if (descriptor_->options().has_ctype()) { printer->Outdent(); @@ -221,29 +211,52 @@ GenerateDestructorCode(io::Printer* printer) const { void StringFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(" - "input, mutable_$name$()));\n"); + "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::VerifyUTF8String(\n" + " this->$name$().data(), this->$name$().length(),\n" + " ::google::protobuf::internal::WireFormat::PARSE);\n"); + } } void StringFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$().data(), this->$name$().length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } printer->Print(variables_, - "::google::protobuf::internal::WireFormat::Write$declared_type$(" - "$number$, this->$name$(), output);\n"); + "::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(), output);\n"); } void StringFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$().data(), this->$name$().length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } printer->Print(variables_, - "target = ::google::protobuf::internal::WireFormat::Write$declared_type$ToArray(" - "$number$, this->$name$(), target);\n"); + "target =\n" + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$ToArray(\n" + " $number$, this->$name$(), target);\n"); } void StringFieldGenerator:: GenerateByteSize(io::Printer* printer) const { printer->Print(variables_, "total_size += $tag_size$ +\n" - " ::google::protobuf::internal::WireFormat::$declared_type$Size(this->$name$());\n"); + " ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" + " this->$name$());\n"); } // =================================================================== @@ -274,18 +287,22 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const;\n" - "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$();\n" - "inline const ::std::string& $name$(int index) const;\n" - "inline ::std::string* mutable_$name$(int index);\n" - "inline void set_$name$(int index, const ::std::string& value);\n" - "inline void set_$name$(int index, const char* value);\n" + "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const" + "$deprecation$;\n" + "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()" + "$deprecation$;\n" + "inline const ::std::string& $name$(int index) const$deprecation$;\n" + "inline ::std::string* mutable_$name$(int index)$deprecation$;\n" + "inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n" + "inline void set_$name$(int index, const char* value)$deprecation$;\n" "inline " - "void set_$name$(int index, const $pointer_type$* value, size_t size);\n" - "inline ::std::string* add_$name$();\n" - "inline void add_$name$(const ::std::string& value);\n" - "inline void add_$name$(const char* value);\n" - "inline void add_$name$(const $pointer_type$* value, size_t size);\n"); + "void set_$name$(int index, const $pointer_type$* value, size_t size)" + "$deprecation$;\n" + "inline ::std::string* add_$name$()$deprecation$;\n" + "inline void add_$name$(const ::std::string& value)$deprecation$;\n" + "inline void add_$name$(const char* value)$deprecation$;\n" + "inline void add_$name$(const $pointer_type$* value, size_t size)" + "$deprecation$;\n"); if (descriptor_->options().has_ctype()) { printer->Outdent(); @@ -361,26 +378,48 @@ GenerateConstructorCode(io::Printer* printer) const { void RepeatedStringFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormat::Read$declared_type$(\n" - " input, add_$name$()));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n" + " input, this->add_$name$()));\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$(0).data(), this->$name$(0).length(),\n" + " ::google::protobuf::internal::WireFormat::PARSE);\n"); + } } void RepeatedStringFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { printer->Print(variables_, - "for (int i = 0; i < this->$name$_size(); i++) {\n" - " ::google::protobuf::internal::WireFormat::Write$declared_type$(" - "$number$, this->$name$(i), output);\n" + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$(i).data(), this->$name$(i).length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } + printer->Print(variables_, + " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + " $number$, this->$name$(i), output);\n" "}\n"); } void RepeatedStringFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { printer->Print(variables_, - "for (int i = 0; i < this->$name$_size(); i++) {\n" - " target = ::google::protobuf::internal::WireFormat::" - "Write$declared_type$ToArray(" - "$number$, this->$name$(i), target);\n" + "for (int i = 0; i < this->$name$_size(); i++) {\n"); + if (HasUtf8Verification(descriptor_->file()) && + descriptor_->type() == FieldDescriptor::TYPE_STRING) { + printer->Print(variables_, + " ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " this->$name$(i).data(), this->$name$(i).length(),\n" + " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + } + printer->Print(variables_, + " target = ::google::protobuf::internal::WireFormatLite::\n" + " Write$declared_type$ToArray($number$, this->$name$(i), target);\n" "}\n"); } @@ -389,7 +428,7 @@ GenerateByteSize(io::Printer* printer) const { printer->Print(variables_, "total_size += $tag_size$ * this->$name$_size();\n" "for (int i = 0; i < this->$name$_size(); i++) {\n" - " total_size += ::google::protobuf::internal::WireFormat::$declared_type$Size(\n" + " total_size += ::google::protobuf::internal::WireFormatLite::$declared_type$Size(\n" " this->$name$(i));\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index cabf08fd..2b16e85d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -50,11 +50,9 @@ #include <google/protobuf/unittest_optimize_for.pb.h> #include <google/protobuf/unittest_embed_optimize_for.pb.h> #include <google/protobuf/test_util.h> -#include <google/protobuf/compiler/cpp/cpp_helpers.h> #include <google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h> #include <google/protobuf/compiler/importer.h> #include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/io/tokenizer.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.pb.h> @@ -75,18 +73,6 @@ namespace cpp { // Can't use an anonymous namespace here due to brokenness of Tru64 compiler. namespace cpp_unittest { -TEST(ExtremeDefaultValues, FloatingPoint) { - const unittest::TestExtremeDefaultValues& extreme_default = - unittest::TestExtremeDefaultValues::default_instance(); - - EXPECT_EQ(0.0f, extreme_default.zero_float()); - EXPECT_EQ(1.0f, extreme_default.one_float()); - EXPECT_EQ(1.5f, extreme_default.small_float()); - EXPECT_EQ(-1.0f, extreme_default.negative_one_float()); - EXPECT_EQ(-1.5f, extreme_default.negative_float()); - EXPECT_EQ(2.0e8f, extreme_default.large_float()); - EXPECT_EQ(-8e-28f, extreme_default.small_negative_float()); -} class MockErrorCollector : public MultiFileErrorCollector { public: @@ -157,6 +143,19 @@ TEST(GeneratedMessageTest, Defaults) { &message.optional_import_message()); } +TEST(GeneratedMessageTest, FloatingPointDefaults) { + const unittest::TestExtremeDefaultValues& extreme_default = + unittest::TestExtremeDefaultValues::default_instance(); + + EXPECT_EQ(0.0f, extreme_default.zero_float()); + EXPECT_EQ(1.0f, extreme_default.one_float()); + EXPECT_EQ(1.5f, extreme_default.small_float()); + EXPECT_EQ(-1.0f, extreme_default.negative_one_float()); + EXPECT_EQ(-1.5f, extreme_default.negative_float()); + EXPECT_EQ(2.0e8f, extreme_default.large_float()); + EXPECT_EQ(-8e-28f, extreme_default.small_negative_float()); +} + TEST(GeneratedMessageTest, Accessors) { // Set every field to a unique value then go back and check all those // values. @@ -710,6 +709,32 @@ TEST(GeneratedMessageTest, TestSpaceUsed) { #endif // !PROTOBUF_TEST_NO_DESCRIPTORS +TEST(GeneratedMessageTest, FieldConstantValues) { + unittest::TestRequired message; + EXPECT_EQ(unittest::TestAllTypes_NestedMessage::kBbFieldNumber, 1); + EXPECT_EQ(unittest::TestAllTypes::kOptionalInt32FieldNumber, 1); + EXPECT_EQ(unittest::TestAllTypes::kOptionalgroupFieldNumber, 16); + EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedMessageFieldNumber, 18); + EXPECT_EQ(unittest::TestAllTypes::kOptionalNestedEnumFieldNumber, 21); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedInt32FieldNumber, 31); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedgroupFieldNumber, 46); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber, 48); + EXPECT_EQ(unittest::TestAllTypes::kRepeatedNestedEnumFieldNumber, 51); +} + +TEST(GeneratedMessageTest, ExtensionConstantValues) { + EXPECT_EQ(unittest::TestRequired::kSingleFieldNumber, 1000); + EXPECT_EQ(unittest::TestRequired::kMultiFieldNumber, 1001); + EXPECT_EQ(unittest::kOptionalInt32ExtensionFieldNumber, 1); + EXPECT_EQ(unittest::kOptionalgroupExtensionFieldNumber, 16); + EXPECT_EQ(unittest::kOptionalNestedMessageExtensionFieldNumber, 18); + EXPECT_EQ(unittest::kOptionalNestedEnumExtensionFieldNumber, 21); + EXPECT_EQ(unittest::kRepeatedInt32ExtensionFieldNumber, 31); + EXPECT_EQ(unittest::kRepeatedgroupExtensionFieldNumber, 46); + EXPECT_EQ(unittest::kRepeatedNestedMessageExtensionFieldNumber, 48); + EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51); +} + // =================================================================== TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) { @@ -803,6 +828,17 @@ TEST(GeneratedEnumTest, Parse) { EXPECT_FALSE(unittest::TestEnumWithDupValue_Parse("FOO", &dup_value)); } +TEST(GeneratedEnumTest, GetEnumDescriptor) { + EXPECT_EQ(unittest::TestAllTypes::NestedEnum_descriptor(), + GetEnumDescriptor<unittest::TestAllTypes::NestedEnum>()); + EXPECT_EQ(unittest::ForeignEnum_descriptor(), + GetEnumDescriptor<unittest::ForeignEnum>()); + EXPECT_EQ(unittest::TestEnumWithDupValue_descriptor(), + GetEnumDescriptor<unittest::TestEnumWithDupValue>()); + EXPECT_EQ(unittest::TestSparseEnum_descriptor(), + GetEnumDescriptor<unittest::TestSparseEnum>()); +} + #endif // PROTOBUF_TEST_NO_DESCRIPTORS // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index 4aac6493..8ade50c9 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -67,14 +67,17 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) EnumGenerator::~EnumGenerator() {} void EnumGenerator::Generate(io::Printer* printer) { - bool is_own_file = - descriptor_->containing_type() == NULL && - descriptor_->file()->options().java_multiple_files(); - printer->Print( - "public $static$ enum $classname$\n" - " implements com.google.protobuf.ProtocolMessageEnum {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public enum $classname$\n" + " implements com.google.protobuf.ProtocolMessageEnum {\n", + "classname", descriptor_->name()); + } else { + printer->Print( + "public enum $classname$\n" + " implements com.google.protobuf.Internal.EnumLite {\n", + "classname", descriptor_->name()); + } printer->Indent(); for (int i = 0; i < canonical_values_.size(); i++) { @@ -126,63 +129,78 @@ void EnumGenerator::Generate(io::Printer* printer) { " default: return null;\n" " }\n" "}\n" - "\n"); + "\n" + "public static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" + " internalGetValueMap() {\n" + " return internalValueMap;\n" + "}\n" + "private static com.google.protobuf.Internal.EnumLiteMap<$classname$>\n" + " internalValueMap =\n" + " new com.google.protobuf.Internal.EnumLiteMap<$classname$>() {\n" + " public $classname$ findValueByNumber(int number) {\n" + " return $classname$.valueOf(number)\n;" + " }\n" + " };\n" + "\n", + "classname", descriptor_->name()); // ----------------------------------------------------------------- // Reflection - printer->Print( - "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" - " getValueDescriptor() {\n" - " return getDescriptor().getValues().get(index);\n" - "}\n" - "public final com.google.protobuf.Descriptors.EnumDescriptor\n" - " getDescriptorForType() {\n" - " return getDescriptor();\n" - "}\n" - "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" - " getDescriptor() {\n"); - - // TODO(kenton): Cache statically? Note that we can't access descriptors - // at module init time because it wouldn't work with descriptor.proto, but - // we can cache the value the first time getDescriptor() is called. - if (descriptor_->containing_type() == NULL) { + if (HasDescriptorMethods(descriptor_)) { printer->Print( - " return $file$.getDescriptor().getEnumTypes().get($index$);\n", - "file", ClassName(descriptor_->file()), - "index", SimpleItoa(descriptor_->index())); - } else { - printer->Print( - " return $parent$.getDescriptor().getEnumTypes().get($index$);\n", - "parent", ClassName(descriptor_->containing_type()), - "index", SimpleItoa(descriptor_->index())); - } + "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n" + " getValueDescriptor() {\n" + " return getDescriptor().getValues().get(index);\n" + "}\n" + "public final com.google.protobuf.Descriptors.EnumDescriptor\n" + " getDescriptorForType() {\n" + " return getDescriptor();\n" + "}\n" + "public static final com.google.protobuf.Descriptors.EnumDescriptor\n" + " getDescriptor() {\n"); + + // TODO(kenton): Cache statically? Note that we can't access descriptors + // at module init time because it wouldn't work with descriptor.proto, but + // we can cache the value the first time getDescriptor() is called. + if (descriptor_->containing_type() == NULL) { + printer->Print( + " return $file$.getDescriptor().getEnumTypes().get($index$);\n", + "file", ClassName(descriptor_->file()), + "index", SimpleItoa(descriptor_->index())); + } else { + printer->Print( + " return $parent$.getDescriptor().getEnumTypes().get($index$);\n", + "parent", ClassName(descriptor_->containing_type()), + "index", SimpleItoa(descriptor_->index())); + } - printer->Print( - "}\n" - "\n" - "private static final $classname$[] VALUES = {\n" - " ", - "classname", descriptor_->name()); + printer->Print( + "}\n" + "\n" + "private static final $classname$[] VALUES = {\n" + " ", + "classname", descriptor_->name()); + + for (int i = 0; i < descriptor_->value_count(); i++) { + printer->Print("$name$, ", + "name", descriptor_->value(i)->name()); + } - for (int i = 0; i < descriptor_->value_count(); i++) { - printer->Print("$name$, ", - "name", descriptor_->value(i)->name()); + printer->Print( + "\n" + "};\n" + "public static $classname$ valueOf(\n" + " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" + " if (desc.getType() != getDescriptor()) {\n" + " throw new java.lang.IllegalArgumentException(\n" + " \"EnumValueDescriptor is not for this type.\");\n" + " }\n" + " return VALUES[desc.getIndex()];\n" + "}\n", + "classname", descriptor_->name()); } - printer->Print( - "\n" - "};\n" - "public static $classname$ valueOf(\n" - " com.google.protobuf.Descriptors.EnumValueDescriptor desc) {\n" - " if (desc.getType() != getDescriptor()) {\n" - " throw new java.lang.IllegalArgumentException(\n" - " \"EnumValueDescriptor is not for this type.\");\n" - " }\n" - " return VALUES[desc.getIndex()];\n" - "}\n", - "classname", descriptor_->name()); - // ----------------------------------------------------------------- printer->Print( @@ -194,14 +212,16 @@ void EnumGenerator::Generate(io::Printer* printer) { "}\n", "classname", descriptor_->name()); - // Force the static initialization code for the file to run, since it may - // initialize static variables declared in this class. - printer->Print( - "\n" - "static {\n" - " $file$.getDescriptor();\n" - "}\n", - "file", ClassName(descriptor_->file())); + if (HasDescriptorMethods(descriptor_)) { + // Force the static initialization code for the file to run, since it may + // initialize static variables declared in this class. + printer->Print( + "\n" + "static {\n" + " $file$.getDescriptor();\n" + "}\n", + "file", ClassName(descriptor_->file())); + } printer->Outdent(); printer->Print("}\n\n"); diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index 2153042d..dc36e06e 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -39,7 +39,7 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/java/java_helpers.h> #include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format_inl.h> +#include <google/protobuf/wire_format.h> #include <google/protobuf/stubs/strutil.h> namespace google { @@ -53,18 +53,13 @@ namespace { // repeat code between this and the other field types. void SetEnumVariables(const FieldDescriptor* descriptor, map<string, string>* variables) { - const EnumValueDescriptor* default_value; - default_value = descriptor->default_value_enum(); - - string type = ClassName(descriptor->enum_type()); - (*variables)["name"] = UnderscoresToCamelCase(descriptor); (*variables)["capitalized_name"] = UnderscoresToCapitalizedCamelCase(descriptor); (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["type"] = type; - (*variables)["default"] = type + "." + default_value->name(); + (*variables)["type"] = ClassName(descriptor->enum_type()); + (*variables)["default"] = DefaultValue(descriptor); (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( internal::WireFormat::TagSize(descriptor->number(), descriptor->type())); @@ -132,10 +127,17 @@ void EnumFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "int rawValue = input.readEnum();\n" - "$type$ value = $type$.valueOf(rawValue);\n" - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n" + "$type$ value = $type$.valueOf(rawValue);\n"); + if (HasUnknownFields(descriptor_->containing_type())) { + printer->Print(variables_, + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n"); + } else { + printer->Print(variables_, + "if (value != null) {\n"); + } + printer->Print(variables_, " set$capitalized_name$(value);\n" "}\n"); } @@ -185,7 +187,7 @@ GenerateMembers(io::Printer* printer) const { "}\n"); if (descriptor_->options().packed() && - descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + HasGeneratedMethods(descriptor_->containing_type())) { printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); } @@ -272,10 +274,17 @@ 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" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n" + "$type$ value = $type$.valueOf(rawValue);\n"); + if (HasUnknownFields(descriptor_->containing_type())) { + printer->Print(variables_, + "if (value == null) {\n" + " unknownFields.mergeVarintField($number$, rawValue);\n" + "} else {\n"); + } else { + printer->Print(variables_, + "if (value != null) {\n"); + } + printer->Print(variables_, " add$capitalized_name$(value);\n" "}\n"); diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc index 302dcea4..4403220b 100644 --- a/src/google/protobuf/compiler/java/java_extension.cc +++ b/src/google/protobuf/compiler/java/java_extension.cc @@ -42,6 +42,39 @@ namespace protobuf { namespace compiler { namespace java { +namespace { + +const char* TypeName(FieldDescriptor::Type field_type) { + switch (field_type) { + case FieldDescriptor::TYPE_INT32 : return "INT32"; + case FieldDescriptor::TYPE_UINT32 : return "UINT32"; + case FieldDescriptor::TYPE_SINT32 : return "SINT32"; + case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; + case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; + case FieldDescriptor::TYPE_INT64 : return "INT64"; + case FieldDescriptor::TYPE_UINT64 : return "UINT64"; + case FieldDescriptor::TYPE_SINT64 : return "SINT64"; + case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; + case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; + case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; + case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; + case FieldDescriptor::TYPE_BOOL : return "BOOL"; + case FieldDescriptor::TYPE_STRING : return "STRING"; + case FieldDescriptor::TYPE_BYTES : return "BYTES"; + case FieldDescriptor::TYPE_ENUM : return "ENUM"; + case FieldDescriptor::TYPE_GROUP : return "GROUP"; + case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +} + ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) : descriptor_(descriptor) { if (descriptor_->extension_scope() != NULL) { @@ -59,6 +92,7 @@ void ExtensionGenerator::Generate(io::Printer* printer) { vars["containing_type"] = ClassName(descriptor_->containing_type()); vars["number"] = SimpleItoa(descriptor_->number()); vars["constant_name"] = FieldConstantName(descriptor_); + vars["lite"] = HasDescriptorMethods(descriptor_->file()) ? "" : "Lite"; JavaType java_type = GetJavaType(descriptor_); string singular_type; @@ -79,13 +113,13 @@ void ExtensionGenerator::Generate(io::Printer* printer) { if (descriptor_->is_repeated()) { printer->Print(vars, "public static\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n" " $containing_type$,\n" " java.util.List<$type$>> $name$;\n"); } else { printer->Print(vars, "public static\n" - " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " com.google.protobuf.GeneratedMessage$lite$.GeneratedExtension<\n" " $containing_type$,\n" " $type$> $name$;\n"); } @@ -96,34 +130,71 @@ void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) { vars["name"] = UnderscoresToCamelCase(descriptor_); vars["scope"] = scope_; vars["index"] = SimpleItoa(descriptor_->index()); + vars["extendee"] = ClassName(descriptor_->containing_type()); + vars["default"] = descriptor_->is_repeated() ? "" : DefaultValue(descriptor_); + vars["number"] = SimpleItoa(descriptor_->number()); + vars["type_constant"] = TypeName(descriptor_->type()); + vars["packed"] = descriptor_->options().packed() ? "true" : "false"; + vars["enum_map"] = "null"; + vars["prototype"] = "null"; JavaType java_type = GetJavaType(descriptor_); string singular_type; switch (java_type) { case JAVATYPE_MESSAGE: vars["type"] = ClassName(descriptor_->message_type()); + vars["prototype"] = ClassName(descriptor_->message_type()) + + ".getDefaultInstance()"; break; case JAVATYPE_ENUM: vars["type"] = ClassName(descriptor_->enum_type()); + vars["enum_map"] = ClassName(descriptor_->enum_type()) + + ".internalGetValueMap()"; break; default: vars["type"] = BoxedPrimitiveTypeName(java_type); break; } - if (descriptor_->is_repeated()) { - printer->Print(vars, - "$scope$.$name$ =\n" - " com.google.protobuf.GeneratedMessage\n" - " .newRepeatedGeneratedExtension(\n" - " $scope$.getDescriptor().getExtensions().get($index$),\n" - " $type$.class);\n"); + if (HasDescriptorMethods(descriptor_->file())) { + if (descriptor_->is_repeated()) { + printer->Print(vars, + "$scope$.$name$ =\n" + " com.google.protobuf.GeneratedMessage\n" + " .newRepeatedGeneratedExtension(\n" + " $scope$.getDescriptor().getExtensions().get($index$),\n" + " $type$.class);\n"); + } else { + printer->Print(vars, + "$scope$.$name$ =\n" + " com.google.protobuf.GeneratedMessage.newGeneratedExtension(\n" + " $scope$.getDescriptor().getExtensions().get($index$),\n" + " $type$.class);\n"); + } } else { - printer->Print(vars, - "$scope$.$name$ =\n" - " com.google.protobuf.GeneratedMessage.newGeneratedExtension(\n" - " $scope$.getDescriptor().getExtensions().get($index$),\n" - " $type$.class);\n"); + if (descriptor_->is_repeated()) { + printer->Print(vars, + "$scope$.$name$ =\n" + " com.google.protobuf.GeneratedMessageLite\n" + " .newRepeatedGeneratedExtension(\n" + " $extendee$.getDefaultInstance(),\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" + " $packed$);\n"); + } else { + printer->Print(vars, + "$scope$.$name$ =\n" + " com.google.protobuf.GeneratedMessageLite\n" + " .newGeneratedExtension(\n" + " $extendee$.getDefaultInstance(),\n" + " $default$,\n" + " $prototype$,\n" + " $enum_map$,\n" + " $number$,\n" + " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n"); + } } } diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index 31d75be6..0e170b38 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -151,7 +151,9 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print( "public static void registerAllExtensions(\n" - " com.google.protobuf.ExtensionRegistry registry) {\n"); + " com.google.protobuf.ExtensionRegistry$lite$ registry) {\n", + "lite", HasDescriptorMethods(file_) ? "" : "Lite"); + printer->Indent(); for (int i = 0; i < file_->extension_count(); i++) { @@ -195,8 +197,42 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print("\n"); - // ----------------------------------------------------------------- + if (HasDescriptorMethods(file_)) { + GenerateEmbeddedDescriptor(printer); + } else { + printer->Print( + "static {\n"); + printer->Indent(); + for (int i = 0; i < file_->message_type_count(); i++) { + // TODO(kenton): Reuse MessageGenerator objects? + MessageGenerator(file_->message_type(i)) + .GenerateStaticVariableInitializers(printer); + } + + for (int i = 0; i < file_->extension_count(); i++) { + // TODO(kenton): Reuse ExtensionGenerator objects? + ExtensionGenerator(file_->extension(i)) + .GenerateInitializationCode(printer); + } + + printer->Outdent(); + printer->Print( + "}\n"); + } + + // Dummy function we can use to force the static initialization block to + // run. Needed by inner classes. Cannot be private due to + // java_multiple_files option. + printer->Print( + "\n" + "public static void internalForceInit() {}\n"); + + printer->Outdent(); + printer->Print("}\n"); +} + +void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { // Embed the descriptor. We simply serialize the entire FileDescriptorProto // and embed it as a string literal, which is parsed and built into real // descriptors at initialization time. We unfortunately have to put it in @@ -310,9 +346,6 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Outdent(); printer->Print( "}\n"); - - printer->Outdent(); - printer->Print("}\n"); } template<typename GeneratorClass, typename DescriptorClass> diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h index f1efd011..cb82cea2 100644 --- a/src/google/protobuf/compiler/java/java_file.h +++ b/src/google/protobuf/compiler/java/java_file.h @@ -81,6 +81,8 @@ class FileGenerator { string java_package_; string classname_; + void GenerateEmbeddedDescriptor(io::Printer* printer); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc index 51af5f0d..8ed3affb 100644 --- a/src/google/protobuf/compiler/java/java_generator.cc +++ b/src/google/protobuf/compiler/java/java_generator.cc @@ -45,32 +45,6 @@ namespace protobuf { namespace compiler { namespace java { -namespace { - -// Parses a set of comma-delimited name/value pairs, e.g.: -// "foo=bar,baz,qux=corge" -// parses to the pairs: -// ("foo", "bar"), ("baz", ""), ("qux", "corge") -void ParseOptions(const string& text, vector<pair<string, string> >* output) { - vector<string> parts; - SplitStringUsing(text, ",", &parts); - - for (int i = 0; i < parts.size(); i++) { - string::size_type equals_pos = parts[i].find_first_of('='); - pair<string, string> value; - if (equals_pos == string::npos) { - value.first = parts[i]; - value.second = ""; - } else { - value.first = parts[i].substr(0, equals_pos); - value.second = parts[i].substr(equals_pos + 1); - } - output->push_back(value); - } -} - -} // namespace - JavaGenerator::JavaGenerator() {} JavaGenerator::~JavaGenerator() {} @@ -79,7 +53,7 @@ bool JavaGenerator::Generate(const FileDescriptor* file, OutputDirectory* output_directory, string* error) const { vector<pair<string, string> > options; - ParseOptions(parameter, &options); + ParseGeneratorParameter(parameter, &options); // ----------------------------------------------------------------- // parse generator options diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index 6a107650..dc6748e3 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -37,6 +37,7 @@ #include <google/protobuf/compiler/java/java_helpers.h> #include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/strutil.h> +#include <google/protobuf/stubs/substitute.h> namespace google { namespace protobuf { @@ -243,6 +244,72 @@ const char* BoxedPrimitiveTypeName(JavaType type) { return NULL; } +bool AllAscii(const string& text) { + for (int i = 0; i < text.size(); i++) { + if ((text[i] & 0x80) != 0) { + return false; + } + } + return true; +} + +string DefaultValue(const FieldDescriptor* field) { + // Switch on cpp_type since we need to know which default_value_* method + // of FieldDescriptor to call. + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + return SimpleItoa(field->default_value_int32()); + case FieldDescriptor::CPPTYPE_UINT32: + // Need to print as a signed int since Java has no unsigned. + return SimpleItoa(static_cast<int32>(field->default_value_uint32())); + case FieldDescriptor::CPPTYPE_INT64: + return SimpleItoa(field->default_value_int64()) + "L"; + case FieldDescriptor::CPPTYPE_UINT64: + return SimpleItoa(static_cast<int64>(field->default_value_uint64())) + + "L"; + case FieldDescriptor::CPPTYPE_DOUBLE: + return SimpleDtoa(field->default_value_double()) + "D"; + case FieldDescriptor::CPPTYPE_FLOAT: + return SimpleFtoa(field->default_value_float()) + "F"; + case FieldDescriptor::CPPTYPE_BOOL: + return field->default_value_bool() ? "true" : "false"; + case FieldDescriptor::CPPTYPE_STRING: + if (field->type() == FieldDescriptor::TYPE_BYTES) { + if (field->has_default_value()) { + // See comments in Internal.java for gory details. + return strings::Substitute( + "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")", + CEscape(field->default_value_string())); + } else { + return "com.google.protobuf.ByteString.EMPTY"; + } + } else { + if (AllAscii(field->default_value_string())) { + // All chars are ASCII. In this case CEscape() works fine. + return "\"" + CEscape(field->default_value_string()) + "\""; + } else { + // See comments in Internal.java for gory details. + return strings::Substitute( + "com.google.protobuf.Internal.stringDefaultValue(\"$0\")", + CEscape(field->default_value_string())); + } + } + + case FieldDescriptor::CPPTYPE_ENUM: + return ClassName(field->enum_type()) + "." + + field->default_value_enum()->name(); + + case FieldDescriptor::CPPTYPE_MESSAGE: + return ClassName(field->message_type()) + ".getDefaultInstance()"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return ""; +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index de3f883b..f1b643c3 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -36,6 +36,7 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__ #include <string> +#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/descriptor.h> namespace google { @@ -115,6 +116,35 @@ inline JavaType GetJavaType(const FieldDescriptor* field) { // types. const char* BoxedPrimitiveTypeName(JavaType type); +string DefaultValue(const FieldDescriptor* field); + +// Does this message class keep track of unknown fields? +inline bool HasUnknownFields(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) { + return descriptor->file()->options().optimize_for() != + FileOptions::CODE_SIZE; +} + +// Does this message class have descriptor and reflection methods? +inline bool HasDescriptorMethods(const Descriptor* descriptor) { + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} +inline bool HasDescriptorMethods(const EnumDescriptor* descriptor) { + return descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} +inline bool HasDescriptorMethods(const FileDescriptor* descriptor) { + return descriptor->options().optimize_for() != + FileOptions::LITE_RUNTIME; +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index c9cbd13f..f79546d6 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -41,7 +41,7 @@ #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/coded_stream.h> -#include <google/protobuf/wire_format_inl.h> +#include <google/protobuf/wire_format.h> #include <google/protobuf/descriptor.pb.h> namespace google { @@ -50,6 +50,7 @@ namespace compiler { namespace java { using internal::WireFormat; +using internal::WireFormatLite; namespace { @@ -153,38 +154,41 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor) MessageGenerator::~MessageGenerator() {} void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { - // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is - // used in the construction of descriptors, we have a tricky bootstrapping - // problem. To help control static initialization order, we make sure all - // descriptors and other static data that depends on them are members of - // the outermost class in the file. This way, they will be initialized in - // a deterministic order. - - map<string, string> vars; - vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = ClassName(descriptor_); - if (descriptor_->containing_type() != NULL) { - vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type()); - } - if (descriptor_->file()->options().java_multiple_files()) { - // We can only make these package-private since the classes that use them - // are in separate files. - vars["private"] = ""; - } else { - vars["private"] = "private "; - } + if (HasDescriptorMethods(descriptor_)) { + // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is + // used in the construction of descriptors, we have a tricky bootstrapping + // problem. To help control static initialization order, we make sure all + // descriptors and other static data that depends on them are members of + // the outermost class in the file. This way, they will be initialized in + // a deterministic order. + + map<string, string> vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + vars["index"] = SimpleItoa(descriptor_->index()); + vars["classname"] = ClassName(descriptor_); + if (descriptor_->containing_type() != NULL) { + vars["parent"] = UniqueFileScopeIdentifier( + descriptor_->containing_type()); + } + if (descriptor_->file()->options().java_multiple_files()) { + // We can only make these package-private since the classes that use them + // are in separate files. + vars["private"] = ""; + } else { + vars["private"] = "private "; + } - // The descriptor for this type. - printer->Print(vars, - "$private$static com.google.protobuf.Descriptors.Descriptor\n" - " internal_$identifier$_descriptor;\n"); + // The descriptor for this type. + printer->Print(vars, + "$private$static com.google.protobuf.Descriptors.Descriptor\n" + " internal_$identifier$_descriptor;\n"); - // And the FieldAccessorTable. - printer->Print(vars, - "$private$static\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internal_$identifier$_fieldAccessorTable;\n"); + // And the FieldAccessorTable. + printer->Print(vars, + "$private$static\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internal_$identifier$_fieldAccessorTable;\n"); + } // Generate static members for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { @@ -196,41 +200,44 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { void MessageGenerator::GenerateStaticVariableInitializers( io::Printer* printer) { - map<string, string> vars; - vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = ClassName(descriptor_); - if (descriptor_->containing_type() != NULL) { - vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type()); - } + if (HasDescriptorMethods(descriptor_)) { + map<string, string> vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + vars["index"] = SimpleItoa(descriptor_->index()); + vars["classname"] = ClassName(descriptor_); + if (descriptor_->containing_type() != NULL) { + vars["parent"] = UniqueFileScopeIdentifier( + descriptor_->containing_type()); + } - // The descriptor for this type. - if (descriptor_->containing_type() == NULL) { - printer->Print(vars, - "internal_$identifier$_descriptor =\n" - " getDescriptor().getMessageTypes().get($index$);\n"); - } else { - printer->Print(vars, - "internal_$identifier$_descriptor =\n" - " internal_$parent$_descriptor.getNestedTypes().get($index$);\n"); - } + // The descriptor for this type. + if (descriptor_->containing_type() == NULL) { + printer->Print(vars, + "internal_$identifier$_descriptor =\n" + " getDescriptor().getMessageTypes().get($index$);\n"); + } else { + printer->Print(vars, + "internal_$identifier$_descriptor =\n" + " internal_$parent$_descriptor.getNestedTypes().get($index$);\n"); + } - // And the FieldAccessorTable. - printer->Print(vars, - "internal_$identifier$_fieldAccessorTable = new\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" - " internal_$identifier$_descriptor,\n" - " new java.lang.String[] { "); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print( - "\"$field_name$\", ", - "field_name", - UnderscoresToCapitalizedCamelCase(descriptor_->field(i))); + // And the FieldAccessorTable. + printer->Print(vars, + "internal_$identifier$_fieldAccessorTable = new\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" + " internal_$identifier$_descriptor,\n" + " new java.lang.String[] { "); + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print( + "\"$field_name$\", ", + "field_name", + UnderscoresToCapitalizedCamelCase(descriptor_->field(i))); + } + printer->Print("},\n" + " $classname$.class,\n" + " $classname$.Builder.class);\n", + "classname", ClassName(descriptor_)); } - printer->Print("},\n" - " $classname$.class,\n" - " $classname$.Builder.class);\n", - "classname", ClassName(descriptor_)); // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { @@ -252,18 +259,35 @@ void MessageGenerator::Generate(io::Printer* printer) { descriptor_->file()->options().java_multiple_files(); if (descriptor_->extension_range_count() > 0) { - printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" - " $classname$> {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" + " $classname$> {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + } else { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" + " $classname$> {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + } } else { - printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + } else { + printer->Print( + "public $static$ final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite {\n", + "static", is_own_file ? "" : "static", + "classname", descriptor_->name()); + } } printer->Indent(); printer->Print( @@ -280,20 +304,23 @@ void MessageGenerator::Generate(io::Printer* printer) { "}\n" "\n", "classname", descriptor_->name()); - printer->Print( - "public static final com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptor() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" - "}\n" - "\n" - "@Override\n" - "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internalGetFieldAccessorTable() {\n" - " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n" - "}\n" - "\n", - "fileclass", ClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public static final com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptor() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n" + "@Override\n" + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internalGetFieldAccessorTable() {\n" + " return $fileclass$.internal_$identifier$_fieldAccessorTable;\n" + "}\n" + "\n", + "fileclass", ClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); + } // Nested types and extensions for (int i = 0; i < descriptor_->enum_type_count(); i++) { @@ -318,7 +345,7 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print("\n"); } - if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (HasGeneratedMethods(descriptor_)) { GenerateIsInitialized(printer); GenerateMessageSerializationMethods(printer); } @@ -326,12 +353,23 @@ void MessageGenerator::Generate(io::Printer* printer) { GenerateParseFromMethods(printer); GenerateBuilder(printer); - // Force the static initialization code for the file to run, since it may - // initialize static variables declared in this class. + if (HasDescriptorMethods(descriptor_)) { + // Force the static initialization code for the file to run, since it may + // initialize static variables declared in this class. + printer->Print( + "\n" + "static {\n" + " $file$.getDescriptor();\n" + "}\n", + "file", ClassName(descriptor_->file())); + } + + // Force initialization of outer class. Otherwise, nested extensions may + // not be initialized. printer->Print( "\n" "static {\n" - " $file$.getDescriptor();\n" + " $file$.internalForceInit();\n" "}\n", "file", ClassName(descriptor_->file())); @@ -360,9 +398,18 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Indent(); if (descriptor_->extension_range_count() > 0) { - printer->Print( - "com.google.protobuf.GeneratedMessage.ExtendableMessage\n" - " .ExtensionWriter extensionWriter = newExtensionWriter();\n"); + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n" + " .ExtensionWriter extensionWriter =\n" + " newMessageSetExtensionWriter();\n", + "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite"); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage\n" + " .ExtensionWriter extensionWriter = newExtensionWriter();\n", + "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite"); + } } // Merge the fields and the extension ranges, both sorted by field number. @@ -380,12 +427,14 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "getUnknownFields().writeAsMessageSetTo(output);\n"); - } else { - printer->Print( - "getUnknownFields().writeTo(output);\n"); + if (HasUnknownFields(descriptor_)) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "getUnknownFields().writeAsMessageSetTo(output);\n"); + } else { + printer->Print( + "getUnknownFields().writeTo(output);\n"); + } } printer->Outdent(); @@ -406,16 +455,23 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } if (descriptor_->extension_range_count() > 0) { - printer->Print( - "size += extensionsSerializedSize();\n"); + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "size += extensionsSerializedSizeAsMessageSet();\n"); + } else { + printer->Print( + "size += extensionsSerializedSize();\n"); + } } - if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "size += getUnknownFields().getSerializedSizeAsMessageSet();\n"); - } else { - printer->Print( - "size += getUnknownFields().getSerializedSize();\n"); + if (HasUnknownFields(descriptor_)) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "size += getUnknownFields().getSerializedSizeAsMessageSet();\n"); + } else { + printer->Print( + "size += getUnknownFields().getSerializedSize();\n"); + } } printer->Outdent(); @@ -439,7 +495,7 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.ByteString data,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" " return newBuilder().mergeFrom(data, extensionRegistry)\n" " .buildParsed();\n" @@ -450,7 +506,7 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseFrom(\n" " byte[] data,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" " return newBuilder().mergeFrom(data, extensionRegistry)\n" " .buildParsed();\n" @@ -461,7 +517,7 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseFrom(\n" " java.io.InputStream input,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" " return newBuilder().mergeFrom(input, extensionRegistry)\n" " .buildParsed();\n" @@ -472,7 +528,7 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseDelimitedFrom(\n" " java.io.InputStream input,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" " return newBuilder().mergeDelimitedFrom(input, extensionRegistry)\n" " .buildParsed();\n" @@ -484,7 +540,7 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n" " return newBuilder().mergeFrom(input, extensionRegistry)\n" " .buildParsed();\n" @@ -509,32 +565,57 @@ void MessageGenerator::GenerateSerializeOneExtensionRange( void MessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( - "public static Builder newBuilder() { return new Builder(); }\n" - "public Builder newBuilderForType() { return new Builder(); }\n" + "public static Builder newBuilder() { return Builder.create(); }\n" + "public Builder newBuilderForType() { return newBuilder(); }\n" "public static Builder newBuilder($classname$ prototype) {\n" - " return new Builder().mergeFrom(prototype);\n" + " return newBuilder().mergeFrom(prototype);\n" "}\n" "public Builder toBuilder() { return newBuilder(this); }\n" "\n", "classname", ClassName(descriptor_)); if (descriptor_->extension_range_count() > 0) { - printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" - " $classname$, Builder> {\n", - "classname", ClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" + " $classname$, Builder> {\n", + "classname", ClassName(descriptor_)); + } else { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n" + " $classname$, Builder> {\n", + "classname", ClassName(descriptor_)); + } } else { - printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.Builder<Builder> {\n", - "classname", ClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessage.Builder<Builder> {\n", + "classname", ClassName(descriptor_)); + } else { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessageLite.Builder<\n" + " $classname$, Builder> {\n", + "classname", ClassName(descriptor_)); + } } printer->Indent(); + // By using a threadlocal queue, we do not have to worry about locking when + // accessing the queue. Current JDKs implement this very efficiently, using + // no locks themselves to acquire the value when needed. + printer->Print( + "private static final " + " com.google.protobuf.Internal.ThreadLocalQuickQueue<Builder> builders =\n" + " new com.google.protobuf.Internal.ThreadLocalQuickQueue<Builder>();\n" + "\n"); + GenerateCommonBuilderMethods(printer); - if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (HasGeneratedMethods(descriptor_)) { GenerateBuilderParsingMethods(printer); } @@ -553,10 +634,19 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { printer->Print( + "private $classname$ result;\n" + "\n" "// Construct using $classname$.newBuilder()\n" "private Builder() {}\n" "\n" - "$classname$ result = new $classname$();\n" + "private static Builder create() {\n" + " Builder builder = builders.get().poll();\n" + " if (builder == null) {\n" + " builder = new Builder();\n" + " }\n" + " builder.result = new $classname$();\n" + " return builder;\n" + "}\n" "\n" "@Override\n" "protected $classname$ internalGetResult() {\n" @@ -565,25 +655,38 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "\n" "@Override\n" "public Builder clear() {\n" + " if (result == null) {\n" + " throw new IllegalStateException(\n" + " \"Cannot call clear() after build().\");\n" + " }\n" " result = new $classname$();\n" " return this;\n" "}\n" "\n" "@Override\n" "public Builder clone() {\n" - " return new Builder().mergeFrom(result);\n" + " return create().mergeFrom(result);\n" "}\n" - "\n" - "@Override\n" - "public com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptorForType() {\n" - " return $classname$.getDescriptor();\n" - "}\n" - "\n" + "\n", + "classname", ClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "@Override\n" + "public com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptorForType() {\n" + " return $classname$.getDescriptor();\n" + "}\n" + "\n", + "classname", ClassName(descriptor_)); + } + printer->Print( "public $classname$ getDefaultInstanceForType() {\n" " return $classname$.getDefaultInstance();\n" "}\n" - "\n", + "\n" + "public boolean isInitialized() {\n" + " return result.isInitialized();\n" + "}\n", "classname", ClassName(descriptor_)); // ----------------------------------------------------------------- @@ -592,8 +695,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "public $classname$ build() {\n" // If result == null, we'll throw an appropriate exception later. " if (result != null && !isInitialized()) {\n" - " throw new com.google.protobuf.UninitializedMessageException(\n" - " result);\n" + " throw newUninitializedMessageException(result);\n" " }\n" " return buildPartial();\n" "}\n" @@ -601,7 +703,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "private $classname$ buildParsed()\n" " throws com.google.protobuf.InvalidProtocolBufferException {\n" " if (!isInitialized()) {\n" - " throw new com.google.protobuf.UninitializedMessageException(\n" + " throw newUninitializedMessageException(\n" " result).asInvalidProtocolBufferException();\n" " }\n" " return buildPartial();\n" @@ -610,7 +712,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "public $classname$ buildPartial() {\n" " if (result == null) {\n" " throw new IllegalStateException(\n" - " \"build() has already been called on this Builder.\");" + " \"build() has already been called on this Builder.\");\n" " }\n", "classname", ClassName(descriptor_)); printer->Indent(); @@ -623,6 +725,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { printer->Print( " $classname$ returnMe = result;\n" " result = null;\n" + " builders.get().offer(this);\n" " return returnMe;\n" "}\n" "\n", @@ -630,18 +733,25 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { // ----------------------------------------------------------------- - if (descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + if (HasGeneratedMethods(descriptor_)) { + // MergeFrom(Message other) requires the ability to distinguish the other + // messages type by its descriptor. + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "@Override\n" + "public Builder mergeFrom(com.google.protobuf.Message other) {\n" + " if (other instanceof $classname$) {\n" + " return mergeFrom(($classname$)other);\n" + " } else {\n" + " super.mergeFrom(other);\n" + " return this;\n" + " }\n" + "}\n" + "\n", + "classname", ClassName(descriptor_)); + } + printer->Print( - "@Override\n" - "public Builder mergeFrom(com.google.protobuf.Message other) {\n" - " if (other instanceof $classname$) {\n" - " return mergeFrom(($classname$)other);\n" - " } else {\n" - " super.mergeFrom(other);\n" - " return this;\n" - " }\n" - "}\n" - "\n" "public Builder mergeFrom($classname$ other) {\n" // Optimization: If other is the default instance, we know none of its // fields are set so we can skip the merge. @@ -661,8 +771,12 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " this.mergeExtensionFields(other);\n"); } + if (HasUnknownFields(descriptor_)) { + printer->Print( + " this.mergeUnknownFields(other.getUnknownFields());\n"); + } + printer->Print( - " this.mergeUnknownFields(other.getUnknownFields());\n" " return this;\n" "}\n" "\n"); @@ -678,23 +792,19 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { printer->Print( "@Override\n" "public Builder mergeFrom(\n" - " com.google.protobuf.CodedInputStream input)\n" - " throws java.io.IOException {\n" - " return mergeFrom(input,\n" - " com.google.protobuf.ExtensionRegistry.getEmptyRegistry());\n" - "}\n" - "\n" - "@Override\n" - "public Builder mergeFrom(\n" " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistry extensionRegistry)\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" " throws java.io.IOException {\n"); printer->Indent(); + if (HasUnknownFields(descriptor_)) { + printer->Print( + "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" + " com.google.protobuf.UnknownFieldSet.newBuilder(\n" + " this.getUnknownFields());\n"); + } + printer->Print( - "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" - " com.google.protobuf.UnknownFieldSet.newBuilder(\n" - " this.getUnknownFields());\n" "while (true) {\n"); printer->Indent(); @@ -703,22 +813,34 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { "switch (tag) {\n"); printer->Indent(); - printer->Print( - "case 0:\n" // zero signals EOF / limit reached - " this.setUnknownFields(unknownFields.build());\n" - " return this;\n" - "default: {\n" - " if (!parseUnknownField(input, unknownFields,\n" - " extensionRegistry, tag)) {\n" - " this.setUnknownFields(unknownFields.build());\n" - " return this;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); + if (HasUnknownFields(descriptor_)) { + printer->Print( + "case 0:\n" // zero signals EOF / limit reached + " this.setUnknownFields(unknownFields.build());\n" + " return this;\n" + "default: {\n" + " if (!parseUnknownField(input, unknownFields,\n" + " extensionRegistry, tag)) {\n" + " this.setUnknownFields(unknownFields.build());\n" + " return this;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + } else { + printer->Print( + "case 0:\n" // zero signals EOF / limit reached + " return this;\n" + "default: {\n" + " if (!parseUnknownField(input, extensionRegistry, tag)) {\n" + " return this;\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]; - uint32 tag = WireFormat::MakeTag(field->number(), + uint32 tag = WireFormatLite::MakeTag(field->number(), WireFormat::WireTypeForField(field)); printer->Print( diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index 798e8608..327c2053 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -39,9 +39,8 @@ #include <google/protobuf/stubs/common.h> #include <google/protobuf/compiler/java/java_helpers.h> #include <google/protobuf/io/printer.h> -#include <google/protobuf/wire_format_inl.h> +#include <google/protobuf/wire_format.h> #include <google/protobuf/stubs/strutil.h> -#include <google/protobuf/stubs/substitute.h> namespace google { namespace protobuf { @@ -49,6 +48,7 @@ namespace compiler { namespace java { using internal::WireFormat; +using internal::WireFormatLite; namespace { @@ -121,16 +121,6 @@ const char* GetCapitalizedType(const FieldDescriptor* field) { return NULL; } -bool AllPrintableAscii(const string& text) { - // Cannot use isprint() because it's locale-specific. :( - for (int i = 0; i < text.size(); i++) { - if ((text[i] < 0x20) || text[i] >= 0x7F) { - return false; - } - } - return true; -} - // For encodings with fixed sizes, returns that size in bytes. Otherwise // returns -1. int FixedSize(FieldDescriptor::Type type) { @@ -141,14 +131,14 @@ int FixedSize(FieldDescriptor::Type type) { case FieldDescriptor::TYPE_UINT64 : return -1; case FieldDescriptor::TYPE_SINT32 : return -1; case FieldDescriptor::TYPE_SINT64 : return -1; - case FieldDescriptor::TYPE_FIXED32 : return WireFormat::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64 : return WireFormat::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: return WireFormat::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: return WireFormat::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT : return WireFormat::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE : return WireFormat::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL : return WireFormat::kBoolSize; + case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; case FieldDescriptor::TYPE_ENUM : return -1; case FieldDescriptor::TYPE_STRING : return -1; @@ -163,64 +153,6 @@ int FixedSize(FieldDescriptor::Type type) { return -1; } -string DefaultValue(const FieldDescriptor* field) { - // Switch on cpp_type since we need to know which default_value_* method - // of FieldDescriptor to call. - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - return SimpleItoa(field->default_value_int32()); - case FieldDescriptor::CPPTYPE_UINT32: - // Need to print as a signed int since Java has no unsigned. - return SimpleItoa(static_cast<int32>(field->default_value_uint32())); - case FieldDescriptor::CPPTYPE_INT64: - return SimpleItoa(field->default_value_int64()) + "L"; - case FieldDescriptor::CPPTYPE_UINT64: - return SimpleItoa(static_cast<int64>(field->default_value_uint64())) + - "L"; - case FieldDescriptor::CPPTYPE_DOUBLE: - return SimpleDtoa(field->default_value_double()) + "D"; - case FieldDescriptor::CPPTYPE_FLOAT: - return SimpleFtoa(field->default_value_float()) + "F"; - case FieldDescriptor::CPPTYPE_BOOL: - return field->default_value_bool() ? "true" : "false"; - case FieldDescriptor::CPPTYPE_STRING: { - bool isBytes = field->type() == FieldDescriptor::TYPE_BYTES; - - if (!isBytes && AllPrintableAscii(field->default_value_string())) { - // All chars are ASCII and printable. In this case CEscape() works - // fine (it will only escape quotes and backslashes). - // Note: If this "optimization" is removed, DescriptorProtos will - // no longer be able to initialize itself due to bootstrapping - // problems. - return "\"" + CEscape(field->default_value_string()) + "\""; - } - - if (isBytes && !field->has_default_value()) { - return "com.google.protobuf.ByteString.EMPTY"; - } - - // Escaping strings correctly for Java and generating efficient - // initializers for ByteStrings are both tricky. We can sidestep the - // whole problem by just grabbing the default value from the descriptor. - return strings::Substitute( - "(($0) $1.getDescriptor().getFields().get($2).getDefaultValue())", - isBytes ? "com.google.protobuf.ByteString" : "java.lang.String", - ClassName(field->containing_type()), field->index()); - } - - case FieldDescriptor::CPPTYPE_ENUM: - case FieldDescriptor::CPPTYPE_MESSAGE: - GOOGLE_LOG(FATAL) << "Can't get here."; - return ""; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return ""; -} - void SetPrimitiveVariables(const FieldDescriptor* descriptor, map<string, string>* variables) { (*variables)["name"] = @@ -285,8 +217,17 @@ GenerateBuilderMembers(io::Printer* printer) const { " return this;\n" "}\n" "public Builder clear$capitalized_name$() {\n" - " result.has$capitalized_name$ = false;\n" - " result.$name$_ = $default$;\n" + " result.has$capitalized_name$ = false;\n"); + if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + // The default value is not a simple literal so we want to avoid executing + // it multiple times. Instead, get the default out of the default instance. + printer->Print(variables_, + " result.$name$_ = getDefaultInstance().get$capitalized_name$();\n"); + } else { + printer->Print(variables_, + " result.$name$_ = $default$;\n"); + } + printer->Print(variables_, " return this;\n" "}\n"); } @@ -355,7 +296,7 @@ GenerateMembers(io::Printer* printer) const { "}\n"); if (descriptor_->options().packed() && - descriptor_->file()->options().optimize_for() == FileOptions::SPEED) { + HasGeneratedMethods(descriptor_->containing_type())) { printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); } diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index e9e01545..02304d6d 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -661,7 +661,7 @@ bool Parser::ParseOptionAssignment(Message* options) { GOOGLE_CHECK(uninterpreted_option_field != NULL) << "No field named \"uninterpreted_option\" in the Options proto."; - UninterpretedOption* uninterpreted_option = ::google::protobuf::down_cast<UninterpretedOption*>( + UninterpretedOption* uninterpreted_option = down_cast<UninterpretedOption*>( options->GetReflection()->AddMessage(options, uninterpreted_option_field)); |