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: ...@@ -2449,12 +2449,19 @@ error:
static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res) static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
{ {
BSTR string, find = NULL, replace = NULL, ret; BSTR string, find = NULL, replace = NULL, ret;
int from = 1, cnt = -1; int from = 1, cnt = -1, mode = 0;
HRESULT hres = S_OK; HRESULT hres = S_OK;
TRACE("%s %s %s %u...\n", debugstr_variant(args), debugstr_variant(args+1), debugstr_variant(args+2), args_cnt); 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); 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) { if(V_VT(args) != VT_BSTR) {
hres = to_string(args, &string); hres = to_string(args, &string);
if(FAILED(hres)) if(FAILED(hres))
...@@ -2499,10 +2506,17 @@ static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *args, unsigned args_cn ...@@ -2499,10 +2506,17 @@ static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *args, unsigned args_cn
} }
} }
if(args_cnt == 6) if(args_cnt == 6) {
FIXME("copare argument not supported\n"); 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) { if(!ret) {
hres = E_OUTOFMEMORY; hres = E_OUTOFMEMORY;
}else if(res) { }else if(res) {
......
...@@ -844,6 +844,7 @@ TestRTrim "", "" ...@@ -844,6 +844,7 @@ TestRTrim "", ""
TestRTrim 123, "123" TestRTrim 123, "123"
if isEnglishLang then TestRTrim true, "True" if isEnglishLang then TestRTrim true, "True"
sub test_replace(str, find, rep, exp) sub test_replace(str, find, rep, exp)
dim r dim r
r = Replace(str, find, rep) r = Replace(str, find, rep)
...@@ -865,8 +866,17 @@ sub test_replace_cnt(str, find, rep, from, cnt, exp) ...@@ -865,8 +866,17 @@ sub test_replace_cnt(str, find, rep, from, cnt, exp)
r & """ expected """ & exp & """" r & """ expected """ & exp & """"
end sub 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 "xx testxx(xx)", "xx", "!", "! test!(!)"
test_replace "", "x", "y", ""
test_replace "xxx", "", "y", "xxx" test_replace "xxx", "", "y", "xxx"
test_replace "yxxy", "x", "", "yy"
test_replace "xxxxx", "xx", "y", "yyx" test_replace "xxxxx", "xx", "y", "yyx"
test_replace 123, 2, 6, "163" test_replace 123, 2, 6, "163"
test_replace "xyz" & Chr(0) & "xyz", "y", "Y", "xYz" & Chr(0) & "xYz" 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)" ...@@ -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, -1, "! test!(!)"
test_replace_cnt "xx testxx(xx)", "xx", "!", 1, 0, "xx testxx(xx)" 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 on error resume next
Replace "xx", "x", "y", -1 Replace "xx", "x", "y", -1
x = err.number x = err.number
...@@ -902,6 +918,24 @@ x = err.number ...@@ -902,6 +918,24 @@ x = err.number
on error goto 0 on error goto 0
ok x = 5, "err = " & x 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) Sub TestRound(val, exval, vt)
Call ok(Round(val) = exval, "Round(" & val & ") = " & Round(val)) Call ok(Round(val) = exval, "Round(" & val & ") = " & Round(val))
Call ok(getVT(Round(val)) = vt, "getVT(Round(" & val & ")) = " & getVT(Round(val))) Call ok(getVT(Round(val)) = vt, "getVT(Round(" & val & ")) = " & getVT(Round(val)))
......
...@@ -1629,33 +1629,36 @@ static const IRegExp2Vtbl RegExp2Vtbl = { ...@@ -1629,33 +1629,36 @@ static const IRegExp2Vtbl RegExp2Vtbl = {
RegExp2_Replace 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; const WCHAR *ptr, *string_end;
strbuf_t buf = { NULL, 0, 0 }; strbuf_t buf = { NULL, 0, 0 };
size_t replace_len, find_len; size_t replace_len, find_len;
BSTR ret = NULL; BSTR ret = NULL;
HRESULT hres = S_OK; HRESULT hres = S_OK;
int pos;
string_end = string + SysStringLen(string); string_end = string + SysStringLen(string);
ptr = from > SysStringLen(string) ? string_end : string + from; ptr = from > SysStringLen(string) ? string_end : string + from;
find_len = SysStringLen(find); find_len = SysStringLen(find);
replace_len = SysStringLen(replace); replace_len = SysStringLen(replace);
if(!replace_len)
cnt = 0;
while(string_end - ptr >= find_len && cnt && find_len) { while(string_end - ptr >= find_len && cnt && find_len) {
if(memcmp(ptr, find, find_len * sizeof(WCHAR))) { pos = FindStringOrdinal(FIND_FROMSTART, ptr, string_end - ptr,
hres = strbuf_append(&buf, ptr, 1); find, find_len, mode);
if(pos == -1)
break;
else {
hres = strbuf_append(&buf, ptr, pos);
if(FAILED(hres)) if(FAILED(hres))
break; break;
ptr++;
}else {
hres = strbuf_append(&buf, replace, replace_len); hres = strbuf_append(&buf, replace, replace_len);
if(FAILED(hres)) if(FAILED(hres))
break; break;
ptr += find_len;
ptr = ptr + pos + find_len;
if(cnt != -1) if(cnt != -1)
cnt--; cnt--;
} }
......
...@@ -393,7 +393,7 @@ static inline BOOL is_digit(WCHAR c) ...@@ -393,7 +393,7 @@ static inline BOOL is_digit(WCHAR c)
} }
HRESULT create_regexp(IDispatch**) DECLSPEC_HIDDEN; 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; 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