/////////////////////////////////////////////////////////////////////////// // FILE: list (Definition of std::list) // // ========================================================================= // // Open Watcom Project // // Copyright (c) 2004-2010 The Open Watcom Contributors. All Rights Reserved. // // This file is automatically generated. Do not edit directly. // // ========================================================================= // // Description: This header is part of the C++ standard library. It // provides the list sequence container. /////////////////////////////////////////////////////////////////////////// #ifndef _LIST_INCLUDED #define _LIST_INCLUDED #ifndef _ENABLE_AUTODEPEND #pragma read_only_file; #endif #ifndef __cplusplus #error This header file requires C++ #endif #ifndef _ITERATOR_INCLUDED #include #endif #ifndef _MEMORY_INCLUDED #include #endif #ifndef _TYPE_TRAITS_INCLUDED #include #endif #ifndef _FUNCTIONAL_INCLUDED #include #endif namespace std { /* ================================================================== * list class template */ template< class Type, class Allocator = allocator< Type > > class list { public: typedef Type value_type; typedef unsigned int size_type; typedef int difference_type; typedef Allocator allocator_type; typedef typename Allocator::reference reference; typedef typename Allocator::const_reference const_reference; typedef typename Allocator::pointer pointer; typedef typename Allocator::const_pointer const_pointer; private: struct DoubleLink{ DoubleLink* fwd; DoubleLink* bwd; }; struct Node : public DoubleLink{ value_type value; Node( value_type const & v ) : value(v) {} }; DoubleLink *sentinel; //sentinel->fwd = first element in list //sentinel->bwd = last element in list Allocator::rebind< Node >::other mMem; //needs to be up here to stop crash Allocator::rebind< DoubleLink >::other dlMem; public: explicit list( Allocator const & a = Allocator( ) ) : mSize(0), mMem(a), dlMem(a) { sentinel = dlMem.allocate( 1 ); sentinel->fwd = sentinel->bwd = sentinel; } explicit list( size_type, Type const &, Allocator const & = Allocator() ); // note compiler feature missing // function templates can't have default params // also has to be inline as doesn't understand syntax otherwise template< class InputIt > list( InputIt f, InputIt l, Allocator const & a )// = Allocator() ) : mSize(0), mMem(a), dlMem(a) { sentinel = dlMem.allocate( 1 ); sentinel->fwd = sentinel->bwd = sentinel; helper_assign( f, l, tr1::is_integral::type() ); } list( list const& ); ~list( ); list &operator=( list const & ); template< class InputIterator > void assign( InputIterator f, InputIterator l ) { clear(); helper_assign( f, l, tr1::is_integral::type() ); } void assign( size_type, value_type const & ); allocator_type get_allocator() const { allocator_type a( mMem ); return( a ); } /* ------------------------------------------------------------------ * iterators */ class iterator_base { public: iterator_base( ) { } iterator_base( DoubleLink *d ) : self( d ) { } bool operator==( iterator_base const it ) const { return( it.self == self ); } bool operator!=( iterator_base const it ) const { return( it.self != self ); } protected: DoubleLink *self; }; class iterator : public iterator_base, public std::iterator< std::bidirectional_iterator_tag, value_type >{ friend class list; public: iterator( ) : iterator_base( ) { } iterator( DoubleLink* d ) : iterator_base( d ) { } reference operator*( ) const { return( static_cast< Node *>( self )->value ); } value_type* operator->( ) const { return( &( static_cast< Node * >( self )->value ) ); } iterator& operator++( ) { self = self->fwd; return( *this ); } iterator& operator--( ) { self = self->bwd; return( *this ); } iterator operator++( int ) { iterator it( *this ); operator++( ); return( it ); }; iterator operator--( int ) { iterator it( *this ); operator--( ); return( it ); }; }; class const_iterator : public iterator_base, public std::iterator< std::bidirectional_iterator_tag, const value_type >{ friend class list; public: const_iterator( iterator_base it ) : iterator_base( it ) { } const_iterator( ) : iterator_base( ) { } const_iterator( DoubleLink const* d ) : iterator_base( const_cast< DoubleLink *>( d ) ) { } value_type& operator*( ) { return( static_cast< Node const *>( self )->value ); } value_type* operator->( ) { return( &( static_cast< Node const * >( self )->value ) ); } const_iterator& operator++( ) { self = self->fwd; return( *this ); } const_iterator& operator--( ) { self = self->bwd; return( *this ); } const_iterator operator++( int ) { const_iterator it( *this ); operator++( ); return( it ); }; const_iterator operator--( int ) { const_iterator it( *this ); operator--( ); return( it ); }; }; typedef std::reverse_iterator< iterator > reverse_iterator; typedef std::reverse_iterator< const_iterator > const_reverse_iterator; /* * end of iterators * ------------------------------------------------------------------ */ iterator begin( ) { return( iterator( sentinel->fwd ) ); } iterator end( ) { return( iterator( sentinel ) ); } const_iterator begin( ) const { return( const_iterator( sentinel->fwd ) ); } const_iterator end( ) const { return( const_iterator( sentinel ) ); } reverse_iterator rbegin( ) { return( reverse_iterator( iterator( sentinel ) ) ); } reverse_iterator rend( ) { return( reverse_iterator( iterator( sentinel->fwd ) ) ); } const_reverse_iterator rbegin( ) const { return( const_reverse_iterator( const_iterator( sentinel ) ) ); } const_reverse_iterator rend ( ) const { return( const_reverse_iterator( const_iterator( sentinel->fwd ) ) ); } //capacity size_type size( ) const { return( mSize ); } bool empty( ) const { return( mSize == 0 ); } //element access reference front( ) { return( static_cast< Node* >( sentinel->fwd )->value ); } reference back( ) { return( static_cast< Node* >( sentinel->bwd )->value ); } //modifiers void push_front( value_type const & x ) { push( static_cast< Node* >( sentinel->fwd ), x ); } void pop_front( ) { pop( static_cast< Node* >( sentinel->fwd ) ); } void push_back( value_type const & x ) { push( static_cast< Node* >( sentinel ), x ); } void pop_back( ) { pop( static_cast< Node* >( sentinel->bwd ) ); } iterator insert( iterator, value_type const & ); void insert( iterator, size_type, value_type const & ); template< class InputIt > void insert( iterator p, InputIt f, InputIt l ) { helper_insert( p, f, l, tr1::is_integral::type() ); } iterator erase( iterator it ); iterator erase( iterator first, iterator last ); void swap( list & ); void clear( ); void remove( value_type const & ); void splice( iterator it, list &other ); void splice( iterator it, list &other, iterator other_it ); void splice( iterator it, list &other, iterator first, iterator last ); void reverse( ); void merge( list &other ); //ow extentions bool _Sane( ); private: inline void pop( Node* ); inline Node* push( Node*, value_type const & ); /* -------------------------------------------------------------- * these ones are called when InputIt isn't an integer type */ template< class InputIt > void helper_assign( InputIt f, InputIt l, tr1::true_type ) { for( int i = 0; i < static_cast< size_type >( f ); i++ ){ push_back( static_cast< value_type >( l ) ); } } template< class InputIt > void helper_insert( iterator i, InputIt f, InputIt l, tr1::true_type ) { for( size_type n = static_cast< size_type >(f); n > 0; n-- ){ push( static_cast< Node* >( i.self ), static_cast< value_type >(l) ); } } /* -------------------------------------------------------------- * these ones are called when InputIt is not an integer type */ template< class InputIt > void helper_assign( InputIt f, InputIt l, tr1::false_type ) { for( ; f != l; ++f ) push_back( *f ); } template< class InputIt > void helper_insert( iterator p, InputIt f, InputIt l, tr1::false_type ) { // this could probably be optimised to remove // unnecessary link rewriting when inserting lots of things for( ; f != l; ++f, ++p ) p = insert( p, *f ); } //Allocator::rebind< Node >::other mMem; //moved above constructors for the time being //as this seems to stop compiler crashing. size_type mSize; // --------------------------------------------------------------- // SORT Add-ons by Alexey Kovalenko. // // recursive merge sort for double-linked list // time_optimized, not memory-. // public: //Sorts self according to the operator <. //sort maintains the relative order of equal elements. void sort( ) { if( size() > 1 ) _merge_sort( sentinel->fwd, sentinel->bwd, size()-1, less< value_type >() ); } template< class Compare > void sort( Compare comp ) { if( size() > 1 ) _merge_sort( sentinel->fwd, sentinel->bwd, size()-1, comp); } private: // internal sort module template< class Compare > void _merge_sort( DoubleLink * first, DoubleLink * last, size_type _distance, Compare comp ) // first, last - pointers in chain // _distance - internal value, distance between first and last, // for first call, it's a size()-1 // comp - compare function, usually less< value_type > // // _distance introduced for simplification of calculating the middle of // given list's range. I's number of steps to go from first to last. // 1 element in range - _distance is 0 // 2 elements in range - _distance is 1 // etc // // Here we can't make inexpensive check, what _distance // corresponds with (last - first). // So, using guard check in loop :( // { if( first != last ) // is it one-element list? { // anchors beyond list borders. DoubleLink * first_bwd = first->bwd; DoubleLink * last_fwd = last->fwd; DoubleLink * middle = first; DoubleLink * l2begin = NULL; size_type middle_pos = _distance / 2; // meaning middle = (first + last) / 2 // 2 elements: _distance == 1 // middle_pos == 0 // middle == first // 3 elements: _distance == 2 // middle_pos == 1 // middle == first+1 // 4 elements: _distance == 3 // middle_pos == 1 // middle == first+1 // etc. // moving throw links while( ( middle_pos >= 1) && (middle != last) ) { middle = middle->fwd; middle_pos-=1; } // Here middle_pos may be not zero. It means, what rounding errors make // such binary cut innacurate. Redo it more nicely. if( middle_pos ) { _distance = _distance / 2 - middle_pos; middle_pos = _distance / 2; middle = first; // moving throw links. Again. while( ( middle_pos >= 1) && (middle != last) ) { middle = middle->fwd; middle_pos-=1; } } if( _distance > 0 ) { // two recursive calls for two subranges l2begin = middle->fwd; _merge_sort(first, middle, (size_type)_distance/2, comp ); middle = l2begin->bwd; // can change _merge_sort( l2begin, last,(size_type) (_distance - _distance/2 - 1), comp); //l2begin = middle->fwd;// can change first = first_bwd->fwd; // can change last = last_fwd->bwd; // can change } _merge_lists( first, middle, /*middle->fwd,*/ last, comp ); } return; }; // // merge two ajacent sorted ranges in one sorted // first is start, middle is end of first subrange (so as middle->fwd is start of // other subrange), last is end. // template< class Compare > void _merge_lists( DoubleLink * first, DoubleLink * middle, DoubleLink * last, Compare comp ) { DoubleLink *list1 = first; DoubleLink *list2 = middle->fwd; DoubleLink *list2end = last->fwd; DoubleLink *temp_l2next = NULL; if( first == last ) return; /* just guard for 1-element lists */ //compare elements on both lists as long as possible. do{ // while( (list2 != list2end) && (list1 != list2) ) while( !comp( static_cast< Node * >( list2 )->value, static_cast< Node * >( list1 )->value ) ) { list1 = list1->fwd; if( list1 == list2 ) return; } // *list2 is less than *list1 // move *list2 _before_ *list1 temp_l2next = list2->fwd; // store list2 next value if( list1->fwd == list2 ) { // ajacent list elements list2->bwd = list1->bwd; list1->bwd->fwd = list2; list2->fwd->bwd = list1; list1->fwd = list2->fwd; list1->bwd = list2; list2->fwd = list1; }else{ // non-ajacent elements list2->bwd->fwd = list2->fwd; list2->fwd->bwd = list2->bwd; list1->bwd->fwd = list2; list2->bwd = list1->bwd; list2->fwd = list1; list1->bwd = list2; } // non-ajacent list2 = temp_l2next; }while( (list2 != list2end) && (list1 != list2) /*guards*/ && (list2 != sentinel) && (list1 != sentinel) ); return; }; // end of sort code by Alexey Kovalenko. // --------------------------------------------------------------- }; /* ------------------------------------------------------------------ * ctor( Allocator ) * construct empty list */ /*err, this only seems to work inlined, whats going on? template< class Type, class Allocator > list< Type, Allocator >::list( Allocator const & a ) : mSize(0), mMem(a), dlMem(a) { sentinel = dlMem.allocate( 1 ); sentinel->fwd = sentinel->bwd = sentinel; } */ /* ------------------------------------------------------------------ * ctor( size_type, Type, Allocator ) * construct with n copies of t */ template< class Type, class Allocator > list< Type, Allocator >::list( size_type n, Type const & t, Allocator const & a ) : mSize(0), mMem(a), dlMem(a) { sentinel = dlMem.allocate( 1 ); sentinel->fwd = sentinel->bwd = sentinel; for( int i = 0; i < n; i++ ){ push_back( t ); } } /* ------------------------------------------------------------------ * copy ctor */ template< class Type, class Allocator > list< Type, Allocator >::list( list const& that ) : mMem(that.mMem), dlMem(that.dlMem) { sentinel = dlMem.allocate( 1 ); DoubleLink const * o = that.sentinel; DoubleLink* n = sentinel; mSize = 0; while( o->fwd != that.sentinel ){ try{ n->fwd = mMem.allocate( 1 ); try{ mMem.construct( static_cast< Node* >( n->fwd ), Node(static_cast< Node* >( o->fwd )->value )); }catch(...){ mMem.deallocate( static_cast( n->fwd ), 1 ); throw; } }catch(...){ //unwind - can't finish copy construction so remove all elements DoubleLink* delme; while( n != sentinel ){ delme = n; n = n->bwd; mMem.destroy( static_cast< Node* >( delme ) ); mMem.deallocate( static_cast< Node* >( delme ), 1 ); }; dlMem.deallocate( sentinel, 1 ); throw; } n->fwd->bwd = n; n = n->fwd; o = o->fwd; }; n->fwd = sentinel; sentinel->bwd = n; mSize = that.mSize; } /* ------------------------------------------------------------------ * ~dtor */ template< class Type, class Allocator > list< Type, Allocator >::~list() { clear(); dlMem.deallocate( sentinel, 1 ); } /* ------------------------------------------------------------------ * operator=( lst ) * assign incoming list to this list */ template< class Type, class Allocator > list< Type, Allocator > & list< Type, Allocator >::operator=( list const & other ) { if( &other == this ) return( *this ); clear( ); const_iterator it = other.begin( ); while( it != other.end( ) ) { push_back( *it ); ++it; } return( *this ); } #ifdef _NEVER // has to be inline as compiler doesn't understand this syntax yet /* ------------------------------------------------------------------ * assign( first, last ) * assigns items in range [first, last) to this list */ template< class Type, class Allocator > template< class InputIterator > void list< Type, Allocator >::assign( InputIterator first, InputIterator last ) { clear( ); while( first != last ) { push_back( *first ); ++first; } } #endif /* ------------------------------------------------------------------ * assign( n, v ) * assigns n copies of v to this list */ template< class Type, class Allocator > void list< Type, Allocator >::assign( size_type n, value_type const &v ) { clear( ); for( size_type i = 0; i < n; ++i ) { push_back( v ); } } /* ------------------------------------------------------------------ * insert( i, x ) * insert type x in list just before element identified by iterator i */ template< class Type, class Allocator > list< Type, Allocator >::iterator list< Type, Allocator >::insert( iterator it, Type const & x ) { Node* n = push( static_cast< Node* >( it.self ), x ); return iterator( n ); } /* ------------------------------------------------------------------ * insert( iterator i, size_type n, x ) * insert type x n times in list just before element identified by iterator i */ template< class Type, class Allocator > void list< Type, Allocator >::insert( iterator i, size_type n, value_type const & x ) { while( n > 0 ){ push( static_cast< Node* >( i.self ), x ); n--; } } /* ------------------------------------------------------------------ * erase( i ) * erase element identified by iterator i */ template< class Type, class Allocator > list< Type, Allocator >::iterator list< Type, Allocator >::erase( iterator it ) { iterator temp( it ); ++temp; pop( static_cast< Node * >( it.self ) ); return( temp ); } /* ------------------------------------------------------------------ * erase( first, last ) * erase all list items in range [first, last) */ template< class Type, class Allocator > list< Type, Allocator >::iterator list< Type, Allocator >::erase( iterator first, iterator last ) { while( first != last ) { first = erase( first ); } return( last ); } /* ------------------------------------------------------------------ * swap * swaps two lists */ template< class Type, class Allocator > void list< Type, Allocator >::swap( list &other ) { DoubleLink *sen_temp( sentinel ); sentinel = other.sentinel; other.sentinel = sen_temp; Allocator::rebind< Node >::other m_temp( mMem ); mMem = other.mMem; other.mMem = m_temp; Allocator::rebind< DoubleLink >::other dl_temp( dlMem ); dlMem = other.dlMem; other.dlMem = dl_temp; size_type siz_temp( mSize ); mSize = other.mSize; other.mSize = siz_temp; } /* ------------------------------------------------------------------ * clear * remove all elements */ template< class Type, class Allocator > void list< Type, Allocator >::clear() { Node* n; Node* delme; n = ( Node* )sentinel->fwd; while( n != ( Node* )sentinel ){ delme = n; n = ( Node* )n->fwd; mMem.destroy( delme ); mMem.deallocate( delme, 1 ); }; sentinel->fwd = sentinel->bwd = sentinel; mSize = 0; } /* ------------------------------------------------------------------ * remove( v ) * remove all occurances of v in the list. */ template< class Type, class Allocator > void list< Type, Allocator >::remove( value_type const &v ) { iterator it( begin( ) ); while( it != end( ) ) { if( *it == v ) it = erase( it ); else ++it; } } /* ------------------------------------------------------------------ * splice( it, other ) * splices the entire contents of other before it */ template< class Type, class Allocator > void list< Type, Allocator >::splice( iterator it, list &other ) { if( other.mSize == 0 ) return; DoubleLink *head = other.sentinel->fwd; DoubleLink *tail = other.sentinel->bwd; //do the splice head->bwd = it.self->bwd; it.self->bwd->fwd = head; tail->fwd = it.self; it.self->bwd = tail; //fix up other's sentinel other.sentinel->fwd = other.sentinel; other.sentinel->bwd = other.sentinel; //fix up list sizes mSize += other.mSize; other.mSize = 0; } /* ------------------------------------------------------------------ * splice( it, other, other_it ) * splices *other_it before it */ template< class Type, class Allocator > void list< Type, Allocator >::splice( iterator it, list &other, iterator other_it ) { if( it.self == other_it.self || it.self == other_it.self->fwd ) return; //do the splice DoubleLink *spliced_node = other_it.self; spliced_node->bwd->fwd = spliced_node->fwd; spliced_node->fwd->bwd = spliced_node->bwd; spliced_node->bwd = it.self->bwd; it.self->bwd->fwd = spliced_node; spliced_node->fwd = it.self; it.self->bwd = spliced_node; //fix up list sizes mSize++; other.mSize--; } /* ------------------------------------------------------------------ * splice( it, other, first last ) * splices [first, last) before it */ template< class Type, class Allocator > void list< Type, Allocator >::splice( iterator it, list &other, iterator first, iterator last ) { size_type count = 0; for( iterator i( first ); i != last; ++i ) ++count; if( count == 0 ) return; DoubleLink *head = first.self; DoubleLink *tail = last.self->bwd; //do the splice head->bwd->fwd = tail->fwd; tail->fwd->bwd = head->bwd; head->bwd = it.self->bwd; it.self->bwd->fwd = head; tail->fwd = it.self; it.self->bwd = tail; //fix up list sizes mSize += count; other.mSize -= count; } /* ------------------------------------------------------------------ * reverse( ) * reverses the elements in the list */ template< class Type, class Allocator > void list< Type, Allocator >::reverse( ) { DoubleLink *temp; //(carefully) reverse pointers in each node DoubleLink *current = sentinel->fwd; while( current != sentinel ) { temp = current->fwd; current->fwd = current->bwd; current->bwd = temp; current = temp; } //reverse pointers in sentinel (to flip head and tail of list) temp = sentinel->fwd; sentinel->fwd = sentinel->bwd; sentinel->bwd = temp; } /* ------------------------------------------------------------------ * merge( list & ) * Merges the argument list into this list. No nodes are created or * destroyed during this process. Only pointers and counters are * changed. */ template< class Type, class Allocator > void list< Type, Allocator >::merge( list &other ) { DoubleLink *temp_link; size_type temp_size; if( other.mSize == 0 ) return; if( mSize == 0 ) { temp_link = sentinel; sentinel = other.sentinel; other.sentinel = temp_link; temp_size = mSize; mSize = other.mSize; other.mSize = temp_size; } DoubleLink *list1 = sentinel->fwd; DoubleLink *list2 = other.sentinel->fwd; //compare elements on both lists as long as possible. while( list1 != sentinel && list2 != other.sentinel ) { if( !( static_cast< Node * >( list2 )->value < static_cast< Node * >( list1 )->value ) ) { list1 = list1->fwd; } else { list1->bwd->fwd = list2; temp_link = list1->bwd; list1->bwd = list2; list2->bwd->fwd = list2->fwd; list2->fwd->bwd = list2->bwd; list2 = list2->fwd; list1->bwd->fwd = list1; list1->bwd->bwd = temp_link; mSize++; other.mSize--; } } //deal with the tail end of list2 (if anything is left). if( list2 != other.sentinel ) { list1 = sentinel->bwd; list1->fwd = list2; list2->bwd = list1; sentinel->bwd = other.sentinel->bwd; other.sentinel->bwd->fwd = sentinel; other.sentinel->bwd = other.sentinel; other.sentinel->fwd = other.sentinel; mSize += other.mSize; other.mSize = 0; } } /* ------------------------------------------------------------------ * push( Node*, x ) (private) * insert copy of x in list just before element identified by Node* */ template< class Type, class Allocator > list< Type, Allocator >::Node* list< Type, Allocator >::push( Node* o, Type const & x ) { Node* n = mMem.allocate( 1 ); try{ mMem.construct( n, Node(x) ); }catch( ... ){ mMem.deallocate( n, 1 ); throw; } n->fwd = o; n->bwd = o->bwd; o->bwd->fwd = n; o->bwd = n; ++mSize; return( n ); } /* ------------------------------------------------------------------ * pop( Node* ) (private) * remove (destroy and deallocate) an element */ template< class Type, class Allocator > void list< Type, Allocator >::pop( Node* n ) { n->fwd->bwd = n->bwd; n->bwd->fwd = n->fwd; mMem.destroy( n ); mMem.deallocate( n, 1 ); --mSize; } /* ------------------------------------------------------------------ * _Sane( ) * returns true if invariants check out ok */ template< class Type, class Allocator > bool list< Type, Allocator >::_Sane( ) { //sentinel can't have null links if( !sentinel->fwd || !sentinel->bwd ) return( false ); DoubleLink* d = sentinel->fwd; size_type c = 0; while( d != sentinel ){ c++; //if exceeded size, something is wrong so abort now if( c > mSize) return( false ); if( !(d->fwd) || !(d->bwd) ) return( false ); //can't have null links if( d->bwd->fwd != d ) return( false ); //broken links if( d->fwd->bwd != d ) return( false ); //broken links d = d->fwd; }; if( c != mSize ) return( false ); //check size return( true ); } } // namespace std #endif