⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 olevar.cpp

📁 c语言编程软件vc6.0中文绿色版_vc6.0官方下载
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		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 + -