windows-nt/Source/XPSP1/NT/base/fs/ntfs/tests/logfile/map.hxx
2020-09-26 16:20:57 +08:00

673 lines
16 KiB
C++

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
Abstract:
map.hxx
Author:
Benjamin Leis (benl) 11/13/95
Revision History:
--*/
#ifndef _MAP
#define _MAP
#define MAP_STACK_SIZE 40
//+---------------------------------------------------------------------------
//
// Class: CMap ()
//
// Purpose:
//
// Interface: CMap --
// ~CMap --
// Insert -- insert a key and item into map
// Replace -- replaces a key's data or inserts it if is not in
// the map already
// Remove --
// Lookup --
// DeleteAll -- removes all the entries in the map and sets it to
// empty
// Lookup --
// Enum --
// DeleteNode --
// pRoot --
//
// History: 12-05-1996 benl Created
// 12-18-1997 benl modified
//
// Notes: works by copying values not be reference - so need constructors
// / destructors
//
//----------------------------------------------------------------------------
template <class T, class S> class CMapIter;
template <class T, class S> class CMap {
public:
friend CMapIter<T,S>;
CMap(void);
~CMap(void);
void Insert(const T & tKey, const S & sItem);
void Replace(const T & tkey, const S& sItem);
BOOL Remove(const T & tKey);
BOOL Lookup(const T & tKey, S & sItem) const;
void DeleteAll();
// Second style of lookup
S * Lookup(const T & tKey);
CMapIter<T,S> * Enum();
protected:
class CNode {
public:
CNode(const T & t, const S & s) {
tKey = t;
sData = s;
pLeft = NULL;
pRight = NULL;
bDeleted = FALSE;
}
CNode() {
pLeft = NULL;
pRight = NULL;
bDeleted = FALSE;
}
CNode * pLeft;
CNode * pRight;
T tKey;
S sData;
BOOL bDeleted;
};
void DeleteNode(CNode * pNode);
CNode * pRoot;
};
//+---------------------------------------------------------------------------
//
// Class: CMapIter ()
//
// Purpose:
//
// Interface: CMapIter --
// ~CMapIter --
// Next --
// _nodeStack --
// _iTop --
// _nodeDummy --
//
// History: 2-13-1997 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template <class T, class S> class CMapIter {
public:
CMapIter ( CMap<T,S>::CNode * pRoot);
~CMapIter();
BOOLEAN Next(T & t, S & s);
private:
//data
CMap<T,S>::CNode * _nodeStack[MAP_STACK_SIZE];
INT _iTop;
CMap<T,S>::CNode _nodeDummy;
};
//+---------------------------------------------------------------------------
//
// Member: CMapIter::CMapiter
//
// Synopsis: Constructor
//
// Arguments: [pRoot] --
//
// Returns:
//
// History: 7-10-1997 benl Created
//
// Notes: called by CMap and given root to traverse
//
//----------------------------------------------------------------------------
template <class T, class S>
CMapIter<T,S>::CMapIter(CMap<T,S>::CNode * pRoot)
{
_iTop = 0;
_nodeStack[_iTop] = pRoot;
while (_nodeStack[_iTop]->pLeft != NULL) {
// assert(_iTop < MAP_STACK_SIZE);
_nodeStack[_iTop + 1] = _nodeStack[_iTop]->pLeft;
_iTop++;
}
//add a dummy node at the bottom
// assert(_iTop < MAP_STACK_SIZE);
_nodeStack[_iTop + 1] = &_nodeDummy;
_iTop++;
} // ::CNode
//+---------------------------------------------------------------------------
//
// Member: ::~CMapIter
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-13-1997 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template <class T, class S>
CMapIter<T,S>::~CMapIter()
{
} //::~CMapIter
//+---------------------------------------------------------------------------
//
// Member: ::Next
//
// Synopsis:
//
// Arguments: [t] --
// [s] --
//
// Returns:
//
// History: 2-13-1997 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template <class T, class S>
BOOLEAN CMapIter<T,S>::Next(T & t, S & s)
{
CMap<T,S>::CNode * pTemp;
if (_nodeStack[_iTop]->pRight != NULL) {
//go to the leftmostest item below
_nodeStack[_iTop] = _nodeStack[_iTop]->pRight;
while (_nodeStack[_iTop]->pLeft != NULL) {
// assert(_iTop < MAP_STACK_SIZE);
_nodeStack[_iTop + 1] = _nodeStack[_iTop]->pLeft;
_iTop++;
}
} else if (_iTop != 0) {
// o.w backtrack up one level
_iTop--;
} else {
//o.w we're done
return FALSE;
}
//if current element is deleted recurse
if (_nodeStack[_iTop]->bDeleted) {
return Next(t, s);
} else {
t = _nodeStack[_iTop]->tKey;
s = _nodeStack[_iTop]->sData;
return TRUE;
}
} //::Next
//+---------------------------------------------------------------------------
//
// Member: CMap::CMap
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 12-05-1996 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, class S>
inline CMap<T,S>::CMap(void)
{
pRoot = NULL;
} //::CMap
//+---------------------------------------------------------------------------
//
// Member: ::DeleteNode
//
// Synopsis:
//
// Arguments: [pNode] --
//
// Returns:
//
// History: 12-05-1996 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, class S>
inline void CMap<T,S>::DeleteNode(CNode * pNode)
{
if (pNode != NULL) {
DeleteNode(pNode->pLeft);
DeleteNode(pNode->pRight);
delete pNode;
}
} //::DeleteNode
//+---------------------------------------------------------------------------
//
// Member: ::~CMap
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 12-05-1996 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, class S>
inline CMap<T,S>::~CMap(void)
{
// printf("map destruct %x\n", this);
DeleteAll();
} //::~CMap
//+---------------------------------------------------------------------------
//
// Member: ::Insert
//
// Synopsis:
//
// Arguments: [tKey] --
// [sData] --
//
// Returns:
//
// History: 12-05-1996 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, class S>
inline void CMap<T,S>::Insert(const T & tKey, const S & sData)
{
CNode * pnodeTemp = pRoot;
if (pRoot == NULL)
pRoot = new CNode(tKey,sData);
else {
while (pnodeTemp != NULL) {
if (pnodeTemp->tKey <= tKey) {
if (pnodeTemp->pRight == NULL) {
pnodeTemp->pRight = new CNode(tKey,sData);
return;
} else pnodeTemp = pnodeTemp->pRight;
} else {
if (pnodeTemp->pLeft == NULL) {
pnodeTemp->pLeft = new CNode(tKey,sData);
return;
} else pnodeTemp = pnodeTemp->pLeft;
}
} //endwhile
} //endif
} //::Insert
//+---------------------------------------------------------------------------
//
// Member: ::Replace
//
// Synopsis: if the key exits replace its data with the new data
// o.w just insert it
//
// Arguments: [tKey] -- the key to search for
// [sData] -- the new data
//
// Returns: always succeeds
//
// History: 12-05-1996 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, class S>
inline void CMap<T,S>::Replace(const T & tKey, const S & sData)
{
CNode * pnodeTemp = pRoot;
if (pRoot == NULL) {
pRoot = new CNode(tKey,sData);
} else {
while (pnodeTemp != NULL) {
//match - so replace its data
if (pnodeTemp->tKey == tKey && !pnodeTemp->bDeleted) {
pnodeTemp->sData = sData;
return;
}
//recurse right
else if (pnodeTemp->tKey < tKey) {
if (NULL == pnodeTemp->pRight) {
pnodeTemp->pRight = new CNode(tKey,sData);
return;
} else pnodeTemp = pnodeTemp->pRight;
}
//recurse left
else {
if (NULL == pnodeTemp->pLeft) {
pnodeTemp->pLeft = new CNode(tKey,sData);
return;
} else pnodeTemp = pnodeTemp->pLeft;
}
} //endwhile
} //endif
} //::Replace
//+---------------------------------------------------------------------------
//
// Member: ::Remove
//
// Synopsis:
//
// Arguments: [tKey] --
//
// Returns:
//
// History: 12-05-1996 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, class S>
inline BOOL CMap<T,S>::Remove(const T & tKey)
{
CNode * pnodeTemp = pRoot;
CNode * pnodeParent = NULL;
CNode * pnodeOrphan = NULL;
if (pRoot == NULL)
return FALSE;
else {
while (pnodeTemp != NULL) {
if (pnodeTemp->tKey == tKey && (pnodeTemp->bDeleted == FALSE)) {
if (pnodeParent == NULL) {
//
// deleting the root
//
if (pnodeTemp->pLeft != NULL) {
pRoot = pnodeTemp->pLeft;
pnodeOrphan = pnodeTemp->pRight;
} else {
pRoot = pnodeTemp->pRight;
pnodeOrphan = pnodeTemp->pLeft;
}
} else {
//
// deleting an interor node
//
if (pnodeParent->pLeft == pnodeTemp) {
pnodeParent->pLeft = pnodeTemp->pRight;
pnodeOrphan = pnodeTemp->pLeft;
} else {
pnodeParent->pRight = pnodeTemp->pLeft;
pnodeOrphan = pnodeTemp->pRight;
}
}
delete pnodeTemp;
//
// re-insert the orphan
//
if (pnodeOrphan != NULL) {
pnodeTemp = pRoot;
while (pnodeTemp != NULL) {
if (pnodeTemp->tKey <= pnodeOrphan->tKey) {
if (pnodeTemp->pRight == NULL) {
pnodeTemp->pRight = pnodeOrphan;
break;
} else pnodeTemp = pnodeTemp->pRight;
} else {
if (pnodeTemp->pLeft == NULL) {
pnodeTemp->pLeft = pnodeOrphan;
break;
} else pnodeTemp = pnodeTemp->pLeft;
}
} //endwhile
}
return TRUE;
} else if (pnodeTemp->tKey < tKey) {
pnodeParent = pnodeTemp;
pnodeTemp = pnodeTemp->pRight;
} else {
pnodeParent = pnodeTemp;
pnodeTemp = pnodeTemp->pLeft;
}
} //endwhile
} //endif
return FALSE;
} //::Remove
//+---------------------------------------------------------------------------
//
// Member: ::Lookup
//
// Synopsis:
//
// Arguments: [tKey] --
// [sItem] --
//
// Returns:
//
// History: 12-05-1996 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, class S>
inline BOOL CMap<T,S>::Lookup(const T & tKey, S & sItem) const
{
CNode * pnodeTemp = pRoot;
if (pRoot == NULL)
return FALSE;
else {
while (pnodeTemp != NULL) {
if (pnodeTemp->tKey == tKey && pnodeTemp->bDeleted == FALSE) {
sItem = pnodeTemp->sData;
return TRUE;
} else if (pnodeTemp->tKey <= tKey) {
pnodeTemp = pnodeTemp->pRight;
} else {
pnodeTemp = pnodeTemp->pLeft;
}
} //endwhile
} //endif
return FALSE;
} //::Lookup
//+---------------------------------------------------------------------------
//
// Member: ::Lookup
//
// Synopsis:
//
// Arguments: [tKey] --
//
// Returns:
//
// History: 12-05-1996 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, class S>
inline S * CMap<T,S>::Lookup(const T & tKey)
{
CNode * pnodeTemp = pRoot;
if (pRoot == NULL)
return NULL;
else {
while (pnodeTemp != NULL) {
if (pnodeTemp->tKey == tKey && pnodeTemp->bDeleted == FALSE) {
return &(pnodeTemp->sData);
} else if (pnodeTemp->tKey < tKey) {
pnodeTemp = pnodeTemp->pRight;
} else {
pnodeTemp = pnodeTemp->pLeft;
}
} //endwhile
} //endif
return NULL;
} //::Lookup
//+---------------------------------------------------------------------------
//
// Member: ::Enum
//
// Synopsis: returns the iterator
//
// Arguments: (none)
//
// Returns: iterator or null if map is empty
//
// History: 2-13-1997 benl Created
//
// Notes:
//
//----------------------------------------------------------------------------
template<class T, class S>
inline CMapIter<T,S> * CMap<T,S>::Enum()
{
if (pRoot) {
return new CMapIter<T,S>(pRoot);
} else {
return NULL;
}
} //::Enum
//+---------------------------------------------------------------------------
//
// Member: ::DeleteAll
//
// Synopsis: NonRecursive delete
//
// Arguments: (none)
//
// Returns:
//
// History: 12-18-1997 benl Created
//
// Notes: Cleans up the entire tree and sets it to empty
// Does it nonrecursively but swiveling ptrs around
//
//----------------------------------------------------------------------------
template <class T, class S>
inline void CMap<T,S>::DeleteAll()
{
CNode * pParent = 0;
CNode * pNext = 0;
CNode * pCurrent = pRoot;
while (pCurrent) {
//advance next to left and the set the left back to parent
pNext = pCurrent->pLeft;
pCurrent->pLeft = pParent;
//If there is a left child move onto it
//else if there is a right child move to it
//o.w move up thru left ptr and delete current node
if (pNext) {
pParent = pCurrent;
pCurrent = pNext;
} else if (pCurrent->pRight) {
pParent = pCurrent;
pCurrent = pCurrent->pRight;
pParent->pRight = 0;
} else {
//this is really a move up back the parent is now in pLeft
pParent = pCurrent->pLeft;
delete pCurrent;
pCurrent = pParent;
if (pCurrent) {
pParent = pCurrent->pLeft;
pCurrent->pLeft = 0;
}
}
}
pRoot = NULL;
} // ::DeleteAll
#endif