/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corp., 1995 **/ /**********************************************************************/ /* FILE HISTORY: */ #include "stdafx.h" #include "comprop.h" #include <stdlib.h> #include <memory.h> #include <ctype.h> #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif CObjHelper :: CObjHelper () : m_ctor_err( 0 ), m_api_err( 0 ), m_b_dirty( FALSE ), m_time_created( ::GetCurrentTime() ) { } void CObjHelper :: ReportError ( LONG errInConstruction ) { TRACEEOLID( _T("CObjectPlus construction failure, error = ") << errInConstruction ); m_ctor_err = errInConstruction; } LONG CObjHelper :: SetApiErr ( LONG errApi ) { return m_api_err = errApi; } void CObjHelper :: AssertValid () const { ASSERT(QueryError() == 0); } BOOL CObjHelper :: IsValid () const { return QueryError() == 0; } DWORD CObjHelper :: QueryAge () const { DWORD dwTime = ::GetCurrentTime(), dwDiff ; if ( dwTime < m_time_created ) { dwDiff = dwTime + (((DWORD) -1) - (m_time_created - 1)); } else { dwDiff = dwTime - m_time_created; } return dwDiff; } // // Constructor of extended object // CObjectPlus :: CObjectPlus () { } // // Compare one object with another: default implementation // orders objects by creation time. Return -1, 0 or 1. // int CObjectPlus :: Compare ( const CObjectPlus * pob ) const { return QueryCreationTime() < pob->QueryCreationTime() ? -1 : QueryCreationTime() != pob->QueryCreationTime(); } CObListIter :: CObListIter ( const CObOwnedList & obList ) : m_obList( obList ) { Reset(); } void CObListIter :: Reset () { m_pos = m_obList.GetCount() ? m_obList.GetHeadPosition() : NULL; } CObject * CObListIter :: Next () { return m_pos == NULL ? NULL : m_obList.GetNext(m_pos); } // // Subclass of CObList whose default behavior is to destroy // its contents during its own destruction // CObOwnedList :: CObOwnedList ( int nBlockSize ) : CObList( nBlockSize ), m_b_owned( TRUE ) { } CObOwnedList :: ~ CObOwnedList () { RemoveAll() ; } void CObOwnedList :: RemoveAll () { if ( m_b_owned ) { // // Remove and discard all the objects // while ( ! IsEmpty() ) { CObject * pob = RemoveHead() ; delete pob ; } } else { // // Just remove the object pointers // CObList::RemoveAll() ; } } CObject * CObOwnedList :: Index ( int index ) { CObListIter oli( *this ) ; CObject * pob ; for (int i = 0 ; (pob = oli.Next()) && i++ < index ; ); return pob; } CObject * CObOwnedList :: RemoveIndex ( int index ) { POSITION pos ; CObListIter oli( *this ) ; int i ; CObject * pob ; for ( i = 0, pos = oli.QueryPosition() ; (pob = oli.Next()) && i < index ; i++, pos = oli.QueryPosition() ); if ( pob && i == index ) { RemoveAt(pos); } else { pob = NULL; } return pob; } // // Remove the first (and hopefully only) occurrence of an object // pointer from this list. // BOOL CObOwnedList :: Remove ( CObject * pob ) { POSITION pos = Find( pob ) ; if (pos == NULL) { return FALSE; } RemoveAt(pos); return TRUE; } // // Set all elements to dirty or clean. Return TRUE if // any element was dirty. // BOOL CObOwnedList :: SetAll ( BOOL bDirty ) { int cDirtyItems = 0 ; CObListIter oli( *this ) ; CObjectPlus * pob ; while ( pob = (CObjectPlus *) oli.Next() ) { cDirtyItems += pob->IsDirty(); pob->SetDirty( bDirty ); } SetDirty(bDirty); return cDirtyItems > 0; } int CObOwnedList :: FindElement ( CObject * pobSought ) const { CObListIter oli( *this ) ; CObject * pob ; for ( int i = 0 ; (pob = oli.Next()) && pob != pobSought; i++ ); return pob ? i : -1; } // // Override of CObList::AddTail() to control exception handling. // Returns NULL if addition fails. // POSITION CObOwnedList :: AddTail ( CObjectPlus * pobj, BOOL bThrowException ) { POSITION pos = NULL ; // // Catch only memory exceptions. // TRY { pos = CObList::AddTail( pobj ) ; } CATCH( CMemoryException, e ) { pos = NULL ; } END_CATCH if ( pos == NULL && bThrowException ) { // // CObList::AddTail() threw an exception. Echo it. // ::AfxThrowMemoryException() ; } return pos ; } typedef struct { CObjectPlus * pObj ; // Pointer to object to be sorted CObjectPlus::PCOBJPLUS_ORDER_FUNC pFunc ; // Pointer to ordering function } CBOWNEDLIST_SORT_HELPER ; // // This static member function is used to quick sort an array of structures // as declared above. Each element contains the object pointer and a // pointer to the object's member function to be invoked for comparison. // // int _cdecl CObOwnedList :: SortHelper ( const void * pa, const void * pb ) { CBOWNEDLIST_SORT_HELPER * pHelp1 = (CBOWNEDLIST_SORT_HELPER *) pa, * pHelp2 = (CBOWNEDLIST_SORT_HELPER *) pb ; return (pHelp1->pObj->*pHelp1->pFunc)( pHelp2->pObj ); } // // Sort the list by recreating it entirely. // LONG CObOwnedList :: Sort ( CObjectPlus::PCOBJPLUS_ORDER_FUNC pOrderFunc ) { LONG err = 0 ; int cItems = GetCount() ; if ( cItems < 2 ) { return NO_ERROR ; } CObListIter obli( *this ) ; CObjectPlus * pObNext ; BOOL bOwned = SetOwnership( FALSE ) ; int i ; CBOWNEDLIST_SORT_HELPER * paSortHelpers = NULL ; CATCH_MEM_EXCEPTION { // // Allocate the helper array // paSortHelpers = new CBOWNEDLIST_SORT_HELPER[ cItems ] ; // // Fill the helper array. // for ( i = 0 ; pObNext = (CObjectPlus *) obli.Next() ; i++ ) { paSortHelpers[i].pFunc = pOrderFunc ; paSortHelpers[i].pObj = pObNext ; } // // Release all object pointer references. Note that we // forced "owned" to FALSE above. // RemoveAll() ; ASSERT( GetCount() == 0 ) ; // // Sort the helper array // ::qsort( (void *) paSortHelpers, cItems, sizeof paSortHelpers[0], SortHelper ); // // Refill the list from the helper array. // for ( i = 0 ; i < cItems ; i++ ) { AddTail( paSortHelpers[i].pObj ) ; } ASSERT( GetCount() == cItems ) ; } END_MEM_EXCEPTION(err) // // Delete the working array // delete [] paSortHelpers; // // Restore the object ownership state // SetOwnership(bOwned); return err; }