Commit 3d7034e7 authored by Fabian Cenedese's avatar Fabian Cenedese Committed by Alexandre Julliard

VarRound implementation (without type DECIMAL yet) with test function.

parent 64ed8487
...@@ -170,7 +170,7 @@ ...@@ -170,7 +170,7 @@
172 stdcall VarInt(ptr ptr) 172 stdcall VarInt(ptr ptr)
173 stdcall VarNeg(ptr ptr) 173 stdcall VarNeg(ptr ptr)
174 stdcall VarNot(ptr ptr) 174 stdcall VarNot(ptr ptr)
175 stub VarRound # stdcall (ptr long ptr) 175 stdcall VarRound(ptr long ptr)
176 stdcall VarCmp(ptr ptr long long) 176 stdcall VarCmp(ptr ptr long long)
177 stdcall VarDecAdd(ptr ptr ptr) 177 stdcall VarDecAdd(ptr ptr ptr)
178 stdcall VarDecDiv(ptr ptr ptr) 178 stdcall VarDecDiv(ptr ptr ptr)
......
...@@ -2548,6 +2548,129 @@ static void test_VarNeg(void) ...@@ -2548,6 +2548,129 @@ static void test_VarNeg(void)
"VarNeg: VT_CY wrong, hres=0x%lX\n", hres); "VarNeg: VT_CY wrong, hres=0x%lX\n", hres);
} }
static HRESULT (WINAPI *pVarRound)(LPVARIANT,int,LPVARIANT);
#define VARROUND(vt,val,deci,rvt,rval) V_VT(&v) = VT_##vt; V_##vt(&v) = val; \
memset(&vDst,0,sizeof(vDst)); hres = pVarRound(&v,deci,&vDst); \
ok(hres == S_OK && V_VT(&vDst) == VT_##rvt && V_##rvt(&vDst) == (rval), \
"VarRound: expected 0x0,%d,%d, got 0x%lX,%d,%d\n", VT_##rvt, (int)(rval), \
hres, V_VT(&vDst), (int)V_##rvt(&vDst))
#define VARROUNDF(vt,val,deci,rvt,rval) V_VT(&v) = VT_##vt; V_##vt(&v) = val; \
memset(&vDst,0,sizeof(vDst)); hres = pVarRound(&v,deci,&vDst); \
ok(hres == S_OK && V_VT(&vDst) == VT_##rvt && V_##rvt(&vDst) == (rval), \
"VarRound: expected 0x0,%d,%f, got 0x%lX,%d,%f\n", VT_##rvt, rval, \
hres, V_VT(&vDst), V_##rvt(&vDst))
static void test_VarRound(void)
{
/* static const WCHAR szNumMin[] = {'-','1','.','4','5','\0' };
static const WCHAR szNum[] = {'1','.','4','5','\0' }; */
HRESULT hres;
VARIANT v, vDst;
CY *pcy = &V_CY(&v);
CHECKPTR(VarRound);
/* first check valid integer types */
VARROUND(BOOL,VARIANT_TRUE,0,I2,-1);
VARROUND(BOOL,VARIANT_FALSE,0,I2,0);
VARROUND(BOOL,1,0,I2,1);
VARROUND(UI1,1,0,UI1,1);
VARROUND(UI1,254,0,UI1,254);
VARROUND(I2,-32768,0,I2,-32768);
VARROUND(I2,-1,0,I2,-1);
VARROUND(I2,1,0,I2,1);
VARROUND(I4,-((int)(~0u >> 1)) - 1,0,I4,-((int)(~0u >> 1)) - 1);
VARROUND(I4,-1,0,I4,-1);
VARROUND(I4,1,0,I4,1);
/* MSDN states that rounding of R4/R8 is dependent on the underlying
* bit pattern of the number and so is architecture dependent. In this
* case Wine returns .2 (which is more correct) and Native returns .3
*/
VARROUNDF(R4,1.0,0,R4,1.0);
VARROUNDF(R4,-1.0,0,R4,-1.0);
VARROUNDF(R8,1.0,0,R8,1.0);
VARROUNDF(R8,-1.0,0,R8,-1.0);
/* floating point numbers aren't exactly equal and we can't just
* compare the first few digits.
todo_wine {
VARROUNDF(DATE,1.451,1,DATE,1.5);
VARROUNDF(DATE,-1.45,1,DATE,-1.4);
VARROUNDF(BSTR,(BSTR)szNumMin,1,R8,-1.40);
VARROUNDF(BSTR,(BSTR)szNum,1,R8,1.50);
VARROUNDF(R4,1.23456,0,R4,1.0);
VARROUNDF(R4,1.23456,1,R4,1.2);
VARROUNDF(R4,1.23456,2,R4,1.23);
VARROUNDF(R4,1.23456,3,R4,1.235);
VARROUNDF(R4,1.23456,4,R4,1.2346);
VARROUNDF(R4,-1.23456,0,R4,-1.0);
VARROUNDF(R4,-1.23456,1,R4,-1.2);
VARROUNDF(R4,-1.23456,2,R4,-1.23);
VARROUNDF(R4,-1.23456,3,R4,-1.235);
VARROUNDF(R4,-1.23456,4,R4,-1.2346);
VARROUNDF(R8,1.23456,0,R8,1.0);
VARROUNDF(R8,1.23456,1,R8,1.2);
VARROUNDF(R8,1.23456,2,R8,1.23);
VARROUNDF(R8,1.23456,3,R8,1.235);
VARROUNDF(R8,1.23456,4,R8,1.2346);
VARROUNDF(R8,-1.23456,0,R8,-1.0);
VARROUNDF(R8,-1.23456,1,R8,-1.2);
VARROUNDF(R8,-1.23456,2,R8,-1.23);
VARROUNDF(R8,-1.23456,3,R8,-1.235);
VARROUNDF(R8,-1.23456,4,R8,-1.2346);
}
*/
V_VT(&v) = VT_EMPTY;
hres = pVarRound(&v,0,&vDst);
ok(hres == S_OK && V_VT(&vDst) == VT_I2 && V_I2(&vDst) == 0,
"VarRound: expected 0x0,%d,0 got 0x%lX,%d,%d\n", VT_EMPTY,
hres, V_VT(&vDst), V_I2(&vDst));
V_VT(&v) = VT_NULL;
hres = pVarRound(&v,0,&vDst);
ok(hres == S_OK && V_VT(&vDst) == VT_NULL,
"VarRound: expected 0x0,%d got 0x%lX,%d\n", VT_NULL, hres, V_VT(&vDst));
/* not yet implemented so no use testing yet
todo_wine {
DECIMAL *pdec = &V_DECIMAL(&v);
V_VT(&v) = VT_DECIMAL;
pdec->u.s.sign = DECIMAL_NEG;
pdec->u.s.scale = 0;
pdec->Hi32 = 0;
pdec->u1.s1.Mid32 = 0;
pdec->u1.s1.Lo32 = 1;
hres = pVarRound(&v,0,&vDst);
ok(hres == S_OK && V_VT(&vDst) == VT_DECIMAL &&
V_DECIMAL(&vDst).u.s.sign == 0,
"VarRound: expected 0x0,%d,0x00, got 0x%lX,%d,%02x\n", VT_DECIMAL,
hres, V_VT(&vDst), V_DECIMAL(&vDst).u.s.sign);
pdec->u.s.sign = 0;
hres = pVarRound(&v,0,&vDst);
ok(hres == S_OK && V_VT(&vDst) == VT_DECIMAL &&
V_DECIMAL(&vDst).u.s.sign == DECIMAL_NEG,
"VarRound: expected 0x0,%d,0x7f, got 0x%lX,%d,%02x\n", VT_DECIMAL,
hres, V_VT(&vDst), V_DECIMAL(&vDst).u.s.sign);
}
*/
V_VT(&v) = VT_CY;
pcy->int64 = 10000;
hres = pVarRound(&v,0,&vDst);
ok(hres == S_OK && V_VT(&vDst) == VT_CY && V_CY(&vDst).int64 == 10000,
"VarRound: VT_CY wrong, hres=0x%lX\n", hres);
}
START_TEST(vartest) START_TEST(vartest)
{ {
hOleaut32 = LoadLibraryA("oleaut32.dll"); hOleaut32 = LoadLibraryA("oleaut32.dll");
...@@ -2573,4 +2696,5 @@ START_TEST(vartest) ...@@ -2573,4 +2696,5 @@ START_TEST(vartest)
test_VarFix(); test_VarFix();
test_VarInt(); test_VarInt();
test_VarNeg(); test_VarNeg();
test_VarRound();
} }
...@@ -3438,6 +3438,135 @@ HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut) ...@@ -3438,6 +3438,135 @@ HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut)
} }
/********************************************************************** /**********************************************************************
* VarRound [OLEAUT32.175]
*
* Perform a round operation on a variant.
*
* PARAMS
* pVarIn [I] Source variant
* deci [I] Number of decimals to round to
* pVarOut [O] Destination for converted value
*
* RETURNS
* Success: S_OK. pVarOut contains the converted value.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* - Floating point values are rounded to the desired number of decimals.
* - Some integer types are just copied to the return variable.
* - Some other integer types are not handled and fail.
*/
HRESULT WINAPI VarRound(LPVARIANT pVarIn, int deci, LPVARIANT pVarOut)
{
VARIANT varIn;
HRESULT hRet = S_OK;
float factor;
TRACE("(%p->(%s%s),%d)\n", pVarIn, debugstr_VT(pVarIn), debugstr_VF(pVarIn), deci);
switch (V_VT(pVarIn))
{
/* cases that fail on windows */
case VT_I1:
case VT_I8:
case VT_UI2:
case VT_UI4:
hRet = DISP_E_BADVARTYPE;
break;
/* cases just copying in to out */
case VT_UI1:
V_VT(pVarOut) = V_VT(pVarIn);
V_UI1(pVarOut) = V_UI1(pVarIn);
break;
case VT_I2:
V_VT(pVarOut) = V_VT(pVarIn);
V_I2(pVarOut) = V_I2(pVarIn);
break;
case VT_I4:
V_VT(pVarOut) = V_VT(pVarIn);
V_I4(pVarOut) = V_I4(pVarIn);
break;
case VT_NULL:
V_VT(pVarOut) = V_VT(pVarIn);
/* value unchanged */
break;
/* cases that change type */
case VT_EMPTY:
V_VT(pVarOut) = VT_I2;
V_I2(pVarOut) = 0;
break;
case VT_BOOL:
V_VT(pVarOut) = VT_I2;
V_I2(pVarOut) = V_BOOL(pVarIn);
break;
case VT_BSTR:
hRet = VarR8FromStr(V_BSTR(pVarIn), LOCALE_USER_DEFAULT, 0, &V_R8(&varIn));
if (FAILED(hRet))
break;
V_VT(&varIn)=VT_R8;
pVarIn = &varIn;
/* Fall through ... */
/* cases we need to do math */
case VT_R8:
if (V_R8(pVarIn)>0) {
V_R8(pVarOut)=floor(V_R8(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
} else {
V_R8(pVarOut)=ceil(V_R8(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
}
V_VT(pVarOut) = V_VT(pVarIn);
break;
case VT_R4:
if (V_R4(pVarIn)>0) {
V_R4(pVarOut)=floor(V_R4(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
} else {
V_R4(pVarOut)=ceil(V_R4(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
}
V_VT(pVarOut) = V_VT(pVarIn);
break;
case VT_DATE:
if (V_DATE(pVarIn)>0) {
V_DATE(pVarOut)=floor(V_DATE(pVarIn)*pow(10, deci)+0.5)/pow(10, deci);
} else {
V_DATE(pVarOut)=ceil(V_DATE(pVarIn)*pow(10, deci)-0.5)/pow(10, deci);
}
V_VT(pVarOut) = V_VT(pVarIn);
break;
case VT_CY:
if (deci>3)
factor=1;
else
factor=pow(10, 4-deci);
if (V_CY(pVarIn).int64>0) {
V_CY(pVarOut).int64=floor(V_CY(pVarIn).int64/factor)*factor;
} else {
V_CY(pVarOut).int64=ceil(V_CY(pVarIn).int64/factor)*factor;
}
V_VT(pVarOut) = V_VT(pVarIn);
break;
/* cases we don't know yet */
default:
FIXME("unimplemented part, V_VT(pVarIn) == 0x%X, deci == %d\n",
V_VT(pVarIn) & VT_TYPEMASK, deci);
hRet = DISP_E_BADVARTYPE;
}
if (FAILED(hRet))
V_VT(pVarOut) = VT_EMPTY;
TRACE("returning 0x%08lx (%s%s),%f\n", hRet, debugstr_VT(pVarOut),
debugstr_VF(pVarOut), (V_VT(pVarOut) == VT_R4) ? V_R4(pVarOut) :
(V_VT(pVarOut) == VT_R8) ? V_R8(pVarOut) : 0);
return hRet;
}
/**********************************************************************
* VarMod [OLEAUT32.154] * VarMod [OLEAUT32.154]
* *
* Perform the modulus operation of the right hand variant on the left * Perform the modulus operation of the right hand variant on the left
......
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