#pragma once
#ifndef _STLLIST_H_
#define _STLLIST_H_
//#include <cstddef>
//#include <functional>
//#include <iterator>
//#include <memory>
//#include <stdexcept>
//#include <xutility>

#include <stlxstdd.h>
#include <stlfunc.h>
#include <stliter.h>
#include <stlmem.h>
#include <stlxutil.h>

#ifdef  _MSC_VER
#pragma pack(push,8)
#endif  /* _MSC_VER */

_STD_BEGIN

// TEMPLATE CLASS list
template<class _Ty, class _A = allocator<_Ty> >
class list
{
protected:
    typedef _POINTER_X(void, _A) _Genptr;
    struct _Node;
    friend struct _Node;
    struct _Node
    {
        _Genptr _Next, _Prev;
        _Ty _Value;
    };
    typedef _POINTER_X(_Node, _A) _Nodeptr;
    struct _Acc;
    friend struct _Acc;
    struct _Acc
    {
        typedef _REFERENCE_X(_Nodeptr, _A) _Nodepref;
        typedef _A::reference _Vref;
        static _Nodepref _Next(_Nodeptr _P)
        {
            return ((_Nodepref)(*_P)._Next);
        }
        static _Nodepref _Prev(_Nodeptr _P)
        {
            return ((_Nodepref)(*_P)._Prev);
        }
        static _Vref _Value(_Nodeptr _P)
        {
            return ((_Vref)(*_P)._Value);
        }
    };
public:
    typedef list<_Ty, _A> _Myt;
    typedef _A allocator_type;
    typedef _A::size_type size_type;
    typedef _A::difference_type difference_type;
    typedef _A::pointer _Tptr;
    typedef _A::const_pointer _Ctptr;
    typedef _A::reference reference;
    typedef _A::const_reference const_reference;
    typedef _A::value_type value_type;
    // CLASS iterator
    class iterator;
    friend class iterator;
    class iterator : public _Bidit<_Ty, difference_type>
    {
    public:
        iterator()
        {

        }
        iterator(_Nodeptr _P)
        : _Ptr(_P)
        {

        }
        reference operator*() const
        {
            return (_Acc::_Value(_Ptr));
        }
        _Tptr operator->() const
        {
            return (&**this);
        }
        iterator& operator++()
        {
            _Ptr = _Acc::_Next(_Ptr);
            return (*this);
        }
        iterator operator++(int)
        {
            iterator _Tmp = *this;
            ++*this;
            return (_Tmp);
        }
        iterator& operator--()
        {
            _Ptr = _Acc::_Prev(_Ptr);
            return (*this);
        }
        iterator operator--(int)
        {
            iterator _Tmp = *this;
            --*this;
            return (_Tmp);
        }
        bool operator==(const iterator& _X) const
        {
            return (_Ptr == _X._Ptr);
        }
        bool operator!=(const iterator& _X) const
        {
            return (!(*this == _X));
        }
        _Nodeptr _Mynode() const
        {
            return (_Ptr);
        }
    protected:
        _Nodeptr _Ptr;
    };
    // CLASS const_iterator
    class const_iterator;
    friend class const_iterator;
    class const_iterator : public iterator
    {
    public:
        const_iterator()
        {

        }
        const_iterator(_Nodeptr _P)
        : iterator(_P)
        {

        }
        const_iterator(const iterator& _X)
        : iterator(_X)
        {

        }
        const_reference operator*() const
        {
            return (_Acc::_Value(_Ptr));
        }
        _Ctptr operator->() const
        {
            return (&**this);
        }
        const_iterator& operator++()
        {
            _Ptr = _Acc::_Next(_Ptr);
            return (*this);
        }
        const_iterator operator++(int)
        {
            iterator _Tmp = *this;
            ++*this;
            return (_Tmp);
        }
        const_iterator& operator--()
        {
            _Ptr = _Acc::_Prev(_Ptr);
            return (*this);
        }
        const_iterator operator--(int)
        {
            iterator _Tmp = *this;
            --*this;
            return (_Tmp);
        }
        bool operator==(const const_iterator& _X) const
        {
            return (_Ptr == _X._Ptr);
        }
        bool operator!=(const const_iterator& _X) const
        {
            return (!(*this == _X));
        }
    };
    typedef reverse_bidirectional_iterator<iterator,
    value_type, reference, _Tptr, difference_type>
    reverse_iterator;
    typedef reverse_bidirectional_iterator<const_iterator,
    value_type, const_reference, _Ctptr, difference_type>
    const_reverse_iterator;
    explicit list(const _A& _Al = _A())
    : allocator(_Al),
    _Head(_Buynode()), _Size(0)
    {

    }
    explicit list(size_type _N, const _Ty& _V = _Ty(),
                  const _A& _Al = _A())
    : allocator(_Al),
    _Head(_Buynode()), _Size(0)
    {
        insert(begin(), _N, _V);
    }
    list(const _Myt& _X)
    : allocator(_X.allocator),
    _Head(_Buynode()), _Size(0)
    {
        insert(begin(), _X.begin(), _X.end());
    }
    typedef const_iterator _It;
    list(_It _F, _It _L, const _A& _Al = _A())
    : allocator(_Al),
    _Head(_Buynode()), _Size(0)
    {
        insert(begin(), _F, _L);
    }
    ~list()
    {
        erase(begin(), end());
        _Freenode(_Head);
        _Head = 0, _Size = 0;
    }
    _Myt& operator=(const _Myt& _X)
    {
        if (this != &_X)
        {
            iterator _F1 = begin();
            iterator _L1 = end();
            const_iterator _F2 = _X.begin();
            const_iterator _L2 = _X.end();
            for (; _F1 != _L1 && _F2 != _L2; ++_F1, ++_F2)
                *_F1 = *_F2;
            erase(_F1, _L1);
            insert(_L1, _F2, _L2);
        }
        return (*this);
    }
    iterator begin()
    {
        return (iterator(_Acc::_Next(_Head)));
    }
    const_iterator begin() const
    {
        return (const_iterator(_Acc::_Next(_Head)));
    }
    iterator end()
    {
        return (iterator(_Head));
    }
    const_iterator end() const
    {
        return (const_iterator(_Head));
    }
    reverse_iterator rbegin()
    {
        return (reverse_iterator(end()));
    }
    const_reverse_iterator rbegin() const
    {
        return (const_reverse_iterator(end()));
    }
    reverse_iterator rend()
    {
        return (reverse_iterator(begin()));
    }
    const_reverse_iterator rend() const
    {
        return (const_reverse_iterator(begin()));
    }
    void resize(size_type _N, _Ty _X = _Ty())
    {
        if (size() < _N)
            insert(end(), _N - size(), _X);
        else
            while (_N < size())
                pop_back();
    }
    size_type size() const
    {
        return (_Size);
    }
    size_type max_size() const
    {
        return (allocator.max_size());
    }
    bool empty() const
    {
        return (size() == 0);
    }
    _A get_allocator() const
    {
        return (allocator);
    }
    reference front()
    {
        return (*begin());
    }
    const_reference front() const
    {
        return (*begin());
    }
    reference back()
    {
        return (*(--end()));
    }
    const_reference back() const
    {
        return (*(--end()));
    }
    void push_front(const _Ty& _X)
    {
        insert(begin(), _X);
    }
    void pop_front()
    {
        erase(begin());
    }
    void push_back(const _Ty& _X)
    {
        insert(end(), _X);
    }
    void pop_back()
    {
        erase(--end());
    }
    void assign(_It _F, _It _L)
    {
        erase(begin(), end());
        insert(begin(), _F, _L);
    }
    void assign(size_type _N, const _Ty& _X = _Ty())
    {
        erase(begin(), end());
        insert(begin(), _N, _X);
    }
    iterator insert(iterator _P, const _Ty& _X = _Ty())
    {
        _Nodeptr _S = _P._Mynode();
        _Acc::_Prev(_S) = _Buynode(_S, _Acc::_Prev(_S));
        _S = _Acc::_Prev(_S);
        _Acc::_Next(_Acc::_Prev(_S)) = _S;
        allocator.construct(&_Acc::_Value(_S), _X);
        ++_Size;
        return (iterator(_S));
    }
    void insert(iterator _P, size_type _M, const _Ty& _X)
    {
        for (; 0 < _M; --_M)
            insert(_P, _X);
    }
    void insert(iterator _P, const _Ty *_F, const _Ty *_L)
    {
        for (; _F != _L; ++_F)
            insert(_P, *_F);
    }
    void insert(iterator _P, _It _F, _It _L)
    {
        for (; _F != _L; ++_F)
            insert(_P, *_F);
    }
    iterator erase(iterator _P)
    {
        _Nodeptr _S = (_P++)._Mynode();
        _Acc::_Next(_Acc::_Prev(_S)) = _Acc::_Next(_S);
        _Acc::_Prev(_Acc::_Next(_S)) = _Acc::_Prev(_S);
        allocator.destroy(&_Acc::_Value(_S));
        _Freenode(_S);
        --_Size;
        return (_P);
    }
    iterator erase(iterator _F, iterator _L)
    {
        while (_F != _L)
            erase(_F++);
        return (_F);
    }
    void clear()
    {
        erase(begin(), end());
    }
    void swap(_Myt& _X)
    {
        if (allocator == _X.allocator)
        {
            std::swap(_Head, _X._Head);
            std::swap(_Size, _X._Size);
        }
        else
        {
            iterator _P = begin();
            splice(_P, _X);
            _X.splice(_X.begin(), *this, _P, end());
        }
    }
    friend void swap(_Myt& _X, _Myt& _Y)
    {
        _X.swap(_Y);
    }
    void splice(iterator _P, _Myt& _X)
    {
        if (!_X.empty())
        {
            _Splice(_P, _X, _X.begin(), _X.end());
            _Size += _X._Size;
            _X._Size = 0;
        }
    }
    void splice(iterator _P, _Myt& _X, iterator _F)
    {
        iterator _L = _F;
        if (_P != _F && _P != ++_L)
        {
            _Splice(_P, _X, _F, _L);
            ++_Size;
            --_X._Size;
        }
    }
    void splice(iterator _P, _Myt& _X, iterator _F, iterator _L)
    {
        if (_F != _L)
        {
            if (&_X != this)
            {
                size_type _N = 0;
                _Distance(_F, _L, _N);
                _Size += _N;
                _X._Size -= _N;
            }
            _Splice(_P, _X, _F, _L);
        }
    }
    void remove(const _Ty& _V)
    {
        iterator _L = end();
        for (iterator _F = begin(); _F != _L; )
            if (*_F == _V)
                erase(_F++);
            else
                ++_F;
    }
    typedef binder2nd<not_equal_to<_Ty> > _Pr1;
    void remove_if(_Pr1 _Pr)
    {
        iterator _L = end();
        for (iterator _F = begin(); _F != _L; )
            if (_Pr(*_F))
                erase(_F++);
            else
                ++_F;
    }
    void unique()
    {
        iterator _F = begin(), _L = end();
        if (_F != _L)
            for (iterator _M = _F; ++_M != _L; _M = _F)
                if (*_F == *_M)
                    erase(_M);
                else
                    _F = _M;
    }
    typedef not_equal_to<_Ty> _Pr2;
    void unique(_Pr2 _Pr)
    {
        iterator _F = begin(), _L = end();
        if (_F != _L)
            for (iterator _M = _F; ++_M != _L; _M = _F)
                if (_Pr(*_F, *_M))
                    erase(_M);
                else
                    _F = _M;
    }
    void merge(_Myt& _X)
    {
        if (&_X != this)
        {
            iterator _F1 = begin(), _L1 = end();
            iterator _F2 = _X.begin(), _L2 = _X.end();
            while (_F1 != _L1 && _F2 != _L2)
                if (*_F2 < *_F1)
                {
                    iterator _Mid2 = _F2;
                    _Splice(_F1, _X, _F2, ++_Mid2);
                    _F2 = _Mid2;
                }
                else
                    ++_F1;
            if (_F2 != _L2)
                _Splice(_L1, _X, _F2, _L2);
            _Size += _X._Size;
            _X._Size = 0;
        }
    }
    typedef greater<_Ty> _Pr3;
    void merge(_Myt& _X, _Pr3 _Pr)
    {
        if (&_X != this)
        {
            iterator _F1 = begin(), _L1 = end();
            iterator _F2 = _X.begin(), _L2 = _X.end();
            while (_F1 != _L1 && _F2 != _L2)
                if (_Pr(*_F2, *_F1))
                {
                    iterator _Mid2 = _F2;
                    _Splice(_F1, _X, _F2, ++_Mid2);
                    _F2 = _Mid2;
                }
                else
                    ++_F1;
            if (_F2 != _L2)
                _Splice(_L1, _X, _F2, _L2);
            _Size += _X._Size;
            _X._Size = 0;
        }
    }
    void sort()
    {
        if (2 <= size())
        {
            const size_t _MAXN = 15;
            _Myt _X(allocator), _A[_MAXN + 1];
            size_t _N = 0;
            while (!empty())
            {
                _X.splice(_X.begin(), *this, begin());
                size_t _I;
                for (_I = 0; _I < _N && !_A[_I].empty(); ++_I)
                {
                    _A[_I].merge(_X);
                    _A[_I].swap(_X);
                }
                if (_I == _MAXN)
                    _A[_I].merge(_X);
                else
                {
                    _A[_I].swap(_X);
                    if (_I == _N)
                        ++_N;
                }
            }
            while (0 < _N)
                merge(_A[--_N]);
        }
    }
    void sort(_Pr3 _Pr)
    {
        if (2 <= size())
        {
            const size_t _MAXN = 15;
            _Myt _X(allocator), _A[_MAXN + 1];
            size_t _N = 0;
            while (!empty())
            {
                _X.splice(_X.begin(), *this, begin());
                size_t _I;
                for (_I = 0; _I < _N && !_A[_I].empty(); ++_I)
                {
                    _A[_I].merge(_X, _Pr);
                    _A[_I].swap(_X);
                }
                if (_I == _MAXN)
                    _A[_I].merge(_X, _Pr);
                else
                {
                    _A[_I].swap(_X);
                    if (_I == _N)
                        ++_N;
                }
            }
            while (0 < _N)
                merge(_A[--_N], _Pr);
        }
    }
    void reverse()
    {
        if (2 <= size())
        {
            iterator _L = end();
            for (iterator _F = ++begin(); _F != _L; )
            {
                iterator _M = _F;
                _Splice(begin(), *this, _M, ++_F);
            }
        }
    }
protected:
    _Nodeptr _Buynode(_Nodeptr _Narg = 0, _Nodeptr _Parg = 0)
    {
        _Nodeptr _S = (_Nodeptr)allocator._Charalloc(
                                                    1 * sizeof (_Node));
        _Acc::_Next(_S) = _Narg != 0 ? _Narg : _S;
        _Acc::_Prev(_S) = _Parg != 0 ? _Parg : _S;
        return (_S);
    }
    void _Freenode(_Nodeptr _S)
    {
        allocator.deallocate(_S, 1);
    }
    void _Splice(iterator _P, _Myt& _X, iterator _F, iterator _L)
    {
        if (allocator == _X.allocator)
        {
            _Acc::_Next(_Acc::_Prev(_L._Mynode())) =
            _P._Mynode();
            _Acc::_Next(_Acc::_Prev(_F._Mynode())) =
            _L._Mynode();
            _Acc::_Next(_Acc::_Prev(_P._Mynode())) =
            _F._Mynode();
            _Nodeptr _S = _Acc::_Prev(_P._Mynode());
            _Acc::_Prev(_P._Mynode()) =
            _Acc::_Prev(_L._Mynode());
            _Acc::_Prev(_L._Mynode()) =
            _Acc::_Prev(_F._Mynode());
            _Acc::_Prev(_F._Mynode()) = _S;
        }
        else
        {
            insert(_P, _F, _L);
            _X.erase(_F, _L);
        }
    }
    void _Xran() const
    {
        _THROW(out_of_range, "invalid list<T> subscript");
    }
    _A allocator;
    _Nodeptr _Head;
    size_type _Size;
};

// list TEMPLATE OPERATORS
template<class _Ty, class _A> inline
bool operator==(const list<_Ty, _A>& _X,
                const list<_Ty, _A>& _Y)
{
    return (_X.size() == _Y.size()
            && equal(_X.begin(), _X.end(), _Y.begin()));
}
template<class _Ty, class _A> inline
bool operator!=(const list<_Ty, _A>& _X,
                const list<_Ty, _A>& _Y)
{
    return (!(_X == _Y));
}
template<class _Ty, class _A> inline
bool operator<(const list<_Ty, _A>& _X,
               const list<_Ty, _A>& _Y)
{
    return (lexicographical_compare(_X.begin(), _X.end(),
                                    _Y.begin(), _Y.end()));
}
template<class _Ty, class _A> inline
bool operator>(const list<_Ty, _A>& _X,
               const list<_Ty, _A>& _Y)
{
    return (_Y < _X);
}
template<class _Ty, class _A> inline
bool operator<=(const list<_Ty, _A>& _X,
                const list<_Ty, _A>& _Y)
{
    return (!(_Y < _X));
}
template<class _Ty, class _A> inline
bool operator>=(const list<_Ty, _A>& _X,
                const list<_Ty, _A>& _Y)
{
    return (!(_X < _Y));
}

_STD_END

#ifdef  _MSC_VER
#pragma pack(pop)
#endif  /* _MSC_VER */

#endif /* _STLLIST_H_ */

/*
 * Copyright (c) 1995 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
 */

/*
 * This file is derived from software bearing the following
 * restrictions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this
 * software and its documentation for any purpose is hereby
 * granted without fee, provided that the above copyright notice
 * appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation.
 * Hewlett-Packard Company makes no representations about the
 * suitability of this software for any purpose. It is provided
 * "as is" without express or implied warranty.
 */