#ifndef __CIRCOBJECTLIST_H__ #define __CIRCOBJECTLIST_H__ #include "genlib.h" // This was adapted from Jordan's object lists which actually put the sentinel // node into the list. I want to be able to splice pieces of circular lists // together without having to worry about having just one sentinel node in // the resulting list(s), and to be able to get the next or previous link // quickly without having to skip over sentinel nodes. // // Given all that, it would probably be more efficient (and the code would // perhaps be clearer) if I dropped the sentinel node and just had two // ptrs to the "head" and "tail" of the circular list. ////////////////////////////////////////////////////////////////////////////// // CCircularList Class // template class CCircObjectListIter; template class CCircObjectList { public: friend class CCircObjectListIter; public: inline CCircObjectList(); inline ~CCircObjectList(); inline BOOL Init(); inline BOOL Init(TLink *); protected: inline VOID Uninit(); inline BOOL Initialized() const; inline BOOL Valid() const; public: // Insertion Functions inline VOID InsertFirst(TLink *pLink); inline VOID InsertLast(TLink *pLink); inline VOID InsertNext(TLink *pLinkBase, TLink *pLink); inline VOID InsertPrev(TLink *pLinkBase, TLink *pLink); // inline VOID SpliceNext(TLink *pLinkBase, CCircObjectList *pList); // inline VOID SplicePrev(TLink *pLinkBase, CCircObjectList *pList); // Deletion Functions inline VOID Remove(TLink *pLink); inline TLink *RemoveFirst(); inline TLink *RemoveLast(); inline TLink *RemoveNext(TLink *pLink); inline TLink *RemovePrev(TLink *pLink); inline BOOL RemoveAll(); // Look up Functions inline TLink *PeekFirst() const; inline TLink *PeekLast() const; inline TLink *PeekNext(TLink *pLink) const; inline TLink *PeekPrev(TLink *pLink) const; // Display Functions inline VOID Display(); public: protected: TLink m_linkSentinel; TLink *m_pHead; TLink *m_pTail; // This is the same Sentinal Node as the Head }; ////////////////////////////////////////////////////////////////////////////// // Class Implementations // // CCircObjectList Class // template inline BOOL CCircObjectList::Initialized() const { return ((m_pHead != NULL) && (m_pTail != NULL)); } template inline BOOL CCircObjectList::Valid() const { return (Initialized() && (m_pHead == m_pTail)); } template inline CCircObjectList::CCircObjectList() { RemoveAll(); } template inline CCircObjectList::~CCircObjectList() { Uninit(); } template inline BOOL CCircObjectList::Init() { ASSERT( m_pHead == &m_linkSentinel ); ASSERT( m_pTail == &m_linkSentinel ); ASSERT( m_pHead->GetNextLink() == m_pTail ); ASSERT( m_pTail->GetPrevLink() == m_pHead ); ASSERT( Valid() ); return TRUE; } template inline BOOL CCircObjectList::Init(TLink *pLink) { ASSERT( m_pHead == &m_linkSentinel ); ASSERT( m_pTail == &m_linkSentinel ); m_pHead->SetNext(pLink); m_pHead->SetPrev(pLink->GetPrev()); ASSERT( Valid() ); return TRUE; } template inline BOOL CCircObjectList::RemoveAll() { m_pHead = &m_linkSentinel; m_pTail = &m_linkSentinel; m_pHead->SetNext(m_pHead); m_pHead->SetPrev(m_pHead); return TRUE; } template inline VOID CCircObjectList::Uninit() { RemoveAll(); } template inline VOID CCircObjectList::InsertFirst(TLink *pLink) { InsertNext(m_pHead, pLink); } template inline VOID CCircObjectList::InsertLast(TLink *pLink) { InsertPrev(m_pTail, pLink); } template inline TLink *CCircObjectList::RemoveFirst() { return RemoveNext(m_pHead); } template inline TLink *CCircObjectList::RemoveLast() { return RemovePrev(m_pTail); } template inline TLink *CCircObjectList::PeekFirst() const { return PeekNext(m_pHead); } template inline TLink *CCircObjectList::PeekLast() const { return PeekPrev(m_pTail); } template inline TLink *CCircObjectList::PeekNext(TLink *pLink) const { ASSERT( pLink != NULL ); return (pLink->GetNext()); } template inline TLink *CCircObjectList::PeekPrev(TLink *pLink) const { ASSERT( pLink != NULL ); return (pLink->GetPrev()); } template inline VOID CCircObjectList::Display() { ASSERT( Valid() ); TLink *pCurr; for ( pCurr = m_pHead; pCurr->GetNext() != m_pTail; pCurr = pCurr->GetNext() ) { if ( pCurr == m_pHead ) { printf("(HEAD)->"); } pCurr->GetNext()->Display(); printf("->"); if ( m_pTail == pCurr->GetNext() ) { printf("<-(TAIL)"); } } printf("\n"); } template inline VOID CCircObjectList::InsertNext(TLink *pCurr, TLink *pCLink) { ASSERT( Initialized() ); ASSERT( pCurr != NULL && pCLink != NULL ); if ((pCurr == m_pHead) && ((pCurr->GetNext()) == pCurr)) { pCLink->SetNext(pCLink); pCLink->SetPrev(pCLink); } else if (pCurr == m_pHead) { pCLink->SetNext(pCurr->GetNext()); pCLink->SetPrev(pCurr->GetPrev()); pCurr->GetPrev()->SetNext(pCLink); } else { pCLink->SetNext(pCurr->GetNext()); pCLink->SetPrev(pCurr); } pCurr->GetNext()->SetPrev(pCLink); pCurr->SetNext(pCLink); ASSERT( Valid() ); } template inline TLink *CCircObjectList::RemoveNext(TLink *pCurr) { ASSERT( Valid() ); ASSERT( pCurr != NULL ); TLink *pCLink; pCLink = pCurr->GetNext(); // list is empty if ( pCLink == m_pTail ) { return NULL; } // only one elt in list else if ( pCLink == pCLink->GetPrev() ) { m_pTail->SetNext(m_pTail); m_pTail->SetPrev(m_pTail); } // Removing first elt in list else if ( pCurr == m_pTail) { pCurr->SetNext(pCLink->GetNext()); pCurr->GetNext()->SetPrev(pCLink->GetPrev()); pCLink->GetPrev()->SetNext(pCLink->GetNext()); } else { pCurr->SetNext(pCLink->GetNext()); pCurr->GetNext()->SetPrev(pCurr); } return pCLink; } template inline VOID CCircObjectList::InsertPrev(TLink *pCurr, TLink *pCLink) { ASSERT( Initialized() ); ASSERT( pCurr != NULL && pCLink != NULL ); if ((pCurr == m_pHead) && ((pCurr->GetNext()) == pCurr)) { pCLink->SetNext(pCLink); pCLink->SetPrev(pCLink); } else if (pCurr == m_pHead) { pCLink->SetNext(pCurr->GetNext()); pCLink->SetPrev(pCurr->GetPrev()); pCurr->GetNext()->SetPrev(pCLink); } else { pCLink->SetPrev(pCurr->GetPrev()); pCLink->SetNext(pCurr); } pCurr->GetPrev()->SetNext(pCLink); pCurr->SetPrev(pCLink); ASSERT( Valid() ); } template inline TLink *CCircObjectList::RemovePrev(TLink *pCurr) { ASSERT( Valid() ); ASSERT( pCurr != NULL ); TLink *pCLink; pCLink = pCurr->GetPrev(); // list is empty if ( pCLink == m_pTail ) { return NULL; } // only one elt in list else if ( pCLink == pCLink->GetPrev()) { m_pTail->SetNext(m_pTail); m_pTail->SetPrev(m_pTail); } // Removing last elt in list else if ( pCurr == m_pTail) { pCurr->SetPrev(pCLink->GetPrev()); pCurr->GetPrev()->SetNext(pCLink->GetNext()); pCLink->GetNext()->SetPrev(pCLink->GetPrev()); } else { pCurr->SetPrev(pCLink->GetPrev()); pCurr->GetPrev()->SetNext(pCurr); } return pCLink; } /* template inline VOID CCircObjectList:: SpliceNext(TLink *pLinkBase, CCircObjectList *pList) { } template inline VOID CCircObjectList:: SplicePrev(TLink *pLinkBase, CCircObjectList *pList) { } */ ////////////////////////////////////////////////////////////////////////////// // CCircObjectListIter Class // template class CCircObjectListIter { public: inline CCircObjectListIter(); inline ~CCircObjectListIter(); inline BOOL Init(CCircObjectList *pCCircObjectList); protected: inline VOID Uninit(); inline BOOL Valid(); public: inline VOID SetCurr(TLink *); // Iteration Functions inline TLink *PeekFirst(); inline TLink *PeekNext(); inline TLink *PeekLast(); inline TLink *PeekPrev(); protected: CCircObjectList *m_pCCircObjectList; TLink *m_pCurr; }; ////////////////////////////////////////////////// // Inlined Functions // ////////////////////////////////////////////////////////////////////////////// // CCircObjectListIter Class // template inline CCircObjectListIter::CCircObjectListIter() { m_pCCircObjectList = NULL; m_pCurr = NULL; } template inline CCircObjectListIter::~CCircObjectListIter() { Uninit(); } template inline BOOL CCircObjectListIter::Init(CCircObjectList *pCCircObjectList) { ASSERT( pCCircObjectList != NULL ); m_pCCircObjectList = pCCircObjectList; // m_pCurr = m_pCCircObjectList->PeekFirst(); return TRUE; } template inline VOID CCircObjectListIter::Uninit() { m_pCCircObjectList = NULL; m_pCurr = NULL; } template inline BOOL CCircObjectListIter::Valid() { return (m_pCCircObjectList != NULL); } template inline VOID CCircObjectListIter::SetCurr(TLink *pCurr) { m_pCurr = pCurr; } template inline TLink *CCircObjectListIter::PeekFirst() { ASSERT( Valid() ); m_pCurr = m_pCCircObjectList->m_pHead->GetNext(); if ( m_pCurr == m_pCCircObjectList->m_pTail ) { m_pCurr = NULL; } return m_pCurr; } template inline TLink *CCircObjectListIter::PeekNext() { ASSERT( Valid() ); if ( m_pCurr == NULL ) { return NULL; } m_pCurr = m_pCurr->GetNext(); return m_pCurr; } template inline TLink *CCircObjectListIter::PeekLast() { ASSERT( Valid() ); m_pCurr = m_pCCircObjectList->m_pTail->GetPrev(); if ( m_pCurr == m_pCCircObjectList->m_pHead ) { m_pCurr = NULL; } return m_pCurr; } template inline TLink *CCircObjectListIter::PeekPrev() { ASSERT( Valid() ); if ( m_pCurr == NULL ) { return NULL; } m_pCurr = m_pCurr->GetPrev(); return m_pCurr; } #endif // __CIRCOBJECTLIST_H__