Module: wine Branch: master Commit: b900567f04dce34c11065411959ad0e3c8335114 URL: https://source.winehq.org/git/wine.git/?a=commit;h=b900567f04dce34c110654119...
Author: Dmitry Kislyuk dimaki@rocketmail.com Date: Fri Aug 7 02:41:15 2020 -0500
vbscript: Implement case insensitive search in InStrRev function.
Signed-off-by: Dmitry Kislyuk dimaki@rocketmail.com Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/vbscript/global.c | 97 +++++++++++++++++++++++++++------------------ dlls/vbscript/tests/api.vbs | 49 ++++++++++++++++++++--- 2 files changed, 102 insertions(+), 44 deletions(-)
diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c index 414ede5ed0..122f5c7b71 100644 --- a/dlls/vbscript/global.c +++ b/dlls/vbscript/global.c @@ -2398,61 +2398,80 @@ static HRESULT Global_StrReverse(BuiltinDisp *This, VARIANT *arg, unsigned args_
static HRESULT Global_InStrRev(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) { - int start, ret = 0; + int start = -1, ret = -1, mode = 0; BSTR str1, str2; + size_t len1, len2; HRESULT hres;
TRACE("%s %s arg_cnt=%u\n", debugstr_variant(args), debugstr_variant(args+1), args_cnt);
- if(args_cnt > 3) { - FIXME("Unsupported args\n"); - return E_NOTIMPL; - } - assert(2 <= args_cnt && args_cnt <= 4);
- if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (args_cnt > 2 && V_VT(args+2) == VT_NULL)) + if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (args_cnt > 2 && V_VT(args+2) == VT_NULL) + || (args_cnt == 4 && V_VT(args+3) == VT_NULL)) return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
- hres = to_string(args, &str1); - if(FAILED(hres)) - return hres; + if(args_cnt == 4) { + hres = to_int(args+3, &mode); + if(FAILED(hres)) + return hres; + if (mode != 0 && mode != 1) + return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL); + }
- hres = to_string(args+1, &str2); - if(SUCCEEDED(hres)) { - if(args_cnt > 2) { - hres = to_int(args+2, &start); - if(SUCCEEDED(hres) && start <= 0) { - FIXME("Unsupported start %d\n", start); - hres = E_NOTIMPL; - } - }else { - start = SysStringLen(str1); - } - } else { - str2 = NULL; + if(args_cnt >= 3) { + hres = to_int(args+2, &start); + if(FAILED(hres)) + return hres; + if(!start || start < -1) + return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL); }
- if(SUCCEEDED(hres)) { - const WCHAR *ptr; - size_t len; - - len = SysStringLen(str2); - if(start >= len && start <= SysStringLen(str1)) { - for(ptr = str1+start-SysStringLen(str2); ptr >= str1; ptr--) { - if(!memcmp(ptr, str2, len*sizeof(WCHAR))) { - ret = ptr-str1+1; - break; - } - } + if(V_VT(args) != VT_BSTR) { + hres = to_string(args, &str1); + if(FAILED(hres)) + return hres; + } + else + str1 = V_BSTR(args); + + if(V_VT(args+1) != VT_BSTR) { + hres = to_string(args+1, &str2); + if(FAILED(hres)) { + if(V_VT(args) != VT_BSTR) + SysFreeString(str1); + return hres; } } + else + str2 = V_BSTR(args+1);
- SysFreeString(str1); - SysFreeString(str2); - if(FAILED(hres)) - return hres; + len1 = SysStringLen(str1); + if(!len1) { + ret = 0; + goto end; + } + + if(start == -1) + start = len1; + + len2 = SysStringLen(str2); + if(!len2) { + ret = start; + goto end; + } + + if(start >= len2 && start <= len1) { + ret = FindStringOrdinal(FIND_FROMEND, str1, start, + str2, len2, mode); + } + ret++;
+end: + if(V_VT(args) != VT_BSTR) + SysFreeString(str1); + if(V_VT(args+1) != VT_BSTR) + SysFreeString(str2); return return_int(res, ret); }
diff --git a/dlls/vbscript/tests/api.vbs b/dlls/vbscript/tests/api.vbs index f829afc101..6af49c849d 100644 --- a/dlls/vbscript/tests/api.vbs +++ b/dlls/vbscript/tests/api.vbs @@ -508,18 +508,57 @@ Call ok(x = 3, "InStrRev returned " & x) x = InStrRev(1234, 34) Call ok(x = 3, "InStrRev returned " & x)
-Sub testInStrRevError(arg1, arg2, arg3, error_num) +x = InStrRev("abcd", "A", 1, 0) +Call ok(x = 0, "InStrRev returned " & x) + +x = InStrRev("abcd", "A", 1, 1) +Call ok(x = 1, "InStrRev returned " & x) + +x = InStrRev("abcd", "Ab", 1, 1) +Call ok(x = 0, "InStrRev returned " & x) + +x = InStrRev("abcd", "Ab", -1, 1) +Call ok(x = 1, "InStrRev returned " & x) + +x = InStrRev("abcd", "cd", 3, 1) +Call ok(x = 0, "InStrRev returned " & x) + +x = InStrRev("abcd", "cd", 4, 1) +Call ok(x = 3, "InStrRev returned " & x) + +x = InStrRev("abcd", "cd", 5, 1) +Call ok(x = 0, "InStrRev returned " & x) + +x = InStrRev("abc" & Chr(0) & "A" & Chr(0) & "BC", "c", 8, 0) +Call ok(x = 3, "InStrRev returned " & x) + +x = InStrRev("abc" & Chr(0) & "ABC", Chr(0) & "a", 6, 1) +Call ok(x = 4, "InStrRev returned " & x) + +x = InStrRev("", "hi", 1, 0) +Call ok(x = 0, "InStrRev returned " & x) + +x = InStrRev("abcd", "", 3, 1) +Call ok(x = 3, "InStrRev returned " & x) + +x = InStrRev("", "", 3, 0) +Call ok(x = 0, "InStrRev returned " & x) + +Sub testInStrRevError(arg1, arg2, arg3, arg4, error_num) on error resume next Dim x
Call Err.clear() - x = InStrRev(arg1, arg2, arg3) + x = InStrRev(arg1, arg2, arg3, arg4) Call ok(Err.number = error_num, "Err.number = " & Err.number) End Sub
-call testInStrRevError("abcd", null, 2, 94) -call testInStrRevError(null, "abcd", 2, 94) -call testInStrRevError("abcd", "abcd", null, 94) +call testInStrRevError("abcd", null, 2, 0, 94) +call testInStrRevError(null, "abcd", 2, 0, 94) +call testInStrRevError("abcd", "abcd", null, 0, 94) +call testInStrRevError("abcd", "abcd", 2, null, 94) +call testInStrRevError("abcd", "abcd", -20, 1, 5) +Call testInStrRevError("abcd", "abcd", 2, 10, 5)
Sub TestMid(str, start, len, ex) x = Mid(str, start, len)