diff options
author | Ulas Kirazci <ulas@google.com> | 2013-07-23 19:03:16 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2013-07-23 19:03:17 +0000 |
commit | 19c4090eddf0eb4d65d1b41f283368c5e0f615a1 (patch) | |
tree | d30df349a57d0279cb3ff8b8b34459f3ebf22669 | |
parent | a400007ed570bbcc638c05c59727b3527238ec70 (diff) | |
parent | 0f2ca89132ab81441f7eb351c7a053a8c8d9d1c3 (diff) | |
download | external_protobuf-19c4090eddf0eb4d65d1b41f283368c5e0f615a1.zip external_protobuf-19c4090eddf0eb4d65d1b41f283368c5e0f615a1.tar.gz external_protobuf-19c4090eddf0eb4d65d1b41f283368c5e0f615a1.tar.bz2 |
Merge "Allow NaN/+inf/-inf defaults in micro/nano."
7 files changed, 141 insertions, 8 deletions
diff --git a/java/src/test/java/com/google/protobuf/MicroTest.java b/java/src/test/java/com/google/protobuf/MicroTest.java index afca135..9e18feb 100644 --- a/java/src/test/java/com/google/protobuf/MicroTest.java +++ b/java/src/test/java/com/google/protobuf/MicroTest.java @@ -2139,6 +2139,18 @@ public class MicroTest extends TestCase { assertEquals(MicroOuterClass.FOREIGN_MICRO_BAR, msg.getDefaultForeignEnum()); assertFalse(msg.hasDefaultImportEnum()); assertEquals(UnittestImportMicro.IMPORT_MICRO_BAR, msg.getDefaultImportEnum()); + assertFalse(msg.hasDefaultFloatInf()); + assertEquals(Float.POSITIVE_INFINITY, msg.getDefaultFloatInf()); + assertFalse(msg.hasDefaultFloatNegInf()); + assertEquals(Float.NEGATIVE_INFINITY, msg.getDefaultFloatNegInf()); + assertFalse(msg.hasDefaultFloatNan()); + assertEquals(Float.NaN, msg.getDefaultFloatNan()); + assertFalse(msg.hasDefaultDoubleInf()); + assertEquals(Double.POSITIVE_INFINITY, msg.getDefaultDoubleInf()); + assertFalse(msg.hasDefaultDoubleNegInf()); + assertEquals(Double.NEGATIVE_INFINITY, msg.getDefaultDoubleNegInf()); + assertFalse(msg.hasDefaultDoubleNan()); + assertEquals(Double.NaN, msg.getDefaultDoubleNan()); } /** diff --git a/java/src/test/java/com/google/protobuf/NanoTest.java b/java/src/test/java/com/google/protobuf/NanoTest.java index 5a04b6f..92ddda6 100644 --- a/java/src/test/java/com/google/protobuf/NanoTest.java +++ b/java/src/test/java/com/google/protobuf/NanoTest.java @@ -2062,6 +2062,12 @@ public class NanoTest extends TestCase { assertEquals(TestAllTypesNano.BAR, msg.defaultNestedEnum); assertEquals(NanoOuterClass.FOREIGN_NANO_BAR, msg.defaultForeignEnum); assertEquals(UnittestImportNano.IMPORT_NANO_BAR, msg.defaultImportEnum); + assertEquals(Float.POSITIVE_INFINITY, msg.defaultFloatInf); + assertEquals(Float.NEGATIVE_INFINITY, msg.defaultFloatNegInf); + assertEquals(Float.NaN, msg.defaultFloatNan); + assertEquals(Double.POSITIVE_INFINITY, msg.defaultDoubleInf); + assertEquals(Double.NEGATIVE_INFINITY, msg.defaultDoubleNegInf); + assertEquals(Double.NaN, msg.defaultDoubleNan); // Default values are not output, except for required fields. byte [] result = MessageNano.toByteArray(msg); @@ -2074,6 +2080,26 @@ public class NanoTest extends TestCase { } /** + * Tests that fields with a default value of NaN are not serialized when + * set to NaN. This is a special case as NaN != NaN, so normal equality + * checks don't work. + */ + public void testNanoNotANumberDefaults() throws Exception { + TestAllTypesNano msg = new TestAllTypesNano(); + msg.defaultDoubleNan = 0; + msg.defaultFloatNan = 0; + byte[] result = MessageNano.toByteArray(msg); + int msgSerializedSize = msg.getSerializedSize(); + assertTrue(msgSerializedSize > 3); + + msg.defaultDoubleNan = Double.NaN; + msg.defaultFloatNan = Float.NaN; + result = MessageNano.toByteArray(msg); + msgSerializedSize = msg.getSerializedSize(); + assertEquals(3, msgSerializedSize); + } + + /** * Test that a bug in skipRawBytes() has been fixed: if the skip skips * exactly up to a limit, this should not break things. */ diff --git a/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc b/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc index c23080e..e406a0e 100644 --- a/src/google/protobuf/compiler/javamicro/javamicro_helpers.cc +++ b/src/google/protobuf/compiler/javamicro/javamicro_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/javamicro/javamicro_helpers.h> @@ -344,10 +345,30 @@ string DefaultValue(const Params& params, 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: diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index 80ee7a0..2564a58 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_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/javanano/javanano_helpers.h> @@ -422,10 +423,30 @@ string DefaultValue(const Params& params, 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: diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index a8afe94..987a103 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -33,6 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include <map> +#include <math.h> #include <string> #include <google/protobuf/compiler/javanano/javanano_primitive_field.h> @@ -174,6 +175,38 @@ int FixedSize(FieldDescriptor::Type type) { return -1; } +// Returns true if the field has a default value equal to NaN. +bool IsDefaultNaN(const FieldDescriptor* field) { + switch (field->type()) { + case FieldDescriptor::TYPE_INT32 : return false; + case FieldDescriptor::TYPE_UINT32 : return false; + case FieldDescriptor::TYPE_SINT32 : return false; + case FieldDescriptor::TYPE_FIXED32 : return false; + case FieldDescriptor::TYPE_SFIXED32: return false; + case FieldDescriptor::TYPE_INT64 : return false; + case FieldDescriptor::TYPE_UINT64 : return false; + case FieldDescriptor::TYPE_SINT64 : return false; + case FieldDescriptor::TYPE_FIXED64 : return false; + case FieldDescriptor::TYPE_SFIXED64: return false; + case FieldDescriptor::TYPE_FLOAT : + return isnan(field->default_value_float()); + case FieldDescriptor::TYPE_DOUBLE : + return isnan(field->default_value_double()); + case FieldDescriptor::TYPE_BOOL : return false; + case FieldDescriptor::TYPE_STRING : return false; + case FieldDescriptor::TYPE_BYTES : return false; + case FieldDescriptor::TYPE_ENUM : return false; + case FieldDescriptor::TYPE_GROUP : return false; + case FieldDescriptor::TYPE_MESSAGE : return false; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + // Return true if the type is a that has variable length // for instance String's. bool IsVariableLenType(JavaType type) { @@ -308,6 +341,9 @@ GenerateSerializationCode(io::Printer* printer) const { } else if (IsReferenceType(GetJavaType(descriptor_))) { printer->Print(variables_, "if (!this.$name$.equals($default$)) {\n"); + } else if (IsDefaultNaN(descriptor_)) { + printer->Print(variables_, + "if (!$capitalized_type$.isNaN(this.$name$)) {\n"); } else { printer->Print(variables_, "if (this.$name$ != $default$) {\n"); @@ -332,6 +368,9 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } else if (IsReferenceType(GetJavaType(descriptor_))) { printer->Print(variables_, "if (!this.$name$.equals($default$)) {\n"); + } else if (IsDefaultNaN(descriptor_)) { + printer->Print(variables_, + "if (!$capitalized_type$.isNaN(this.$name$)) {\n"); } else { printer->Print(variables_, "if (this.$name$ != $default$) {\n"); diff --git a/src/google/protobuf/unittest_micro.proto b/src/google/protobuf/unittest_micro.proto index 3d7fcd2..e6b4618 100644 --- a/src/google/protobuf/unittest_micro.proto +++ b/src/google/protobuf/unittest_micro.proto @@ -133,6 +133,13 @@ message TestAllTypesMicro { optional string default_string = 74 [default = "hello"]; optional bytes default_bytes = 75 [default = "world"]; + optional float default_float_inf = 96 [default = inf]; + optional float default_float_neg_inf = 97 [default = -inf]; + optional float default_float_nan = 98 [default = nan]; + optional double default_double_inf = 99 [default = inf]; + optional double default_double_neg_inf = 100 [default = -inf]; + optional double default_double_nan = 101 [default = nan]; + optional NestedEnum default_nested_enum = 81 [default = BAR]; optional ForeignEnumMicro default_foreign_enum = 82 [default = FOREIGN_MICRO_BAR]; diff --git a/src/google/protobuf/unittest_nano.proto b/src/google/protobuf/unittest_nano.proto index e9a0d83..1a6ba26 100644 --- a/src/google/protobuf/unittest_nano.proto +++ b/src/google/protobuf/unittest_nano.proto @@ -142,6 +142,13 @@ message TestAllTypesNano { optional string default_string_nonascii = 76 [default = "dünya"]; optional bytes default_bytes_nonascii = 77 [default = "dünyab"]; + optional float default_float_inf = 97 [default = inf]; + optional float default_float_neg_inf = 98 [default = -inf]; + optional float default_float_nan = 99 [default = nan]; + optional double default_double_inf = 100 [default = inf]; + optional double default_double_neg_inf = 101 [default = -inf]; + optional double default_double_nan = 102 [default = nan]; + optional NestedEnum default_nested_enum = 81 [default = BAR]; optional ForeignEnumNano default_foreign_enum = 82 [default = FOREIGN_NANO_BAR]; |