LIST.H

//----------------------------------------------------------------------------- 
// Microsoft OLE DB TABLECOPY Sample
// Copyright (C) 1996 By Microsoft Corporation.
//
// @doc
//
// @module LIST.H
//
//-----------------------------------------------------------------------------
#ifndef _LIST_H_
#define _LIST_H_


/////////////////////////////////////////////////////////////////////////////
// Includes
//
/////////////////////////////////////////////////////////////////////////////
#include "winmain.h"


/////////////////////////////////////////////////////////////////////////////
// Defines
//
/////////////////////////////////////////////////////////////////////////////
#define POSITION CNode<TYPE>*


/////////////////////////////////////////////////////////////////////////////
// CNode
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> class CNode
{
public:
// constructors
CNode(TYPE val, CNode* pPrevNode, CNode* pNextNode);

// members
TYPE m_data; // element data
CNode* m_pNextNode; // next CNode
CNode* m_pPrevNode; // prev CNode
};


/////////////////////////////////////////////////////////////////////////////
// CNode::CNode
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> CNode<TYPE>::CNode(TYPE data, CNode<TYPE>* pPrevNode, CNode<TYPE>* pNextNode)
{
//Constructor
m_data = data;
m_pPrevNode = pPrevNode;
m_pNextNode = pNextNode;
}



/////////////////////////////////////////////////////////////////////////////
// CList
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> class CList
{
public:

//constructors
CList();
virtual ~CList();

//members

//list modifying operations
virtual POSITIONAddHead(TYPE element);// Add to Head
virtual POSITIONAddTail(TYPE element);// Add to Tail

virtual POSITIONInsertBefore(POSITION position, TYPE newdata);// Add before position
virtual POSITIONInsertAfter(POSITION position, TYPE newdata);// Add after m_pItr

virtual TYPERemoveHead();// Remove from Head
virtual TYPERemoveTail();// Remove from Tail
virtual voidRemoveAt(POSITION position);// RemoveAt position
virtual voidRemoveAll();// Remove all elements

//Seeking operations
virtual POSITIONFind(TYPE element); // Find element

//Peek operations
virtual TYPEGetHead();// Head element
virtual TYPEGetTail();// Tail element
virtual TYPEGetNext(POSITION position);// Next element
virtual TYPEGetPrev(POSITION position);// Prev element

//informational operations
virtual BOOLIsEmpty();// IsEmpty
virtual ULONGGetCount();// m_ulLengthgth of CList

//data
CNode<TYPE>* m_pHeadNode;// Head of CList
CNode<TYPE>* m_pTailNode;// Tail of CList

ULONGm_ulLength;// m_ulLengthgth of CList
};


/////////////////////////////////////////////////////////////////////////////
// CList::CList
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> CList<TYPE>::CList()
{
//constructor
m_pHeadNode = NULL;
m_pTailNode = NULL;
m_ulLength = 0;
}

/////////////////////////////////////////////////////////////////////////////
// CList::~CList
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> CList<TYPE>::~CList()
{
//Remove all elements
RemoveAll();
}


/////////////////////////////////////////////////////////////////////////////
// CList::AddHead
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> POSITION CList<TYPE>::AddHead(TYPE element)
{
//Add to the Head of the CList, (stack)
CNode<TYPE>* pHeadNode = new CNode<TYPE>(element, NULL, m_pHeadNode);
ASSERT(pHeadNode);

//If there was a list hook the head->prev to the new head
if(m_pHeadNode)
m_pHeadNode->m_pPrevNode = pHeadNode;

//If there isn't a tail element, hook it to the head
if(!m_pTailNode)
m_pTailNode = pHeadNode;

m_pHeadNode = pHeadNode;
m_ulLength++;
return m_pHeadNode;
}


/////////////////////////////////////////////////////////////////////////////
// CList::AddTail
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> POSITION CList<TYPE>::AddTail(TYPE element)
{
//Add to the m_pTailNode of the CList
CNode<TYPE>* pTailNode = new CNode<TYPE>(element, m_pTailNode, 0);
ASSERT(pTailNode);

//if previously empty
if(!m_pHeadNode)
m_pHeadNode = pTailNode;
else
m_pTailNode->m_pNextNode = pTailNode;

m_pTailNode = pTailNode;
m_ulLength++;
return m_pTailNode;
}



/////////////////////////////////////////////////////////////////////////////
// CList::GetHead
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> inline TYPE CList<TYPE>::GetHead()
{
//return Head element value
ASSERT(m_pHeadNode);
return m_pHeadNode->m_data;
}

/////////////////////////////////////////////////////////////////////////////
// CList::AddTail
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> inline TYPE CList<TYPE>::GetTail()
{
// return Tail element value
ASSERT(m_pTailNode);
return m_pTailNode->m_data;
}


/////////////////////////////////////////////////////////////////////////////
// CList::GetNext
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> inline TYPE CList<TYPE>::GetNext(POSITION position)
{
ASSERT(position);

// return the next element
return position->m_pNextNode->m_data;
}


/////////////////////////////////////////////////////////////////////////////
// CList::GetPrev
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> inline TYPE CList<TYPE>::GetPrev(POSITION position)
{
ASSERT(position);

// return the prev element
return position->m_pPrevNode->m_data;
}


/////////////////////////////////////////////////////////////////////////////
// CList::Find
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> POSITION CList<TYPE>::Find(TYPE element)
{
//return pointer to found element
for(CNode<TYPE>* p = m_pHeadNode; p; p = p->m_pNextNode)
if(p->m_data == element)
return p; // return position to found CNode

return NULL; // return NULL if not found
}


/////////////////////////////////////////////////////////////////////////////
// CList::IsEmpty
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> inline BOOL CList<TYPE>::IsEmpty()
{
// returns TRUE if Empty
return m_ulLength == 0;
}



/////////////////////////////////////////////////////////////////////////////
// CList::RemoveHead
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> TYPE CList<TYPE>::RemoveHead()
{
//Remove and return from the Head of the List
ASSERT(m_pHeadNode);

CNode<TYPE>* pHeadNode = m_pHeadNode;// pointer to the Removed node
TYPE element = GetHead();//make a copy, before deleteing

m_pHeadNode = pHeadNode->m_pNextNode;// reroute Head to exclude the first element
if(m_pHeadNode)
m_pHeadNode->m_pPrevNode = NULL;
else
m_pTailNode = NULL;

m_ulLength--;
delete pHeadNode;// delete head
return element;
}


/////////////////////////////////////////////////////////////////////////////
// CList::RemoveTail
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> TYPE CList<TYPE>::RemoveTail()
{
//Remove and return from the m_pTailNode of the CList
ASSERT(m_pTailNode);

CNode<TYPE>* pTailNode = m_pTailNode->m_pPrevNode;
TYPE element = GetTail(); //make a copy before deleteing

m_pTailNode = pTailNode;
if(m_pTailNode)
m_pTailNode->m_pNextNode = NULL;
else
m_pHeadNode = NULL;

m_ulLength--;
delete m_pTailNode;
return element;
}


/////////////////////////////////////////////////////////////////////////////
// CList::RemoveAt
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> void CList<TYPE>::RemoveAt(POSITION position)
{
//Remove CList[position]
ASSERT(position);

CNode<TYPE>* pNode = position;

// If removing the head
if (pNode == m_pHeadNode)
m_pHeadNode = pNode->m_pNextNode;
else
pNode->m_pPrevNode->m_pNextNode = pNode->m_pNextNode;

//If removing the tail
if (pNode == m_pTailNode)
m_pTailNode = pNode->m_pPrevNode;
else
pNode->m_pNextNode->m_pPrevNode = pNode->m_pPrevNode;

m_ulLength--;
delete pNode;
}


/////////////////////////////////////////////////////////////////////////////
// CList::RemoveAll
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> void CList<TYPE>::RemoveAll()
{
// Remove all items from the CList
for (CNode<TYPE>* p = m_pHeadNode; p; p = p->m_pNextNode)
delete p;

m_pHeadNode = NULL;
m_pTailNode = NULL;
m_ulLength = 0;
}


/////////////////////////////////////////////////////////////////////////////
// CList::GetCount
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> inline ULONG CList<TYPE>::GetCount()
{
// return the Length
return m_ulLength;
}


/////////////////////////////////////////////////////////////////////////////
// CList::InsertBefore
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> POSITION CList<TYPE>::InsertBefore(POSITION position, TYPE element)
{
//insert before the position
if(position == m_pHeadNode) // Add before Head
return AddHead(element);

//otherwise a little more difficult
CNode<TYPE>* pNode = new CNode<TYPE>(element, position->m_pPrevNode, position);

//Create the new node
pNode->m_pNextNode = new CNode<TYPE>(element, position->m_pPrevNode, position->m_pNextNode);

//Hook up before after nodes to it
position->m_pPrevNode->m_pNextNode = pNode;
position->m_pPrevNode = pNode;

m_ulLength++;
return pNode;
}



/////////////////////////////////////////////////////////////////////////////
// CList::InsertAfter
//
/////////////////////////////////////////////////////////////////////////////
template <class TYPE> POSITION CList<TYPE>::InsertAfter(POSITION position, TYPE element)
{
//insert after the position
if(position == m_pTailNode) // Add after the m_pTailNode
return AddTail(element);

//other wise a little more difficult
CNode<TYPE>* pNode = new CNode<TYPE>(element, position, position->m_pNextNode);

//Hook up before after nodes to it
position->m_pNextNode->m_pPrevNode = pNode;
position->m_pNextNode = pNode;

m_ulLength++;
return pNode;
}



#endif //_LIST_H_