vbscript: Add Replace function implementation.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
be89f93687
commit
e343fcaf76
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue