vbscript: Implement Split.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47570 Signed-off-by: Robert Wilhelm <robert.wilhelm@gmx.net> Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
60f1fe59a9
commit
d50f5f67c7
|
@ -2291,10 +2291,153 @@ static HRESULT Global_Join(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, V
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT Global_Split(BuiltinDisp *This, VARIANT *arg, unsigned args_cnt, VARIANT *res)
|
static HRESULT Global_Split(BuiltinDisp *This, VARIANT *args, unsigned args_cnt, VARIANT *res)
|
||||||
{
|
{
|
||||||
FIXME("\n");
|
BSTR str, string, delimeter = NULL;
|
||||||
return E_NOTIMPL;
|
int count, max, mode, len, start, end, ret, delimeterlen = 1;
|
||||||
|
int i,*indices = NULL, indices_max = 8;
|
||||||
|
SAFEARRAYBOUND bounds;
|
||||||
|
SAFEARRAY *sa = NULL;
|
||||||
|
VARIANT *data, var;
|
||||||
|
HRESULT hres = S_OK;
|
||||||
|
|
||||||
|
TRACE("%s %u...\n", debugstr_variant(args), args_cnt);
|
||||||
|
|
||||||
|
assert(1 <= args_cnt && args_cnt <= 4);
|
||||||
|
|
||||||
|
if(V_VT(args) == VT_NULL || (args_cnt > 1 && V_VT(args+1) == VT_NULL) || (args_cnt > 2 && V_VT(args+2) == VT_NULL)
|
||||||
|
|| (args_cnt == 4 && V_VT(args+3) == VT_NULL))
|
||||||
|
return MAKE_VBSERROR(VBSE_ILLEGAL_NULL_USE);
|
||||||
|
|
||||||
|
if(V_VT(args) != VT_BSTR) {
|
||||||
|
hres = to_string(args, &string);
|
||||||
|
if(FAILED(hres))
|
||||||
|
return hres;
|
||||||
|
}else {
|
||||||
|
string = V_BSTR(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(args_cnt > 1) {
|
||||||
|
if(V_VT(args+1) != VT_BSTR) {
|
||||||
|
hres = to_string(args+1, &delimeter);
|
||||||
|
if(FAILED(hres))
|
||||||
|
goto error;
|
||||||
|
}else {
|
||||||
|
delimeter = V_BSTR(args+1);
|
||||||
|
}
|
||||||
|
delimeterlen = SysStringLen(delimeter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(args_cnt > 2) {
|
||||||
|
hres = to_int(args+2, &max);
|
||||||
|
if(FAILED(hres))
|
||||||
|
goto error;
|
||||||
|
if (max < -1) {
|
||||||
|
hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
max = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(args_cnt == 4) {
|
||||||
|
hres = to_int(args+3, &mode);
|
||||||
|
if(FAILED(hres))
|
||||||
|
goto error;
|
||||||
|
if (mode != 0 && mode != 1) {
|
||||||
|
hres = MAKE_VBSERROR(VBSE_ILLEGAL_FUNC_CALL);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
mode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = 0;
|
||||||
|
|
||||||
|
len = SysStringLen(string);
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
indices = heap_alloc( indices_max * sizeof(int));
|
||||||
|
if(!indices) {
|
||||||
|
hres = E_OUTOFMEMORY;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
ret = -1;
|
||||||
|
if (delimeterlen) {
|
||||||
|
ret = FindStringOrdinal(FIND_FROMSTART, string + start, len - start,
|
||||||
|
delimeter ? delimeter : L" ", delimeterlen, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == -1) {
|
||||||
|
end = len;
|
||||||
|
}else {
|
||||||
|
end = start + ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == indices_max) {
|
||||||
|
indices_max *= 2;
|
||||||
|
indices = heap_realloc( indices, indices_max * sizeof(int));
|
||||||
|
if(!indices) {
|
||||||
|
hres = E_OUTOFMEMORY;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indices[count++] = end;
|
||||||
|
|
||||||
|
if (ret == -1 || count == max) break;
|
||||||
|
start = start + ret + delimeterlen;
|
||||||
|
if (start > len) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds.lLbound = 0;
|
||||||
|
bounds.cElements = count;
|
||||||
|
sa = SafeArrayCreate( VT_VARIANT, 1, &bounds);
|
||||||
|
if (!sa) {
|
||||||
|
hres = E_OUTOFMEMORY;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
hres = SafeArrayAccessData(sa, (void**)&data);
|
||||||
|
if(FAILED(hres)) {
|
||||||
|
SafeArrayDestroy(sa);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = 0;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
str = SysAllocStringLen(string + start, indices[i] - start);
|
||||||
|
if (!str) {
|
||||||
|
hres = E_OUTOFMEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
V_VT(&var) = VT_BSTR;
|
||||||
|
V_BSTR(&var) = str;
|
||||||
|
|
||||||
|
hres = VariantCopyInd(data+i, &var);
|
||||||
|
if(FAILED(hres)) {
|
||||||
|
SafeArrayUnaccessData(sa);
|
||||||
|
SafeArrayDestroy(sa);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
start = indices[i]+delimeterlen;
|
||||||
|
}
|
||||||
|
SafeArrayUnaccessData(sa);
|
||||||
|
|
||||||
|
error:
|
||||||
|
if(SUCCEEDED(hres) && res) {
|
||||||
|
V_VT(res) = VT_ARRAY|VT_VARIANT;
|
||||||
|
V_ARRAY(res) = sa;
|
||||||
|
}else {
|
||||||
|
if (sa) SafeArrayDestroy(sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_free(indices);
|
||||||
|
if(V_VT(args) != VT_BSTR)
|
||||||
|
SysFreeString(string);
|
||||||
|
if(V_VT(args+1) != VT_BSTR)
|
||||||
|
SysFreeString(delimeter);
|
||||||
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
@ -609,6 +609,71 @@ TestLCase 0.123, doubleAsString(0.123)
|
||||||
TestLCase Empty, ""
|
TestLCase Empty, ""
|
||||||
Call ok(getVT(LCase(Null)) = "VT_NULL", "getVT(LCase(Null)) = " & getVT(LCase(Null)))
|
Call ok(getVT(LCase(Null)) = "VT_NULL", "getVT(LCase(Null)) = " & getVT(LCase(Null)))
|
||||||
|
|
||||||
|
x=Split("abc")
|
||||||
|
Call ok(x(0) = "abc", "Split(""abc"")(0)=" & x(0))
|
||||||
|
x = Split("abc def")
|
||||||
|
Call ok(x(0) = "abc", "Split(""abc def"")(0)=" & x(0))
|
||||||
|
Call ok(x(1) = "def", "Split(""abc def"")(1)=" & x(1))
|
||||||
|
x = Split("abc def ghi")
|
||||||
|
Call ok(x(0) = "abc", "Split(""abc def ghi"")(0)=" & x(0))
|
||||||
|
Call ok(x(1) = "def", "Split(""abc def ghi"")(1)=" & x(1))
|
||||||
|
Call ok(x(2) = "ghi", "Split(""abc def ghi"")(2)=" & x(2))
|
||||||
|
x = Split("abc def","")
|
||||||
|
Call ok(x(0) = "abc def", "Split(""abc def"","""")(0)=" & x(0))
|
||||||
|
x = Split("abc-def","-")
|
||||||
|
Call ok(x(0) = "abc", "Split(""abc-def"",""-"")(0)=" & x(0))
|
||||||
|
Call ok(x(1) = "def", "Split(""abc-def"",""-"")(1)=" & x(1))
|
||||||
|
x = Split("abc--def","-")
|
||||||
|
Call ok(x(0) = "abc", "Split(""abc--def"",""-"")(0)=" & x(0))
|
||||||
|
Call ok(x(1) = "", "Split(""abc--def"",""-"")(1)=" & x(1))
|
||||||
|
Call ok(x(2) = "def", "Split(""abc--def"",""-"")(2)=" & x(2))
|
||||||
|
x = Split("abcdefghi","def")
|
||||||
|
Call ok(x(0) = "abc", "Split(""abcdefghi"",""def"")(0)=" & x(0))
|
||||||
|
Call ok(x(1) = "ghi", "Split(""abcdefghi"",""def"")(1)=" & x(1))
|
||||||
|
x = Split("12345",3)
|
||||||
|
Call ok(x(0) = "12", "Split(""12345"",3)(0)=" & x(0))
|
||||||
|
Call ok(x(1) = "45", "Split(""12345"",3)(1)=" & x(1))
|
||||||
|
x = Split("12345",5)
|
||||||
|
Call ok(x(0) = "1234", "Split(""12345"",5)(0)=" & x(0))
|
||||||
|
Call ok(x(1) = "", "Split(""12345"",5)(1)=" & x(1))
|
||||||
|
x = Split("12345",12)
|
||||||
|
Call ok(x(0) = "", "Split(""12345"",12)(0)=" & x(0))
|
||||||
|
Call ok(x(1) = "345", "Split(""12345"",12)(1)=" & x(1))
|
||||||
|
x = Split("abc-def-ghi","-")
|
||||||
|
Call ok(UBound(x) = 2, "UBound(Split(""abc-def-ghi"",""-""))=" & UBound(x))
|
||||||
|
x = Split("a b c d e f g h i j k l m n o p q")
|
||||||
|
Call ok(UBound(x) = 16, "UBound(Split(""a b c d e f g h i j k l m n o p q""))=" & UBound(x))
|
||||||
|
x = Split("abc-def-ghi","-",2)
|
||||||
|
Call ok(UBound(x) = 1, "UBound(Split(""abc-def-ghi"",""-"",2))=" & UBound(x))
|
||||||
|
x = Split("abc-def-ghi","-",4)
|
||||||
|
Call ok(UBound(x) = 2, "UBound(Split(""abc-def-ghi"",""-"",4))=" & UBound(x))
|
||||||
|
x = Split("abc-def-ghi","-",-1)
|
||||||
|
Call ok(UBound(x) = 2, "UBound(Split(""abc-def-ghi"",""-"",-1))=" & UBound(x))
|
||||||
|
x = Split("abc-def-ghi","-",-1)
|
||||||
|
Call ok(UBound(x) = 2, "UBound(Split(""abc-def-ghi"",""-"",-42))=" & UBound(x))
|
||||||
|
x = Split("abcZdefZghi","Z",3,0)
|
||||||
|
Call ok(UBound(x) = 2, "UBound(Split(""abcZdefZghi"",""Z"",3,0))=" & UBound(x))
|
||||||
|
x = Split("abcZdefZghi","z",3,0)
|
||||||
|
Call ok(UBound(x) = 0, "UBound(Split(""abcZdefZghi"",""z"",3,0))=" & UBound(x))
|
||||||
|
x = Split("abcZdefZghi","z",3,1)
|
||||||
|
Call ok(UBound(x) = 2, "UBound(Split(""abcZdefZghi"",""z"",3,1))=" & UBound(x))
|
||||||
|
|
||||||
|
Sub testSplitError(arg1, arg2, arg3, arg4, error_num)
|
||||||
|
on error resume next
|
||||||
|
Dim x
|
||||||
|
|
||||||
|
Call Err.clear()
|
||||||
|
x = Split(arg1, arg2, arg3, arg4)
|
||||||
|
Call ok(Err.number = error_num, "Err.number = " & Err.number)
|
||||||
|
End Sub
|
||||||
|
|
||||||
|
call testSplitError("abc-def-ghi", "-", -1, 2, 5)
|
||||||
|
call testSplitError("abc-def-ghi", "-", -42, 0, 5)
|
||||||
|
call testSplitError(null, "-", -1, 0, 94)
|
||||||
|
call testSplitError("abc-def-ghi", null, -1, 0, 94)
|
||||||
|
call testSplitError("abc-def-ghi", "-", null, 0, 94)
|
||||||
|
call testSplitError("abc-def-ghi", "-", -1, null, 94)
|
||||||
|
|
||||||
Sub TestStrComp(str_left, str_right, mode, ex)
|
Sub TestStrComp(str_left, str_right, mode, ex)
|
||||||
x = StrComp(str_left, str_right, mode)
|
x = StrComp(str_left, str_right, mode)
|
||||||
Call ok(x = ex, "StrComp(" & str_left & ", " & str_right & ", " & mode & ") = " & x & " expected " & ex)
|
Call ok(x = ex, "StrComp(" & str_left & ", " & str_right & ", " & mode & ") = " & x & " expected " & ex)
|
||||||
|
|
Loading…
Reference in New Issue