mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
405 lines
7.1 KiB
405 lines
7.1 KiB
/**********************************************************************/
|
|
/** 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;
|
|
}
|
|
|