am 42b5c369: am 8a15121c: Merge "Allow for ref-type arrays containing null elements."

* commit '42b5c369cd0559025938d07c73ca51d1c0c32f2e':
  Allow for ref-type arrays containing null elements.
pull/91/head
Max Cai 11 years ago committed by Android Git Automerger
commit 78fd829c6e
  1. 33
      java/src/test/java/com/google/protobuf/NanoTest.java
  2. 14
      src/google/protobuf/compiler/javanano/javanano_message_field.cc
  3. 47
      src/google/protobuf/compiler/javanano/javanano_primitive_field.cc

@ -2724,8 +2724,6 @@ public class NanoTest extends TestCase {
// Complete equality for messages with accessors: // Complete equality for messages with accessors:
TestNanoAccessors f = createMessageWithAccessorsForHashCodeEqualsTest(); TestNanoAccessors f = createMessageWithAccessorsForHashCodeEqualsTest();
TestNanoAccessors fEquivalent = createMessageWithAccessorsForHashCodeEqualsTest(); TestNanoAccessors fEquivalent = createMessageWithAccessorsForHashCodeEqualsTest();
System.out.println("equals: " + f.equals(fEquivalent));
System.out.println("hashCode: " + f.hashCode() + " vs " + fEquivalent.hashCode());
// If using accessors, explicitly setting a field to its default value // If using accessors, explicitly setting a field to its default value
// should make the message different. // should make the message different.
@ -2965,6 +2963,37 @@ public class NanoTest extends TestCase {
assertEquals(TestAllTypesNano.BAR, message.repeatedPackedNestedEnum[1]); assertEquals(TestAllTypesNano.BAR, message.repeatedPackedNestedEnum[1]);
} }
public void testNullRepeatedFieldElements() throws Exception {
// Check that serialization with null array elements doesn't NPE.
String string1 = "1";
String string2 = "2";
byte[] bytes1 = {3, 4};
byte[] bytes2 = {5, 6};
TestAllTypesNano.NestedMessage msg1 = new TestAllTypesNano.NestedMessage();
msg1.bb = 7;
TestAllTypesNano.NestedMessage msg2 = new TestAllTypesNano.NestedMessage();
msg2.bb = 8;
TestAllTypesNano message = new TestAllTypesNano();
message.repeatedString = new String[] {null, string1, string2};
message.repeatedBytes = new byte[][] {bytes1, null, bytes2};
message.repeatedNestedMessage = new TestAllTypesNano.NestedMessage[] {msg1, msg2, null};
message.repeatedGroup = new TestAllTypesNano.RepeatedGroup[] {null, null, null};
byte[] serialized = MessageNano.toByteArray(message); // should not NPE
TestAllTypesNano deserialized = MessageNano.mergeFrom(new TestAllTypesNano(), serialized);
assertEquals(2, deserialized.repeatedString.length);
assertEquals(string1, deserialized.repeatedString[0]);
assertEquals(string2, deserialized.repeatedString[1]);
assertEquals(2, deserialized.repeatedBytes.length);
assertTrue(Arrays.equals(bytes1, deserialized.repeatedBytes[0]));
assertTrue(Arrays.equals(bytes2, deserialized.repeatedBytes[1]));
assertEquals(2, deserialized.repeatedNestedMessage.length);
assertEquals(msg1.bb, deserialized.repeatedNestedMessage[0].bb);
assertEquals(msg2.bb, deserialized.repeatedNestedMessage[1].bb);
assertEquals(0, deserialized.repeatedGroup.length);
}
public void testRepeatedMerge() throws Exception { public void testRepeatedMerge() throws Exception {
// Check that merging repeated fields cause the arrays to expand with // Check that merging repeated fields cause the arrays to expand with
// new data. // new data.

@ -304,21 +304,27 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedMessageFieldGenerator:: void RepeatedMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const { GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"if (this.$name$ != null) {\n" "if (this.$name$ != null && this.$name$.length > 0) {\n"
" for ($type$ element : this.$name$) {\n" " for (int i = 0; i < this.$name$.length; i++) {\n"
" $type$ element = this.$name$[i];\n"
" if (element != null) {\n"
" output.write$group_or_message$($number$, element);\n" " output.write$group_or_message$($number$, element);\n"
" }\n" " }\n"
" }\n"
"}\n"); "}\n");
} }
void RepeatedMessageFieldGenerator:: void RepeatedMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const { GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_, printer->Print(variables_,
"if (this.$name$ != null) {\n" "if (this.$name$ != null && this.$name$.length > 0) {\n"
" for ($type$ element : this.$name$) {\n" " for (int i = 0; i < this.$name$.length; i++) {\n"
" $type$ element = this.$name$[i];\n"
" if (element != null) {\n"
" size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$group_or_message$Size($number$, element);\n" " .compute$group_or_message$Size($number$, element);\n"
" }\n" " }\n"
" }\n"
"}\n"); "}\n");
} }

@ -685,7 +685,7 @@ GenerateClearCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator:: void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const { GenerateMergingCode(io::Printer* printer) const {
// First, figure out the length of the array, then parse. // First, figure out the length of the array, then parse.
if (descriptor_->options().packed()) { if (descriptor_->is_packable() && descriptor_->options().packed()) {
printer->Print(variables_, printer->Print(variables_,
"int length = input.readRawVarint32();\n" "int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n" "int limit = input.pushLimit(length);\n"
@ -736,12 +736,26 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator:: void RepeatedPrimitiveFieldGenerator::
GenerateRepeatedDataSizeCode(io::Printer* printer) const { GenerateRepeatedDataSizeCode(io::Printer* printer) const {
// Creates a variable dataSize and puts the serialized size in // Creates a variable dataSize and puts the serialized size in there.
// there. // If the element type is a Java reference type, also generates
if (FixedSize(descriptor_->type()) == -1) { // dataCount which stores the number of non-null elements in the field.
if (IsReferenceType(GetJavaType(descriptor_))) {
printer->Print(variables_,
"int dataCount = 0;\n"
"int dataSize = 0;\n"
"for (int i = 0; i < this.$name$.length; i++) {\n"
" $type$ element = this.$name$[i];\n"
" if (element != null) {\n"
" dataCount++;\n"
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$capitalized_type$SizeNoTag(element);\n"
" }\n"
"}\n");
} else if (FixedSize(descriptor_->type()) == -1) {
printer->Print(variables_, printer->Print(variables_,
"int dataSize = 0;\n" "int dataSize = 0;\n"
"for ($type$ element : this.$name$) {\n" "for (int i = 0; i < this.$name$.length; i++) {\n"
" $type$ element = this.$name$[i];\n"
" dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n" " dataSize += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .compute$capitalized_type$SizeNoTag(element);\n" " .compute$capitalized_type$SizeNoTag(element);\n"
"}\n"); "}\n");
@ -757,18 +771,26 @@ GenerateSerializationCode(io::Printer* printer) const {
"if (this.$name$ != null && this.$name$.length > 0) {\n"); "if (this.$name$ != null && this.$name$.length > 0) {\n");
printer->Indent(); printer->Indent();
if (descriptor_->options().packed()) { if (descriptor_->is_packable() && descriptor_->options().packed()) {
GenerateRepeatedDataSizeCode(printer); GenerateRepeatedDataSizeCode(printer);
printer->Print(variables_, printer->Print(variables_,
"output.writeRawVarint32($tag$);\n" "output.writeRawVarint32($tag$);\n"
"output.writeRawVarint32(dataSize);\n" "output.writeRawVarint32(dataSize);\n"
"for ($type$ element : this.$name$) {\n" "for (int i = 0; i < this.$name$.length; i++) {\n"
" output.write$capitalized_type$NoTag(element);\n" " output.write$capitalized_type$NoTag(this.$name$[i]);\n"
"}\n"); "}\n");
} else { } else if (IsReferenceType(GetJavaType(descriptor_))) {
printer->Print(variables_, printer->Print(variables_,
"for ($type$ element : this.$name$) {\n" "for (int i = 0; i < this.$name$.length; i++) {\n"
" $type$ element = this.$name$[i];\n"
" if (element != null) {\n"
" output.write$capitalized_type$($number$, element);\n" " output.write$capitalized_type$($number$, element);\n"
" }\n"
"}\n");
} else {
printer->Print(variables_,
"for (int i = 0; i < this.$name$.length; i++) {\n"
" output.write$capitalized_type$($number$, this.$name$[i]);\n"
"}\n"); "}\n");
} }
@ -786,11 +808,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print( printer->Print(
"size += dataSize;\n"); "size += dataSize;\n");
if (descriptor_->options().packed()) { if (descriptor_->is_packable() && descriptor_->options().packed()) {
printer->Print(variables_, printer->Print(variables_,
"size += $tag_size$;\n" "size += $tag_size$;\n"
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" "size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeRawVarint32Size(dataSize);\n"); " .computeRawVarint32Size(dataSize);\n");
} else if (IsReferenceType(GetJavaType(descriptor_))) {
printer->Print(variables_,
"size += $tag_size$ * dataCount;\n");
} else { } else {
printer->Print(variables_, printer->Print(variables_,
"size += $tag_size$ * this.$name$.length;\n"); "size += $tag_size$ * this.$name$.length;\n");

Loading…
Cancel
Save