From: James Ahlborn Date: Fri, 2 Nov 2018 20:14:59 +0000 (+0000) Subject: implement Val function X-Git-Tag: jackcess-2.2.1~18 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=504a1d8c0b68ba1235e2ffb56d957f23eb515a35;p=jackcess.git implement Val function git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1214 f203690c-595d-4dc9-a70b-905162fa7fd2 --- 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 4db1b0d..e9f84db 100644 --- a/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java +++ b/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java @@ -111,7 +111,7 @@ limitations under the License. * Oct[$]Y * Str[$]Y * StringFromGUID - * Val + * ValY * CBoolY * CByteY * CCurY 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 ae4d268..24f6d99 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctions.java @@ -350,43 +350,52 @@ public class DefaultFunctions } }); - // public static final Function VAL = registerStringFunc(new Func1NullIsNull("Val") { - // @Override - // protected Value eval1(EvalContext ctx, Value param1) { - // String str = param1.getAsString(ctx).trim(); - - // if(str.length() == 0) { - // return ValueSupport.ZERO_VAL; - // } - - // Matcher m = null; - - // if(str.charAt(0) == ValueSupport.NUMBER_BASE_PREFIX) { - // // see if we can parse as a radix format - // if((m = ValueSupport.HEX_PAT.matcher(str)).find()) { - // BigInteger bi = ValueSupport.parseIntegerString(m.group(), 16); - // // FIXME, what to do with large numbers? to double or decimal? - // return ValueSupport.toValue(bi.intValue()); - // } else if((m = ValueSupport.OCTAL_PAT.matcher(str)).find()) { - // BigInteger bi = ValueSupport.parseIntegerString(m.group(), 8); - // // FIXME, what to do with large numbers? to double or decimal? - // return ValueSupport.toValue(bi.intValue()); - // } - - // return ValueSupport.ZERO_VAL; - // } - - // // parse ase normal "decimal" number. - // // FIXME - leading '+'? exponent? - // if((m = ValueSupport.NUMBER_PAT.matcher(str)).find()) { - - // } - - // // return ValueSupport.toValue(Integer.toHexString(lv).toUpperCase()); - // return null; - // } - // }); - + public static final Function VAL = registerStringFunc(new Func1NullIsNull("Val") { + @Override + protected Value eval1(EvalContext ctx, Value param1) { + + // strip all whitespace from string + String str = ValueSupport.WHITESPACE_PAT.matcher(param1.getAsString(ctx)) + .replaceAll(""); + + if(str.length() == 0) { + return ValueSupport.ZERO_D_VAL; + } + + Matcher m = null; + + if(str.charAt(0) == ValueSupport.NUMBER_BASE_PREFIX) { + + // see if we can parse as a radix format + BigInteger bi = null; + if((m = ValueSupport.HEX_PAT.matcher(str)).find()) { + bi = ValueSupport.parseIntegerString(m.group(), 16); + } else if((m = ValueSupport.OCTAL_PAT.matcher(str)).find()) { + bi = ValueSupport.parseIntegerString(m.group(), 8); + } + + if(bi != null) { + // this function works differently than normal string to number + // conversion. it seems to coerce these values to a short/long int + // depending on the size of the number (which creates + // positive/negative values dependent on the value length) + int iVal = ((bi.bitLength() <= 16) ? bi.shortValue() : bi.intValue()); + return ValueSupport.toValue((double)iVal); + } + + } else { + + // parse as normal "decimal" number. + if((m = ValueSupport.NUMBER_PAT.matcher(str)).find()) { + BigDecimal bd = new BigDecimal(m.group()); + return ValueSupport.toValue(bd.doubleValue()); + } + } + + return ValueSupport.ZERO_D_VAL; + } + }); + private static boolean stringIsNumeric(EvalContext ctx, Value param) { try { param.getAsBigDecimal(ctx); diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/ValueSupport.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/ValueSupport.java index e2a7173..d0f8bf8 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/ValueSupport.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/ValueSupport.java @@ -53,6 +53,7 @@ public class ValueSupport public static final Value ZERO_VAL = FALSE_VAL; public static final Value NEG_ONE_VAL = TRUE_VAL; public static final Value ONE_VAL = new LongValue(1); + public static final Value ZERO_D_VAL = new DoubleValue(0d); static final char NUMBER_BASE_PREFIX = '&'; static final Pattern OCTAL_PAT = @@ -60,8 +61,10 @@ public class ValueSupport static final Pattern HEX_PAT = Pattern.compile("^" + NUMBER_BASE_PREFIX + "[hH]\\p{XDigit}+"); static final char CANON_DEC_SEP = '.'; - static final Pattern NUMBER_PAT = Pattern.compile("^[-+]?[0-9]*[.]?[0-9]*"); - + static final Pattern NUMBER_PAT = + Pattern.compile("^[+-]?(([0-9]+[.]?[0-9]*)|([.][0-9]+))([eE][+-]?[0-9]+)?"); + static final Pattern WHITESPACE_PAT = Pattern.compile("[ \\t\\r\\n]+"); + private ValueSupport() {} public static Value toValue(boolean b) { 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 5f0a045..98aea88 100644 --- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java @@ -195,6 +195,16 @@ public class DefaultFunctionsTest extends TestCase } catch(EvalException e) { assertTrue(e.getMessage().contains("Invalid function call")); } + + assertEquals(1615198d, eval("=Val(' 1615 198th Street N.E.')")); + assertEquals(-1d, eval("=Val(' &HFFFFwhatever')")); + assertEquals(131071d, eval("=Val(' &H1FFFFwhatever')")); + assertEquals(-1d, eval("=Val(' &HFFFFFFFFwhatever')")); + assertEquals(291d, eval("=Val(' &H123whatever')")); + assertEquals(83d, eval("=Val(' &O123whatever')")); + assertEquals(1.23d, eval("=Val(' 1 2 3 e -2 whatever')")); + assertEquals(0d, eval("=Val(' whatever123 ')")); + assertEquals(0d, eval("=Val('')")); } public void testNumberFuncs() throws Exception