diff options
author | Brian S. O'Neill <bronee@gmail.com> | 2009-02-26 17:39:28 +0000 |
---|---|---|
committer | Brian S. O'Neill <bronee@gmail.com> | 2009-02-26 17:39:28 +0000 |
commit | 05ef3b9f962c3bf5cdf3c27d87111015ddbb55e6 (patch) | |
tree | 417985da462be94fa4b5f9a55b7915bc08e09069 /src/main/java/com | |
parent | bda8398355eeb3c3e6ec3041d961efc1f5ae68a1 (diff) |
NPE fix when comparing nullable Float/Double/BigDecimal properties for equality.
Diffstat (limited to 'src/main/java/com')
-rw-r--r-- | src/main/java/com/amazon/carbonado/gen/CodeBuilderUtil.java | 64 |
1 files changed, 44 insertions, 20 deletions
diff --git a/src/main/java/com/amazon/carbonado/gen/CodeBuilderUtil.java b/src/main/java/com/amazon/carbonado/gen/CodeBuilderUtil.java index 7fad91f..3362ad0 100644 --- a/src/main/java/com/amazon/carbonado/gen/CodeBuilderUtil.java +++ b/src/main/java/com/amazon/carbonado/gen/CodeBuilderUtil.java @@ -445,17 +445,49 @@ public class CodeBuilderUtil { Label cont = b.createLabel();
b.branch(cont);
- // First value popped off stack is not null, but second one might
- // be. Call equals method, but swap values so that the second value is
- // an argument into the equals method.
+ // First value popped off stack is not null, but second one might be.
isNotNull.setLocation();
- b.loadLocal(value);
- b.swap();
+ if (compareToType(valueType) == null) {
+ // Call equals method, but swap values so that the second value is
+ // an argument into the equals method.
+ b.loadLocal(value);
+ b.swap();
+ } else {
+ // Need to test for second argument too, since compareTo method
+ // cannot cope with null.
+ LocalVariable value2 = b.createLocalVariable(null, valueType);
+ b.storeLocal(value2);
+ b.loadLocal(value2);
+ b.ifNullBranch(label, !choice);
+ // Load both values in preparation for calling compareTo method.
+ b.loadLocal(value);
+ b.loadLocal(value2);
+ }
+
String op = addEqualsCallTo(b, valueType, choice);
b.ifZeroComparisonBranch(label, op);
-
+
cont.setLocation();
}
+
+ /**
+ * @param fieldType must be an object type
+ * @return null if compareTo should not be called
+ */
+ private static TypeDesc compareToType(TypeDesc fieldType) {
+ if (fieldType.toPrimitiveType() == TypeDesc.FLOAT) {
+ // Special treatment to handle NaN.
+ return TypeDesc.FLOAT.toObjectType();
+ } else if (fieldType.toPrimitiveType() == TypeDesc.DOUBLE) {
+ // Special treatment to handle NaN.
+ return TypeDesc.DOUBLE.toObjectType();
+ } else if (BigDecimal.class.isAssignableFrom(fieldType.toClass())) {
+ // Call compareTo to disregard scale.
+ return TypeDesc.forClass(BigDecimal.class);
+ } else {
+ return null;
+ }
+ }
/**
* @param fieldType must be an object type
@@ -473,20 +505,12 @@ public class CodeBuilderUtil { TypeDesc.BOOLEAN, new TypeDesc[] {fieldType, fieldType});
}
return choice ? "!=" : "==";
- } else if (fieldType.toPrimitiveType() == TypeDesc.FLOAT) {
- // Special treatment to handle NaN.
- b.invokeVirtual(TypeDesc.FLOAT.toObjectType(), "compareTo", TypeDesc.INT,
- new TypeDesc[] {TypeDesc.FLOAT.toObjectType()});
- return choice ? "==" : "!=";
- } else if (fieldType.toPrimitiveType() == TypeDesc.DOUBLE) {
- // Special treatment to handle NaN.
- b.invokeVirtual(TypeDesc.DOUBLE.toObjectType(), "compareTo", TypeDesc.INT,
- new TypeDesc[] {TypeDesc.DOUBLE.toObjectType()});
- return choice ? "==" : "!=";
- } else if (BigDecimal.class.isAssignableFrom(fieldType.toClass())) {
- // Call compareTo to disregard scale.
- TypeDesc bdType = TypeDesc.forClass(BigDecimal.class);
- b.invokeVirtual(bdType, "compareTo", TypeDesc.INT, new TypeDesc[] {bdType});
+ }
+
+ TypeDesc compareToType = compareToType(fieldType);
+ if (compareToType != null) {
+ b.invokeVirtual(compareToType, "compareTo",
+ TypeDesc.INT, new TypeDesc[] {compareToType});
return choice ? "==" : "!=";
} else {
TypeDesc[] params = {TypeDesc.OBJECT};
|