vbscript: Implement case-insensitive search in Replace 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-25 12:47:17 -05:00 committed by Alexandre Julliard
parent 65c37cee24
commit 3be18bb757
4 changed files with 64 additions and 13 deletions

View File

@ -2449,12 +2449,19 @@ error:
static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
{
BSTR string, find = NULL, replace = NULL, ret;
int from = 1, cnt = -1;
int from = 1, cnt = -1, mode = 0;
HRESULT hres = S_OK;
TRACE("%s %s %s %u...\n", debugstr_variant(args), debugstr_variant(args+1), debugstr_variant(args+2), args_cnt);
assert(3 <= args_cnt && args_cnt <= 6);
if(V_VT(args) == VT_NULL || V_VT(args+1) == VT_NULL || (V_VT(args+2) == VT_NULL)
|| (args_cnt >= 4 && V_VT(args+3) == VT_NULL) || (args_cnt >= 5 && V_VT(args+4) == VT_NULL)
|| (args_cnt == 6 && V_VT(args+5) == VT_NULL))
return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
if(V_VT(args) != VT_BSTR) {
hres = to_string(args, &string);
if(FAILED(hres))
@ -2499,10 +2506,17 @@ static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *args, unsigned args_cn
}
}
if(args_cnt == 6)
FIXME("copare argument not supported\n");
if(args_cnt == 6) {
hres = to_int(args+5, &mode);
if(FAILED(hres))
goto error;
if (mode != 0 && mode != 1) {
hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
goto error;
}
}
ret = string_replace(string, find, replace, from - 1, cnt);
ret = string_replace(string, find, replace, from - 1, cnt, mode);
if(!ret) {
hres = E_OUTOFMEMORY;
}else if(res) {

View File

@ -844,6 +844,7 @@ TestRTrim "", ""
TestRTrim 123, "123"
if isEnglishLang then TestRTrim true, "True"
sub test_replace(str, find, rep, exp)
dim r
r = Replace(str, find, rep)
@ -865,8 +866,17 @@ sub test_replace_cnt(str, find, rep, from, cnt, exp)
r & """ expected """ & exp & """"
end sub
sub test_replace_mode(str, find, rep, from, cnt, mode, exp)
dim r
r = Replace(str, find, rep, from, cnt, mode)
ok r = exp, "Replace(""" & str & """, """ & find & """, """ & rep & """, " & from & ", " & cnt & ", " & mode _
& ") = """ & r & """ expected """ & exp & """"
end sub
test_replace "xx testxx(xx)", "xx", "!", "! test!(!)"
test_replace "", "x", "y", ""
test_replace "xxx", "", "y", "xxx"
test_replace "yxxy", "x", "", "yy"
test_replace "xxxxx", "xx", "y", "yyx"
test_replace 123, 2, 6, "163"
test_replace "xyz" & Chr(0) & "xyz", "y", "Y", "xYz" & Chr(0) & "xYz"
@ -884,6 +894,12 @@ test_replace_cnt "xx testxx(xx)", "xx", "!", 2, 1, "x test!(xx)"
test_replace_cnt "xx testxx(xx)", "xx", "!", 1, -1, "! test!(!)"
test_replace_cnt "xx testxx(xx)", "xx", "!", 1, 0, "xx testxx(xx)"
test_replace_mode "Aa testAAa(aa)", "aa", "!", 1, 2, 1, "! test!a(aa)"
test_replace_mode "aA testaa(aa)", "AA", "!", 1, 1, 1, "! testaa(aa)"
test_replace_mode "aa testAa(aa)", "aa", "!", 2, 2, 0, "a testAa(!)"
test_replace_mode "aa testAA(aA)", "Aa", "!", 1, -1, 1, "! test!(!)"
test_replace_mode "aa testaa(aa)", "A", "!", 1, -1, 1, "!! test!!(!!)"
on error resume next
Replace "xx", "x", "y", -1
x = err.number
@ -902,6 +918,24 @@ x = err.number
on error goto 0
ok x = 5, "err = " & x
Sub testReplaceError(arg1, arg2, arg3, arg4, arg5, arg6, error_num)
on error resume next
Dim x
Call Err.clear()
x = Replace(arg1, arg2, arg3, arg4, arg5, arg6)
Call ok(Err.number = error_num, "Err.number = " & Err.number)
End Sub
Call testReplaceError(Null, "x", "y", 1, 1, 0, 94)
Call testReplaceError("xx", null, "y", 1, 1, 0, 94)
Call testReplaceError("xx", "x", null, 1, 1, 0, 94)
Call testReplaceError("xx", "x", "y", null, 1, 0, 94)
Call testReplaceError("xx", "x", "y", 1, null, 0, 94)
Call testReplaceError("xx", "x", "y", 1, 1, null, 94)
Call testReplaceError("xx", "x", "y", 1, 1, 8, 5)
Sub TestRound(val, exval, vt)
Call ok(Round(val) = exval, "Round(" & val & ") = " & Round(val))
Call ok(getVT(Round(val)) = vt, "getVT(Round(" & val & ")) = " & getVT(Round(val)))

View File

@ -1629,33 +1629,36 @@ static const IRegExp2Vtbl RegExp2Vtbl = {
RegExp2_Replace
};
BSTR string_replace(BSTR string, BSTR find, BSTR replace, int from, int cnt)
BSTR string_replace(BSTR string, BSTR find, BSTR replace, int from, int cnt, int mode)
{
const WCHAR *ptr, *string_end;
strbuf_t buf = { NULL, 0, 0 };
size_t replace_len, find_len;
BSTR ret = NULL;
HRESULT hres = S_OK;
int pos;
string_end = string + SysStringLen(string);
ptr = from > SysStringLen(string) ? string_end : string + from;
find_len = SysStringLen(find);
replace_len = SysStringLen(replace);
if(!replace_len)
cnt = 0;
while(string_end - ptr >= find_len && cnt && find_len) {
if(memcmp(ptr, find, find_len * sizeof(WCHAR))) {
hres = strbuf_append(&buf, ptr, 1);
pos = FindStringOrdinal(FIND_FROMSTART, ptr, string_end - ptr,
find, find_len, mode);
if(pos == -1)
break;
else {
hres = strbuf_append(&buf, ptr, pos);
if(FAILED(hres))
break;
ptr++;
}else {
hres = strbuf_append(&buf, replace, replace_len);
if(FAILED(hres))
break;
ptr += find_len;
ptr = ptr + pos + find_len;
if(cnt != -1)
cnt--;
}

View File

@ -393,7 +393,7 @@ static inline BOOL is_digit(WCHAR c)
}
HRESULT create_regexp(IDispatch**) DECLSPEC_HIDDEN;
BSTR string_replace(BSTR,BSTR,BSTR,int,int) DECLSPEC_HIDDEN;
BSTR string_replace(BSTR,BSTR,BSTR,int,int,int) DECLSPEC_HIDDEN;
HRESULT map_hres(HRESULT) DECLSPEC_HIDDEN;