aboutsummaryrefslogtreecommitdiff
path: root/src/google/protobuf/compiler/java
diff options
context:
space:
mode:
authorkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-07-29 01:13:20 +0000
committerkenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-07-29 01:13:20 +0000
commit80b1d62bfcea65c59e2160da71dad84b1bd19cef (patch)
tree5423b830c53174fec83a7ea01ff0877e11c1ddb6 /src/google/protobuf/compiler/java
parentd2fd0638c309113ccae3731a58e30419f522269a (diff)
downloadprotobuf-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.cc148
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc43
-rw-r--r--src/google/protobuf/compiler/java/java_extension.cc99
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc43
-rw-r--r--src/google/protobuf/compiler/java/java_file.h2
-rw-r--r--src/google/protobuf/compiler/java/java_generator.cc28
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.cc67
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h30
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc478
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc103
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");
}