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.
345 lines
7.8 KiB
345 lines
7.8 KiB
//
|
|
|
|
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
|
|
#include <precomp.h>
|
|
|
|
|
|
CTreeElement :: CTreeElement(LPCWSTR lpszHashedName, CRefCountedObject *pObject)
|
|
{
|
|
m_lpszHashedName = new WCHAR[wcslen(lpszHashedName) + 1];
|
|
wcscpy(m_lpszHashedName, lpszHashedName);
|
|
|
|
m_pObject = pObject;
|
|
m_pObject->AddRef();
|
|
m_pLeft = NULL;
|
|
m_pRight = NULL;
|
|
}
|
|
|
|
CTreeElement :: ~CTreeElement()
|
|
{
|
|
if (m_lpszHashedName)
|
|
{
|
|
delete [] m_lpszHashedName;
|
|
}
|
|
m_pObject->Release();
|
|
}
|
|
|
|
LPCWSTR CTreeElement :: GetHashedName() const
|
|
{
|
|
return m_lpszHashedName;
|
|
}
|
|
|
|
CRefCountedObject *CTreeElement :: GetObject() const
|
|
{
|
|
m_pObject->AddRef();
|
|
return m_pObject;
|
|
}
|
|
|
|
CTreeElement *CTreeElement :: GetRight() const
|
|
{
|
|
return m_pRight;
|
|
}
|
|
|
|
CTreeElement *CTreeElement :: GetLeft() const
|
|
{
|
|
return m_pLeft;
|
|
}
|
|
|
|
void CTreeElement :: SetRight(CTreeElement *pNext)
|
|
{
|
|
m_pRight = pNext;
|
|
}
|
|
|
|
void CTreeElement :: SetLeft(CTreeElement *pNext)
|
|
{
|
|
m_pLeft = pNext;
|
|
}
|
|
|
|
CObjectTree :: CObjectTree()
|
|
{
|
|
// Initialize the critical section
|
|
InitializeCriticalSection(&m_ModificationSection);
|
|
|
|
m_dwNumElements = 0;
|
|
m_pHead = NULL;
|
|
|
|
}
|
|
|
|
CObjectTree :: ~CObjectTree()
|
|
{
|
|
// Destroy the data
|
|
DeleteTree();
|
|
|
|
// Destroy the critical section
|
|
DeleteCriticalSection(&m_ModificationSection);
|
|
|
|
}
|
|
|
|
void CObjectTree :: DeleteTree()
|
|
{
|
|
EnterCriticalSection(&m_ModificationSection);
|
|
if(m_pHead)
|
|
DeleteSubTree(m_pHead);
|
|
m_dwNumElements = 0;
|
|
LeaveCriticalSection(&m_ModificationSection);
|
|
}
|
|
|
|
|
|
void CObjectTree :: DeleteSubTree(CTreeElement *pRoot)
|
|
{
|
|
if(pRoot->GetLeft())
|
|
DeleteSubTree(pRoot->GetLeft());
|
|
if(pRoot->GetRight())
|
|
DeleteSubTree(pRoot->GetRight());
|
|
delete pRoot;
|
|
}
|
|
|
|
BOOLEAN CObjectTree :: AddElement(LPCWSTR lpszHashedName, CRefCountedObject *pObject)
|
|
{
|
|
BOOLEAN retVal = TRUE;
|
|
|
|
EnterCriticalSection(&m_ModificationSection);
|
|
CTreeElement *pCurrent = m_pHead;
|
|
CTreeElement *pParent = NULL;
|
|
int iCompare;
|
|
// Locate the position where the new element is to be inserted
|
|
while(pCurrent)
|
|
{
|
|
iCompare = _wcsicmp(lpszHashedName, pCurrent->GetHashedName());
|
|
if(iCompare == 0)
|
|
{
|
|
retVal = FALSE; // The element already exists
|
|
break;
|
|
}
|
|
else if(iCompare > 0)
|
|
{
|
|
pParent = pCurrent;
|
|
pCurrent = pCurrent->GetRight();
|
|
}
|
|
else
|
|
{
|
|
pParent = pCurrent;
|
|
pCurrent = pCurrent->GetLeft();
|
|
}
|
|
}
|
|
|
|
// Create the new element at the appropriate position
|
|
if(retVal == TRUE && pParent)
|
|
{
|
|
iCompare = _wcsicmp(lpszHashedName, pParent->GetHashedName());
|
|
if(iCompare == 0)
|
|
retVal = FALSE;
|
|
else if(iCompare > 0)
|
|
{
|
|
retVal = TRUE;
|
|
pParent->SetRight(new CTreeElement(lpszHashedName, pObject));
|
|
}
|
|
else
|
|
{
|
|
retVal = TRUE;
|
|
pParent->SetLeft(new CTreeElement(lpszHashedName, pObject));
|
|
}
|
|
}
|
|
else if (retVal == TRUE)
|
|
{
|
|
m_pHead = new CTreeElement(lpszHashedName, pObject);
|
|
retVal = TRUE;
|
|
}
|
|
// Increment the object count if the insertion was successful
|
|
if(retVal)
|
|
m_dwNumElements ++;
|
|
|
|
LeaveCriticalSection(&m_ModificationSection);
|
|
return retVal;
|
|
}
|
|
|
|
BOOLEAN CObjectTree :: DeleteElement(LPCWSTR lpszHashedName)
|
|
{
|
|
BOOLEAN retVal = FALSE;
|
|
int iDirection = 0; // 0 indicates Unknown, 1 indicates LEFT and 2 indicates RIGHT
|
|
EnterCriticalSection(&m_ModificationSection);
|
|
if(m_pHead == NULL)
|
|
retVal = FALSE;
|
|
else
|
|
{
|
|
// Find the node to be deleted and its parent
|
|
CTreeElement *pParent = NULL;
|
|
CTreeElement *pCurrent = m_pHead;
|
|
int iCompare;
|
|
while(pCurrent)
|
|
{
|
|
iCompare = _wcsicmp(lpszHashedName, pCurrent->GetHashedName());
|
|
if(iCompare == 0)
|
|
break;
|
|
else if(iCompare < 0)
|
|
{
|
|
iDirection = 1;
|
|
pParent = pCurrent;
|
|
pCurrent = pCurrent->GetLeft();
|
|
}
|
|
else
|
|
{
|
|
iDirection = 2;
|
|
pParent = pCurrent;
|
|
pCurrent = pCurrent->GetRight();
|
|
}
|
|
}
|
|
|
|
if(!pCurrent)
|
|
// The element was not found
|
|
retVal = FALSE;
|
|
else
|
|
{
|
|
CTreeElement *pCutPart = NULL;
|
|
|
|
// If its left child is null, attach the right subtree to parent
|
|
if(pCurrent->GetLeft() == NULL)
|
|
pCutPart = pCurrent->GetRight();
|
|
// If its right child is null, attach the left subtree to parent
|
|
else if(pCurrent->GetRight() == NULL)
|
|
pCutPart = pCurrent->GetLeft();
|
|
else // We need to find the inorder successor
|
|
{
|
|
CTreeElement *pInorderSuccessor = pCurrent->GetRight();
|
|
if(pInorderSuccessor->GetLeft() == NULL)
|
|
{
|
|
pInorderSuccessor->SetLeft(pCurrent->GetLeft());
|
|
pCutPart = pInorderSuccessor;
|
|
}
|
|
else
|
|
{
|
|
CTreeElement *pPredecessor = pCurrent->GetRight();
|
|
pInorderSuccessor = pPredecessor->GetLeft();
|
|
while(pInorderSuccessor->GetLeft())
|
|
{
|
|
pPredecessor = pInorderSuccessor;
|
|
pInorderSuccessor = pPredecessor->GetLeft();
|
|
}
|
|
pPredecessor->SetLeft(pInorderSuccessor->GetRight());
|
|
pInorderSuccessor->SetLeft(pCurrent->GetLeft());
|
|
pInorderSuccessor->SetRight(pCurrent->GetRight());
|
|
pCutPart = pInorderSuccessor;
|
|
}
|
|
}
|
|
|
|
if(iDirection == 0)
|
|
m_pHead = pCutPart;
|
|
else if (iDirection == 1)
|
|
pParent->SetLeft(pCutPart);
|
|
else
|
|
pParent->SetRight(pCutPart);
|
|
|
|
delete pCurrent;
|
|
retVal = TRUE;
|
|
|
|
}
|
|
}
|
|
// Decrement the count of items in the tree
|
|
if(retVal)
|
|
m_dwNumElements --;
|
|
|
|
LeaveCriticalSection(&m_ModificationSection);
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
CRefCountedObject * CObjectTree :: GetElement(LPCWSTR lpszHashedName)
|
|
{
|
|
EnterCriticalSection(&m_ModificationSection);
|
|
CTreeElement *pCurrent = m_pHead;
|
|
CRefCountedObject *pRetVal = NULL;
|
|
|
|
int iCompare;
|
|
while(pCurrent)
|
|
{
|
|
iCompare = _wcsicmp(lpszHashedName, pCurrent->GetHashedName());
|
|
if(iCompare == 0)
|
|
{
|
|
pRetVal = pCurrent->GetObject();
|
|
break;
|
|
}
|
|
else if (iCompare > 0)
|
|
pCurrent = pCurrent->GetRight();
|
|
else
|
|
pCurrent = pCurrent->GetLeft();
|
|
}
|
|
LeaveCriticalSection(&m_ModificationSection);
|
|
return pRetVal;
|
|
}
|
|
|
|
BOOLEAN CObjectTree :: DeleteLeastRecentlyAccessedElement()
|
|
{
|
|
BOOLEAN retVal = FALSE;
|
|
EnterCriticalSection(&m_ModificationSection);
|
|
if(m_pHead)
|
|
{
|
|
CRefCountedObject *pOldestElement = m_pHead->GetObject();
|
|
CRefCountedObject *pLeftOldestElement = GetLeastRecentlyAccessedElementRecursive(m_pHead->GetLeft());
|
|
CRefCountedObject *pRightOldestElement = GetLeastRecentlyAccessedElementRecursive(m_pHead->GetRight());
|
|
|
|
if (pLeftOldestElement)
|
|
{
|
|
if(pLeftOldestElement->GetLastAccessTime() < pOldestElement->GetLastAccessTime())
|
|
{
|
|
pOldestElement->Release();
|
|
pOldestElement = pLeftOldestElement;
|
|
}
|
|
else
|
|
pLeftOldestElement->Release();
|
|
}
|
|
|
|
if (pRightOldestElement)
|
|
{
|
|
if(pRightOldestElement->GetLastAccessTime() < pOldestElement->GetLastAccessTime())
|
|
{
|
|
pOldestElement->Release();
|
|
pOldestElement = pRightOldestElement;
|
|
}
|
|
else
|
|
pRightOldestElement->Release();
|
|
}
|
|
|
|
retVal = DeleteElement(pOldestElement->GetName());
|
|
pOldestElement->Release();
|
|
}
|
|
LeaveCriticalSection(&m_ModificationSection);
|
|
return retVal;
|
|
}
|
|
|
|
CRefCountedObject * CObjectTree :: GetLeastRecentlyAccessedElementRecursive(CTreeElement *pElement)
|
|
{
|
|
CRefCountedObject *pObject = NULL;
|
|
if(pElement)
|
|
{
|
|
pObject = pElement->GetObject();
|
|
CRefCountedObject *pLeftObject = GetLeastRecentlyAccessedElementRecursive(pElement->GetLeft());
|
|
if(pLeftObject)
|
|
{
|
|
if(pLeftObject->GetCreationTime() < pObject->GetCreationTime())
|
|
{
|
|
pObject->Release();
|
|
pObject = pLeftObject;
|
|
}
|
|
else
|
|
pLeftObject->Release();
|
|
}
|
|
|
|
CRefCountedObject *pRightObject = GetLeastRecentlyAccessedElementRecursive(pElement->GetRight());
|
|
if(pRightObject)
|
|
{
|
|
if (pRightObject->GetCreationTime() < pObject->GetCreationTime())
|
|
{
|
|
pObject->Release();
|
|
pObject = pRightObject;
|
|
}
|
|
else
|
|
pRightObject->Release();
|
|
}
|
|
|
|
}
|
|
|
|
return pObject;
|
|
}
|