Dmitry Kislyuk : vbscript: Implement case-insensitive search in Replace function.
Alexandre Julliard
julliard at winehq.org
Wed Aug 26 15:24:44 CDT 2020
Module: wine
Branch: master
Commit: 3be18bb757de4fbd7515c47b71df70395f01a44a
URL: https://source.winehq.org/git/wine.git/?a=commit;h=3be18bb757de4fbd7515c47b71df70395f01a44a
Author: Dmitry Kislyuk <dimaki at rocketmail.com>
Date: Tue Aug 25 12:47:17 2020 -0500
vbscript: Implement case-insensitive search in Replace function.
Signed-off-by: Dmitry Kislyuk <dimaki at rocketmail.com>
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/vbscript/global.c | 22 ++++++++++++++++++----
dlls/vbscript/tests/api.vbs | 34 ++++++++++++++++++++++++++++++++++
dlls/vbscript/vbregexp.c | 19 +++++++++++--------
dlls/vbscript/vbscript.h | 2 +-
4 files changed, 64 insertions(+), 13 deletions(-)
diff --git a/dlls/vbscript/global.c b/dlls/vbscript/global.c
index cdfbdf2215..80323fe136 100644
--- a/dlls/vbscript/global.c
+++ b/dlls/vbscript/global.c
@@ -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) {
diff --git a/dlls/vbscript/tests/api.vbs b/dlls/vbscript/tests/api.vbs
index 4834029183..be95aae4b9 100644
--- a/dlls/vbscript/tests/api.vbs
+++ b/dlls/vbscript/tests/api.vbs
@@ -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)))
diff --git a/dlls/vbscript/vbregexp.c b/dlls/vbscript/vbregexp.c
index 60c99772d3..49046bc781 100644
--- a/dlls/vbscript/vbregexp.c
+++ b/dlls/vbscript/vbregexp.c
@@ -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--;
}
diff --git a/dlls/vbscript/vbscript.h b/dlls/vbscript/vbscript.h
index aa75b1c0dd..1edf7906af 100644
--- a/dlls/vbscript/vbscript.h
+++ b/dlls/vbscript/vbscript.h
@@ -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;
More information about the wine-cvs
mailing list