/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ /* * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd * * type safe doubly linked list templates * * Author Jeffrey O. Hill * johill@lanl.gov * 505 665 1831 */ #ifndef tsDLListH_include #define tsDLListH_include template class tsDLList; template class tsDLIterConst; template class tsDLIter; // // class tsDLNode // // a node in a doubly linked list containing entries of type T // ( class T must publicly derive from class tsDLNode ) // template < class T > class tsDLNode { public: tsDLNode (); tsDLNode ( const tsDLNode & ); const tsDLNode & operator = ( const tsDLNode & ); private: T * pNext; T * pPrev; friend class tsDLList; friend class tsDLIter; friend class tsDLIterConst; }; // // class tsDLList // // a doubly linked list containing entries of type T // ( class T must publicly derive from class tsDLNode ) // template < class T > class tsDLList { public: tsDLList (); // create empty list unsigned count () const; // number of items on list void add ( T & item ); // add item to end of list void add ( tsDLList & addList ); // add to end of list - addList left empty void push ( T & item ); // add item to beginning of list void push ( tsDLList & pushList ); // add to beg of list - pushList left empty void remove ( T & item ); // remove item from list void removeAll ( tsDLList & destination ); T * get (); // removes first item on list T * pop (); // same as get () void insertAfter ( T & item, T & itemBefore ); // insert item immediately after itemBefore void insertBefore ( T & item, T & itemAfter ); // insert item immediately before itemAfter int find ( const T & item ) const; // returns -1 if not present, node number if present T * first ( void ) const; // ptr to first item on list T * last ( void ) const; // ptr to last item on list tsDLIterConst firstIter () const; tsDLIter firstIter (); tsDLIterConst lastIter () const; tsDLIter lastIter (); static tsDLIterConst invalidConstIter (); static tsDLIter invalidIter (); private: T * pFirst; T * pLast; unsigned itemCount; void clear (); tsDLList ( const tsDLList & ); // not allowed const tsDLList & operator = ( const tsDLList & ); // not allowed }; // // class tsDLIterConst // // bi-directional iterator for a const doubly linked list // template class tsDLIterConst { public: tsDLIterConst (); bool valid () const; bool operator == ( const tsDLIterConst & rhs ) const; bool operator != ( const tsDLIterConst & rhs ) const; tsDLIterConst & operator = ( const tsDLIterConst & ); const T & operator * () const; const T * operator -> () const; tsDLIterConst & operator ++ (); tsDLIterConst operator ++ (int); tsDLIterConst & operator -- (); tsDLIterConst operator -- (int); const T * pointer () const; private: const T * pEntry; tsDLIterConst ( const T * pInitialEntry ); friend class tsDLList ; }; // // class tsDLIter // // bi-directional iterator for a doubly linked list // template class tsDLIter { public: tsDLIter (); bool valid () const; bool operator == ( const tsDLIter & rhs ) const; bool operator != ( const tsDLIter & rhs ) const; tsDLIter & operator = ( const tsDLIter & ); T & operator * () const; T * operator -> () const; tsDLIter & operator ++ (); tsDLIter operator ++ ( int ); tsDLIter & operator -- (); tsDLIter operator -- ( int ); T * pointer () const; private: T * pEntry; tsDLIter ( T *pInitialEntry ); friend class tsDLList ; }; /////////////////////////////////// // tsDLNode member functions /////////////////////////////////// // // tsDLNode::tsDLNode () // template inline tsDLNode::tsDLNode() : pNext(0), pPrev(0) {} template inline tsDLNode::tsDLNode ( const tsDLNode & ) : pNext (0), pPrev(0) {} // // tsDLNode::operator = () // // when someone tries to copy another node into a node // do _not_ change the node pointers // template inline const tsDLNode & tsDLNode::operator = ( const tsDLNode & ) { return * this; } ////////////////////////////////////// // tsDLList member functions ////////////////////////////////////// // // tsDLList::tsDLList () // template inline tsDLList::tsDLList () { this->clear (); } // // tsDLList::count () // // (returns the number of items on the list) // template inline unsigned tsDLList::count () const { return this->itemCount; } // // tsDLList::first () // template inline T * tsDLList::first (void) const { return this->pFirst; } // // tsDLList::last () // template inline T *tsDLList::last (void) const { return this->pLast; } // // tsDLList::clear () // template inline void tsDLList::clear () { this->pFirst = 0; this->pLast = 0; this->itemCount = 0u; } // // tsDLList::remove () // template inline void tsDLList::remove ( T &item ) { tsDLNode &theNode = item; if ( this->pLast == &item ) { this->pLast = theNode.pPrev; } else { tsDLNode &nextNode = *theNode.pNext; nextNode.pPrev = theNode.pPrev; } if ( this->pFirst == &item ) { this->pFirst = theNode.pNext; } else { tsDLNode &prevNode = *theNode.pPrev; prevNode.pNext = theNode.pNext; } this->itemCount--; } // // tsDLList::removeAll () // template inline void tsDLList::removeAll ( tsDLList & destination ) { destination.pFirst = this->pFirst; destination.pLast = this->pLast; destination.itemCount = this->itemCount; this->pFirst = 0; this->pLast = 0; this->itemCount = 0; } // // tsDLList::get () // template inline T * tsDLList::get() { T *pItem = this->pFirst; if ( pItem ) { this->remove ( *pItem ); } return pItem; } // // tsDLList::pop () // // (returns the first item on the list) template inline T * tsDLList::pop () { return this->get (); } // // tsDLList::add () // // adds addList to the end of the list // (and removes all items from addList) // template inline void tsDLList::add ( tsDLList &addList ) { if ( addList.itemCount != 0u ) { if ( this->itemCount == 0u ) { this->pFirst = addList.pFirst; } else { tsDLNode *pLastNode = this->pLast; tsDLNode *pAddListFirstNode = addList.pFirst; pLastNode->pNext = addList.pFirst; pAddListFirstNode->pPrev = addList.pLast; } this->pLast = addList.pLast; this->itemCount += addList.itemCount; addList.clear(); } } // // tsDLList::add () // // add an item to the end of the list // template inline void tsDLList::add (T &item) { tsDLNode &theNode = item; theNode.pNext = 0; theNode.pPrev = this->pLast; if ( this->itemCount ) { tsDLNode &lastNode = *this->pLast; lastNode.pNext = &item; } else { this->pFirst = &item; } this->pLast = &item; this->itemCount++; } // // tsDLList::insertAfter () // // place item in the list immediately after itemBefore // template inline void tsDLList::insertAfter (T &item, T &itemBefore) { tsDLNode &nodeItem = item; tsDLNode &nodeBefore = itemBefore; nodeItem.pPrev = &itemBefore; nodeItem.pNext = nodeBefore.pNext; nodeBefore.pNext = &item; if (nodeItem.pNext) { tsDLNode *pNextNode = nodeItem.pNext; pNextNode->pPrev = &item; } else { this->pLast = &item; } this->itemCount++; } // // tsDLList::insertBefore () // // place item in the list immediately before itemAfter // template inline void tsDLList::insertBefore (T &item, T &itemAfter) { tsDLNode &node = item; tsDLNode &nodeAfter = itemAfter; node.pNext = &itemAfter; node.pPrev = nodeAfter.pPrev; nodeAfter.pPrev = &item; if (node.pPrev) { tsDLNode &prevNode = *node.pPrev; prevNode.pNext = &item; } else { this->pFirst = &item; } this->itemCount++; } // // tsDLList::push () // // adds pushList to the beginning of the list // (and removes all items from pushList) // template inline void tsDLList::push ( tsDLList & pushList ) { if ( pushList.itemCount != 0u ) { if ( this->itemCount ) { tsDLNode * pFirstNode = this->pFirst; tsDLNode * pAddListLastNode = pushList.pLast; pFirstNode->pPrev = pushList.pLast; pAddListLastNode->pNext = this->pFirst; } else { this->pLast = pushList.pLast; } this->pFirst = pushList.pFirst; this->itemCount += pushList.itemCount; pushList.clear(); } } // // tsDLList::push () // // add an item at the beginning of the list // template inline void tsDLList::push (T &item) { tsDLNode &theNode = item; theNode.pPrev = 0; theNode.pNext = this->pFirst; if ( this->itemCount ) { tsDLNode *pFirstNode = this->pFirst; pFirstNode->pPrev = & item; } else { this->pLast = & item; } this->pFirst = &item; this->itemCount++; } // // tsDLList::find () // returns -1 if the item isnt on the list // and the node number (beginning with zero if // it is) // template < class T > int tsDLList < T > :: find ( const T &item ) const { tsDLIterConst < T > thisItem ( &item ); tsDLIterConst < T > iter ( this->first () ); int itemNo = 0; while ( iter.valid () ) { if ( iter == thisItem ) { return itemNo; } itemNo++; iter++; } return -1; } template < class T > inline tsDLIterConst tsDLList < T > :: firstIter () const { return tsDLIterConst < T > ( this->pFirst ); } template < class T > inline tsDLIter tsDLList < T > :: firstIter () { return tsDLIter < T > ( this->pFirst ); } template < class T > inline tsDLIterConst tsDLList < T > :: lastIter () const { return tsDLIterConst < T > ( this->pLast ); } template < class T > inline tsDLIter tsDLList < T > :: lastIter () { return tsDLIter < T > ( this->pLast ); } template < class T > inline tsDLIterConst tsDLList < T > :: invalidConstIter () { return tsDLIterConst < T > ( 0 ); } template < class T > inline tsDLIter tsDLList < T > :: invalidIter () { return tsDLIter < T > ( 0 ); } ////////////////////////////////////////// // tsDLIterConst member functions ////////////////////////////////////////// template inline tsDLIterConst::tsDLIterConst ( const T *pInitialEntry ) : pEntry ( pInitialEntry ) {} template inline tsDLIterConst::tsDLIterConst () : pEntry ( 0 ) {} template inline bool tsDLIterConst::valid () const { return this->pEntry != 0; } template inline bool tsDLIterConst::operator == (const tsDLIterConst &rhs) const { return this->pEntry == rhs.pEntry; } template inline bool tsDLIterConst::operator != (const tsDLIterConst &rhs) const { return this->pEntry != rhs.pEntry; } template inline tsDLIterConst & tsDLIterConst::operator = ( const tsDLIterConst & rhs ) { this->pEntry = rhs.pEntry; return *this; } template inline const T & tsDLIterConst::operator * () const { return *this->pEntry; } template inline const T * tsDLIterConst::operator -> () const { return this->pEntry; } // // prefix ++ // template inline tsDLIterConst & tsDLIterConst::operator ++ () { const tsDLNode &node = *this->pEntry; this->pEntry = node.pNext; return *this; } // // postfix ++ // template inline tsDLIterConst tsDLIterConst::operator ++ (int) { const tsDLIterConst tmp = *this; const tsDLNode &node = *this->pEntry; this->pEntry = node.pNext; return tmp; } // // prefix -- // template inline tsDLIterConst & tsDLIterConst::operator -- () { const tsDLNode &entryNode = *this->pEntry; this->pEntry = entryNode.pPrev; return *this; } // // postfix -- // template inline tsDLIterConst tsDLIterConst::operator -- (int) { const tsDLIterConst tmp = *this; const tsDLNode &entryNode = *this->pEntry; this->pEntry = entryNode.pPrev; return tmp; } template inline const T * tsDLIterConst::pointer () const { return this->pEntry; } ////////////////////////////////////////// // tsDLIter member functions ////////////////////////////////////////// template inline tsDLIter::tsDLIter ( T * pInitialEntry ) : pEntry ( pInitialEntry ) {} template inline tsDLIter::tsDLIter () : pEntry ( 0 ) {} template inline bool tsDLIter::valid () const { return this->pEntry != 0; } template inline bool tsDLIter::operator == (const tsDLIter &rhs) const { return this->pEntry == rhs.pEntry; } template inline bool tsDLIter::operator != (const tsDLIter &rhs) const { return this->pEntry != rhs.pEntry; } template inline tsDLIter & tsDLIter::operator = ( const tsDLIter & rhs ) { this->pEntry = rhs.pEntry; return *this; } template inline T & tsDLIter::operator * () const { return *this->pEntry; } template inline T * tsDLIter::operator -> () const { return this->pEntry; } template inline tsDLIter & tsDLIter::operator ++ () // prefix ++ { const tsDLNode &entryNode = *this->pEntry; this->pEntry = entryNode.pNext; return *this; } template inline tsDLIter tsDLIter::operator ++ (int) // postfix ++ { const tsDLIter tmp = *this; const tsDLNode &entryNode = *this->pEntry; this->pEntry = entryNode.pNext; return tmp; } template inline tsDLIter & tsDLIter::operator -- () // prefix -- { const tsDLNode &entryNode = *this->pEntry; this->pEntry = entryNode.pPrev; return *this; } template inline tsDLIter tsDLIter::operator -- (int) // postfix -- { const tsDLIter tmp = *this; const tsDLNode &entryNode = *this->pEntry; this->pEntry = entryNode.pPrev; return tmp; } template inline T * tsDLIter::pointer () const { return this->pEntry; } #endif // tsDLListH_include