oleaut32: Get rid of the DECIMAL access macros.

This commit is contained in:
Alexandre Julliard 2023-07-04 12:42:53 +02:00
parent 641623ffe8
commit 36963b6d27
3 changed files with 188 additions and 218 deletions

View file

@ -30,9 +30,6 @@
#include <stdarg.h>
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
@ -428,13 +425,13 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
{
case VT_EMPTY:
case VT_BOOL:
DEC_SIGNSCALE(&V_DECIMAL(pd)) = SIGNSCALE(DECIMAL_POS,0);
DEC_HI32(&V_DECIMAL(pd)) = 0;
DEC_MID32(&V_DECIMAL(pd)) = 0;
V_DECIMAL(pd).sign = DECIMAL_POS;
V_DECIMAL(pd).scale = 0;
V_DECIMAL(pd).Hi32 = 0;
/* VarDecFromBool() coerces to -1/0, ChangeTypeEx() coerces to 1/0.
* VT_NULL and VT_EMPTY always give a 0 value.
*/
DEC_LO32(&V_DECIMAL(pd)) = vtFrom == VT_BOOL && V_BOOL(ps) ? 1 : 0;
V_DECIMAL(pd).Lo64 = vtFrom == VT_BOOL && V_BOOL(ps) ? 1 : 0;
return S_OK;
case VT_I1: return VarDecFromI1(V_I1(ps), &V_DECIMAL(pd));
case VT_I2: return VarDecFromI2(V_I2(ps), &V_DECIMAL(pd));
@ -903,7 +900,7 @@ HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, const VARIANTARG* pvargSrc)
}
else if (V_VT(pSrc) == (VT_DECIMAL|VT_BYREF))
{
memcpy(&DEC_SCALE(&V_DECIMAL(pvargDest)), &DEC_SCALE(V_DECIMALREF(pSrc)),
memcpy(&V_DECIMAL(pvargDest).scale, &V_DECIMALREF(pSrc)->scale,
sizeof(DECIMAL) - sizeof(USHORT));
}
else
@ -2159,9 +2156,10 @@ HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig,
else if ((dwVtBits & VTBIT_DECIMAL) == VTBIT_DECIMAL)
{
V_VT(pVarDst) = VT_DECIMAL;
DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
V_DECIMAL(pVarDst).sign = DECIMAL_POS;
V_DECIMAL(pVarDst).scale = 0;
V_DECIMAL(pVarDst).Hi32 = 0;
V_DECIMAL(pVarDst).Lo64 = ul64;
return S_OK;
}
else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
@ -2344,9 +2342,10 @@ HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig,
{
/* Decimal is only output choice left - fast path */
V_VT(pVarDst) = VT_DECIMAL;
DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_NEG,0);
DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
DEC_LO64(&V_DECIMAL(pVarDst)) = -ul64;
V_DECIMAL(pVarDst).sign = DECIMAL_NEG;
V_DECIMAL(pVarDst).scale = 0;
V_DECIMAL(pVarDst).Hi32 = 0;
V_DECIMAL(pVarDst).Lo64 = -ul64;
return S_OK;
}
}
@ -2406,9 +2405,10 @@ HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig,
{
/* Decimal is only output choice left - fast path */
V_VT(pVarDst) = VT_DECIMAL;
DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
V_DECIMAL(pVarDst).sign = DECIMAL_POS;
V_DECIMAL(pVarDst).scale = 0;
V_DECIMAL(pVarDst).Hi32 = 0;
V_DECIMAL(pVarDst).Lo64 = ul64;
return S_OK;
}
}
@ -2514,30 +2514,30 @@ HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig,
DECIMAL* pDec = &V_DECIMAL(pVarDst);
DECIMAL_SETZERO(*pDec);
DEC_LO32(pDec) = 0;
pDec->Lo32 = 0;
if (pNumprs->dwOutFlags & NUMPRS_NEG)
DEC_SIGN(pDec) = DECIMAL_NEG;
pDec->sign = DECIMAL_NEG;
else
DEC_SIGN(pDec) = DECIMAL_POS;
pDec->sign = DECIMAL_POS;
/* Factor the significant digits */
for (i = 0; i < pNumprs->cDig; i++)
{
tmp = (ULONG64)DEC_LO32(pDec) * 10 + rgbDig[i];
tmp = (ULONG64)pDec->Lo32 * 10 + rgbDig[i];
carry = (ULONG)(tmp >> 32);
DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
pDec->Lo32 = (ULONG)tmp;
tmp = (ULONG64)pDec->Mid32 * 10 + carry;
carry = (ULONG)(tmp >> 32);
DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
pDec->Mid32 = (ULONG)tmp;
tmp = (ULONG64)pDec->Hi32 * 10 + carry;
pDec->Hi32 = (ULONG)tmp;
if (tmp >> 32 & UI4_MAX)
if (tmp >> 32)
{
VarNumFromParseNum_DecOverflow:
TRACE("Overflow\n");
DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
pDec->Lo32 = pDec->Mid32 = pDec->Hi32 = UI4_MAX;
return DISP_E_OVERFLOW;
}
}
@ -2545,20 +2545,20 @@ VarNumFromParseNum_DecOverflow:
/* Account for the scale of the number */
while (multiplier10 > 0)
{
tmp = (ULONG64)DEC_LO32(pDec) * 10;
tmp = (ULONG64)pDec->Lo32 * 10;
carry = (ULONG)(tmp >> 32);
DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
pDec->Lo32 = (ULONG)tmp;
tmp = (ULONG64)pDec->Mid32 * 10 + carry;
carry = (ULONG)(tmp >> 32);
DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
pDec->Mid32 = (ULONG)tmp;
tmp = (ULONG64)pDec->Hi32 * 10 + carry;
pDec->Hi32 = (ULONG)tmp;
if (tmp >> 32 & UI4_MAX)
if (tmp >> 32)
goto VarNumFromParseNum_DecOverflow;
multiplier10--;
}
DEC_SCALE(pDec) = divisor10;
pDec->scale = divisor10;
V_VT(pVarDst) = VT_DECIMAL;
return S_OK;
@ -3077,8 +3077,7 @@ HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
resvt = VT_NULL;
break;
case VT_DECIMAL:
if (DEC_HI32(&V_DECIMAL(right)) ||
DEC_LO64(&V_DECIMAL(right)))
if (V_DECIMAL(right).Hi32 || V_DECIMAL(right).Lo64)
resvt = VT_NULL;
break;
case VT_BSTR:
@ -4113,7 +4112,7 @@ HRESULT WINAPI VarOr(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
hRet = S_OK;
goto VarOr_Exit;
case VT_DECIMAL:
if (DEC_HI32(&V_DECIMAL(pVarLeft)) || DEC_LO64(&V_DECIMAL(pVarLeft)))
if (V_DECIMAL(pVarLeft).Hi32 || V_DECIMAL(pVarLeft).Lo64)
goto VarOr_AsEmpty;
hRet = S_OK;
goto VarOr_Exit;
@ -4386,7 +4385,7 @@ HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut)
hRet = VarCyAbs(V_CY(pVarIn), & V_CY(pVarOut));
break;
case VT_DECIMAL:
DEC_SIGN(&V_DECIMAL(pVarOut)) &= ~DECIMAL_NEG;
V_DECIMAL(pVarOut).sign &= ~DECIMAL_NEG;
break;
case VT_UI1:
case VT_UI2:
@ -5872,7 +5871,7 @@ HRESULT WINAPI VarImp(LPVARIANT left, LPVARIANT right, LPVARIANT result)
case VT_DATE: if (!V_DATE(right)) resvt = VT_NULL; break;
case VT_CY: if (!V_CY(right).int64) resvt = VT_NULL; break;
case VT_DECIMAL:
if (!(DEC_HI32(&V_DECIMAL(right)) || DEC_LO64(&V_DECIMAL(right))))
if (!V_DECIMAL(right).Hi32 || V_DECIMAL(right).Lo64)
resvt = VT_NULL;
break;
case VT_BSTR:
@ -5922,7 +5921,7 @@ HRESULT WINAPI VarImp(LPVARIANT left, LPVARIANT right, LPVARIANT result)
case VT_R8: if (V_R8(left) == -1.0) resvt = VT_NULL; break;
case VT_CY: if (V_CY(left).int64 == -1) resvt = VT_NULL; break;
case VT_DECIMAL:
if (DEC_HI32(&V_DECIMAL(left)) == 0xffffffff)
if (V_DECIMAL(left).Hi32 == 0xffffffff)
resvt = VT_NULL;
break;
case VT_BSTR:

View file

@ -74,26 +74,6 @@
/* Value of sign for a positive decimal number */
#define DECIMAL_POS 0
/* Native headers don't change the union ordering for DECIMAL sign/scale (duh).
* This means that the signscale member is only useful for setting both members to 0.
* SIGNSCALE creates endian-correct values so that we can properly set both at once
* to values other than 0.
*/
#ifdef WORDS_BIGENDIAN
#define SIGNSCALE(sign,scale) (((scale) << 8) | sign)
#else
#define SIGNSCALE(sign,scale) (((sign) << 8) | scale)
#endif
/* Macros for getting at a DECIMAL's parts */
#define DEC_SIGN(d) ((d)->u.s.sign)
#define DEC_SCALE(d) ((d)->u.s.scale)
#define DEC_SIGNSCALE(d) ((d)->u.signscale)
#define DEC_HI32(d) ((d)->Hi32)
#define DEC_MID32(d) ((d)->u1.s1.Mid32)
#define DEC_LO32(d) ((d)->u1.s1.Lo32)
#define DEC_LO64(d) ((d)->u1.Lo64)
#define DEC_MAX_SCALE 28 /* Maximum scale for a decimal */
/* Internal flags for low level conversion functions */

View file

@ -19,9 +19,6 @@
*/
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "wine/debug.h"
#include "winbase.h"
#include "winuser.h"
@ -2176,9 +2173,9 @@ HRESULT WINAPI VarI8FromCy(CY cyIn, LONG64* pi64Out)
(*pi64Out)--; /* Mimic Win32 bug */
else
{
cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
cyIn.int64 -= *pi64Out * CY_MULTIPLIER; /* cyIn.Lo now holds fractional remainder */
if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pi64Out & 0x1)))
if (cyIn.Lo > CY_HALF || (cyIn.Lo == CY_HALF && (*pi64Out & 0x1)))
(*pi64Out)++;
}
return S_OK;
@ -2331,19 +2328,19 @@ HRESULT WINAPI VarI8FromUI4(ULONG ulIn, LONG64* pi64Out)
*/
HRESULT WINAPI VarI8FromDec(const DECIMAL *pdecIn, LONG64* pi64Out)
{
if (!DEC_SCALE(pdecIn))
if (!pdecIn->scale)
{
/* This decimal is just a 96 bit integer */
if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
if (pdecIn->sign & ~DECIMAL_NEG)
return E_INVALIDARG;
if (DEC_HI32(pdecIn) || DEC_MID32(pdecIn) & 0x80000000)
if (pdecIn->Hi32 || pdecIn->Mid32 & 0x80000000)
return DISP_E_OVERFLOW;
if (DEC_SIGN(pdecIn))
*pi64Out = -DEC_LO64(pdecIn);
if (pdecIn->sign)
*pi64Out = -pdecIn->Lo64;
else
*pi64Out = DEC_LO64(pdecIn);
*pi64Out = pdecIn->Lo64;
return S_OK;
}
else
@ -2504,9 +2501,9 @@ HRESULT WINAPI VarUI8FromCy(CY cyIn, ULONG64* pui64Out)
{
*pui64Out = cyIn.int64 / CY_MULTIPLIER;
cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.s.Lo now holds fractional remainder */
cyIn.int64 -= *pui64Out * CY_MULTIPLIER; /* cyIn.Lo now holds fractional remainder */
if (cyIn.s.Lo > CY_HALF || (cyIn.s.Lo == CY_HALF && (*pui64Out & 0x1)))
if (cyIn.Lo > CY_HALF || (cyIn.Lo == CY_HALF && (*pui64Out & 0x1)))
(*pui64Out)++;
}
return S_OK;
@ -2666,22 +2663,22 @@ HRESULT WINAPI VarUI8FromUI4(ULONG ulIn, ULONG64* pui64Out)
*/
HRESULT WINAPI VarUI8FromDec(const DECIMAL *pdecIn, ULONG64* pui64Out)
{
if (!DEC_SCALE(pdecIn))
if (!pdecIn->scale)
{
/* This decimal is just a 96 bit integer */
if (DEC_SIGN(pdecIn) & ~DECIMAL_NEG)
if (pdecIn->sign & ~DECIMAL_NEG)
return E_INVALIDARG;
if (DEC_HI32(pdecIn))
if (pdecIn->Hi32)
return DISP_E_OVERFLOW;
if (DEC_SIGN(pdecIn))
if (pdecIn->sign)
{
WARN("Sign would be ignored under Win32!\n");
return DISP_E_OVERFLOW;
}
*pui64Out = DEC_LO64(pdecIn);
*pui64Out = pdecIn->Lo64;
return S_OK;
}
else
@ -2942,29 +2939,29 @@ HRESULT WINAPI VarR4FromUI4(ULONG ulIn, float *pFltOut)
*/
HRESULT WINAPI VarR4FromDec(const DECIMAL* pDecIn, float *pFltOut)
{
BYTE scale = DEC_SCALE(pDecIn);
BYTE scale = pDecIn->scale;
double divisor = 1.0;
double highPart;
if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
if (scale > DEC_MAX_SCALE || pDecIn->sign & ~DECIMAL_NEG)
return E_INVALIDARG;
while (scale--)
divisor *= 10.0;
if (DEC_SIGN(pDecIn))
if (pDecIn->sign)
divisor = -divisor;
if (DEC_HI32(pDecIn))
if (pDecIn->Hi32)
{
highPart = (double)DEC_HI32(pDecIn) / divisor;
highPart = (double)pDecIn->Hi32 / divisor;
highPart *= 4294967296.0F;
highPart *= 4294967296.0F;
}
else
highPart = 0.0;
*pFltOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
*pFltOut = (double)pDecIn->Lo64 / divisor + highPart;
return S_OK;
}
@ -3263,28 +3260,28 @@ HRESULT WINAPI VarR8FromUI4(ULONG ulIn, double *pDblOut)
*/
HRESULT WINAPI VarR8FromDec(const DECIMAL* pDecIn, double *pDblOut)
{
BYTE scale = DEC_SCALE(pDecIn);
BYTE scale = pDecIn->scale;
double divisor = 1.0, highPart;
if (scale > DEC_MAX_SCALE || DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
if (scale > DEC_MAX_SCALE || pDecIn->sign & ~DECIMAL_NEG)
return E_INVALIDARG;
while (scale--)
divisor *= 10;
if (DEC_SIGN(pDecIn))
if (pDecIn->sign)
divisor = -divisor;
if (DEC_HI32(pDecIn))
if (pDecIn->Hi32)
{
highPart = (double)DEC_HI32(pDecIn) / divisor;
highPart = (double)pDecIn->Hi32 / divisor;
highPart *= 4294967296.0F;
highPart *= 4294967296.0F;
}
else
highPart = 0.0;
*pDblOut = (double)DEC_LO64(pDecIn) / divisor + highPart;
*pDblOut = (double)pDecIn->Lo64 / divisor + highPart;
return S_OK;
}
@ -3709,12 +3706,12 @@ HRESULT WINAPI VarCyFromDec(const DECIMAL* pdecIn, CY* pCyOut)
{
double d;
if (DEC_HI32(&rounded))
if (rounded.Hi32)
return DISP_E_OVERFLOW;
/* Note: Without the casts this promotes to int64 which loses precision */
d = (double)DEC_LO64(&rounded) / (double)CY_Divisors[DEC_SCALE(&rounded)];
if (DEC_SIGN(&rounded))
d = (double)rounded.Lo64 / (double)CY_Divisors[rounded.scale];
if (rounded.sign)
d = -d;
return VarCyFromR8(d, pCyOut);
}
@ -3872,7 +3869,7 @@ HRESULT WINAPI VarCySub(CY cyLeft, CY cyRight, CY* pCyOut)
*/
HRESULT WINAPI VarCyAbs(CY cyIn, CY* pCyOut)
{
if (cyIn.s.Hi == 0x80000000 && !cyIn.s.Lo)
if (cyIn.Hi == 0x80000000 && !cyIn.Lo)
return DISP_E_OVERFLOW;
pCyOut->int64 = cyIn.int64 < 0 ? -cyIn.int64 : cyIn.int64;
@ -3947,7 +3944,7 @@ HRESULT WINAPI VarCyInt(CY cyIn, CY* pCyOut)
*/
HRESULT WINAPI VarCyNeg(CY cyIn, CY* pCyOut)
{
if (cyIn.s.Hi == 0x80000000 && !cyIn.s.Lo)
if (cyIn.Hi == 0x80000000 && !cyIn.Lo)
return DISP_E_OVERFLOW;
pCyOut->int64 = -cyIn.int64;
@ -4127,18 +4124,19 @@ HRESULT WINAPI VarDecFromI2(SHORT sIn, DECIMAL* pDecOut)
*/
HRESULT WINAPI VarDecFromI4(LONG lIn, DECIMAL* pDecOut)
{
DEC_HI32(pDecOut) = 0;
DEC_MID32(pDecOut) = 0;
pDecOut->Hi32 = 0;
pDecOut->Mid32 = 0;
pDecOut->scale = 0;
if (lIn < 0)
{
DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
DEC_LO32(pDecOut) = -lIn;
pDecOut->sign = DECIMAL_NEG;
pDecOut->Lo32 = -lIn;
}
else
{
DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
DEC_LO32(pDecOut) = lIn;
pDecOut->sign = DECIMAL_POS;
pDecOut->Lo32 = lIn;
}
return S_OK;
}
@ -4235,19 +4233,18 @@ HRESULT WINAPI VarDecFromDate(DATE dateIn, DECIMAL* pDecOut)
*/
HRESULT WINAPI VarDecFromCy(CY cyIn, DECIMAL* pDecOut)
{
DEC_HI32(pDecOut) = 0;
pDecOut->Hi32 = 0;
pDecOut->scale = 4;
/* Note: This assumes 2s complement integer representation */
if (cyIn.s.Hi & 0x80000000)
if (cyIn.int64 < 0)
{
DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,4);
DEC_LO64(pDecOut) = -cyIn.int64;
pDecOut->sign = DECIMAL_NEG;
pDecOut->Lo64 = -cyIn.int64;
}
else
{
DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,4);
DEC_MID32(pDecOut) = cyIn.s.Hi;
DEC_LO32(pDecOut) = cyIn.s.Lo;
pDecOut->sign = DECIMAL_POS;
pDecOut->Lo64 = cyIn.int64;
}
return S_OK;
}
@ -4308,17 +4305,17 @@ HRESULT WINAPI VarDecFromDisp(IDispatch* pdispIn, LCID lcid, DECIMAL* pDecOut)
*/
HRESULT WINAPI VarDecFromBool(VARIANT_BOOL bIn, DECIMAL* pDecOut)
{
DEC_HI32(pDecOut) = 0;
DEC_MID32(pDecOut) = 0;
pDecOut->Hi32 = 0;
pDecOut->scale = 0;
if (bIn)
{
DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
DEC_LO32(pDecOut) = 1;
pDecOut->sign = DECIMAL_NEG;
pDecOut->Lo64 = 1;
}
else
{
DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
DEC_LO32(pDecOut) = 0;
pDecOut->sign = DECIMAL_POS;
pDecOut->Lo64 = 0;
}
return S_OK;
}
@ -4371,11 +4368,11 @@ HRESULT WINAPI VarDecFromUI2(USHORT usIn, DECIMAL* pDecOut)
*/
HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
{
DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
DEC_HI32(pDecOut) = 0;
DEC_MID32(pDecOut) = 0;
DEC_LO32(pDecOut) = ulIn;
return S_OK;
pDecOut->sign = DECIMAL_POS;
pDecOut->scale = 0;
pDecOut->Hi32 = 0;
pDecOut->Lo64 = ulIn;
return S_OK;
}
/************************************************************************
@ -4392,23 +4389,20 @@ HRESULT WINAPI VarDecFromUI4(ULONG ulIn, DECIMAL* pDecOut)
*/
HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
{
PULARGE_INTEGER pLi = (PULARGE_INTEGER)&llIn;
pDecOut->Hi32 = 0;
pDecOut->scale = 0;
DEC_HI32(pDecOut) = 0;
/* Note: This assumes 2s complement integer representation */
if (pLi->u.HighPart & 0x80000000)
{
DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_NEG,0);
DEC_LO64(pDecOut) = -pLi->QuadPart;
}
else
{
DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
DEC_MID32(pDecOut) = pLi->u.HighPart;
DEC_LO32(pDecOut) = pLi->u.LowPart;
}
return S_OK;
if (llIn < 0)
{
pDecOut->sign = DECIMAL_NEG;
pDecOut->Lo64 = -llIn;
}
else
{
pDecOut->sign = DECIMAL_POS;
pDecOut->Lo64 = llIn;
}
return S_OK;
}
/************************************************************************
@ -4425,10 +4419,11 @@ HRESULT WINAPI VarDecFromI8(LONG64 llIn, DECIMAL* pDecOut)
*/
HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut)
{
DEC_SIGNSCALE(pDecOut) = SIGNSCALE(DECIMAL_POS,0);
DEC_HI32(pDecOut) = 0;
DEC_LO64(pDecOut) = ullIn;
return S_OK;
pDecOut->sign = DECIMAL_POS;
pDecOut->scale = 0;
pDecOut->Hi32 = 0;
pDecOut->Lo64 = ullIn;
return S_OK;
}
/* Make two DECIMALS the same scale; used by math functions below */
@ -4442,12 +4437,12 @@ static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
VARIANT_DI di;
int scaleAmount, i;
if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG)
if ((*ppDecLeft)->sign & ~DECIMAL_NEG || (*ppDecRight)->sign & ~DECIMAL_NEG)
return E_INVALIDARG;
DEC_LO32(&scaleFactor) = 10;
scaleFactor.Lo32 = 10;
i = scaleAmount = DEC_SCALE(*ppDecLeft) - DEC_SCALE(*ppDecRight);
i = scaleAmount = (*ppDecLeft)->scale - (*ppDecRight)->scale;
if (!scaleAmount)
return S_OK; /* Same scale */
@ -4473,7 +4468,7 @@ static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
if (!i)
{
DEC_SCALE(&pDecOut[0]) += (scaleAmount > 0) ? scaleAmount : (-scaleAmount);
pDecOut[0].scale += (scaleAmount > 0) ? scaleAmount : (-scaleAmount);
return S_OK; /* Same scale */
}
@ -4481,13 +4476,13 @@ static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft,
pDecOut[0] = decTemp;
if (scaleAmount > 0)
{
DEC_SCALE(&pDecOut[0]) += scaleAmount - i;
pDecOut[0].scale += scaleAmount - i;
VARIANT_DIFromDec(*ppDecLeft, &di);
*ppDecLeft = &pDecOut[1];
}
else
{
DEC_SCALE(&pDecOut[0]) += (-scaleAmount) - i;
pDecOut[0].scale += (-scaleAmount) - i;
VARIANT_DIFromDec(*ppDecRight, &di);
*ppDecRight = &pDecOut[1];
}
@ -4519,8 +4514,8 @@ static ULONG VARIANT_Add(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
ULARGE_INTEGER ul64;
ul64.QuadPart = (ULONG64)ulLeft + (ULONG64)ulRight + (ULONG64)*pulHigh;
*pulHigh = ul64.u.HighPart;
return ul64.u.LowPart;
*pulHigh = ul64.HighPart;
return ul64.LowPart;
}
/* Subtract two unsigned 32 bit values with underflow */
@ -4541,10 +4536,10 @@ static ULONG VARIANT_Sub(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
invert = TRUE;
}
if (invert)
ul64.u.HighPart = -ul64.u.HighPart ;
ul64.HighPart = -ul64.HighPart ;
*pulHigh = ul64.u.HighPart;
return ul64.u.LowPart;
*pulHigh = ul64.HighPart;
return ul64.LowPart;
}
/* Multiply two unsigned 32 bit values with overflow */
@ -4553,17 +4548,17 @@ static ULONG VARIANT_Mul(ULONG ulLeft, ULONG ulRight, ULONG* pulHigh)
ULARGE_INTEGER ul64;
ul64.QuadPart = (ULONG64)ulLeft * (ULONG64)ulRight + (ULONG64)*pulHigh;
*pulHigh = ul64.u.HighPart;
return ul64.u.LowPart;
*pulHigh = ul64.HighPart;
return ul64.LowPart;
}
/* Compare two decimals that have the same scale */
static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRight)
{
if ( DEC_HI32(pDecLeft) < DEC_HI32(pDecRight) ||
(DEC_HI32(pDecLeft) <= DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) < DEC_LO64(pDecRight)))
if ( pDecLeft->Hi32 < pDecRight->Hi32 ||
(pDecLeft->Hi32 <= pDecRight->Hi32 && pDecLeft->Lo64 < pDecRight->Lo64))
return -1;
else if (DEC_HI32(pDecLeft) == DEC_HI32(pDecRight) && DEC_LO64(pDecLeft) == DEC_LO64(pDecRight))
else if (pDecLeft->Hi32 == pDecRight->Hi32 && pDecLeft->Lo64 == pDecRight->Lo64)
return 0;
return 1;
}
@ -4597,13 +4592,13 @@ HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECI
int cmp;
/* Correct for the sign of the result */
if (DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
if (pDecLeft->sign && pDecRight->sign)
{
/* -x + -y : Negative */
sign = DECIMAL_NEG;
goto VarDecAdd_AsPositive;
}
else if (DEC_SIGN(pDecLeft) && !DEC_SIGN(pDecRight))
else if (pDecLeft->sign && !pDecRight->sign)
{
cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
@ -4612,19 +4607,19 @@ HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECI
{
sign = DECIMAL_NEG;
VarDecAdd_AsNegative:
DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
pDecOut->Lo32 = VARIANT_Sub(pDecLeft->Lo32, pDecRight->Lo32, &overflow);
pDecOut->Mid32 = VARIANT_Sub(pDecLeft->Mid32, pDecRight->Mid32, &overflow);
pDecOut->Hi32 = VARIANT_Sub(pDecLeft->Hi32, pDecRight->Hi32, &overflow);
}
else
{
VarDecAdd_AsInvertedNegative:
DEC_LO32(pDecOut) = VARIANT_Sub(DEC_LO32(pDecRight), DEC_LO32(pDecLeft), &overflow);
DEC_MID32(pDecOut) = VARIANT_Sub(DEC_MID32(pDecRight), DEC_MID32(pDecLeft), &overflow);
DEC_HI32(pDecOut) = VARIANT_Sub(DEC_HI32(pDecRight), DEC_HI32(pDecLeft), &overflow);
pDecOut->Lo32 = VARIANT_Sub(pDecRight->Lo32, pDecLeft->Lo32, &overflow);
pDecOut->Mid32 = VARIANT_Sub(pDecRight->Mid32, pDecLeft->Mid32, &overflow);
pDecOut->Hi32 = VARIANT_Sub(pDecRight->Hi32, pDecLeft->Hi32, &overflow);
}
}
else if (!DEC_SIGN(pDecLeft) && DEC_SIGN(pDecRight))
else if (!pDecLeft->sign && pDecRight->sign)
{
cmp = VARIANT_DecCmp(pDecLeft, pDecRight);
@ -4640,9 +4635,9 @@ VarDecAdd_AsInvertedNegative:
{
/* x + y : Positive */
VarDecAdd_AsPositive:
DEC_LO32(pDecOut) = VARIANT_Add(DEC_LO32(pDecLeft), DEC_LO32(pDecRight), &overflow);
DEC_MID32(pDecOut) = VARIANT_Add(DEC_MID32(pDecLeft), DEC_MID32(pDecRight), &overflow);
DEC_HI32(pDecOut) = VARIANT_Add(DEC_HI32(pDecLeft), DEC_HI32(pDecRight), &overflow);
pDecOut->Lo32 = VARIANT_Add(pDecLeft->Lo32, pDecRight->Lo32, &overflow);
pDecOut->Mid32 = VARIANT_Add(pDecLeft->Mid32, pDecRight->Mid32, &overflow);
pDecOut->Hi32 = VARIANT_Add(pDecLeft->Hi32, pDecRight->Hi32, &overflow);
if (overflow)
{
@ -4650,15 +4645,15 @@ VarDecAdd_AsPositive:
DWORD n[4];
unsigned char remainder;
if (!DEC_SCALE(pDecLeft))
if (!pDecLeft->scale)
return DISP_E_OVERFLOW;
DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft) - 1;
DEC_SIGN(pDecOut) = sign;
pDecOut->scale = pDecLeft->scale - 1;
pDecOut->sign = sign;
n[0] = DEC_LO32(pDecOut);
n[1] = DEC_MID32(pDecOut);
n[2] = DEC_HI32(pDecOut);
n[0] = pDecOut->Lo32;
n[1] = pDecOut->Mid32;
n[2] = pDecOut->Hi32;
n[3] = overflow;
remainder = VARIANT_int_divbychar(n,4,10);
@ -4674,9 +4669,9 @@ VarDecAdd_AsPositive:
}
}
DEC_LO32(pDecOut) = n[0] ;
DEC_MID32(pDecOut) = n[1];
DEC_HI32(pDecOut) = n[2];
pDecOut->Lo32 = n[0] ;
pDecOut->Mid32 = n[1];
pDecOut->Hi32 = n[2];
return S_OK;
}
@ -4685,8 +4680,8 @@ VarDecAdd_AsPositive:
if (overflow)
return DISP_E_OVERFLOW; /* overflowed */
DEC_SCALE(pDecOut) = DEC_SCALE(pDecLeft);
DEC_SIGN(pDecOut) = sign;
pDecOut->scale = pDecLeft->scale;
pDecOut->sign = sign;
}
return hRet;
}
@ -4694,25 +4689,21 @@ VarDecAdd_AsPositive:
/* translate from external DECIMAL format into an internal representation */
static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to)
{
to->scale = DEC_SCALE(from);
to->sign = DEC_SIGN(from) ? 1 : 0;
to->scale = from->scale;
to->sign = from->sign ? 1 : 0;
to->bitsnum[0] = DEC_LO32(from);
to->bitsnum[1] = DEC_MID32(from);
to->bitsnum[2] = DEC_HI32(from);
to->bitsnum[0] = from->Lo32;
to->bitsnum[1] = from->Mid32;
to->bitsnum[2] = from->Hi32;
}
static void VARIANT_DecFromDI(const VARIANT_DI * from, DECIMAL * to)
{
if (from->sign) {
DEC_SIGNSCALE(to) = SIGNSCALE(DECIMAL_NEG, from->scale);
} else {
DEC_SIGNSCALE(to) = SIGNSCALE(DECIMAL_POS, from->scale);
}
DEC_LO32(to) = from->bitsnum[0];
DEC_MID32(to) = from->bitsnum[1];
DEC_HI32(to) = from->bitsnum[2];
to->sign = from->sign ? DECIMAL_NEG : DECIMAL_POS;
to->scale = from->scale;
to->Lo32 = from->bitsnum[0];
to->Mid32 = from->bitsnum[1];
to->Hi32 = from->bitsnum[2];
}
/* clear an internal representation of a DECIMAL */
@ -5732,7 +5723,7 @@ HRESULT WINAPI VarDecSub(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECI
HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut)
{
*pDecOut = *pDecIn;
DEC_SIGN(pDecOut) &= ~DECIMAL_NEG;
pDecOut->sign &= ~DECIMAL_NEG;
return S_OK;
}
@ -5758,10 +5749,10 @@ HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut)
double dbl;
HRESULT hr;
if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
if (pDecIn->sign & ~DECIMAL_NEG)
return E_INVALIDARG;
if (!DEC_SCALE(pDecIn))
if (!pDecIn->scale)
{
*pDecOut = *pDecIn; /* Already an integer */
return S_OK;
@ -5798,10 +5789,10 @@ HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
double dbl;
HRESULT hr;
if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG)
if (pDecIn->sign & ~DECIMAL_NEG)
return E_INVALIDARG;
if (!(DEC_SIGN(pDecIn) & DECIMAL_NEG) || !DEC_SCALE(pDecIn))
if (!(pDecIn->sign & DECIMAL_NEG) || !pDecIn->scale)
return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */
hr = VarR8FromDec(pDecIn, &dbl);
@ -5828,7 +5819,7 @@ HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut)
HRESULT WINAPI VarDecNeg(const DECIMAL* pDecIn, DECIMAL* pDecOut)
{
*pDecOut = *pDecIn;
DEC_SIGN(pDecOut) ^= DECIMAL_NEG;
pDecOut->sign ^= DECIMAL_NEG;
return S_OK;
}
@ -5852,10 +5843,10 @@ HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOu
HRESULT hr;
unsigned int i;
if (cDecimals < 0 || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) || DEC_SCALE(pDecIn) > DEC_MAX_SCALE)
if (cDecimals < 0 || (pDecIn->sign & ~DECIMAL_NEG) || pDecIn->scale > DEC_MAX_SCALE)
return E_INVALIDARG;
if (cDecimals >= DEC_SCALE(pDecIn))
if (cDecimals >= pDecIn->scale)
{
*pDecOut = *pDecIn; /* More precision than we have */
return S_OK;
@ -5863,11 +5854,11 @@ HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOu
/* truncate significant digits and rescale */
memset(&divisor, 0, sizeof(divisor));
DEC_LO64(&divisor) = 1;
divisor.Lo64 = 1;
memset(&tmp, 0, sizeof(tmp));
DEC_LO64(&tmp) = 10;
for (i = 0; i < DEC_SCALE(pDecIn) - cDecimals; ++i)
tmp.Lo64 = 10;
for (i = 0; i < pDecIn->scale - cDecimals; ++i)
{
hr = VarDecMul(&divisor, &tmp, &divisor);
if (FAILED(hr))
@ -5878,7 +5869,7 @@ HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOu
if (FAILED(hr))
return hr;
DEC_SCALE(pDecOut) = cDecimals;
pDecOut->scale = cDecimals;
return S_OK;
}
@ -5905,11 +5896,11 @@ HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
if (!pDecLeft || !pDecRight)
return VARCMP_NULL;
if ((!(DEC_SIGN(pDecLeft) & DECIMAL_NEG)) && (DEC_SIGN(pDecRight) & DECIMAL_NEG) &&
(DEC_HI32(pDecLeft) | DEC_MID32(pDecLeft) | DEC_LO32(pDecLeft)))
if ((!(pDecLeft->sign & DECIMAL_NEG)) && (pDecRight->sign & DECIMAL_NEG) &&
(pDecLeft->Hi32 || pDecLeft->Lo64))
return VARCMP_GT;
else if ((DEC_SIGN(pDecLeft) & DECIMAL_NEG) && (!(DEC_SIGN(pDecRight) & DECIMAL_NEG)) &&
(DEC_HI32(pDecLeft) | DEC_MID32(pDecLeft) | DEC_LO32(pDecLeft)))
else if ((pDecLeft->sign & DECIMAL_NEG) && (!(pDecRight->sign & DECIMAL_NEG)) &&
(pDecLeft->Hi32 || pDecLeft->Lo64))
return VARCMP_LT;
/* Subtract right from left, and compare the result to 0 */
@ -5917,9 +5908,9 @@ HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight)
if (SUCCEEDED(hRet))
{
int non_zero = DEC_HI32(&result) | DEC_MID32(&result) | DEC_LO32(&result);
int non_zero = result.Hi32 || result.Lo64;
if ((DEC_SIGN(&result) & DECIMAL_NEG) && non_zero)
if ((result.sign & DECIMAL_NEG) && non_zero)
hRet = (HRESULT)VARCMP_LT;
else if (non_zero)
hRet = (HRESULT)VARCMP_GT;
@ -6308,10 +6299,10 @@ HRESULT WINAPI VarBoolFromUI4(ULONG ulIn, VARIANT_BOOL *pBoolOut)
*/
HRESULT WINAPI VarBoolFromDec(const DECIMAL* pDecIn, VARIANT_BOOL *pBoolOut)
{
if (DEC_SCALE(pDecIn) > DEC_MAX_SCALE || (DEC_SIGN(pDecIn) & ~DECIMAL_NEG))
if (pDecIn->scale > DEC_MAX_SCALE || (pDecIn->sign & ~DECIMAL_NEG))
return E_INVALIDARG;
if (DEC_HI32(pDecIn) || DEC_MID32(pDecIn) || DEC_LO32(pDecIn))
if (pDecIn->Hi32 || pDecIn->Lo64)
*pBoolOut = VARIANT_TRUE;
else
*pBoolOut = VARIANT_FALSE;
@ -6650,9 +6641,9 @@ HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
decVal.scale = 4;
decVal.sign = 0;
decVal.bitsnum[0] = cyIn.s.Lo;
decVal.bitsnum[1] = cyIn.s.Hi;
if (cyIn.s.Hi & 0x80000000UL) {
decVal.bitsnum[0] = cyIn.Lo;
decVal.bitsnum[1] = cyIn.Hi;
if (cyIn.Hi & 0x80000000UL) {
DWORD one = 1;
/* Negative number! */