Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

779 lines
10 KiB

/*++
Copyright (c) 1994-1998 Microsoft Corporation
Module Name :
objplus.cpp
Abstract:
Base object classes
Author:
Ronald Meijer (ronaldm)
Project:
Internet Services Manager
Revision History:
--*/
//
// Include Files
//
#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()
/*++
Routine Description:
Constructor for super object help class
Arguments:
None
Return Value:
N/A
--*/
: m_ctor_err(ERROR_SUCCESS),
m_api_err(ERROR_SUCCESS),
m_fDirty(FALSE),
m_time_created(::GetCurrentTime())
{
}
void
CObjHelper::ReportError(
IN LONG errInConstruction
)
/*++
Routine Description:
Set the constructor error code, and dump the error message to
the debugging context.
Arguments:
LONG errInConstruction : Error code
Return Value:
None
--*/
{
TRACEEOLID("CObjectPlus construction failure, error = "
<< errInConstruction);
m_ctor_err = errInConstruction;
}
LONG
CObjHelper::SetApiErr(
IN LONG errApi
)
/*++
Routine Description:
Set the API error code.
Arguments:
LONG errApi : API error code
Return Value:
The API error code
--*/
{
return m_api_err = errApi;
}
BOOL
CObjHelper::IsValid() const
/*++
Routine Description:
Determine if the object is in a valid state
Arguments:
LONG errApi : API error code
Return Value:
TRUE if the the object is in a valid state, FALSE otherwise
--*/
{
return QueryError() == 0;
}
DWORD
CObjHelper::QueryAge() const
/*++
Routine Description:
Determine the age of the object.
Arguments:
None
Return Value:
time_t value indicating the age of the object.
--*/
{
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;
}
#ifdef _DEBUG
void
CObjHelper::AssertValid() const
/*++
Routine Description:
Assert the object if the object is in a valid state
Arguments:
None
Return Value:
None
--*/
{
ASSERT(IsValid());
}
#endif // _DEBUG
CObjectPlus::CObjectPlus()
/*++
Routine Description:
Constructor of extended object
Arguments:
None
Return Value:
N/A
--*/
{
}
int
CObjectPlus::Compare(
IN const CObjectPlus * pob
) const
/*++
Routine Description:
Compare one object with another: default implementation orders objects
by creation time. Return -1, 0 or 1.
Arguments:
const CObjectPlus * pob : Object to be compared against
Return Value:
-1 if this object is < than the compared object
0 if this object is == to the compared object
+1 if this object is > than the compared object
--*/
{
return QueryCreationTime() < pob->QueryCreationTime()
? -1
: QueryCreationTime() != pob->QueryCreationTime();
}
CObListPlus::CObListPlus(
IN int nBlockSize
)
/*++
Routine Description:
Subclass of CObList whose default behavior is to destroy its
contents during its own destruction
Arguments:
int nBlockSize : Initial block size
Return Value:
None
--*/
: CObList(nBlockSize),
m_fOwned(TRUE)
{
}
CObListPlus::~CObListPlus()
/*++
Routine Description:
Destructor. If the objects are owned, clean them up.
Arguments:
N/A
Return Value:
N/A
--*/
{
RemoveAll();
}
void
CObListPlus::RemoveAll()
/*++
Routine Description:
Remove all the objects in the list if the list owns its objects
Arguments:
None
Return Value:
None
--*/
{
if (m_fOwned)
{
//
// Remove and discard all the objects
//
while (!IsEmpty())
{
CObject * pob = RemoveHead();
delete pob ;
}
}
else
{
//
// Just remove the object pointers
//
CObList::RemoveAll();
}
}
CObject *
CObListPlus::Index(
IN int index
)
/*++
Routine Description:
Get object by index
Arguments:
int index : The index of the object to be returned
Return Value:
The object, or NULL if the index is invalid
--*/
{
CObListIter obli(*this);
CObject * pob = NULL;
for (int i = 0; (pob = obli.Next()) && i++ < index; /**/ );
return pob;
}
BOOL
CObListPlus::RemoveIndex(
IN int index
)
/*++
Routine Description:
Remove object by index
Arguments:
int index : The index of the object to be removed
Return Value:
The object, or NULL if the index is invalid
--*/
{
int i;
POSITION pos;
CObListIter obli(*this);
CObject * pob;
for (i = 0, pos = obli.QueryPosition();
(pob = obli.Next()) && i < index;
i++, pos = obli.QueryPosition());
if (pob && i == index)
{
RemoveAt(pos);
return TRUE;
}
return FALSE;
}
BOOL
CObListPlus::Remove(
IN CObject * pob
)
/*++
Routine Description:
Remove the first (and hopefully only) occurrence of an object
pointer from this list.
Arguments:
CObject * pob : The object to be removed
Return Value:
TRUE if the object was found and succesfully removed, FALSE otherwise
--*/
{
POSITION pos = Find(pob);
if (pos == NULL)
{
return FALSE;
}
RemoveAt(pos);
return TRUE;
}
void
CObListPlus::RemoveAt(
IN POSITION & pos
)
/*++
Routine Description:
Override of RemoveAt to delete the pointer at the position
given
Arguments:
POSITION pos : Position of item to delete
Return Value:
None.
Notes:
The item will only be deleted if this is an "owned" list.
--*/
{
CObject * pItem = GetAt(pos);
CObList::RemoveAt(pos);
if (m_fOwned)
{
delete pItem;
}
}
BOOL
CObListPlus::SetAll(
IN BOOL fDirty
)
/*++
Routine Description:
Set all elements to dirty or clean. Return TRUE if any element was dirty.
Arguments:
BOOL fDirty : Dirty flag to set the objects with
Return Value:
TRUE if any element was dirty.
--*/
{
int cDirtyItems = 0;
CObjectPlus * pob;
CObListIter obli(*this);
while (pob = (CObjectPlus *)obli.Next())
{
cDirtyItems += pob->IsDirty();
pob->SetDirty(fDirty);
}
SetDirty(fDirty);
return cDirtyItems > 0;
}
int
CObListPlus::FindElement(
IN CObject * pobSought
) const
/*++
Routine Description:
Find the object in the list.
Arguments:
CObject * pobSought : Object to be looked for
Return Value:
The index of the object, or -1 if it wasn't found.
--*/
{
CObject * pob;
CObListIter obli(*this);
for (int i = 0;
(pob = obli.Next()) && pob != pobSought;
i++);
return pob
? i
: -1;
}
//
// Sorting structure
//
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
typedef struct
{
CObjectPlus * pObj; // Pointer to object to be sorted
CObjectPlus::PCOBJPLUS_ORDER_FUNC pFunc; // Pointer to ordering function
} CBOWNEDLIST_SORT_HELPER;
int _cdecl
CObListPlus::SortHelper(
IN const void * pa,
IN const void * pb
)
/*++
Routine Description:
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.
Arguments:
const void * pa : Sorting help struct 1
const void * pb : Sorting help struct 2
Return Value:
Sort return code
--*/
{
CBOWNEDLIST_SORT_HELPER *pHelp1 = (CBOWNEDLIST_SORT_HELPER *)pa,
*pHelp2 = (CBOWNEDLIST_SORT_HELPER *)pb;
return (pHelp1->pObj->*pHelp1->pFunc)(pHelp2->pObj);
}
/* INTRINSA suppress=null_pointers, uninitialized */
DWORD
CObListPlus::Sort(
IN CObjectPlus::PCOBJPLUS_ORDER_FUNC pOrderFunc
)
/*++
Routine Description:
Sort the list by recreating it entirely.
Arguments:
CObjectPlus::PCOBJPLUS_ORDER_FUNC pOrderFunc : Ordering function
Return Value:
Error code
--*/
{
DWORD err = ERROR_SUCCESS;
int cItems = (int)GetCount();
if (cItems < 2)
{
return err;
}
CObjectPlus * pObNext;
CObListIter obli(*this);
BOOL fOwned = SetOwnership(FALSE);
int i;
CBOWNEDLIST_SORT_HELPER * paSortHelpers = NULL;
try
{
//
// Allocate the helper array
//
paSortHelpers = AllocMemByType(cItems, CBOWNEDLIST_SORT_HELPER);
//
// 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);
}
catch(CMemoryException * e)
{
err = ERROR_NOT_ENOUGH_MEMORY;
e->Delete();
}
//
// Delete the working array
//
FreeMem(paSortHelpers);
//
// Restore the object ownership state
//
SetOwnership(fOwned);
return err;
}
CObListIter::CObListIter(
IN const CObListPlus & obList
)
/*++
Routine Description:
Constructor of ObOwnedList iterator
Arguments:
const CObListPlus & obList : List to be iterated
Return Value:
N/A
--*/
: m_obList(obList)
{
Reset();
}
void
CObListIter::Reset()
/*++
Routine Description:
Reset the iterator
Arguments:
None
Return Value:
None
--*/
{
m_pos = m_obList.GetCount()
? m_obList.GetHeadPosition()
: NULL;
}
CObject * CObListIter::Next()
/*++
Routine Description:
Get the next object in the list, or NULL
Arguments:
None
Return Value:
The next object in the list, or NULL
--*/
{
return m_pos == NULL
? NULL
: m_obList.GetNext(m_pos);
}