From: James Ahlborn Date: Sat, 3 Nov 2018 06:06:36 +0000 (+0000) Subject: implement replace function X-Git-Tag: jackcess-2.2.1~17 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=45699400f09b0fe60543841f2105af25367ef53f;p=jackcess.git implement replace function git-svn-id: https://svn.code.sf.net/p/jackcess/code/jackcess/trunk@1215 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 e9f84db..a8a697c 100644 --- a/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java +++ b/src/main/java/com/healthmarketscience/jackcess/expr/package-info.java @@ -225,7 +225,7 @@ limitations under the License. * RTrim[$]Y * Trim[$]Y * Mid[$]Y - * Replace + * ReplaceY * Right[$]Y * Space[$]Y * StrCompY diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java index 5752d58..42b037e 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultDateFunctions.java @@ -464,18 +464,6 @@ public class DefaultDateFunctions return getOptionalIntParam(ctx, params, idx, 1, 0); } - private static int getOptionalIntParam( - LocaleContext ctx, Value[] params, int idx, int defValue, int useDefValue) { - int val = defValue; - if(params.length > idx) { - val = params[idx].getAsLongInt(ctx); - if(val == useDefValue) { - val = defValue; - } - } - return val; - } - private static int weekOfYear(EvalContext ctx, Value param, int firstDay, int firstWeekType) { Calendar cal = nonNullToCalendar(ctx, param); diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java index 2e8a04e..43bf5f4 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultNumberFunctions.java @@ -184,14 +184,4 @@ public class DefaultNumberFunctions return ValueSupport.toValue(Math.tan(param1.getAsDouble(ctx))); } }); - - - // public static final Function VAL = registerFunc(new Func1("Val") { - // @Override - // protected Value eval1(EvalContext ctx, Value param1) { - // // FIXME, maybe leverage ExpressionTokenizer.maybeParseNumberLiteral (note, leading - or + is valid, exponent form is valid) - // } - // }); - - } diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java index 42212cf..5291c3c 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/DefaultTextFunctions.java @@ -136,10 +136,7 @@ public class DefaultTextFunctions // 1 based offsets return ValueSupport.toValue(start + 1); } - boolean ignoreCase = true; - if(params.length > 3) { - ignoreCase = doIgnoreCase(ctx, params[3]); - } + boolean ignoreCase = getIgnoreCase(ctx, params, 3); int end = s1Len - s2Len; while(start < end) { if(s1.regionMatches(ignoreCase, start, s2, 0, s2Len)) { @@ -183,10 +180,7 @@ public class DefaultTextFunctions // 1 based offsets --start; } - boolean ignoreCase = true; - if(params.length > 3) { - ignoreCase = doIgnoreCase(ctx, params[3]); - } + boolean ignoreCase = getIgnoreCase(ctx, params, 3); start = Math.min(s1Len - s2Len, start - s2Len + 1); while(start >= 0) { if(s1.regionMatches(ignoreCase, start, s2, 0, s2Len)) { @@ -290,6 +284,54 @@ public class DefaultTextFunctions } }); + public static final Function REPLACE = registerStringFunc(new FuncVar("Replace", 3, 6) { + @Override + protected Value evalVar(EvalContext ctx, Value[] params) { + String str = params[0].getAsString(ctx); + String searchStr = params[1].getAsString(ctx); + String replStr = params[2].getAsString(ctx); + + int strLen = str.length(); + + int start = getOptionalIntParam(ctx, params, 3, 1) - 1; + int count = getOptionalIntParam(ctx, params, 4, -1); + boolean ignoreCase = getIgnoreCase(ctx, params, 5); + + if(start >= strLen) { + return ValueSupport.EMPTY_STR_VAL; + } + + int searchLen = searchStr.length(); + if((searchLen == 0) || (count == 0)) { + String result = str; + if(start > 0) { + result = str.substring(start); + } + return ValueSupport.toValue(result); + } + + if(count < 0) { + count = strLen; + } + + StringBuilder result = new StringBuilder(strLen); + + int matchCount = 0; + for(int i = start; i < strLen; ++i) { + if((matchCount < count) && + str.regionMatches(ignoreCase, i, searchStr, 0, searchLen)) { + result.append(replStr); + ++matchCount; + i += searchLen - 1; + } else { + result.append(str.charAt(i)); + } + } + + return ValueSupport.toValue(result.toString()); + } + }); + public static final Function SPACE = registerStringFunc(new Func1("Space") { @Override protected Value eval1(EvalContext ctx, Value param1) { @@ -308,10 +350,7 @@ public class DefaultTextFunctions } String s1 = param1.getAsString(ctx); String s2 = param2.getAsString(ctx); - boolean ignoreCase = true; - if(params.length > 2) { - ignoreCase = doIgnoreCase(ctx, params[2]); - } + boolean ignoreCase = getIgnoreCase(ctx, params, 2); int cmp = (ignoreCase ? s1.compareToIgnoreCase(s2) : s1.compareTo(s2)); // stupid java doesn't return 1, -1, 0... @@ -412,6 +451,14 @@ public class DefaultTextFunctions return str.substring(start, end); } + private static boolean getIgnoreCase(EvalContext ctx, Value[] params, int idx) { + boolean ignoreCase = true; + if(params.length > idx) { + ignoreCase = doIgnoreCase(ctx, params[idx]); + } + return ignoreCase; + } + private static boolean doIgnoreCase(LocaleContext ctx, Value paramCmp) { int cmpType = paramCmp.getAsLongInt(ctx); switch(cmpType) { diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/FunctionSupport.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/FunctionSupport.java index 79e4609..aa978e2 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/FunctionSupport.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/FunctionSupport.java @@ -254,4 +254,22 @@ public class FunctionSupport } return defValue; } + + public static int getOptionalIntParam( + LocaleContext ctx, Value[] params, int idx, int defValue) { + return getOptionalIntParam(ctx, params, idx, defValue, defValue); + } + + public static int getOptionalIntParam( + LocaleContext ctx, Value[] params, int idx, int defValue, int useDefValue) { + int val = defValue; + if(params.length > idx) { + val = params[idx].getAsLongInt(ctx); + if(val == useDefValue) { + val = defValue; + } + } + return val; + } + } 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 98aea88..4b6e388 100644 --- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java @@ -205,6 +205,22 @@ public class DefaultFunctionsTest extends TestCase assertEquals(1.23d, eval("=Val(' 1 2 3 e -2 whatever')")); assertEquals(0d, eval("=Val(' whatever123 ')")); assertEquals(0d, eval("=Val('')")); + + assertEquals("faa", eval("=Replace('foo','o','a')")); + assertEquals("faa", eval("=Replace('fOo','o','a')")); + assertEquals("aa", eval("=Replace('foo','o','a',2)")); + assertEquals("oo", eval("=Replace('foo','o','a',2,0)")); + assertEquals("", eval("=Replace('foo','o','a',4)")); + assertEquals("foo", eval("=Replace('foo','','a')")); + assertEquals("o", eval("=Replace('foo','','a',3)")); + assertEquals("fahhabahhaahha", eval("=Replace('fooboooo','OO','ahha')")); + assertEquals("fahhaboooo", eval("=Replace('fooboooo','OO','ahha',1,1)")); + assertEquals("fooboooo", eval("=Replace('fooboooo','OO','ahha',1,1,0)")); + assertEquals("ahhabahhaahha", eval("=Replace('fooboooo','OO','ahha',2)")); + assertEquals("obahhaahha", eval("=Replace('fooboooo','OO','ahha',3)")); + assertEquals("fb", eval("=Replace('fooboooo','OO','')")); + assertEquals("", eval("=Replace('','o','a')")); + assertEquals("foo", eval("=Replace('foo','foobar','a')")); } public void testNumberFuncs() throws Exception