/*++ Copyright (c) 1994-1999 Microsoft Corporation Module Name : objplus.cpp Abstract: Base object classes Author: Ronald Meijer (ronaldm) Project: Internet Services Manager (cluster edition) Revision History: --*/ // // Include Files // #include "stdafx.h" #include "common.h" #include #include #include #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW 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; (NULL != (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(); (NULL != (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 (NULL != (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; (NULL != (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); } 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; // // Allocate the helper array // paSortHelpers = AllocMemByType(cItems, CBOWNEDLIST_SORT_HELPER); if (paSortHelpers == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } // // Fill the helper array. // for (i = 0; NULL != (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); // // 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); }