/////////////////////////////////////////////////////////////////////////// // FILE: list (Definition of _watcom::slist) // // ========================================================================= // // 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 OW extentions to the standard // library. It provides a single link list container. /////////////////////////////////////////////////////////////////////////// #ifndef _SLIST_INCLUDED #define _SLIST_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 _LIMITS_INCLUDED #include #endif #ifndef _FUNCTIONAL_INCLUDED #include #endif #ifndef __META_H_INCLUDED #include <_meta.h> #endif namespace _watcom { /* ================================================================== * slist class template * see list and SGI slist for inspiration */ template< class T, class A = std::allocator< T > > class slist{ public: typedef T value_type; typedef typename A::size_type size_type; typedef typename A::difference_type difference_type; typedef A allocator_type; typedef typename A::reference reference; typedef typename A::const_reference const_reference; typedef typename A::pointer pointer; typedef typename A::const_pointer const_pointer; private: struct Node; typedef typename A::rebind::other::pointer n_ptr; struct Node{ n_ptr fwd; T value; Node( T const & v ) : value( v ) { } }; A::rebind::other nmem; //--------------------------------------------------------------- // iterators // todo: move definition outside class struct iterator_base: public std::iterator< std::forward_iterator_tag, T > { n_ptr self; iterator_base( n_ptr x ) : self(x){} iterator_base( ) : self(0) {} iterator_base( iterator_base const & that ) { self = that.self; } bool operator==( iterator_base const & that ){ return( self == that.self ); } bool operator!=( iterator_base const & that ){ return( self != that.self ); } }; public: struct const_iterator; struct iterator : public iterator_base, public std::iterator< std::forward_iterator_tag, value_type, difference_type, pointer, reference >{ iterator( n_ptr x ) : iterator_base( x ) {} iterator( ) : iterator_base () {} iterator& operator++() { self = self->fwd; return *this; } //prefix iterator operator++( int ) { iterator old = *this; self = self->fwd; return old; } //postfix reference operator*() { return( self->value ); } }; struct const_iterator: public iterator_base, public std::iterator< std::forward_iterator_tag, value_type const, difference_type, const_pointer, const_reference >{ const_iterator( n_ptr x ) : iterator_base( x ) {} const_iterator( ) : iterator_base () {} const_iterator( slist::iterator const & that ) : iterator_base( that.self ){} const_iterator& operator++() { self = self->fwd; return *this; } //prefix const_iterator operator++( int ) { const_iterator old = *this; self = self->fwd; return old; } //postfix const_reference operator*(){ return( self->value ); } }; // end of iterators //----------------------------------------------------------------- public: // construct/copy/destroy explicit slist( A const & a = A() ) : mSize(0), nmem(a) { first = NULL; } explicit slist( size_type ); slist( size_type, T const &, A const & = A() ); template< class InputIt > slist( InputIt f, InputIt l )//, A const & = A() ) : mSize( 0 ), first( 0 ) { helper_assign( f, l, std::tr1::is_integral< InputIt >::type() ); } slist( slist const & ); //slist( slist&& ); ~slist(){ clear(); } slist& operator=( slist const & ); //slist& operator=( slist && ); template < class InputIt > void assign( InputIt f, InputIt l ) { helper_assign( f, l, std::tr1::is_integral< InputIt >::type() ); } void assign( size_type, T const & ); allocator_type get_allocator() const { allocator_type a(nmem); return( a ); } // iterators iterator begin() { return( iterator( first ) ); } const_iterator begin() const { return( const_iterator( first ) ); } iterator end(){ return( iterator( 0 ) ); } const_iterator end() const { return( const_iterator( 0 ) ); } const_iterator cbegin() const { return( const_iterator( first ) ); } const_iterator cend() const{ return( const_iterator( 0 ) ); } iterator previous( iterator it ) { return( previous(it.self) ); } //special for SLL const_iterator previous( const_iterator it ) const { return( previous(it.self) ); }; //special for SLL // capacity bool empty() const { return( mSize == 0 ); } size_type size() const { return mSize; } size_type max_size() const; void resize( size_type, T ); void resize( size_type s ) { resize( s, T() ); } // access reference front() { return( first->value ); } const_reference front() const { return( first->value ); } // modifiers void pop_front(); void push_front( T const & v ); //template< class... Args> void push_front( Args&&... ); //template < class... Args> iterator emplace( const_iterator, ARgs&&... ); iterator insert( const_iterator, T const & ); //iterator insert( const_iterator, T&& ); void insert( const_iterator, size_type, T const & ); template< class InputIt > void insert( const_iterator it, InputIt f, InputIt l ) { helper_insert( it, f, l, std::tr1::is_integral< InputIt >::type() ); } iterator insert_after( const_iterator, T const & ); //special for SLL void insert_after( const_iterator, size_type, T const & ); template< class InputIt > void insert_after( const_iterator it, InputIt f, InputIt l ) { helper_insert_after( it, f, l, std::tr1::is_integral< InputIt >::type() ); } iterator erase( const_iterator ); iterator erase( const_iterator, const_iterator ); iterator erase_after( const_iterator ); //special for SLL iterator erase_after( const_iterator, const_iterator ); //special for SSL //void swap( slist&& ); void swap( slist& ); void clear(); //operations void splice( const_iterator, slist& ); void splice( const_iterator, slist&, const_iterator ); //void splice( const_iterator, slist&&, const_iterator, const_iterator); void splice_after( const_iterator pos, slist&, const_iterator prev ); // different to sgi interface void splice_after( const_iterator pos, slist&, const_iterator before_first, const_iterator before_last ); void remove( T const& ); void unique() { unique( std::equal_to< T >() ); } void merge( slist& other ) { merge( other, std::less< T >() ); } void sort() { sort( std::less< T >() ); } void reverse(); template< class U, class V > friend bool operator==( slist const & a, slist const & b ); template< class U, class V > friend bool operator!=( slist const & a, slist const & b ); template< class U, class V > friend bool operator<=( slist const & a, slist const & b ); template< class U, class V > friend bool operator>=( slist const & a, slist const & b ); template< class U, class V > friend bool operator<( slist const & a, slist const & b ); template< class U, class V > friend bool operator>( slist const & a, slist const & b ); //OW special bool _Sane(); /* ------------------------------------------------------------------ * remove_if( Predicate ) * inline due to missing compiler feature * exception safety: strong only if Predicate can't throw */ template< class Predicate > void remove_if( Predicate pred ) { n_ptr p = first; n_ptr n = first; while( n != 0 ){ if( pred( n->value ) != false ){ if( n == first ){ first = n->fwd; nmem.destroy( n ); nmem.deallocate( n, 1 ); --mSize; p = n = first; }else{ p->fwd = n->fwd; nmem.destroy( n ); nmem.deallocate( n, 1 ); --mSize; n = p->fwd; } }else{ p = n; n = n->fwd; } }; } /* ------------------------------------------------------------------ * unique( BinaryPredicate ) * inline due to missing compiler feature * exception safety: nothing only if Predicate can't throw */ template< class Predicate > void unique( Predicate cmp ) { n_ptr p = first; n_ptr n = p->fwd; while( p && n ){ if( cmp( n->value, p->value ) ){ n_ptr del = n; p->fwd = n->fwd; nmem.destroy( del ); nmem.deallocate( del, 1 ); --mSize; }else{ p = p->fwd; } n = p->fwd; } } /* ------------------------------------------------------------------ * merge( slist, compare ) * inline due to missing compiler feature * exception saftey: to do, what can throw? */ template< class Compare > void merge( slist& other, Compare cmp ) { n_ptr o = other.first; n_ptr t = first; n_ptr m = first; // do first element if( !o ) return; if( o && !t ){ first = other.first; other.first = 0; mSize = other.mSize; other.mSize = 0; return; } if( cmp( o->value, t->value ) ){ first = o; m = o; o = o->fwd; }else{ t = t->fwd; } // do main block while( o && t ){ if( cmp( o->value, t->value ) ){ m->fwd = o; m = m->fwd; o = o->fwd; }else{ m->fwd = t; m = m->fwd; t = t->fwd; } }; // do tails if( o ) m->fwd = o; if( t ) m->fwd = t; // fix sizes and unlink other mSize += other.mSize; other.mSize = 0; other.first = 0; } /* ------------------------------------------------------------------ * sort( compare ) * inline due to missing compiler feature * * following is a list of reasons for the features used in this vesion * of merge sort: * > iterative : * to over come additional call overhead of iterative version * and give the optimiser more of a chance to do it's stuff * > same walk order as an iterative implementation : * use an explicit stack to keep track of data so nodes are * visited as if it were iterative, this gives good (optimal?) * cache usage as there is good locality of visiting the nodes * > take as much sorted list in one go: * instead dividing down to list of size 1 and then merging * take as much sorted list as possible in one go and then merge * these sublist. This gives a massive improvement on * lists that are already (partially) sorted in exchange for * a few (my limited testing surgests 2-5%) extra comparisions * when presented with random data * * Before changing this algorithm do some benchmarking to prove improvements * * exception safety: to do: what can throw??? */ template< class Compare > void sort( Compare cmp ) { if( mSize < 2 ) return; struct StackData{ n_ptr data; int depth; }; // Ideally stack would be log2 of current container size // but don't want dynamic alloc overhead, thus a little memory // is wasted here but in most cases it will be insignificant. // Do log2 of max_size() instead - this is currently making // somewhat dodgey assumptions StackData stack[ std::numeric_limits< difference_type >::digits - _ow::log2_floor< sizeof( T ) >::value ]; int top = 0; // index the empty top element which is next to be filled bool input_done = false; n_ptr input = first; // keep track of next element of unsorted data do{ if( (top >= 2 && stack[top-1].depth == stack[top-2].depth) || input_done ){ // merge top two n_ptr a,b,prev,merged; a = stack[top-2].data; b = stack[top-1].data; // compare the first a or b separately to set up head if( cmp( b->value, a->value ) ){ merged = b; prev = b; b = b->fwd; }else{ merged = a; prev = a; a = a->fwd; } // add next a or b in turn until one is exhausted while( a && b ){ if( cmp( b->value, a->value ) ){ // move b into place location prev->fwd = b; prev=prev->fwd; b = b->fwd; }else{ // move a into merged list prev->fwd = a; prev=prev->fwd; a = a->fwd; } }; // link in tails if( a ) prev->fwd = a; if( b ) prev->fwd = b; // replace stack entry stack[top-2].data = merged; stack[top-2].depth++; top--; }else{// top < 2 || stack[top].depth != stack[top-1].depth // get another piece of sorted input data n_ptr fst = input; n_ptr next = input->fwd; n_ptr temp; int c = 1; while( next != 0 ){ if( !cmp( next->value, input->value ) ){ // next>=input c++; input = next; next = next->fwd; }else if( c == 1 ){ // swap two elements fst = next; temp = next->fwd; next->fwd = input; next = temp; input->fwd = next; c = 2; //#define _SLIST_do_place3 //this doesn't improve matters #ifndef _SLIST_do_place3 break; #endif #ifdef _SLIST_do_place3 }else if( c == 2 ){ // only one more compare needed to insert third // element in correct place so we might as well do it temp = next->fwd; if( !cmp( next->value, fst->value ) ){ next->fwd = input; fst->fwd = next; }else{ next->fwd = fst; fst = next; } next = temp; break; #undef _SLIST_do_place3 #endif }else{ // input > next, finish sublist break; } }; input->fwd = 0; // mark end of subsection input = next; // set ready for next bit of list if( next == 0 ) input_done = true; // push onto stack stack[top].data = fst; stack[top].depth = 1; ++top; } }while( top != 1 || !input_done ); first = stack[0].data; } private: size_type mSize; // so counting is fast n_ptr first; // single linked listed with first element held here (no sentinals) inline n_ptr previous( n_ptr ) const; // find previous node inline n_ptr copy( n_ptr, size_type ); // copy a number of nodes inline n_ptr make( size_type, T const &, n_ptr& ); // make a number of new nodes /* ------------------------------------------------------------------ * make_from * make a list of nodes holding [ *f, *l ) * set c to number of elements and ft to first node and return last node * for use by strong safe functions */ template< class InputIt > n_ptr make_from( InputIt f, InputIt l, n_ptr& ft, size_type & c ) { n_ptr n, p; ft = 0; c = 0; if( f == l ) return( 0 ); try{ // do first element ft = nmem.allocate( 1 ); nmem.construct( ft, Node(*f) ); c++; ++f; p = ft; // do the rest while( f != l ){ n = nmem.allocate( 1 ); nmem.construct( n, Node(*f) ); c++; ++f; p->fwd = n; p = n; } }catch( ... ){ while( ft ){ n = ft->fwd; if( c-- ) nmem.destroy( ft ); // possibly alloc ok but construct failed nmem.deallocate( ft, 1 ); ft = n; } } n->fwd = 0; return( n ); } /* ------------------------------------------------------------------ * helper functions that are overloaded so can be called depending on InputIt type * have to be inline at mo due to compiler * exception safety: strong (although standard says multi inserts don't have to be) */ template< class InputIt > void helper_assign( InputIt f, InputIt l, std::tr1::true_type ) { //std::cout<<"true_type\n"; assign( static_cast(f), static_cast(l) ); } template< class InputIt > void helper_assign( InputIt f, InputIt l, std::tr1::false_type ) { //std::cout<<"false_type\n"; size_type c; n_ptr temp; make_from( f, l, temp, c ); // exception safe clear(); first = temp; mSize = c; } template< class InputIt > void helper_insert( const_iterator it, InputIt f, InputIt l, std::tr1::true_type ) { //std::cout<<"insert true\n"; insert( it, static_cast(f), static_cast(l) ); } template< class InputIt > void helper_insert( const_iterator cit, InputIt f, InputIt l, std::tr1::false_type ) { //std::cout<<"insert false\n"; size_type c; n_ptr n; n_ptr e = make_from( f, l, n, c ); if( cit.self == first ){ e->fwd = first; first = n; }else{ n_ptr p = previous( cit.self ); p->fwd = n; e->fwd = cit.self; } mSize += c; } template< class InputIt > void helper_insert_after( const_iterator it, InputIt f, InputIt l, std::tr1::true_type ) { //std::cout<<"insert after true\n"; insert_after( it, static_cast(f), static_cast(l) ); } template< class InputIt > void helper_insert_after( const_iterator cit, InputIt f, InputIt l, std::tr1::false_type ) { //std::cout<<"insert after false\n"; size_type c; n_ptr n; n_ptr e = make_from( f, l, n, c ); e->fwd = (cit.self)->fwd; (cit.self)->fwd = n; mSize += c; } }; //end class slist /* ------------------------------------------------------------------ * previous(n_ptr) private * used by previous( iterator ), previous( const_iterator ) and internally * not explicit from sgi docs what previous( begin() ) should return * sgi code uses a header node so ++previous( begin() ) = begin() * we will not allow previous( begin() ), but this implementation will * actually return end() */ template< class T, class A > inline slist::n_ptr slist::previous( n_ptr n ) const { n_ptr p = first; while( (p != 0) && (p->fwd != n ) ) p = p->fwd; return( p ); } /* ------------------------------------------------------------------ * copy( n_ptr, size_type ) * helper to make copy chain of links * unwinds on exception for use by other strong excption safe methods * returns ptr to first in new chain */ template< class T, class A > slist::n_ptr slist::copy( n_ptr src, size_type i ) { n_ptr dst = 0; if( src == 0 ) return dst; //do the first element separately size_type a = 0; size_type c = 0; n_ptr n = nmem.allocate( 1 ); a++; dst = n; try{ nmem.construct( n, *src ); c++; n_ptr p = n; // previous element for loop src = src->fwd; // now the rest of the elements while( c < i ){ n = nmem.allocate( 1 ); a++; p->fwd = n; nmem.construct( n, *src ); c++; p = n; src = src->fwd; } }catch( ... ){ // something failed, unwind the completed elements while( a ){ n = dst->fwd; //last element might have been alloced but not constructed if( c ) nmem.destroy( dst ); nmem.deallocate( dst, 1 ); dst = n; c--; a--; } throw; } n->fwd=0; return dst; } /* ------------------------------------------------------------------ * n_ptr make( size_type, Tconst&, nptr& f ) * helper to make chain of links initialised to T * unwinds on exception for use by other strong excption safe methods * sets pointer param to first and returns last in new chain */ template< class T, class A > slist::n_ptr slist::make( size_type i, T const & t, n_ptr& f ) { n_ptr p = 0; n_ptr l = 0; f = 0; try{ // build links backwards for( int c = 0; c < i; c++ ){ f = nmem.allocate( 1 ); try{ nmem.construct( f, Node(t) ); }catch( ... ){ nmem.deallocate( f, 1 ); throw; } if( c == 0 ) l = f; // save ptr last f->fwd = p; p = f; } }catch( ... ){ while( p ){ f = p->fwd; nmem.destroy( p ); nmem.deallocate( p, 1 ); p = f; } } return( l ); } /* ------------------------------------------------------------------ * ctor( size_type n ) * construct list with n default constructed elements * exception safety: strong */ template< class T, class A > slist::slist( size_type i ) : mSize( i ) { make( i, T(), first ); } /* ------------------------------------------------------------------ * cpyctor( slist & ) * strong exception safety */ template< class T, class A > slist::slist( slist const & that ) : mSize( that.mSize ) { first = copy( that.first, mSize ); } /* ------------------------------------------------------------------ * assignment operator * exception safety: strong */ template< class T, class A > slist& slist::operator=( slist const & that ) { if( this == &that ) return( *this ); n_ptr temp = copy( that.first, that.mSize ); // following can't throw clear(); first = temp; mSize = that.mSize; return( *this ); } /* ------------------------------------------------------------------ * assign( size_type, T const & ) * exception safety: strong */ template< class T, class A > void slist::assign( size_type s, T const & t ) { n_ptr temp; make( s, t, temp ); // following can't throw clear(); first = temp; mSize = s; } /* ------------------------------------------------------------------ * max_size */ template< class T, class A > typename slist::size_type slist::max_size() const { return( std::numeric_limits< difference_type >::max() / sizeof( T ) ); // hmm } /* ------------------------------------------------------------------ * resize * exception safety: strong */ template< class T, class A > void slist::resize( size_type s, T t ) { if( s == 0 ){ clear(); }else if( s < mSize ){ n_ptr del, p = first; int i; for( i = 1; i < s; i++ ) p = p->fwd; // find previous to sth element del = p->fwd; p->fwd = 0; // new end while( del != 0 ){ p = del->fwd; // save next nmem.destroy( del ); nmem.deallocate( del, 1 ); del = p; }; mSize = s; }else{ // s > size n_ptr n; make( s - mSize, t, n ); // alloc new nodes if( mSize == 0 ){ first = n; }else{ // find last n_ptr last = first; while( last->fwd ) last = last->fwd; last->fwd = n; // link in new nodes } mSize = s; } } /* ------------------------------------------------------------------ * pop_front( ) * destroy front node */ template< class T, class A > void slist::pop_front( ) { n_ptr o = first; first = first->fwd; --mSize; nmem.destroy( o ); nmem.deallocate( o, 1 ); } /* ------------------------------------------------------------------ * push_front( T const & ) * insert a new node at front */ template< class T, class A > void slist::push_front( T const & v ) { n_ptr n = nmem.allocate( 1 ); try{ nmem.construct( n, Node(v) ); }catch( ... ){ nmem.deallocate( n, 1 ); throw; } n->fwd = first; first = n; ++mSize; } /* ------------------------------------------------------------------ * insert( iterator, T const & ) * insert a new node before it * Note this is slow for ssl */ template< class T, class A > slist::iterator slist::insert( const_iterator it , T const & v ) { n_ptr n = nmem.allocate( 1 ); try{ nmem.construct( n, Node(v) ); }catch( ... ){ nmem.deallocate( n, 1 ); throw; } if( it.self == first ){ n->fwd = first; first = n; }else{ n_ptr p = previous( it.self ); n->fwd = p->fwd; p->fwd = n; } ++mSize; return( iterator( n ) ); } /* ------------------------------------------------------------------ * insert_after( Node* o, T const & ) * insert a new node after node o * NOTE this op is constant time for sll */ template< class T, class A > slist::iterator slist::insert_after( const_iterator it, T const & v ) { n_ptr n = nmem.allocate( 1 ); try{ nmem.construct( n, Node(v) ); }catch( ... ){ nmem.deallocate( n, 1 ); throw; } n_ptr p = it.self; n->fwd = p->fwd; p->fwd = n; ++mSize; return( n ); } /* ------------------------------------------------------------------ * insert( const_iterator, size_type s, T const & ) * insert s new nodes before it * Note this is slow for ssl */ template< class T, class A > void slist::insert( const_iterator cit, size_type s, T const & t ) { if( s == 0 ) return; n_ptr n; n_ptr e = make( s, t, n ); n_ptr l = cit.self; if( l == first ){ e->fwd = first; first = n; }else{ n_ptr p = previous( l ); p->fwd = n; e->fwd = l; } mSize += s; } /* ------------------------------------------------------------------ * insert_after( const_iterator, size_type s, T const & ) * insert s new nodes before it * Note this is special/fast for ssl */ template< class T, class A > void slist::insert_after( const_iterator cit, size_type s, T const & t ) { if( s == 0 ) return; n_ptr n; n_ptr e = make( s, t, n ); n_ptr o = cit.self; e->fwd = o->fwd; o->fwd = n; mSize += s; } /* ------------------------------------------------------------------ * erase( iterator ) * NOTE this op is slow for sll */ template< class T, class A > slist::iterator slist::erase( const_iterator it ) { n_ptr ret; if( it.self == first ){ first = it.self->fwd; ret = it.self->fwd; }else{ n_ptr p = previous( it.self ); p->fwd = (it.self)->fwd; ret = p->fwd; } --mSize; nmem.destroy( it.self ); nmem.deallocate( it.self, 1 ); return( ret ); } /* ------------------------------------------------------------------ * erase_after( iterator ) * this op is special/constant time for sll */ template< class T, class A > slist::iterator slist::erase_after( const_iterator it ) { n_ptr t = it.self; n_ptr del = t->fwd; n_ptr next = del->fwd; t->fwd = next; --mSize; nmem.destroy( del ); nmem.deallocate( del, 1 ); return( next ); } /* ------------------------------------------------------------------ * erase( iterator first , iterator last ) * erase all list items in range [first, last) */ template< class T, class A > slist::iterator slist::erase( const_iterator fit, const_iterator lit ) { n_ptr b,del; if( fit.self == first ) { del = fit.self; while( del != lit.self ){ first = del->fwd; nmem.destroy( del ); nmem.deallocate( del, 1 ); del = first; --mSize; } }else{ b = previous( fit ).self; del = fit.self; while( del != lit.self ){ b->fwd = del->fwd; nmem.destroy( del ); nmem.deallocate( del, 1 ); del = b->fwd; --mSize; } } return( del ); } /* ------------------------------------------------------------------ * erase_after( iterator first , iterator last ) * erase all list items in range [first+1, last) */ template< class T, class A > slist::iterator slist::erase_after( const_iterator fit, const_iterator lit ) { n_ptr s, del; del = fit.self->fwd; while( del != lit.self ){ s = del->fwd; nmem.destroy( del ); nmem.deallocate( del, 1 ); del = s; --mSize; } fit.self->fwd = lit.self; return( s ); } /* ------------------------------------------------------------------ * swap * exception safety : no throw */ template< class T, class A > void slist::swap( slist& other ) { n_ptr tempn = first; first = other.first; other.first = tempn; size_type tempi = mSize; mSize = other.mSize; other.mSize = tempi; } /* ------------------------------------------------------------------ * clear * exception safety : no throw */ template< class T, class A > void slist::clear( ) { n_ptr del; n_ptr x = first; while( x != 0 ){ del = x; x = x->fwd; nmem.destroy( del ); nmem.deallocate( del, 1 ); }; mSize = 0; first = 0; } /* ------------------------------------------------------------------ * splice( iterator, slist& ) * exception safety: no throw */ template< class T, class A > void slist::splice( const_iterator it, slist& that ) { if( that.mSize == 0 ) return; // link this to start of that n_ptr n = it.self; if( n == first ){ first = that.first; }else{ // n != first n_ptr p = previous( n ); p->fwd = that.first; } // find end of that and link to rest of this n_ptr e = that.first; while( e->fwd ) e = e->fwd; e->fwd = n; mSize += that.mSize; // remove links from that that.mSize = 0; that.first = 0; } /* ------------------------------------------------------------------ * splice( iterator, slist, iterator ) * splice node src before dst * src can point to this container or another slist * exception safety: no throw */ template< class T, class A > void slist::splice( const_iterator dst, slist& that, const_iterator src ) { // check not splicing on top of itself if( ( this == &that ) && ( src.self == dst.self || src.self->fwd == dst.self ) ) return; // unlink src from src container if( src.self == that.first ){ that.first = src.self->fwd; }else{ that.previous( src.self )->fwd = src.self->fwd; } // link in new node if( dst.self == first ){ first = src.self; }else{ previous( dst.self )->fwd = src.self; } // link back in the tail of this list src.self->fwd = dst.self; --that.mSize; ++mSize; } /* ------------------------------------------------------------------ * splice_after( iterator, slist, iterator ) * splice node ++src after dst, constant time * dst & src must be dereferenceable, ++src must be dereferenceable * ( it doesn't seem to make sense to splice "end" of one list into another list ) * that can be this container or another slist * differs from sgi in that it takes a ref to the other list * (so iterators don't need to store list reference) * exception safety: no throw */ template< class T, class A > void slist:: splice_after( const_iterator dst, slist& that, const_iterator src ) { // check not splicing on top of itself if( src.self->fwd == dst.self->fwd || src.self->fwd == src.self ) return; // link in ++src node after dst ( can't be first node ) n_ptr spliceme = src.self->fwd; n_ptr tail = dst.self->fwd; dst.self->fwd = spliceme; // unlink ++src from src container ( can't be first node or end ) src.self->fwd = src.self->fwd->fwd; // link back in the tail of this list spliceme->fwd = tail; --that.mSize; ++mSize; } /* ------------------------------------------------------------------ * splice_after( iterator dst, slist, iterator b4_first, iterator b4_last ) * splice nodes [++b4_first, ++b4_last) after dst, constant time * dst b4_first b4_last iterators must be dereferenceable * that can be this container or another slist * bad things will happen if dst is in range[first, last ) * differs from sgi in that it takes a ref to the other list * (so iterators don't need to store list reference) * exception safety: no throw */ template< class T, class A > void slist::splice_after( const_iterator dst, slist& that, const_iterator b4_first, const_iterator b4_last ) { if( &that != this ){ // count elements int c = 0; const_iterator it = b4_first; while( it != b4_last ) { ++it; ++c; } that.mSize -= c; mSize += c; } n_ptr tail = dst.self->fwd; //save tail dst.self->fwd = b4_first.self->fwd; //splice in b4_first.self->fwd = b4_last.self->fwd; //splice out b4_last.self->fwd = tail; //join tail } /* ------------------------------------------------------------------ * remove( T const & ) * exception safety: strong only if operator== can't throw */ template< class T, class A > void slist::remove( T const & v ) { n_ptr p = first; n_ptr n = first; while( n != 0 ){ if( n->value == v ){ if( n == first ){ first = n->fwd; nmem.destroy( n ); nmem.deallocate( n, 1 ); --mSize; p = n = first; }else{ p->fwd = n->fwd; nmem.destroy( n ); nmem.deallocate( n, 1 ); --mSize; n = p->fwd; } }else{ p = n; n = n->fwd; } }; } /* ------------------------------------------------------------------ * reverse( ) * exception safety: strong */ template< class T, class A > void slist::reverse( ) { n_ptr n = first; n_ptr p = 0; n_ptr s; while( n != 0 ){ s = n->fwd; // save next link n->fwd = p; // link this to previous p = n; // advance previous to this n = s; // advance this to saved next }; first = p; } /* ------------------------------------------------------------------ * _Sane * check internal structure of list ok */ template< class T, class A > bool slist::_Sane() { if( ( mSize == 0 ) && ( first != NULL ) ) return( false ); n_ptr n = first; for( int i = 0; i < mSize; ++i ){ if( n == NULL ) return( false ); n = n->fwd; } if( n != NULL ) return( false ); return( true ); } // lexicographical comparisons template< class T, class A > bool operator==( slist const & a, slist const & b ) { if( a.mSize != b.mSize ) return( false ); slist::n_ptr n = a.first; slist::n_ptr m = b.first; while( n && m ){ if( !( n->value == m->value ) ) return( false ); n = n->fwd; m = m->fwd; }; return( true ); } template< class T, class A > bool operator<( slist const & a, slist const & b ) { slist::n_ptr n = a.first; slist::n_ptr m = b.first; while( n && m ){ if( n->value < m->value ) return( true ); if( m->value < n->value ) return( false ); n = n->fwd; m = m->fwd; }; return( !n && m ); } template< class T, class A > bool operator>( slist const & a, slist const & b ) { return( b < a ); } template< class T, class A> bool operator!=( slist const & a, slist const & b) { return( !( a == b ) ); } template< class T, class A> bool operator<=( slist const & a, slist const & b ) { return( !( b < a ) ); } template< class T, class A> bool operator>=( slist const & a, slist const & b ) { return( !( a < b ) ); } // specialised algorithms template< class T, class A> void swap( slist const & x, slist const & y ) { x.swap( y ); } //template< class T, class A> void swap( slist const &&, slist const & ); //template< class T, class A> void swap( slist const &, slist const && ); } // namespace _watcom #endif