aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/java
diff options
context:
space:
mode:
authorGravatar kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-12-18 02:11:36 +0000
committerGravatar kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d>2009-12-18 02:11:36 +0000
commitfccb146e3fe437b0df1e9c50d4b8e1080ddb4bd9 (patch)
tree9f2d9fe0267d96a54e541377ffeada3d0bff0d1d /src/google/protobuf/compiler/java
parentd5cf7b55a6a1f959d1646785f63ca2b62da78079 (diff)
Massive roll-up of changes. See CHANGES.txt.
Diffstat (limited to 'src/google/protobuf/compiler/java')
-rw-r--r--src/google/protobuf/compiler/java/java_enum.cc5
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.cc46
-rw-r--r--src/google/protobuf/compiler/java/java_enum_field.h3
-rw-r--r--src/google/protobuf/compiler/java/java_extension.cc3
-rw-r--r--src/google/protobuf/compiler/java/java_field.cc10
-rw-r--r--src/google/protobuf/compiler/java/java_field.h2
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc40
-rw-r--r--src/google/protobuf/compiler/java/java_file.h5
-rw-r--r--src/google/protobuf/compiler/java/java_generator.cc1
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.cc43
-rw-r--r--src/google/protobuf/compiler/java/java_helpers.h18
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc83
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.cc18
-rw-r--r--src/google/protobuf/compiler/java/java_message_field.h2
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.cc46
-rw-r--r--src/google/protobuf/compiler/java/java_primitive_field.h3
16 files changed, 242 insertions, 86 deletions
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index 8ade50c9..85e39f53 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -223,6 +223,11 @@ void EnumGenerator::Generate(io::Printer* printer) {
"file", ClassName(descriptor_->file()));
}
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(enum_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
+
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 dc36e06e..af6b1cd2 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -62,7 +62,7 @@ void SetEnumVariables(const FieldDescriptor* descriptor,
(*variables)["default"] = DefaultValue(descriptor);
(*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
- internal::WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
}
} // namespace
@@ -81,7 +81,7 @@ void EnumFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private boolean has$capitalized_name$;\n"
- "private $type$ $name$_ = $default$;\n"
+ "private $type$ $name$_;\n"
"public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
"public $type$ get$capitalized_name$() { return $name$_; }\n");
}
@@ -111,6 +111,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void EnumFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $default$;\n");
+}
+
+void EnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
@@ -241,6 +246,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void RepeatedEnumFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void RepeatedEnumFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\n"
@@ -262,15 +272,6 @@ GenerateBuildingCode(io::Printer* printer) const {
void RepeatedEnumFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- // If packed, set up the while loop
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "int length = input.readRawVarint32();\n"
- "int oldLimit = input.pushLimit(length);\n"
- "while(input.getBytesUntilLimit() > 0) {\n");
- printer->Indent();
- }
-
// Read and store the enum
printer->Print(variables_,
"int rawValue = input.readEnum();\n"
@@ -287,13 +288,24 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
" add$capitalized_name$(value);\n"
"}\n");
+}
- if (descriptor_->options().packed()) {
- printer->Outdent();
- printer->Print(variables_,
- "}\n"
- "input.popLimit(oldLimit);\n");
- }
+void RepeatedEnumFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ // Wrap GenerateParsingCode's contents with a while loop.
+
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int oldLimit = input.pushLimit(length);\n"
+ "while(input.getBytesUntilLimit() > 0) {\n");
+ printer->Indent();
+
+ GenerateParsingCode(printer);
+
+ printer->Outdent();
+ printer->Print(variables_,
+ "}\n"
+ "input.popLimit(oldLimit);\n");
}
void RepeatedEnumFieldGenerator::
diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h
index 63f68153..c54a0faf 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.h
+++ b/src/google/protobuf/compiler/java/java_enum_field.h
@@ -52,6 +52,7 @@ class EnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
@@ -75,9 +76,11 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 4403220b..5932433f 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -133,7 +133,7 @@ void ExtensionGenerator::GenerateInitializationCode(io::Printer* printer) {
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["type_constant"] = TypeName(GetType(descriptor_));
vars["packed"] = descriptor_->options().packed() ? "true" : "false";
vars["enum_map"] = "null";
vars["prototype"] = "null";
@@ -208,5 +208,4 @@ void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) {
} // namespace java
} // namespace compiler
} // namespace protobuf
-
} // namespace google
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index f9d34ad7..978c8f33 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -46,6 +46,16 @@ namespace java {
FieldGenerator::~FieldGenerator() {}
+void FieldGenerator::GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ // Reaching here indicates a bug. Cases are:
+ // - This FieldGenerator should support packing, but this method should be
+ // overridden.
+ // - This FieldGenerator doesn't support packing, and this method should
+ // never have been called.
+ GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() "
+ << "called on field generator that does not support packing.";
+}
+
FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
: descriptor_(descriptor),
field_generators_(
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index cab463c8..f5bef7ab 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -57,9 +57,11 @@ class FieldGenerator {
virtual void GenerateMembers(io::Printer* printer) const = 0;
virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
+ virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
virtual void GenerateMergingCode(io::Printer* printer) const = 0;
virtual void GenerateBuildingCode(io::Printer* printer) const = 0;
virtual void GenerateParsingCode(io::Printer* printer) const = 0;
+ virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const;
virtual void GenerateSerializationCode(io::Printer* printer) const = 0;
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 2aedde5e..7ea127c0 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -64,7 +64,7 @@ bool UsesExtensions(const Message& message) {
for (int i = 0; i < fields.size(); i++) {
if (fields[i]->is_extension()) return true;
- if (fields[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
if (fields[i]->is_repeated()) {
int size = reflection->FieldSize(message, fields[i]);
for (int j = 0; j < size; j++) {
@@ -82,6 +82,7 @@ bool UsesExtensions(const Message& message) {
return false;
}
+
} // namespace
FileGenerator::FileGenerator(const FileDescriptor* file)
@@ -134,7 +135,9 @@ void FileGenerator::Generate(io::Printer* printer) {
// fully-qualified names in the generated source.
printer->Print(
"// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
- "\n");
+ "// source: $filename$\n"
+ "\n",
+ "filename", file_->name());
if (!java_package_.empty()) {
printer->Print(
"package $package$;\n"
@@ -178,8 +181,10 @@ void FileGenerator::Generate(io::Printer* printer) {
for (int i = 0; i < file_->message_type_count(); i++) {
MessageGenerator(file_->message_type(i)).Generate(printer);
}
- for (int i = 0; i < file_->service_count(); i++) {
- ServiceGenerator(file_->service(i)).Generate(printer);
+ if (HasGenericServices(file_)) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ ServiceGenerator(file_->service(i)).Generate(printer);
+ }
}
}
@@ -228,6 +233,10 @@ void FileGenerator::Generate(io::Printer* printer) {
"\n"
"public static void internalForceInit() {}\n");
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(outer_class_scope)\n");
+
printer->Outdent();
printer->Print("}\n");
}
@@ -245,6 +254,7 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
// embedded raw, which is what we want.
FileDescriptorProto file_proto;
file_->CopyTo(&file_proto);
+
string file_data;
file_proto.SerializeToString(&file_data);
@@ -343,9 +353,11 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
" new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
for (int i = 0; i < file_->dependency_count(); i++) {
- printer->Print(
- " $dependency$.getDescriptor(),\n",
- "dependency", ClassName(file_->dependency(i)));
+ if (ShouldIncludeDependency(file_->dependency(i))) {
+ printer->Print(
+ " $dependency$.getDescriptor(),\n",
+ "dependency", ClassName(file_->dependency(i)));
+ }
}
printer->Print(
@@ -396,14 +408,20 @@ void FileGenerator::GenerateSiblings(const string& package_dir,
file_->message_type(i),
output_directory, file_list);
}
- for (int i = 0; i < file_->service_count(); i++) {
- GenerateSibling<ServiceGenerator>(package_dir, java_package_,
- file_->service(i),
- output_directory, file_list);
+ if (HasGenericServices(file_)) {
+ for (int i = 0; i < file_->service_count(); i++) {
+ GenerateSibling<ServiceGenerator>(package_dir, java_package_,
+ file_->service(i),
+ output_directory, file_list);
+ }
}
}
}
+bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) {
+ return true;
+}
+
} // namespace java
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
index cb82cea2..9e35d330 100644
--- a/src/google/protobuf/compiler/java/java_file.h
+++ b/src/google/protobuf/compiler/java/java_file.h
@@ -77,6 +77,11 @@ class FileGenerator {
const string& classname() { return classname_; }
private:
+ // Returns whether the dependency should be included in the output file.
+ // Always returns true for opensource, but used internally at Google to help
+ // improve compatibility with version 1 of protocol buffers.
+ bool ShouldIncludeDependency(const FileDescriptor* descriptor);
+
const FileDescriptor* file_;
string java_package_;
string classname_;
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 8ed3affb..745b55ae 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -45,6 +45,7 @@ namespace protobuf {
namespace compiler {
namespace java {
+
JavaGenerator::JavaGenerator() {}
JavaGenerator::~JavaGenerator() {}
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index dc6748e3..7ed0c3cc 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -32,6 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
+#include <limits>
#include <vector>
#include <google/protobuf/compiler/java/java_helpers.h>
@@ -57,7 +58,7 @@ const string& FieldName(const FieldDescriptor* field) {
// Groups are hacky: The name of the field is just the lower-cased name
// of the group type. In Java, though, we would like to retain the original
// capitalization of the type name.
- if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
return field->message_type()->name();
} else {
return field->name();
@@ -178,8 +179,12 @@ string FieldConstantName(const FieldDescriptor *field) {
return name;
}
-JavaType GetJavaType(FieldDescriptor::Type field_type) {
- switch (field_type) {
+FieldDescriptor::Type GetType(const FieldDescriptor* field) {
+ return field->type();
+}
+
+JavaType GetJavaType(const FieldDescriptor* field) {
+ switch (GetType(field)) {
case FieldDescriptor::TYPE_INT32:
case FieldDescriptor::TYPE_UINT32:
case FieldDescriptor::TYPE_SINT32:
@@ -254,7 +259,7 @@ bool AllAscii(const string& text) {
}
string DefaultValue(const FieldDescriptor* field) {
- // Switch on cpp_type since we need to know which default_value_* method
+ // Switch on CppType since we need to know which default_value_* method
// of FieldDescriptor to call.
switch (field->cpp_type()) {
case FieldDescriptor::CPPTYPE_INT32:
@@ -267,14 +272,34 @@ string DefaultValue(const FieldDescriptor* field) {
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_DOUBLE: {
+ double value = field->default_value_double();
+ if (value == numeric_limits<double>::infinity()) {
+ return "Double.POSITIVE_INFINITY";
+ } else if (value == -numeric_limits<double>::infinity()) {
+ return "Double.NEGATIVE_INFINITY";
+ } else if (value != value) {
+ return "Double.NaN";
+ } else {
+ return SimpleDtoa(value) + "D";
+ }
+ }
+ case FieldDescriptor::CPPTYPE_FLOAT: {
+ float value = field->default_value_float();
+ if (value == numeric_limits<float>::infinity()) {
+ return "Float.POSITIVE_INFINITY";
+ } else if (value == -numeric_limits<float>::infinity()) {
+ return "Float.NEGATIVE_INFINITY";
+ } else if (value != value) {
+ return "Float.NaN";
+ } else {
+ return SimpleFtoa(value) + "F";
+ }
+ }
case FieldDescriptor::CPPTYPE_BOOL:
return field->default_value_bool() ? "true" : "false";
case FieldDescriptor::CPPTYPE_STRING:
- if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
if (field->has_default_value()) {
// See comments in Internal.java for gory details.
return strings::Substitute(
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index f1b643c3..3c8974c9 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -93,6 +93,11 @@ string ClassName(const FileDescriptor* descriptor);
// number constant.
string FieldConstantName(const FieldDescriptor *field);
+// Returns the type of the FieldDescriptor.
+// This does nothing interesting for the open source release, but is used for
+// hacks that improve compatability with version 1 protocol buffers at Google.
+FieldDescriptor::Type GetType(const FieldDescriptor* field);
+
enum JavaType {
JAVATYPE_INT,
JAVATYPE_LONG,
@@ -105,11 +110,7 @@ enum JavaType {
JAVATYPE_MESSAGE
};
-JavaType GetJavaType(FieldDescriptor::Type field_type);
-
-inline JavaType GetJavaType(const FieldDescriptor* field) {
- return GetJavaType(field->type());
-}
+JavaType GetJavaType(const FieldDescriptor* field);
// Get the fully-qualified class name for a boxed primitive type, e.g.
// "java.lang.Integer" for JAVATYPE_INT. Returns NULL for enum and message
@@ -145,6 +146,13 @@ inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
FileOptions::LITE_RUNTIME;
}
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor *file) {
+ return file->service_count() > 0 &&
+ file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+ file->options().java_generic_services();
+}
+
} // 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 99b57c95..1f8e209c 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -127,7 +127,7 @@ static bool HasRequiredFields(
if (field->is_required()) {
return true;
}
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+ if (GetJavaType(field) == JAVATYPE_MESSAGE) {
if (HasRequiredFields(field->message_type(), already_seen)) {
return true;
}
@@ -292,9 +292,14 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Indent();
printer->Print(
"// Use $classname$.newBuilder() to construct.\n"
- "private $classname$() {}\n"
+ "private $classname$() {\n"
+ " initFields();\n"
+ "}\n"
+ // Used when constructing the default instance, which cannot be initialized
+ // immediately because it may cyclically refer to other default instances.
+ "private $classname$(boolean noInit) {}\n"
"\n"
- "private static final $classname$ defaultInstance = new $classname$();\n"
+ "private static final $classname$ defaultInstance;\n"
"public static $classname$ getDefaultInstance() {\n"
" return defaultInstance;\n"
"}\n"
@@ -344,6 +349,17 @@ void MessageGenerator::Generate(io::Printer* printer) {
printer->Print("\n");
}
+ // Called by the constructor, except in the case of the default instance,
+ // in which case this is called by static init code later on.
+ printer->Print("private void initFields() {\n");
+ printer->Indent();
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateInitializationCode(printer);
+ }
+ printer->Outdent();
+ printer->Print("}\n");
+
if (HasGeneratedMethods(descriptor_)) {
GenerateIsInitialized(printer);
GenerateMessageSerializationMethods(printer);
@@ -352,25 +368,23 @@ void MessageGenerator::Generate(io::Printer* printer) {
GenerateParseFromMethods(printer);
GenerateBuilder(printer);
- 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.
+ // not be initialized. Also carefully initialize the default instance in
+ // such a way that it doesn't conflict with other initialization.
printer->Print(
"\n"
"static {\n"
+ " defaultInstance = new $classname$(true);\n"
" $file$.internalForceInit();\n"
+ " defaultInstance.initFields();\n"
"}\n",
- "file", ClassName(descriptor_->file()));
+ "file", ClassName(descriptor_->file()),
+ "classname", descriptor_->name());
+
+ printer->Print(
+ "\n"
+ "// @@protoc_insertion_point(class_scope:$full_name$)\n",
+ "full_name", descriptor_->full_name());
printer->Outdent();
printer->Print("}\n\n");
@@ -529,14 +543,23 @@ GenerateParseFromMethods(io::Printer* printer) {
"}\n"
"public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
" throws java.io.IOException {\n"
- " return newBuilder().mergeDelimitedFrom(input).buildParsed();\n"
+ " Builder builder = newBuilder();\n"
+ " if (builder.mergeDelimitedFrom(input)) {\n"
+ " return builder.buildParsed();\n"
+ " } else {\n"
+ " return null;\n"
+ " }\n"
"}\n"
"public static $classname$ parseDelimitedFrom(\n"
" java.io.InputStream input,\n"
" com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n"
" throws java.io.IOException {\n"
- " return newBuilder().mergeDelimitedFrom(input, extensionRegistry)\n"
- " .buildParsed();\n"
+ " Builder builder = newBuilder();\n"
+ " if (builder.mergeDelimitedFrom(input, extensionRegistry)) {\n"
+ " return builder.buildParsed();\n"
+ " } else {\n"
+ " return null;\n"
+ " }\n"
"}\n"
"public static $classname$ parseFrom(\n"
" com.google.protobuf.CodedInputStream input)\n"
@@ -827,7 +850,7 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = sorted_fields[i];
uint32 tag = WireFormatLite::MakeTag(field->number(),
- WireFormat::WireTypeForField(field));
+ WireFormat::WireTypeForFieldType(field->type()));
printer->Print(
"case $tag$: {\n",
@@ -840,6 +863,24 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) {
printer->Print(
" break;\n"
"}\n");
+
+ if (field->is_packable()) {
+ // To make packed = true wire compatible, we generate parsing code from a
+ // packed version of this field regardless of field->options().packed().
+ uint32 packed_tag = WireFormatLite::MakeTag(field->number(),
+ WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+ printer->Print(
+ "case $tag$: {\n",
+ "tag", SimpleItoa(packed_tag));
+ printer->Indent();
+
+ field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " break;\n"
+ "}\n");
+ }
}
printer->Outdent();
@@ -875,7 +916,7 @@ void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
// Now check that all embedded messages are initialized.
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
- if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
+ if (GetJavaType(field) == JAVATYPE_MESSAGE &&
HasRequiredFields(field->message_type())) {
switch (field->label()) {
case FieldDescriptor::LABEL_REQUIRED:
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index bbddddde..71edc024 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -59,7 +59,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor,
(*variables)["number"] = SimpleItoa(descriptor->number());
(*variables)["type"] = ClassName(descriptor->message_type());
(*variables)["group_or_message"] =
- (descriptor->type() == FieldDescriptor::TYPE_GROUP) ?
+ (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ?
"Group" : "Message";
}
@@ -79,7 +79,7 @@ void MessageFieldGenerator::
GenerateMembers(io::Printer* printer) const {
printer->Print(variables_,
"private boolean has$capitalized_name$;\n"
- "private $type$ $name$_ = $type$.getDefaultInstance();\n"
+ "private $type$ $name$_;\n"
"public boolean has$capitalized_name$() { return has$capitalized_name$; }\n"
"public $type$ get$capitalized_name$() { return $name$_; }\n");
}
@@ -125,6 +125,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n");
+}
+
+void MessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
@@ -145,7 +150,7 @@ GenerateParsingCode(io::Printer* printer) const {
" subBuilder.mergeFrom(get$capitalized_name$());\n"
"}\n");
- if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup($number$, subBuilder, extensionRegistry);\n");
} else {
@@ -262,6 +267,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void RepeatedMessageFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\n"
@@ -286,7 +296,7 @@ GenerateParsingCode(io::Printer* printer) const {
printer->Print(variables_,
"$type$.Builder subBuilder = $type$.newBuilder();\n");
- if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) {
+ if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) {
printer->Print(variables_,
"input.readGroup($number$, subBuilder, extensionRegistry);\n");
} else {
diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h
index 90a90976..66bdd884 100644
--- a/src/google/protobuf/compiler/java/java_message_field.h
+++ b/src/google/protobuf/compiler/java/java_message_field.h
@@ -52,6 +52,7 @@ class MessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
@@ -75,6 +76,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 1fbca5a2..f6179bfa 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -93,7 +93,7 @@ bool IsReferenceType(JavaType type) {
}
const char* GetCapitalizedType(const FieldDescriptor* field) {
- switch (field->type()) {
+ switch (GetType(field)) {
case FieldDescriptor::TYPE_INT32 : return "Int32" ;
case FieldDescriptor::TYPE_UINT32 : return "UInt32" ;
case FieldDescriptor::TYPE_SINT32 : return "SInt32" ;
@@ -166,7 +166,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
(*variables)["capitalized_type"] = GetCapitalizedType(descriptor);
(*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor));
(*variables)["tag_size"] = SimpleItoa(
- WireFormat::TagSize(descriptor->number(), descriptor->type()));
+ WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
if (IsReferenceType(GetJavaType(descriptor))) {
(*variables)["null_check"] =
" if (value == null) {\n"
@@ -175,7 +175,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor,
} else {
(*variables)["null_check"] = "";
}
- int fixed_size = FixedSize(descriptor->type());
+ int fixed_size = FixedSize(GetType(descriptor));
if (fixed_size != -1) {
(*variables)["fixed_size"] = SimpleItoa(fixed_size);
}
@@ -218,7 +218,8 @@ GenerateBuilderMembers(io::Printer* printer) const {
"}\n"
"public Builder clear$capitalized_name$() {\n"
" result.has$capitalized_name$ = false;\n");
- if (descriptor_->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
+ JavaType type = GetJavaType(descriptor_);
+ if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
// 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_,
@@ -233,6 +234,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void PrimitiveFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void PrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (other.has$capitalized_name$()) {\n"
@@ -346,6 +352,11 @@ GenerateBuilderMembers(io::Printer* printer) const {
}
void RepeatedPrimitiveFieldGenerator::
+GenerateInitializationCode(io::Printer* printer) const {
+ // Initialized inline.
+}
+
+void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!other.$name$_.isEmpty()) {\n"
@@ -367,18 +378,19 @@ GenerateBuildingCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateParsingCode(io::Printer* printer) const {
- if (descriptor_->options().packed()) {
- printer->Print(variables_,
- "int length = input.readRawVarint32();\n"
- "int limit = input.pushLimit(length);\n"
- "while (input.getBytesUntilLimit() > 0) {\n"
- " add$capitalized_name$(input.read$capitalized_type$());\n"
- "}\n"
- "input.popLimit(limit);\n");
- } else {
- printer->Print(variables_,
- "add$capitalized_name$(input.read$capitalized_type$());\n");
- }
+ printer->Print(variables_,
+ "add$capitalized_name$(input.read$capitalized_type$());\n");
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateParsingCodeFromPacked(io::Printer* printer) const {
+ printer->Print(variables_,
+ "int length = input.readRawVarint32();\n"
+ "int limit = input.pushLimit(length);\n"
+ "while (input.getBytesUntilLimit() > 0) {\n"
+ " add$capitalized_name$(input.read$capitalized_type$());\n"
+ "}\n"
+ "input.popLimit(limit);\n");
}
void RepeatedPrimitiveFieldGenerator::
@@ -407,7 +419,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
" int dataSize = 0;\n");
printer->Indent();
- if (FixedSize(descriptor_->type()) == -1) {
+ if (FixedSize(GetType(descriptor_)) == -1) {
printer->Print(variables_,
"for ($type$ element : get$capitalized_name$List()) {\n"
" dataSize += com.google.protobuf.CodedOutputStream\n"
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h
index f9da0a62..4e482a05 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field.h
@@ -52,6 +52,7 @@ class PrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
@@ -75,9 +76,11 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
// implements FieldGenerator ---------------------------------------
void GenerateMembers(io::Printer* printer) const;
void GenerateBuilderMembers(io::Printer* printer) const;
+ void GenerateInitializationCode(io::Printer* printer) const;
void GenerateMergingCode(io::Printer* printer) const;
void GenerateBuildingCode(io::Printer* printer) const;
void GenerateParsingCode(io::Printer* printer) const;
+ void GenerateParsingCodeFromPacked(io::Printer* printer) const;
void GenerateSerializationCode(io::Printer* printer) const;
void GenerateSerializedSizeCode(io::Printer* printer) const;