#if !defined(_WINDOWS_BCL_COMMON_H_INCLUDED_) #define _WINDOWS_BCL_COMMON_H_INCLUDED_ #pragma once /*++ Copyright (c) 2000 Microsoft Corporation Module Name: bcl_common.h Abstract: Definitions common to all of the Base Class Libraries implementation. Author: Michael Grier (MGrier) 2/6/2002 Revision History: --*/ #include // for memcpy #include // for memmove #include // for CHAR_BIT namespace BCL { // // Macros for error handling in BCL functions // // Rather than try to break down the purpose of each, here's a couple of // examples: // // TCallDisposition Foo(int i) { // TCallDisposition indicates internal linkage // BCL_MAYFAIL_PROLOG // first line of any function that can fail // int j; // BCL_PARAMETER_CHECK((i >= 0) && (i <= 100)); // BCL_IFCALLFAILED_EXIT(Bar(i, &j)); // assumes Bar also has internal linkage // BCL_ASSERT(j >= 0); // BCL_INTERNAL_ERROR_CHECK(i != j); // BCL_MAYFAIL_EPILOG_INTERNAL // last line when internal linkage // } // // BOOL Win32ishFoo(int i) { // BCL_MAYFAIL_PROLOG // BCL_IFCALLFAILED_EXIT(Foo(i)); // BCL_MAYFAIL_EPILOG_PUBLIC // } // #define BCL_ORIGINATE_ERROR(_error) do { _bcl_cd = (_error); goto Exit; } while (0) #define BCL_CALLBACK_FAILED do { goto Exit; } while (0) #if _X86_ #define BCL_DEBUG_BREAK do { __asm { int 3 } } while (0) #else #define BCL_DEBUG_BREAK do { DebugBreak(VOID); } while (0) #endif #define BCL_ASSERTION_FAILURE_ACTION(_szExpr) BCL_DEBUG_BREAK #define BCL_ASSERT(_e) do { if (!(_e)) { BCL_ASSERTION_FAILURE_ACTION(#_e); } } while (0) #define BCL_COMPILE_TIME_ASSERT(_e) typedef char __c_assert[(_e) ? 1 : -1] #define BCL_INTERNAL_ERROR_FAILURE_ACTION(_szExpr) do { BCL_DEBUG_BREAK; _bcl_cd = TCallDisposition::InternalError_RuntimeCheck(); goto Exit; } while (0) #define BCL_INTERNAL_ERROR_CHECK(_e) do { if (!(_e)) { BCL_INTERNAL_ERROR_FAILURE_ACTION(#_e); } } while (0) #define BCL_MAYFAIL_PROLOG \ TCallDisposition _bcl_cd = TCallDisposition::InternalError_EpilogSkipped(); #define BCL_MAYFAIL_EPILOG_INTERNAL \ _bcl_cd = TCallDisposition::Success(); \ if (false) { goto Exit; } \ Exit: \ return _bcl_cd; #define BCL_MAYFAIL_EPILOG_PUBLIC \ _bcl_cd = TCallDisposition::Success(); \ if (false) { goto Exit; } \ Exit: \ return _bcl_cd.OnPublicReturn(); #define BCL_NOFAIL_PROLOG /* nothing */ #define BCL_NOFAIL_EPILOG /* nothing */ #define BCL_PARAMETER_CHECK_FAILURE_ACTION(_p) do { _bcl_cd = TCallDisposition::BadParameter(); goto Exit; } while (0) #define BCL_PARAMETER_CHECK(_p) do { if (!(_p)) { BCL_PARAMETER_CHECK_FAILURE_ACTION(_p); } } while (0) #define BCL_IFCALLFAILED_EXIT(_e) do { const TCallDisposition _bcl_cd_temp = (_e); if (_bcl_cd_temp.DidFail()) { _bcl_cd = _bcl_cd_temp; goto Exit; } } while (0) #define BCL_NUMBER_OF(_x) (sizeof(_x) / sizeof((_x)[0])) template class CConstantPointerAndCountPair; template class CMutablePointerAndCountPair; template class CConstantPointerAndCountRefPair; template class CMutablePointerAndCountRefPair; template class CConstantPointerAndCountPair { public: typedef const T *TConstantArray; typedef T *TMutableArray; typedef T TPointee; typedef TSizeT TCount; inline CConstantPointerAndCountPair() : m_prg(NULL), m_c(0) { } inline CConstantPointerAndCountPair(TConstantArray prg, TSizeT c) : m_prg(prg), m_c(c) { } inline CConstantPointerAndCountPair(const CMutablePointerAndCountPair &r) : m_prg(r.m_prg), m_c(r.m_c) { } inline CConstantPointerAndCountPair(const CConstantPointerAndCountPair &r) : m_prg(r.m_prg), m_c(r.m_c) { } inline ~CConstantPointerAndCountPair() { } CConstantPointerAndCountPair &operator =(const CConstantPointerAndCountPair &r) { m_prg = r.m_prg; m_c = r.m_c; return *this; } CConstantPointerAndCountPair &operator =(const CMutablePointerAndCountPair &r) { m_prg = r.m_prg; m_c = r.m_c; return *this; } inline TConstantArray GetPointer() const { return m_prg; } inline TSizeT GetCount() const { return m_c; } inline TConstantArray &Pointer() { return m_prg; } inline TSizeT &Count() { return m_c; } inline void SetCount(TSizeT c) { m_c = c; } inline void SetPointer(TConstantArray prg) { m_prg = prg; } inline void SetPointerAndCount(TConstantArray prg, TSizeT c) { m_prg = prg; m_c = c; } inline bool Valid() const { return (m_prg != NULL) || (m_c == 0); } inline CConstantPointerAndCountPair GetOffsetPair(TSizeT n) { return CConstantPointerAndCountPair(m_prg + n, m_c - n); } protected: TConstantArray m_prg; TSizeT m_c; }; // BCL::CConstantPointerAndCountPair template class CMutablePointerAndCountPair : public CConstantPointerAndCountPair { public: typedef const T *TConstantArray; typedef T *TMutableArray; inline CMutablePointerAndCountPair() { } inline CMutablePointerAndCountPair(TMutableArray prg, TSizeT c) : CConstantPointerAndCountPair(prg, c) { } inline ~CMutablePointerAndCountPair() { } using CConstantPointerAndCountPair::Valid; CMutablePointerAndCountPair &operator =(const CMutablePointerAndCountPair &r) { m_prg = r.m_prg; m_c = r.m_c; return *this; } inline TMutableArray GetPointer() const { return const_cast(m_prg); } inline TSizeT GetCount() const { return m_c; } inline TMutableArray &Pointer() { return const_cast(m_prg); } inline TSizeT &Count() { return m_c; } inline void SetPointer(TMutableArray prg) { m_prg = prg; } inline void SetCount(TSizeT c) { m_c = c; } inline void SetPointerAndCount(TMutableArray prg, TSizeT c) { m_prg = prg; m_c = c; } }; // BCL::CMutablePointerAndCountPair template class CConstantPointerAndCountRefPair { public: typedef const T *TConstantArray; typedef T *TMutableArray; typedef T TPointee; typedef TSizeT TCount; inline CConstantPointerAndCountRefPair(TConstantArray &rprg, TSizeT &rc) : m_rprg(rprg), m_rc(rc) { } inline CConstantPointerAndCountRefPair(const CMutablePointerAndCountRefPair &r) : m_rprg(r.m_rprg), m_rc(r.m_rc) { } inline CConstantPointerAndCountRefPair(const CConstantPointerAndCountRefPair &r) : m_rprg(r.m_rprg), m_rc(r.m_rc) { } inline ~CConstantPointerAndCountRefPair() { } inline CConstantPointerAndCountRefPair &operator =(const CConstantPointerAndCountPair &r) { m_rprg = r.GetPointer(); m_rc = r.GetCount(); return *this; } inline operator CConstantPointerAndCountPair() const { return BCL::CConstantPointerAndCountPair(m_rprg, m_rc); } inline TConstantArray GetPointer() const { return m_rprg; } inline TSizeT GetCount() const { return m_rc; } inline TConstantArray &Pointer() { return m_rprg; } inline TSizeT &Count() { return m_rc; } inline void SetCount(TSizeT c) { m_rc = c; } inline void SetPointer(TConstantArray prg) { m_rprg = prg; } inline void SetPointerAndCount(TConstantArray prg, TSizeT c) { m_rprg = prg; m_rc = c; } inline bool Valid() const { return (m_rprg != NULL) || (m_rc == 0); } inline CConstantPointerAndCountPair GetOffsetPair(TSizeT n) { return CConstantPointerAndCountPair(m_rprg + n, m_rc - n); } protected: TConstantArray &m_rprg; TSizeT &m_rc; }; // BCL::CConstantPointerAndCountRefPair template class CMutablePointerAndCountRefPair : public CConstantPointerAndCountRefPair { public: typedef const T *TConstantArray; typedef T *TMutableArray; inline CMutablePointerAndCountRefPair(TMutableArray &rprg, TSizeT &rc) : CConstantPointerAndCountRefPair(rprg, rc) { } inline ~CMutablePointerAndCountRefPair() { } using CConstantPointerAndCountRefPair::Valid; CMutablePointerAndCountRefPair &operator =(const CMutablePointerAndCountPair &r) { m_rprg = r.GetPointer(); m_rc = r.GetCount(); return *this; } inline operator CMutablePointerAndCountPair() const { return BCL::CMutablePointerAndCountPair(m_rprg, m_rc); } inline TMutableArray GetPointer() const { return const_cast(m_rprg); } inline TSizeT GetCount() const { return m_c; } inline TMutableArray &Pointer() { return const_cast(m_rprg); } inline TSizeT &Count() { return m_c; } inline void SetPointer(TMutableArray prg) { m_rprg = prg; } inline void SetCount(TSizeT c) { m_rc = c; } inline void SetPointerAndCount(TMutableArray prg, TSizeT c) { m_rprg = prg; m_rc = c; } }; // BCL::CMutablePointerAndCountRefPair #pragma intrinsic(memcmp) #pragma intrinsic(memcpy) inline bool __fastcall IsMemoryEqual( const void *pv1, const void *pv2, size_t cb ) { return (memcmp(pv1, pv2, cb) == 0); } // BCL::IsMemoryEqual template inline bool __fastcall IsMemoryEqual( const CConstantPointerAndCountPair &rpair1, const CConstantPointerAndCountPair &rpair2 ) { return ((rpair1.GetCount() == rpair2.GetCount()) && (BCL::IsMemoryEqual( rpair1.GetPointer(), rpair2.GetPointer(), rpair1.GetCount() * sizeof(T)))); } // BCL::IsMemoryEqual template inline TComparisonResult __fastcall CompareBytes( const void *pv1, const void *pv2, size_t cb ) { int i = memcmp(pv1, pv2, cb); if (i < 0) return TComparisonResult::LessThan(); else if (i == 0) return TComparisonResult::EqualTo(); else return TComparisonResult::GreaterThan(); } // BCL::CompareBytes template inline TComparisonResult __fastcall CompareBytes( const CConstantPointerAndCountPair &rpair1, const CConstantPointerAndCountPair &rpair2 ) { TComparisonResult cr = BCL::CompareBytes( rpair1.GetPointer(), rpair2.GetPointer(), ((rpair1.GetCount() < rpair2.GetCount()) ? rpair1.GetCount() : rpair2.GetCount()) * sizeof(T)); if (cr.IsEqualTo()) { if (rpair1.GetCount() < rpair2.GetCount()) cr.SetLessThan(); else if (rpair1.GetCount() > rpair2.GetCount()) cr.SetGreaterThan(); } return cr; } // BCL::CompareBytes inline void __fastcall CopyBytes( void *pvDestination, const void *pvSource, size_t cbToCopy ) { memcpy(pvDestination, pvSource, cbToCopy); } // BCL::CopyBytes template inline void __fastcall CopyBytes( const CMutablePointerAndCountPair &rpairOut, const CConstantPointerAndCountPair &rpairIn ) { BCL_ASSERT(rpairOut.GetCount() >= rpairIn.GetCount()); // Be defensive... BCL::CopyBytes( rpairOut.GetPointer(), rpairIn.GetPointer(), (rpairIn.GetCount() > rpairOut.GetCount()) ? rpairOut.GetCount() : rpairIn.GetCount()); } // BCL::CopyBytes inline void __fastcall MoveBytes( void *pvDestination, const void *pvSource, size_t cbToCopy ) { memmove(pvDestination, pvSource, cbToCopy); } // BCL::MoveBytes template inline void __fastcall MoveBytes( const CMutablePointerAndCountPair &rpairOut, const CConstantPointerAndCountPair &rpairIn ) { BCL_ASSERT(rpairOut.GetCount() >= rpairIn.GetCount()); // Be defensive... BCL::MoveBytes( rpairOut.GetPointer(), rpairIn.GetPointer(), (rpairIn.GetCount() > rpairOut.GetCount()) ? rpairOut.GetCount() : rpairIn.GetCount()); } // BCL::MoveBytes template inline void __fastcall CopyBytesAndAdvance( CMutablePointerAndCountPair &rpairOut, const CConstantPointerAndCountPair &rpairIn ) { const TSizeT cToCopy = (rpairIn.GetCount() > rpairOut.GetCount()) ? rpairOut.GetCount() : rpairIn.GetCount(); BCL_ASSERT(cToCopy == rpairIn.GetCount()); BCL::CopyBytes( rpairOut.GetPointer(), rpairIn.GetPointer(), cToCopy * sizeof(T)); rpairOut.SetPointerAndCount(rpairOut.GetPointer() + cToCopy, rpairOut.GetCount() - cToCopy); } // BCL::CopyBytesAndAdvance template inline TCallDisposition __fastcall AddWithOverflowCheck(T left, T right, T& output) { const T Result = left + right; if ((Result < left) || (Result < right)) return TCallDisposition::ArithmeticOverflow(); output = Result; return TCallDisposition::Success(); } template inline TCallDisposition __fastcall MultiplyWithOverflowCheck(T factor1, T factor2, T &rproduct) { // // Ok, this is somewhat tricky for SIZE_T. Here's what we'll assume: // // We'll assume that we can take each factor and split it into two halves // by using (CHAR_BITS * sizeof(SIZE_T) / 2). (This of course assumes that // one or the other is even which is a pretty safe bet.) // #define HALF_T_BITS(_t) (CHAR_BIT * sizeof(_t) / 2) #define HALF_T_MASK(_t) ((1 << HALF_T_BITS(_t)) - 1) const T lowFactor1 = factor1 & HALF_T_MASK(T); const T highFactor1 = (factor1 >> HALF_T_BITS(T)) & HALF_T_MASK(T); const T lowFactor2 = factor2 & HALF_T_MASK(T); const T highFactor2 = (factor2 >> HALF_T_BITS(T)) & HALF_T_MASK(T); // If both have non-zero high halves, we definitely have an overflow if ((highFactor1 != 0) && (highFactor2 != 0)) return TCallDisposition::ArithmeticOverflow(); const T crossproduct1 = (lowFactor1 * highFactor2); const T crossproduct2 = (lowFactor2 * highFactor1); const T crossproductsum = (crossproduct1 + crossproduct2); if ((crossproductsum < crossproduct1) || (crossproductsum < crossproduct2)) return TCallDisposition::ArithmeticOverflow(); // We're going to have to shift the cross product sum by HALF_SIZE_T_BITS // so let's make sure we don't lose anything. if ((crossproductsum >> HALF_T_BITS(T)) != 0) return TCallDisposition::ArithmeticOverflow(); // Ok, we should be OK... rproduct = (crossproductsum << HALF_T_BITS(T)) + (lowFactor1 * lowFactor2); return TCallDisposition::Success(); } }; // namespace BCL #endif // !defined(_WINDOWS_BCL_COMMON_H_INCLUDED_)