📄 olevar.cpp
字号:
m_cur = varSrc.cyVal;
SetStatus(valid);
}
return *this;
}
BOOL COleCurrency::operator<(const COleCurrency& cur) const
{
ASSERT(GetStatus() == valid);
ASSERT(cur.GetStatus() == valid);
return((m_cur.Hi == cur.m_cur.Hi) ?
(m_cur.Lo < cur.m_cur.Lo) : (m_cur.Hi < cur.m_cur.Hi));
}
BOOL COleCurrency::operator>(const COleCurrency& cur) const
{
ASSERT(GetStatus() == valid);
ASSERT(cur.GetStatus() == valid);
return((m_cur.Hi == cur.m_cur.Hi) ?
(m_cur.Lo > cur.m_cur.Lo) : (m_cur.Hi > cur.m_cur.Hi));
}
BOOL COleCurrency::operator<=(const COleCurrency& cur) const
{
ASSERT(GetStatus() == valid);
ASSERT(cur.GetStatus() == valid);
return((m_cur.Hi == cur.m_cur.Hi) ?
(m_cur.Lo <= cur.m_cur.Lo) : (m_cur.Hi < cur.m_cur.Hi));
}
BOOL COleCurrency::operator>=(const COleCurrency& cur) const
{
ASSERT(GetStatus() == valid);
ASSERT(cur.GetStatus() == valid);
return((m_cur.Hi == cur.m_cur.Hi) ?
(m_cur.Lo >= cur.m_cur.Lo) : (m_cur.Hi > cur.m_cur.Hi));
}
COleCurrency COleCurrency::operator+(const COleCurrency& cur) const
{
COleCurrency curResult;
// If either operand Null, result Null
if (GetStatus() == null || cur.GetStatus() == null)
{
curResult.SetStatus(null);
return curResult;
}
// If either operand Invalid, result Invalid
if (GetStatus() == invalid || cur.GetStatus() == invalid)
{
curResult.SetStatus(invalid);
return curResult;
}
// Add separate CURRENCY components
curResult.m_cur.Hi = m_cur.Hi + cur.m_cur.Hi;
curResult.m_cur.Lo = m_cur.Lo + cur.m_cur.Lo;
// Increment Hi if Lo overflows
if (m_cur.Lo > curResult.m_cur.Lo)
curResult.m_cur.Hi++;
// Overflow if operands same sign and result sign different
if (!((m_cur.Hi ^ cur.m_cur.Hi) & 0x80000000) &&
((m_cur.Hi ^ curResult.m_cur.Hi) & 0x80000000))
{
curResult.SetStatus(invalid);
}
return curResult;
}
COleCurrency COleCurrency::operator-(const COleCurrency& cur) const
{
COleCurrency curResult;
// If either operand Null, result Null
if (GetStatus() == null || cur.GetStatus() == null)
{
curResult.SetStatus(null);
return curResult;
}
// If either operand Invalid, result Invalid
if (GetStatus() == invalid || cur.GetStatus() == invalid)
{
curResult.SetStatus(invalid);
return curResult;
}
// Subtract separate CURRENCY components
curResult.m_cur.Hi = m_cur.Hi - cur.m_cur.Hi;
curResult.m_cur.Lo = m_cur.Lo - cur.m_cur.Lo;
// Decrement Hi if Lo overflows
if (m_cur.Lo < curResult.m_cur.Lo)
curResult.m_cur.Hi--;
// Overflow if operands not same sign and result not same sign
if (((m_cur.Hi ^ cur.m_cur.Hi) & 0x80000000) &&
((m_cur.Hi ^ curResult.m_cur.Hi) & 0x80000000))
{
curResult.SetStatus(invalid);
}
return curResult;
}
COleCurrency COleCurrency::operator-() const
{
// If operand not Valid, just return
if (!GetStatus() == valid)
return *this;
COleCurrency curResult;
// Negating MIN_CURRENCY,will set invalid
if (m_cur.Hi == 0x80000000 && m_cur.Lo == 0x00000000)
{
curResult.SetStatus(invalid);
}
curResult.m_cur.Hi = ~m_cur.Hi;
curResult.m_cur.Lo = -(long)m_cur.Lo;
// If cy was -1 make sure Hi correctly set
if (curResult.m_cur.Lo == 0)
curResult.m_cur.Hi++;
return curResult;
}
COleCurrency COleCurrency::operator*(long nOperand) const
{
// If operand not Valid, just return
if (!GetStatus() == valid)
return *this;
COleCurrency curResult(m_cur);
DWORD nTempOp;
// Return now if one operand is 0 (optimization)
if ((m_cur.Hi == 0x00000000 && m_cur.Lo == 0x00000000) || nOperand == 0)
{
curResult.m_cur.Hi = 0;
curResult.m_cur.Lo = 0;
return curResult;
}
// Handle only valid case of multiplying MIN_CURRENCY
if (m_cur.Hi == 0x80000000 && m_cur.Lo == 0x00000000 && nOperand == 1)
return curResult;
// Compute absolute values.
if (m_cur.Hi < 0)
curResult = -curResult;
nTempOp = labs(nOperand);
// Check for overflow
if (curResult.m_cur.Hi != 0)
{
WORD wHiBitCur, wHiBitOp;
HI_BIT(curResult.m_cur.Hi, wHiBitCur);
HI_BIT(nTempOp, wHiBitOp);
// 63-bit limit on result. (n bits)*(m bits) = (n+m-1) bits.
if (wHiBitCur + wHiBitOp - 1 > 63)
{
// Overflow!
curResult.SetStatus(invalid);
// Set to maximum negative value
curResult.m_cur.Hi = 0x80000000;
curResult.m_cur.Lo = 0x00000000;
return curResult;
}
}
// Break up into WORDs
WORD wCy4, wCy3, wCy2, wCy1, wL2, wL1;
wCy4 = HIWORD(curResult.m_cur.Hi);
wCy3 = LOWORD(curResult.m_cur.Hi);
wCy2 = HIWORD(curResult.m_cur.Lo);
wCy1 = LOWORD(curResult.m_cur.Lo);
wL2 = HIWORD(nTempOp);
wL1 = LOWORD(nTempOp);
// Multiply each set of WORDs
DWORD dwRes11, dwRes12, dwRes21, dwRes22;
DWORD dwRes31, dwRes32, dwRes41; // Don't need dwRes42
dwRes11 = wCy1 * wL1;
dwRes12 = wCy1 * wL2;
dwRes21 = wCy2 * wL1;
dwRes22 = wCy2 * wL2;
dwRes31 = wCy3 * wL1;
dwRes32 = wCy3 * wL2;
dwRes41 = wCy4 * wL1;
// Add up low order pieces
dwRes11 += dwRes12<<16;
curResult.m_cur.Lo = dwRes11 + (dwRes21<<16);
curResult.m_cur.Hi = 0;
// Check if carry required
if (dwRes11 < dwRes12<<16)
curResult.m_cur.Hi++;
if ((DWORD)curResult.m_cur.Lo < dwRes11)
curResult.m_cur.Hi++;
// Add up the high order pieces
curResult.m_cur.Hi += dwRes31 + (dwRes32<<16) + (dwRes41<<16) +
dwRes22 + (dwRes12>>16) + (dwRes21>>16);
// Compute result sign
if ((m_cur.Hi ^ nOperand) & 0x80000000)
curResult = -curResult;
return curResult;
}
COleCurrency COleCurrency::operator/(long nOperand) const
{
// If operand not Valid, just return
if (!GetStatus() == valid)
return *this;
COleCurrency curTemp(m_cur);
DWORD nTempOp;
// Check for divide by 0
if (nOperand == 0)
{
curTemp.SetStatus(invalid);
// Set to maximum negative value
curTemp.m_cur.Hi = 0x80000000;
curTemp.m_cur.Lo = 0x00000000;
return curTemp;
}
// Compute absolute values
if (curTemp.m_cur.Hi < 0)
curTemp = -curTemp;
nTempOp = labs(nOperand);
// Optimization - division is simple if Hi == 0
if (curTemp.m_cur.Hi == 0x0000)
{
curTemp.m_cur.Lo = m_cur.Lo / nTempOp;
// Compute result sign
if ((m_cur.Hi ^ nOperand) & 0x80000000)
curTemp = -curTemp;
return curTemp;
}
// Now curTemp represents remainder
COleCurrency curResult; // Initializes to zero
COleCurrency curTempResult;
COleCurrency curOperand;
curOperand.m_cur.Lo = nTempOp;
WORD wHiBitRem;
WORD wScaleOp;
// Quit if remainder can be truncated
while (curTemp >= curOperand)
{
// Scale up and divide Hi portion
HI_BIT(curTemp.m_cur.Hi, wHiBitRem);
if (wHiBitRem != 0)
wHiBitRem += 32;
else
HI_BIT(curTemp.m_cur.Lo, wHiBitRem);
WORD wShift = (WORD)(64 - wHiBitRem);
LSHIFT_UCUR(curTemp, wShift);
// If Operand bigger than Hi it must be scaled
wScaleOp = (WORD)((nTempOp > (DWORD)curTemp.m_cur.Hi) ? 1 : 0);
// Perform synthetic division
curTempResult.m_cur.Hi =
(DWORD)curTemp.m_cur.Hi / (nTempOp >> wScaleOp);
// Scale back to get correct result and remainder
RSHIFT_UCUR(curTemp, wShift);
wShift = (WORD)(wShift - wScaleOp);
RSHIFT_UCUR(curTempResult, wShift);
// Now calculate result and remainder
curResult += curTempResult;
curTemp -= curTempResult * nTempOp;
}
// Compute result sign
if ((m_cur.Hi ^ nOperand) & 0x80000000)
curResult = -curResult;
return curResult;
}
void COleCurrency::SetCurrency(long nUnits, long nFractionalUnits)
{
COleCurrency curUnits; // Initializes to 0
COleCurrency curFractionalUnits; // Initializes to 0
// Set temp currency value to Units (need to multiply by 10,000)
curUnits.m_cur.Lo = (DWORD)labs(nUnits);
curUnits = curUnits * 10000;
if (nUnits < 0)
curUnits = -curUnits;
curFractionalUnits.m_cur.Lo = (DWORD)labs(nFractionalUnits);
if (nFractionalUnits < 0)
curFractionalUnits = -curFractionalUnits;
// Now add together Units and FractionalUnits
*this = curUnits + curFractionalUnits;
SetStatus(valid);
}
BOOL COleCurrency::ParseCurrency(LPCTSTR lpszCurrency,
DWORD dwFlags, LCID lcid)
{
USES_CONVERSION;
CString strCurrency = lpszCurrency;
SCODE sc;
if ( FAILED(sc = VarCyFromStr((LPOLESTR)T2COLE(strCurrency),
lcid, dwFlags, &m_cur)))
{
if (sc == DISP_E_TYPEMISMATCH)
{
// Can't convert string to CURRENCY, set 0 & invalid
m_cur.Hi = 0x00000000;
m_cur.Lo = 0x00000000;
SetStatus(invalid);
return FALSE;
}
else if (sc == DISP_E_OVERFLOW)
{
// Can't convert string to CURRENCY, set max neg & invalid
m_cur.Hi = 0x80000000;
m_cur.Lo = 0x00000000;
SetStatus(invalid);
return FALSE;
}
else
{
TRACE0("\nCOleCurrency VarCyFromStr call failed.\n\t");
if (sc == E_OUTOFMEMORY)
AfxThrowMemoryException();
else
AfxThrowOleException(sc);
}
}
SetStatus(valid);
return TRUE;
}
CString COleCurrency::Format(DWORD dwFlags, LCID lcid) const
{
USES_CONVERSION;
CString strCur;
// If null, return empty string
if (GetStatus() == null)
return strCur;
// If invalid, return Currency resource string
if (GetStatus() == invalid)
{
VERIFY(strCur.LoadString(AFX_IDS_INVALID_CURRENCY));
return strCur;
}
COleVariant var;
// Don't need to trap error. Should not fail due to type mismatch
AfxCheckError(VarBstrFromCy(m_cur, lcid, dwFlags, &V_BSTR(&var)));
var.vt = VT_BSTR;
return OLE2CT(V_BSTR(&var));
}
// serialization
#ifdef _DEBUG
CDumpContext& AFXAPI operator<<(CDumpContext& dc, COleCurrency curSrc)
{
dc << "\nCOleCurrency Object:";
dc << "\n\tm_status = " << (long)curSrc.m_status;
COleVariant var(curSrc);
var.ChangeType(VT_CY);
return dc << "\n\tCurrency = " << var.bstrVal;
}
#endif // _DEBUG
CArchive& AFXAPI operator<<(CArchive& ar, COleCurrency curSrc)
{
ar << (long)curSrc.m_status;
ar << curSrc.m_cur.Hi;
return ar << curSrc.m_cur.Lo;
}
CArchive& AFXAPI operator>>(CArchive& ar, COleCurrency& curSrc)
{
ar >> (long&)curSrc.m_status;
ar >> curSrc.m_cur.Hi;
return ar >> curSrc.m_cur.Lo;
}
/////////////////////////////////////////////////////////////////////////////
// COleDateTime class HELPER definitions
// Verifies will fail if the needed buffer size is too large
#define MAX_TIME_BUFFER_SIZE 128 // matches that in timecore.cpp
#define MIN_DATE (-657434L) // about year 100
#define MAX_DATE 2958465L // about year 9999
// Half a second, expressed in days
#define HALF_SECOND (1.0/172800.0)
// One-based array of days in year at month start
AFX_STATIC_DATA int _afxMonthDays[13] =
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
/////////////////////////////////////////////////////////////////////////////
// COleDateTime class HELPERS - implementation
AFX_STATIC BOOL AFXAPI _AfxOleDateFromTm(WORD wYear, WORD wMonth, WORD wDay,
WORD wHour, WORD wMinute, WORD wSecond, DATE& dtDest)
{
// Validate year and month (ignore day of week and milliseconds)
if (wYear > 9999 || wMonth < 1 || wMonth > 12)
return FALSE;
// Check for leap year and set the number of days in the month
BOOL bLeapYear = ((wYear & 3) == 0) &&
((wYear % 100) != 0 || (wYear % 400) == 0);
int nDaysInMonth =
_afxMonthDays[wMonth] - _afxMonthDays[wMonth-1] +
((bLeapYear && wDay == 29 && wMonth == 2) ? 1 : 0);
// Finish validating the date
if (wDay < 1 || wDay > nDaysInMonth ||
wHour > 23 || wMinute > 59 ||
wSecond > 59)
{
return FALSE;
}
// Cache the date in days and time in fractional days
long nDate;
double dblTime;
//It is a valid date; make Jan 1, 1AD be 1
nDate = wYear*365L + wYear/4 - wYear/100 + wYear/400 +
_afxMonthDays[wMonth-1] + wDay;
// If leap year and it's before March, subtract 1:
if (wMonth <= 2 && bLeapYear)
--nDate;
// Offset so that 12/30/1899 is 0
nDate -= 693959L;
dblTime = (((long)wHour * 3600L) + // hrs in seconds
((long)wMinute * 60L) + // mins in seconds
((long)wSecond)) / 86400.;
dtDest = (double) nDate + ((nDate >= 0) ? dblTime : -dblTime);
return TRUE;
}
AFX_STATIC BOOL AFXAPI _AfxTmFromOleDate(DATE dtSrc, struct tm& tmDest)
{
// The legal range does not actually span year 0 to 9999.
if (dtSrc > MAX_DATE || dtSrc < MIN_DATE) // about year 100 to about 9999
return FALSE;
long nDays; // Number of days since Dec. 30, 1899
long nDaysAbsolute; // Number of days since 1/1/0
long nSecsInDay; // Time in seconds since midnight
long nMinutesInDay; // Minutes in day
long n400Years; // Number of 400 year increments since 1/1/0
long n400Century; // Century within 400 year block (0,1,2 or 3)
long n4Years; // Number of 4 year increments since 1/1/0
long n4Day; // Day within 4 year block
// (0 is 1/1/yr1, 1460 is 12/31/yr4)
long n4Yr; // Year within 4 year block (0,1,2 or 3)
BOOL bLeap4 = TRUE; // TRUE if 4 year block includes leap year
double dblDate = dtSrc; // tempory serial date
// If a valid date, then this conversion should not overflow
nDays = (long)dblDate;
// Round to the second
dblDate += ((dtSrc > 0.0) ? HALF_SECOND : -HALF_SECOND);
nDaysAbsolute = (long)dblDate + 693959L; // Add days from 1/1/0 to 12/30/1899
dblDate = fabs(dblDate);
nSecsInDay = (long)((dblDate - floor(dblDate)) * 86400.);
// Calculate the day of week (sun=1, mon=2...)
// -1 because 1/1/0 is Sat. +1 because we want 1-based
tmDest.tm_wday = (int)((nDaysAbsolute - 1) % 7L) + 1;
// Leap years every 4 yrs except centuries not multiples of 400.
n400Years = (long)(nDaysAbsolute / 146097L);
// Set nDaysAbsolute to day within 400-year block
nDaysAbsolute %= 146097L;
// -1 because first century has extra day
n400Century = (long)((nDaysAbsolute - 1) / 36524L);
// Non-leap century
if (n400Century != 0)
{
// Set nDaysAbsolute to day within century
nDaysAbsolute = (nDaysAbsolute - 1) % 36524L;
// +1 because 1st 4 year increment has 1460 days
n4Years = (long)((nDaysAbsolute + 1) / 1461L);
if (n4Years != 0)
n4Day = (long)((nDaysAbsolute + 1) % 1461L);
else
{
bLeap4 = FALSE;
n4Day = (long)nDaysAbsolute;
}
}
else
{
// Leap century - not special case!
n4Years = (long)(nDaysAbsolute / 1461L);
n4Day = (long)(nDaysAbsolute % 1461L);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -