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>
This commit is contained in:
Dmitry Kislyuk 2020-08-07 02:41:15 -05:00 committed by Alexandre Julliard
parent 9b7311e709
commit b900567f04
2 changed files with 104 additions and 46 deletions

View File

@ -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) 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; BSTR str1, str2;
size_t len1, len2;
HRESULT hres; HRESULT hres;
TRACE("%s %s arg_cnt=%u\n", debugstr_variant(args), debugstr_variant(args+1), args_cnt); 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); 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); return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
hres = to_string(args, &str1); if(args_cnt == 4) {
if(FAILED(hres)) hres = to_int(args+3, &mode);
return hres; if(FAILED(hres))
return hres;
hres = to_string(args+1, &str2); if (mode != 0 && mode != 1)
if(SUCCEEDED(hres)) { return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
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(SUCCEEDED(hres)) { if(args_cnt >= 3) {
const WCHAR *ptr; hres = to_int(args+2, &start);
size_t len; if(FAILED(hres))
return hres;
len = SysStringLen(str2); if(!start || start < -1)
if(start >= len && start <= SysStringLen(str1)) { return MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
for(ptr = str1+start-SysStringLen(str2); ptr >= str1; ptr--) {
if(!memcmp(ptr, str2, len*sizeof(WCHAR))) {
ret = ptr-str1+1;
break;
}
}
}
} }
SysFreeString(str1); if(V_VT(args) != VT_BSTR) {
SysFreeString(str2); hres = to_string(args, &str1);
if(FAILED(hres)) if(FAILED(hres))
return 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);
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); return return_int(res, ret);
} }

View File

@ -508,18 +508,57 @@ Call ok(x = 3, "InStrRev returned " & x)
x = InStrRev(1234, 34) x = InStrRev(1234, 34)
Call ok(x = 3, "InStrRev returned " & x) 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 on error resume next
Dim x Dim x
Call Err.clear() Call Err.clear()
x = InStrRev(arg1, arg2, arg3) x = InStrRev(arg1, arg2, arg3, arg4)
Call ok(Err.number = error_num, "Err.number = " & Err.number) Call ok(Err.number = error_num, "Err.number = " & Err.number)
End Sub End Sub
call testInStrRevError("abcd", null, 2, 94) call testInStrRevError("abcd", null, 2, 0, 94)
call testInStrRevError(null, "abcd", 2, 94) call testInStrRevError(null, "abcd", 2, 0, 94)
call testInStrRevError("abcd", "abcd", null, 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) Sub TestMid(str, start, len, ex)
x = Mid(str, start, len) x = Mid(str, start, len)