Commit 3be18bb7 authored by Dmitry Kislyuk's avatar Dmitry Kislyuk Committed by Alexandre Julliard

vbscript: Implement case-insensitive search in Replace function.

parent 65c37cee
......@@ -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) {
......
......@@ -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)))
......
......@@ -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--;
}
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment