VarRound implementation (without type DECIMAL yet) with test function.
This commit is contained in:
parent
64ed848712
commit
3d7034e79e
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue