///////////////////////////////////////////////////////////////////////////
// FILE: list (Definition of _watcom::slist)
//
//                          Open Watcom Project
//
// Copyright (c) 2004-2008 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

#if !defined(_ENABLE_AUTODEPEND)
  #pragma read_only_file;
#endif


#ifndef __cplusplus
#error The header list requires C++
#endif

#ifndef _ITERATOR_INCLUDED
    #include <iterator>
#endif

#ifndef _MEMORY_INCLUDED
    #include <memory>
#endif

#ifndef _TYPE_TRAITS_INCLUDED
    #include <type_tra>
#endif

#ifndef _LIMITS_INCLUDED
    #include <limits>
#endif

#ifndef _FUNCTIONAL_INCLUDED
    #include <function>
#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<Node>::other::pointer n_ptr;
    struct Node{
        n_ptr fwd;
        T value;
        Node( T const & v ) : value( v ) { }
    };
    A::rebind<Node>::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<T,A> const & );
    //slist( slist&& );
    ~slist(){ clear(); }
    slist<T,A>& operator=( slist<T,A> const & );
    //slist<T,A>& operator=( slist<T,A> && );
    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<T,A>&& );
    void swap( slist<T,A>& );
    void clear();
    
    //operations
    void splice( const_iterator, slist& );
    void splice( const_iterator, slist&, const_iterator );
    //void splice( const_iterator, slist<T,A>&&, 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<T,A>& other ) { merge( other, std::less< T >() ); }
    void sort() { sort( std::less< T >() ); }
    void reverse();
    
    template< class U, class V >
    friend bool operator==( slist<U,V> const & a, slist<U,V> const & b );
    template< class U, class V >
    friend bool operator!=( slist<U,V> const & a, slist<U,V> const & b );
    template< class U, class V >
    friend bool operator<=( slist<U,V> const & a, slist<U,V> const & b );
    template< class U, class V >
    friend bool operator>=( slist<U,V> const & a, slist<U,V> const & b );
    template< class U, class V >
    friend bool operator<( slist<U,V> const & a, slist<U,V> const & b );
    template< class U, class V >
    friend bool operator>( slist<U,V> const & a, slist<U,V> 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<T,A>& 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<size_type>(f), static_cast<T const>(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<size_type>(f), static_cast<T const>(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<size_type>(f), static_cast<T const>(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<T,A>::n_ptr slist<T,A>::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<T,A>::n_ptr slist<T,A>::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<T,A>::n_ptr slist<T,A>::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<T,A>::slist( size_type i ) : mSize( i )
{
    make( i, T(), first );
}

/* ------------------------------------------------------------------
 * cpyctor( slist & )
 * strong exception safety
 */
template< class T, class A >
slist<T,A>::slist( slist const & that ) : mSize( that.mSize )
{
    first = copy( that.first, mSize );
}



/* ------------------------------------------------------------------
 * assignment operator
 * exception safety: strong
 */
template< class T, class A >
slist<T,A>& slist<T,A>::operator=( slist<T,A> 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<T,A>::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<T,A>::size_type slist<T,A>::max_size() const
{ 
    return( std::numeric_limits< difference_type >::max() /
            sizeof( T ) ); // hmm
}

/* ------------------------------------------------------------------
 * resize
 * exception safety: strong
 */
template< class T, class A >
void slist<T,A>::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<T,A>::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<T,A>::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<T,A>::iterator slist<T,A>::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<T,A>::iterator slist<T,A>::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<T,A>::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<T,A>::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<T,A>::iterator slist<T,A>::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<T,A>::iterator slist<T,A>::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<T,A>::iterator slist<T,A>::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<T,A>::iterator slist<T,A>::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<T,A>::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<T,A>::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<T,A>::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<T,A>::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<T,A>:: 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<T,A>::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<T,A>::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<T,A>::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<T,A>::_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<T,A> const & a, slist<T,A> const & b )
{
    if( a.mSize != b.mSize ) return( false );
    slist<T,A>::n_ptr n = a.first;
    slist<T,A>::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<T,A> const & a, slist<T,A> const & b )
{
    slist<T,A>::n_ptr n = a.first;
    slist<T,A>::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<T,A> const & a, slist<T,A> const & b )
{
    return( b < a );
}

template< class T, class A>
bool operator!=( slist<T,A> const & a, slist<T,A> const & b)
{
    return( !( a == b ) );
}

template< class T, class A>
bool operator<=( slist<T,A> const & a, slist<T,A> const & b )
{
    return( !( b < a ) );
}

template< class T, class A>
bool operator>=( slist<T,A> const & a, slist<T,A> const & b )
{
    return( !( a < b ) );
}

// specialised algorithms
template< class T, class A>
void swap( slist<T,A> const & x, slist<T,A> const & y )
{
    x.swap( y );
}
//template< class T, class A> void swap( slist<T,A> const &&, slist<T,A> const & );
//template< class T, class A> void swap( slist<T,A> const &, slist<T,A> const && );



}; //end namespace _watcom

#endif
