aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJames Ahlborn <jtahlborn@yahoo.com>2018-09-18 02:55:40 +0000
committerJames Ahlborn <jtahlborn@yahoo.com>2018-09-18 02:55:40 +0000
commit010cc904a5ab759f24825f34f2924c347b3b2790 (patch)
tree7cb6358c8ef9621673754e13d5d62c89b7051561 /src
parent8d5ae34b81cfc38744be68ebd9871359a8e6cbe8 (diff)
downloadjackcess-010cc904a5ab759f24825f34f2924c347b3b2790.tar.gz
jackcess-010cc904a5ab759f24825f34f2924c347b3b2790.zip
implement IsNumeric; add support for hex/oct integer strings
git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1199 f203690c-595d-4dc9-a70b-905162fa7fd2
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/expr/package-info.java4
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java20
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java39
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java14
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java4
5 files changed, 75 insertions, 6 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java b/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java
index 6531eea..416c96e 100644
--- a/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java
+++ b/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java
@@ -178,7 +178,7 @@ limitations under the License.
* <tr class="TableRowColor"><td>IsError</td><td></td></tr>
* <tr class="TableRowColor"><td>IsMissing</td><td></td></tr>
* <tr class="TableRowColor"><td>IsNull</td><td>Y</td></tr>
- * <tr class="TableRowColor"><td>IsNumeric</td><td></td></tr>
+ * <tr class="TableRowColor"><td>IsNumeric</td><td>Y</td></tr>
* <tr class="TableRowColor"><td>IsObject</td><td></td></tr>
* <tr class="TableRowColor"><td>TypeName</td><td>Y</td></tr>
* <tr class="TableRowColor"><td>VarType</td><td>Y</td></tr>
@@ -216,7 +216,7 @@ limitations under the License.
*
* <table border="1" width="25%" cellpadding="3" cellspacing="0">
* <tr class="TableHeadingColor" align="left"><th>Function</th><th>Supported</th></tr>
- * <tr class="TableRowColor"><td>Format</td><td></td></tr>
+ * <tr class="TableRowColor"><td>Format[$]</td><td></td></tr>
* <tr class="TableRowColor"><td>InStr</td><td>Y</td></tr>
* <tr class="TableRowColor"><td>InStrRev</td><td>Y</td></tr>
* <tr class="TableRowColor"><td>LCase[$]</td><td>Y</td></tr>
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java
index e927f9a..20de8ca 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java
@@ -246,6 +246,26 @@ public class DefaultFunctions
}
});
+ public static final Function ISNUMERIC = registerFunc(new Func1("IsNumeric") {
+ @Override
+ protected Value eval1(EvalContext ctx, Value param1) {
+ if(param1.getType().isNumeric()) {
+ return ValueSupport.TRUE_VAL;
+ }
+
+ if(param1.getType() == Value.Type.STRING) {
+ try {
+ param1.getAsBigDecimal();
+ return ValueSupport.TRUE_VAL;
+ } catch(NumberFormatException ignored) {
+ // fall through to FALSE_VAL
+ }
+ }
+
+ return ValueSupport.FALSE_VAL;
+ }
+ });
+
public static final Function VARTYPE = registerFunc(new Func1("VarType") {
@Override
protected Value eval1(EvalContext ctx, Value param1) {
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java
index d3e2cac..51b9c6a 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/StringValue.java
@@ -17,6 +17,8 @@ limitations under the License.
package com.healthmarketscience.jackcess.impl.expr;
import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.regex.Pattern;
/**
*
@@ -26,6 +28,12 @@ public class StringValue extends BaseValue
{
private static final Object NOT_A_NUMBER = new Object();
+ private static final char NUMBER_BASE_PREFIX = '&';
+ private static final Pattern OCTAL_PAT =
+ Pattern.compile(NUMBER_BASE_PREFIX + "[oO][0-7]+");
+ private static final Pattern HEX_PAT =
+ Pattern.compile(NUMBER_BASE_PREFIX + "[hH]\\p{XDigit}+");
+
private final String _val;
private Object _num;
@@ -75,13 +83,36 @@ public class StringValue extends BaseValue
if(_num == null) {
// see if it is parseable as a number
try {
- _num = ValueSupport.normalize(new BigDecimal(_val));
- return (BigDecimal)_num;
+ // ignore extraneous whitespace whitespace and handle "&[hH]" or
+ // "&[oO]" prefix (only supports integers)
+ String tmpVal = _val.trim();
+ if(tmpVal.length() > 0) {
+
+ if(tmpVal.charAt(0) != NUMBER_BASE_PREFIX) {
+ // parse using standard numeric support
+ _num = ValueSupport.normalize(new BigDecimal(tmpVal));
+ return (BigDecimal)_num;
+ }
+
+ // parse as hex/octal symbolic value
+ if(HEX_PAT.matcher(tmpVal).matches()) {
+ return parseIntegerString(tmpVal, 16);
+ } else if(OCTAL_PAT.matcher(tmpVal).matches()) {
+ return parseIntegerString(tmpVal, 8);
+ }
+
+ // fall through to NaN
+ }
} catch(NumberFormatException nfe) {
- _num = NOT_A_NUMBER;
- // fall through to throw...
+ // fall through to NaN...
}
+ _num = NOT_A_NUMBER;
}
throw new NumberFormatException("Invalid number '" + _val + "'");
}
+
+ private BigDecimal parseIntegerString(String tmpVal, int radix) {
+ _num = new BigDecimal(new BigInteger(tmpVal.substring(2), radix));
+ return (BigDecimal)_num;
+ }
}
diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java
index ca1a67c..e8aa234 100644
--- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java
@@ -80,7 +80,21 @@ public class DefaultFunctionsTest extends TestCase
assertEquals("-42", eval("=CStr(-42)"));
assertEquals(-1, eval("=IsNull(Null)"));
+ assertEquals(0, eval("=IsNull(13)"));
assertEquals(-1, eval("=IsDate(#01/02/2003#)"));
+ assertEquals(0, eval("=IsDate('foo')"));
+
+ assertEquals(0, eval("=IsNumeric(Null)"));
+ assertEquals(0, eval("=IsNumeric('foo')"));
+ assertEquals(0, eval("=IsNumeric(#01/02/2003#)"));
+ assertEquals(-1, eval("=IsNumeric(37)"));
+ assertEquals(-1, eval("=IsNumeric(' 37 ')"));
+ assertEquals(-1, eval("=IsNumeric(' -37.5e2 ')"));
+ assertEquals(-1, eval("=IsNumeric(' &H37 ')"));
+ assertEquals(0, eval("=IsNumeric(' &H37foo ')"));
+ assertEquals(0, eval("=IsNumeric(' &o39 ')"));
+ assertEquals(-1, eval("=IsNumeric(' &o36 ')"));
+ assertEquals(0, eval("=IsNumeric(' &o36.1 ')"));
assertEquals(1, eval("=VarType(Null)"));
assertEquals(8, eval("=VarType('blah')"));
diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java
index 188172d..5b623a0 100644
--- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java
@@ -383,6 +383,10 @@ public class ExpressionatorTest extends TestCase
assertEquals(37d, eval("=\"25\" + 12"));
assertEquals(37d, eval("=12 + \"25\""));
+ assertEquals(37d, eval("=\" 25 \" + 12"));
+ assertEquals(37d, eval("=\" &h1A \" + 11"));
+ assertEquals(37d, eval("=\" &h1a \" + 11"));
+ assertEquals(37d, eval("=\" &O32 \" + 11"));
evalFail(("=12 - \"foo\""), RuntimeException.class);
evalFail(("=\"foo\" - 12"), RuntimeException.class);