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