#ifndef LIST_CPP_ #define LIST_CPP_ #include "list.h" #include "Except.h" #include "StartConv.h" template list::list( ) { init( ); } template void list::init( ) { theSize = 0; head = new node; tail = new node; head->next = tail; tail->prev = head; } template list::~list( ) { makeEmpty( ); delete head; delete tail; } template void list::makeEmpty( ) { while( !empty( ) ) pop_front( ); } template list::list( const list & rhs ) { init( ); *this = rhs; } template const list & list::operator= ( const list & rhs ) { if( this == &rhs ) return *this; makeEmpty( ); for( const_iterator itr = rhs.begin( ); itr != rhs.end( ); ++itr ) push_back( *itr ); return *this; } // Return iterator representing beginning of list. // Mutator version is first, then accessor version. template typename list::iterator list::begin( ) { iterator itr( *this, head ); return ++itr; } template typename list::const_iterator list::begin( ) const { const_iterator itr( *this, head ); return ++itr; } // Return iterator representing endmarker of list. // Mutator version is first, then accessor version. template typename list::iterator list::end( ) { return iterator( *this, tail ); } template typename list::const_iterator list::end( ) const { return const_iterator( *this, tail ); } // Return number of elements currently in the list. template int list::size( ) const { return theSize; } // Return true if the list is empty, false otherwise. template bool list::empty( ) const { return size( ) == 0; } // front, back, push_front, push_back, pop_front, and pop_back // are the basic double-ended queue operations. template Object & list::front( ) { return *begin( ); } template const Object & list::front( ) const { return *begin( ); } template Object & list::back( ) { return *--end( ); } template const Object & list::back( ) const { return *--end( ); } template void list::push_front( const Object & x ) { insert( begin( ), x ); } template void list::push_back( const Object & x ) { insert( end( ), x ); } template void list::pop_front( ) { erase( begin( ) ); } template void list::pop_back( ) { erase( --end( ) ); } // Insert x before itr. template typename list::iterator list::insert( iterator itr, const Object & x ) { itr.assertIsValid( ); if( itr.head != head ) throw IteratorMismatchException( "insert iterator not in this list" ); node *p = itr.current; p->prev->next = new node( x, p->prev, p ); p->prev = p->prev->next; theSize++; return iterator( *this, p->prev ); } // Erase item at itr. template typename list::iterator list::erase( iterator itr ) { itr.assertIsValid( ); if( itr == end( ) ) throw IteratorOutOfBoundsException( "cannot erase at end( )" ); if( itr.head != head ) throw IteratorMismatchException( "erase iterator not in this list" ); node *p = itr.current; iterator retVal( *this, p->next ); p->prev->next = p->next; p->next->prev = p->prev; delete p; theSize--; return retVal; } template typename list::iterator list::erase( iterator from, iterator to ) { for( iterator itr = from; itr != to; ) itr = erase( itr ); return to; } // Public constructor for const_iterator. template ConstListItr::ConstListItr( ) : head( NULL ), current( NULL ) { } // Throws an exception if this iterator is obviously // uninitialized. Otherwise, returns safely. template void ConstListItr::assertIsInitialized( ) const { if( head == NULL || current == NULL ) throw IteratorUninitializedException( "list iterator" ); } // Throws an exception if the current position is // not somewhere in the range from begin to end, inclusive. // Otherwise, returns safely. template void ConstListItr::assertIsValid( ) const { assertIsInitialized( ); if( current == head ) throw IteratorOutOfBoundsException( "At position prior to begin( ) in list" ); } // Protected helper in const_iterator that returns the object // stored at the current position. Can be called by all // three versions of operator* without any type conversions. template Object & ConstListItr::retrieve( ) const { assertIsValid( ); if( current->next == NULL ) throw IteratorOutOfBoundsException( "Cannot perform *end( ) in list" ); return current->data; } // Return the object stored at the current position. // For const_iterator, this is an accessor with a // const reference return type. template const Object & ConstListItr::operator* ( ) const { return this->retrieve( ); } // Throws an exception if operator++ cannot be safely applied // to the current position. Otherwise, returns safely. template void ConstListItr::assertCanAdvance( ) const { assertIsInitialized( ); if( current->next == NULL ) throw IteratorOutOfBoundsException( "Cannot perform ++end( ) in list" ); } // Throws an exception if operator-- cannot be safely applied // to the current position. Otherwise, returns safely. template void ConstListItr::assertCanRetreat( ) const { assertIsValid( ); if( current->prev == head ) throw IteratorOutOfBoundsException( "Cannot perform --begin( ) in list" ); } template ConstListItr & ConstListItr::operator++ ( ) { assertCanAdvance( ); current = current->next; return *this; } template ConstListItr ConstListItr::operator++ ( int ) { ConstListItr old = *this; ++( *this ); return old; } template ConstListItr & ConstListItr::operator-- ( ) { assertCanRetreat( ); current = current->prev; return *this; } template ConstListItr ConstListItr::operator-- ( int ) { ConstListItr old = *this; --( *this ); return old; } template bool ConstListItr::operator== ( const ConstListItr & rhs ) const { return current == rhs.current; } template bool ConstListItr::operator!= ( const ConstListItr & rhs ) const { return !( *this == rhs ); } // Protected constructor for const_iterator. // Expects the list that owns the iterator and a // pointer that represents the current position. template ConstListItr::ConstListItr( const list & source, node *p ) : head( source.head ), current( p ) { } // Public constructor for iterator. // Calls the base-class constructor. // Must be provided because the private constructor // is written; otherwise zero-parameter constructor // would be disabled. template ListItr::ListItr( ) { } // Return the object stored at the current position. // For iterator, there is an accessor with a // const reference return type and a mutator with // a reference return type. The accessor is shown first. template const Object & ListItr::operator* ( ) const { return ConstListItr::operator*( ); } template Object & ListItr::operator* ( ) { return this->retrieve( ); } template ListItr & ListItr::operator++ ( ) { this->assertCanAdvance( ); this->current = this->current->next; return *this; } template ListItr ListItr::operator++ ( int ) { ListItr old = *this; ++( *this ); return old; } template ListItr & ListItr::operator-- ( ) { this->assertCanRetreat( ); this->current = this->current->prev; return *this; } template ListItr ListItr::operator-- ( int ) { ListItr old = *this; --( *this ); return old; } // Protected constructor for iterator. // Expects the list that owns the iterator and a // pointer that represents the current position. template ListItr::ListItr( const list & source, node *p ) : ConstListItr( source, p ) { } #include "EndConv.h" #endif