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/java | |
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/java')
-rw-r--r-- | src/google/protobuf/compiler/java/java_enum.cc | 148 | ||||
-rw-r--r-- | src/google/protobuf/compiler/java/java_enum_field.cc | 43 | ||||
-rw-r--r-- | src/google/protobuf/compiler/java/java_extension.cc | 99 | ||||
-rw-r--r-- | src/google/protobuf/compiler/java/java_file.cc | 43 | ||||
-rw-r--r-- | src/google/protobuf/compiler/java/java_file.h | 2 | ||||
-rw-r--r-- | src/google/protobuf/compiler/java/java_generator.cc | 28 | ||||
-rw-r--r-- | src/google/protobuf/compiler/java/java_helpers.cc | 67 | ||||
-rw-r--r-- | src/google/protobuf/compiler/java/java_helpers.h | 30 | ||||
-rw-r--r-- | src/google/protobuf/compiler/java/java_message.cc | 478 | ||||
-rw-r--r-- | src/google/protobuf/compiler/java/java_primitive_field.cc | 103 |
10 files changed, 655 insertions, 386 deletions
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"); } |