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

This commit is contained in:
Fabian Cenedese 2004-02-26 05:27:11 +00:00 committed by Alexandre Julliard
parent 64ed848712
commit 3d7034e79e
3 changed files with 254 additions and 1 deletions

View File

@ -170,7 +170,7 @@
172 stdcall VarInt(ptr ptr)
173 stdcall VarNeg(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)
177 stdcall VarDecAdd(ptr ptr ptr)
178 stdcall VarDecDiv(ptr ptr ptr)

View File

@ -2548,6 +2548,129 @@ static void test_VarNeg(void)
"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)
{
hOleaut32 = LoadLibraryA("oleaut32.dll");
@ -2573,4 +2696,5 @@ START_TEST(vartest)
test_VarFix();
test_VarInt();
test_VarNeg();
test_VarRound();
}

View File

@ -3437,6 +3437,135 @@ HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut)
return hRet;
}
/**********************************************************************
* 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]
*