//----------------------------------------------------------------------------- // Microsoft OLE DB TABLECOPY Sample // Copyright (C) 1991 - 1999 By Microsoft Corporation. // // @doc // // @module CEXLIST.H // //----------------------------------------------------------------------------- #ifndef _CEXLIST_H_ #define _CEXLIST_H_ ///////////////////////////////////////////////////////////////////////////// // Includes // ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // Defines // ///////////////////////////////////////////////////////////////////////////// typedef void* POS; ///////////////////////////////////////////////////////////////////////////// // CNode // ///////////////////////////////////////////////////////////////////////////// template 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 CNode::CNode(TYPE data, CNode* pPrevNode, CNode* pNextNode) { //Constructor m_data = data; m_pPrevNode = pPrevNode; m_pNextNode = pNextNode; } ///////////////////////////////////////////////////////////////////////////// // CExList // ///////////////////////////////////////////////////////////////////////////// template class CExList { public: //constructors CExList(); virtual ~CExList(); //members //list modifying operations virtual POS AddHead(TYPE element); // Add to Head virtual POS AddTail(TYPE element); // Add to Tail virtual POS InsertBefore(POS position, TYPE element); // Add before position virtual POS InsertAfter(POS position, TYPE element); // Add after position virtual TYPE RemoveHead(); // Remove from Head virtual TYPE RemoveTail(); // Remove from Tail virtual TYPE RemoveAt(POS position); // RemoveAt position virtual void RemoveAll(); // Remove all elements //Seeking methods virtual POS Find(TYPE element); // Find element //Peek methods virtual POS GetHeadPosition(); // Head Position virtual POS GetTailPosition(); // Tail Position virtual TYPE GetHead(); // Head element virtual TYPE GetTail(); // Tail element virtual TYPE GetNext(POS& position); // Next element virtual TYPE GetPrev(POS& position); // Prev element //Data methods virtual TYPE GetAt(POS position) const; //Get element value virtual TYPE SetAt(POS position, TYPE element); //Set element value //Array-like methods virtual POS FindIndex(ULONG iIndex); //Index element //informational methods virtual BOOL IsEmpty(); // IsEmpty virtual ULONG GetCount(); // Elements in the list private: //data CNode* m_pHeadNode; // Head of CExList CNode* m_pTailNode; // Tail of CExList ULONG m_ulElements; // Elements in the list }; ///////////////////////////////////////////////////////////////////////////// // CExList::CExList // ///////////////////////////////////////////////////////////////////////////// template CExList::CExList() { //constructor m_pHeadNode = NULL; m_pTailNode = NULL; m_ulElements = 0; } ///////////////////////////////////////////////////////////////////////////// // CExList::~CExList // ///////////////////////////////////////////////////////////////////////////// template CExList::~CExList() { //Remove all elements RemoveAll(); } ///////////////////////////////////////////////////////////////////////////// // CExList::AddHead // ///////////////////////////////////////////////////////////////////////////// template POS CExList::AddHead(TYPE element) { //Add to the Head of the CExList, (stack) CNode* pHeadNode = new CNode(element, NULL, m_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_ulElements++; return m_pHeadNode; } ///////////////////////////////////////////////////////////////////////////// // CExList::AddTail // ///////////////////////////////////////////////////////////////////////////// template POS CExList::AddTail(TYPE element) { //Add to the m_pTailNode of the CExList CNode* pTailNode = new CNode(element, m_pTailNode, 0); //if previously empty if(!m_pHeadNode) m_pHeadNode = pTailNode; else m_pTailNode->m_pNextNode = pTailNode; m_pTailNode = pTailNode; m_ulElements++; return m_pTailNode; } ///////////////////////////////////////////////////////////////////////////// // CExList::GetHeadPosition // ///////////////////////////////////////////////////////////////////////////// template inline POS CExList::GetHeadPosition() { //return Head element Position return m_pHeadNode; } ///////////////////////////////////////////////////////////////////////////// // CExList::GetTailPosition // ///////////////////////////////////////////////////////////////////////////// template inline POS CExList::GetTailPosition() { //return Tail element Position return m_pTailNode; } ///////////////////////////////////////////////////////////////////////////// // CExList::GetHead // ///////////////////////////////////////////////////////////////////////////// template inline TYPE CExList::GetHead() { //return Head element value return m_pHeadNode->m_data; } ///////////////////////////////////////////////////////////////////////////// // CExList::AddTail // ///////////////////////////////////////////////////////////////////////////// template inline TYPE CExList::GetTail() { // return Tail element value return m_pTailNode->m_data; } ///////////////////////////////////////////////////////////////////////////// // CExList::GetNext // ///////////////////////////////////////////////////////////////////////////// template inline TYPE CExList::GetNext(POS& position) { //Set position to the next element CNode* pNode = (CNode*)position; position = pNode->m_pNextNode; //return the current element return pNode->m_data; } ///////////////////////////////////////////////////////////////////////////// // CExList::GetPrev // ///////////////////////////////////////////////////////////////////////////// template inline TYPE CExList::GetPrev(POS& position) { //Set position to the next element CNode* pNode = (CNode*)position; position = pNode->m_pPrevNode; //return the current element return pNode->m_data; } ///////////////////////////////////////////////////////////////////////////// // CExList::GetAt // ///////////////////////////////////////////////////////////////////////////// template inline TYPE CExList::GetAt(POS position) const { return ((CNode*)position)->m_data; } ///////////////////////////////////////////////////////////////////////////// // CExList::SetAt // ///////////////////////////////////////////////////////////////////////////// template inline TYPE CExList::SetAt(POS position, TYPE element) { //Save the old data CNode* pNode = (CNode*)position; TYPE oldData = pNode->m_data; //Store new data pNode->m_data = element; //return olddata return oldData; } ///////////////////////////////////////////////////////////////////////////// // CExList::Find // ///////////////////////////////////////////////////////////////////////////// template POS CExList::Find(TYPE element) { //return pointer to found element for(CNode* 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 } ///////////////////////////////////////////////////////////////////////////// // CExList::IsEmpty // ///////////////////////////////////////////////////////////////////////////// template inline BOOL CExList::IsEmpty() { // returns TRUE if Empty return m_ulElements == 0; } ///////////////////////////////////////////////////////////////////////////// // CExList::RemoveHead // ///////////////////////////////////////////////////////////////////////////// template TYPE CExList::RemoveHead() { //Remove and return from the Head of the List CNode* 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_ulElements--; delete pHeadNode; // delete head return element; } ///////////////////////////////////////////////////////////////////////////// // CExList::RemoveTail // ///////////////////////////////////////////////////////////////////////////// template TYPE CExList::RemoveTail() { //Remove and return from the m_pTailNode of the CExList CNode* 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_ulElements--; delete m_pTailNode; return element; } ///////////////////////////////////////////////////////////////////////////// // CExList::RemoveAt // ///////////////////////////////////////////////////////////////////////////// template TYPE CExList::RemoveAt(POS position) { //Remove CExList[position] CNode* pNode = (CNode*)position; TYPE oldData = pNode->m_data; // 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_ulElements--; delete pNode; return oldData; } ///////////////////////////////////////////////////////////////////////////// // CExList::RemoveAll // ///////////////////////////////////////////////////////////////////////////// template void CExList::RemoveAll() { // Remove all items from the CExList CNode* pNode = m_pHeadNode; while(pNode) { CNode* pTemp = pNode; pNode = pNode->m_pNextNode; delete pTemp; } m_pHeadNode = NULL; m_pTailNode = NULL; m_ulElements = 0; } ///////////////////////////////////////////////////////////////////////////// // CExList::GetCount // ///////////////////////////////////////////////////////////////////////////// template inline ULONG CExList::GetCount() { // return the Length return m_ulElements; } ///////////////////////////////////////////////////////////////////////////// // CExList::InsertBefore // ///////////////////////////////////////////////////////////////////////////// template POS CExList::InsertBefore(POS position, TYPE element) { //insert before the position if(position == m_pHeadNode) // Add before Head return AddHead(element); CNode* pOldNode = (CNode*)position; //otherwise a little more difficult CNode* pNewNode = new CNode(element, pOldNode->m_pPrevNode, pOldNode); //Create the new node pNewNode->m_pNextNode = new CNode(element, pOldNode->m_pPrevNode, pOldNode->m_pNextNode); //Hook up before after nodes to it pOldNode->m_pPrevNode->m_pNextNode = pNewNode; pOldNode->m_pPrevNode = pNewNode; m_ulElements++; return pNewNode; } ///////////////////////////////////////////////////////////////////////////// // CExList::InsertAfter // ///////////////////////////////////////////////////////////////////////////// template POS CExList::InsertAfter(POS position, TYPE element) { //insert after the position if(position == m_pTailNode) // Add after the m_pTailNode return AddTail(element); CNode* pOldNode = (CNode*)position; //other wise a little more difficult CNode* pNewNode = new CNode(element, pOldNode, pOldNode->m_pNextNode); //Hook up before after nodes to it pOldNode->m_pNextNode->m_pPrevNode = pNewNode; pOldNode->m_pNextNode = pNewNode; m_ulElements++; return pNewNode; } ///////////////////////////////////////////////////////////////////////////// // CExList::FindIndex // ///////////////////////////////////////////////////////////////////////////// template POS CExList::FindIndex(ULONG iIndex) { CNode* pNode = m_pHeadNode; //Find the specified index while(iIndex--) pNode = pNode->m_pNextNode; return (POS)pNode; } #endif //_LIST_H_