Commit e343fcaf authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

vbscript: Add Replace function implementation.

parent be89f936
......@@ -2278,10 +2278,80 @@ static HRESULT Global_Split(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt,
return E_NOTIMPL;
}
static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
static HRESULT Global_Replace(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
{
FIXME("\n");
return E_NOTIMPL;
BSTR string, find = NULL, replace = NULL, ret;
int from = 1, cnt = -1;
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_BSTR) {
hres = to_string(args, &string);
if(FAILED(hres))
return hres;
}else {
string = V_BSTR(args);
}
if(V_VT(args+1) != VT_BSTR) {
hres = to_string(args+1, &find);
if(FAILED(hres))
goto error;
}else {
find = V_BSTR(args+1);
}
if(V_VT(args+2) != VT_BSTR) {
hres = to_string(args+2, &replace);
if(FAILED(hres))
goto error;
}else {
replace = V_BSTR(args+2);
}
if(args_cnt >= 4) {
hres = to_int(args+3, &from);
if(FAILED(hres))
goto error;
if(from < 1) {
hres = E_INVALIDARG;
goto error;
}
}
if(args_cnt >= 5) {
hres = to_int(args+4, &cnt);
if(FAILED(hres))
goto error;
if(cnt < -1) {
hres = E_INVALIDARG;
goto error;
}
}
if(args_cnt == 6)
FIXME("copare argument not supported\n");
ret = string_replace(string, find, replace, from - 1, cnt);
if(!ret) {
hres = E_OUTOFMEMORY;
}else if(res) {
V_VT(res) = VT_BSTR;
V_BSTR(res) = ret;
}else {
SysFreeString(ret);
}
error:
if(V_VT(args) != VT_BSTR)
SysFreeString(string);
if(V_VT(args+1) != VT_BSTR)
SysFreeString(find);
if(V_VT(args+2) != VT_BSTR)
SysFreeString(replace);
return hres;
}
static HRESULT Global_StrReverse(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
......
......@@ -640,11 +640,6 @@ TestLTrim "", ""
TestLTrim 123, "123"
if isEnglishLang then TestLTrim true, "True"
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)))
End Sub
Sub TestRTrim(str, exstr)
Call ok(RTrim(str) = exstr, "RTrim(" & str & ") = " & RTrim(str))
End Sub
......@@ -657,6 +652,69 @@ TestRTrim "", ""
TestRTrim 123, "123"
if isEnglishLang then TestRTrim true, "True"
sub test_replace(str, find, rep, exp)
dim r
r = Replace(str, find, rep)
ok r = exp, "Replace(""" & str & """, """ & find & """, """ & rep & """) = """ & _
r & """ expected """ & exp & """"
end sub
sub test_replace_from(str, find, rep, from, exp)
dim r
r = Replace(str, find, rep, from)
ok r = exp, "Replace(""" & str & """, """ & find & """, """ & rep & """, " & from & ") = """ & _
r & """ expected """ & exp & """"
end sub
sub test_replace_cnt(str, find, rep, from, cnt, exp)
dim r
r = Replace(str, find, rep, from, cnt)
ok r = exp, "Replace(""" & str & """, """ & find & """, """ & rep & """, " & from & ", " & cnt & ") = """ & _
r & """ expected """ & exp & """"
end sub
test_replace "xx testxx(xx)", "xx", "!", "! test!(!)"
test_replace "xxx", "", "y", "xxx"
test_replace "xxxxx", "xx", "y", "yyx"
test_replace 123, 2, 6, "163"
test_replace "xyz" & Chr(0) & "xyz", "y", "Y", "xYz" & Chr(0) & "xYz"
test_replace "xyz" & Chr(0) & "xyz", Chr(0) & "x", "Y" & Chr(0) & Chr(0), "xyzY" & Chr(0) & Chr(0) & "yz"
test_replace_from "xx testxx(xx)", "xx", "!", 1, "! test!(!)"
test_replace_from "xx testxx(xx)", "xx", "!", 1, "! test!(!)"
test_replace_from "xx testxx(xx)", "xx", "!", 2, "x test!(!)"
test_replace_from "xx testxx(xx)", "xx", "!", 2000, ""
test_replace_from "xxx", "", "y", 2, "xx"
test_replace_cnt "xx testxx(xx)", "xx", "!", 1, 2, "! test!(xx)"
test_replace_cnt "xx testxx(xx)", "xx", "!", 1, 1, "! testxx(xx)"
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)"
on error resume next
Replace "xx", "x", "y", -1
x = err.number
on error goto 0
ok x = 5, "err = " & x
on error resume next
Replace "xx", "x", "y", 0
x = err.number
on error goto 0
ok x = 5, "err = " & x
on error resume next
Replace "xx", "x", "y", 1, -2
x = err.number
on error goto 0
ok x = 5, "err = " & x
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)))
End Sub
TestRound 3, 3, "VT_I2"
TestRound 3.3, 3, "VT_R8"
TestRound 3.8, 4, "VT_R8"
......
......@@ -1629,6 +1629,48 @@ static const IRegExp2Vtbl RegExp2Vtbl = {
RegExp2_Replace
};
BSTR string_replace(BSTR string, BSTR find, BSTR replace, int from, int cnt)
{
const WCHAR *ptr, *string_end;
strbuf_t buf = { NULL, 0, 0 };
size_t replace_len, find_len;
BSTR ret = NULL;
HRESULT hres = S_OK;
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);
if(FAILED(hres))
break;
ptr++;
}else {
hres = strbuf_append(&buf, replace, replace_len);
if(FAILED(hres))
break;
ptr += find_len;
if(cnt != -1)
cnt--;
}
}
if(SUCCEEDED(hres)) {
hres = strbuf_append(&buf, ptr, string_end - ptr);
if(SUCCEEDED(hres))
ret = SysAllocStringLen(buf.buf, buf.len);
}
heap_free(buf.buf);
return ret;
}
static inline RegExp2 *impl_from_IRegExp(IRegExp *iface)
{
return CONTAINING_RECORD(iface, RegExp2, IRegExp_iface);
......
......@@ -373,6 +373,7 @@ static inline BOOL is_int32(double d)
}
HRESULT create_regexp(IDispatch**) DECLSPEC_HIDDEN;
BSTR string_replace(BSTR,BSTR,BSTR,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