summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAurash Mahbod <aurash@google.com>2013-08-14 14:09:52 -0700
committerMax Cai <maxtroy@google.com>2013-11-05 18:17:06 +0000
commitbeb57e08a44a140bf52235717f1f907ca857f360 (patch)
tree461e3f0b97a639536d0b3b34e748eeefc8890917 /src
parentbb971d53626cb286f8dc491c15d2731001c4891b (diff)
downloadexternal_protobuf-beb57e08a44a140bf52235717f1f907ca857f360.zip
external_protobuf-beb57e08a44a140bf52235717f1f907ca857f360.tar.gz
external_protobuf-beb57e08a44a140bf52235717f1f907ca857f360.tar.bz2
Allow for ref-type arrays containing null elements.
Strip the null elements out before serializing the array. This is helpful in the cases where the user wants to construct an array of an inexact size for serialization. For example: User constructs array of size 5 because they anticipate adding more than 1 element before serialization. Only 3 get added, so the array looks like [Obj, Obj, Obj, null, null]. This would curently crash without this CL. All repeated fields of ref-type elements can contain null elements: repeated strings, repeated bytes, and repeated messages/groups. Change-Id: I117391c868c9a436536d70d6151780e9cc7e8227 Conflicts: src/google/protobuf/compiler/javanano/javanano_message_field.cc
Diffstat (limited to 'src')
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.cc20
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.cc51
2 files changed, 51 insertions, 20 deletions
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
index 9f8298c..d9abea3 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
@@ -304,9 +304,12 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateSerializationCode(io::Printer* printer) const {
printer->Print(variables_,
- "if (this.$name$ != null) {\n"
- " for ($type$ element : this.$name$) {\n"
- " output.write$group_or_message$($number$, element);\n"
+ "if (this.$name$ != null && this.$name$.length > 0) {\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"
+ " }\n"
" }\n"
"}\n");
}
@@ -314,10 +317,13 @@ GenerateSerializationCode(io::Printer* printer) const {
void RepeatedMessageFieldGenerator::
GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(variables_,
- "if (this.$name$ != null) {\n"
- " for ($type$ element : this.$name$) {\n"
- " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
- " .compute$group_or_message$Size($number$, element);\n"
+ "if (this.$name$ != null && this.$name$.length > 0) {\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"
+ " .compute$group_or_message$Size($number$, element);\n"
+ " }\n"
" }\n"
"}\n");
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
index cc5fd45..5887a7e 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
@@ -685,7 +685,7 @@ GenerateClearCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateMergingCode(io::Printer* printer) const {
// First, figure out the length of the array, then parse.
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packable() && descriptor_->options().packed()) {
printer->Print(variables_,
"int length = input.readRawVarint32();\n"
"int limit = input.pushLimit(length);\n"
@@ -736,14 +736,28 @@ GenerateMergingCode(io::Printer* printer) const {
void RepeatedPrimitiveFieldGenerator::
GenerateRepeatedDataSizeCode(io::Printer* printer) const {
- // Creates a variable dataSize and puts the serialized size in
- // there.
- if (FixedSize(descriptor_->type()) == -1) {
+ // Creates a variable dataSize and puts the serialized size in there.
+ // If the element type is a Java reference type, also generates
+ // 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_,
"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"
- " .compute$capitalized_type$SizeNoTag(element);\n"
+ " .compute$capitalized_type$SizeNoTag(element);\n"
"}\n");
} else {
printer->Print(variables_,
@@ -757,18 +771,26 @@ GenerateSerializationCode(io::Printer* printer) const {
"if (this.$name$ != null && this.$name$.length > 0) {\n");
printer->Indent();
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packable() && descriptor_->options().packed()) {
GenerateRepeatedDataSizeCode(printer);
printer->Print(variables_,
"output.writeRawVarint32($tag$);\n"
"output.writeRawVarint32(dataSize);\n"
- "for ($type$ element : this.$name$) {\n"
- " output.write$capitalized_type$NoTag(element);\n"
+ "for (int i = 0; i < this.$name$.length; i++) {\n"
+ " output.write$capitalized_type$NoTag(this.$name$[i]);\n"
+ "}\n");
+ } else if (IsReferenceType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "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"
+ " }\n"
"}\n");
} else {
printer->Print(variables_,
- "for ($type$ element : this.$name$) {\n"
- " output.write$capitalized_type$($number$, element);\n"
+ "for (int i = 0; i < this.$name$.length; i++) {\n"
+ " output.write$capitalized_type$($number$, this.$name$[i]);\n"
"}\n");
}
@@ -786,14 +808,17 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
printer->Print(
"size += dataSize;\n");
- if (descriptor_->options().packed()) {
+ if (descriptor_->is_packable() && descriptor_->options().packed()) {
printer->Print(variables_,
"size += $tag_size$;\n"
"size += com.google.protobuf.nano.CodedOutputByteBufferNano\n"
" .computeRawVarint32Size(dataSize);\n");
+ } else if (IsReferenceType(GetJavaType(descriptor_))) {
+ printer->Print(variables_,
+ "size += $tag_size$ * dataCount;\n");
} else {
printer->Print(variables_,
- "size += $tag_size$ * this.$name$.length;\n");
+ "size += $tag_size$ * this.$name$.length;\n");
}
printer->Outdent();