/*
 * Copyright (C) 2005 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// Templated list class.  Normally we'd use STL, but we don't have that.
// This class mimics STL's interfaces.
//
// Objects are copied into the list with the '=' operator or with copy-
// construction, so if the compiler's auto-generated versions won't work for
// you, define your own.
//
// The only class you want to use from here is "List".
//
#ifndef _LIBS_UTILS_LIST_H
#define _LIBS_UTILS_LIST_H

#include <stddef.h>
#include <stdint.h>

namespace keymaster {

/*
 * Doubly-linked list.  Instantiate with "List<MyClass> myList".
 *
 * Objects added to the list are copied using the assignment operator,
 * so this must be defined.
 */
template<typename T> 
class List 
{
protected:
    /*
     * One element in the list.
     */
    class _Node {
    public:
        explicit _Node(const T& val) : mVal(val) {}
        ~_Node() {}
        inline T& getRef() { return mVal; }
        inline const T& getRef() const { return mVal; }
        inline _Node* getPrev() const { return mpPrev; }
        inline _Node* getNext() const { return mpNext; }
        inline void setVal(const T& val) { mVal = val; }
        inline void setPrev(_Node* ptr) { mpPrev = ptr; }
        inline void setNext(_Node* ptr) { mpNext = ptr; }
    private:
        friend class List;
        friend class _ListIterator;
        T           mVal;
        _Node*      mpPrev;
        _Node*      mpNext;
    };

    /*
     * Iterator for walking through the list.
     */
    
    template <typename TYPE>
    struct CONST_ITERATOR {
        typedef _Node const * NodePtr;
        typedef const TYPE Type;
    };
    
    template <typename TYPE>
    struct NON_CONST_ITERATOR {
        typedef _Node* NodePtr;
        typedef TYPE Type;
    };
    
    template<
        typename U,
        template <class> class Constness
    > 
    class _ListIterator {
        typedef _ListIterator<U, Constness>     _Iter;
        typedef typename Constness<U>::NodePtr  _NodePtr;
        typedef typename Constness<U>::Type     _Type;

        explicit _ListIterator(_NodePtr ptr) : mpNode(ptr) {}

    public:
        _ListIterator() {}
        _ListIterator(const _Iter& rhs) : mpNode(rhs.mpNode) {}
        ~_ListIterator() {}
        
        // this will handle conversions from iterator to const_iterator
        // (and also all convertible iterators)
        // Here, in this implementation, the iterators can be converted
        // if the nodes can be converted
        template<typename V> explicit 
        _ListIterator(const V& rhs) : mpNode(rhs.mpNode) {}
        

        /*
         * Dereference operator.  Used to get at the juicy insides.
         */
        _Type& operator*() const { return mpNode->getRef(); }
        _Type* operator->() const { return &(mpNode->getRef()); }

        /*
         * Iterator comparison.
         */
        inline bool operator==(const _Iter& right) const { 
            return mpNode == right.mpNode; }
        
        inline bool operator!=(const _Iter& right) const { 
            return mpNode != right.mpNode; }

        /*
         * handle comparisons between iterator and const_iterator
         */
        template<typename OTHER>
        inline bool operator==(const OTHER& right) const { 
            return mpNode == right.mpNode; }
        
        template<typename OTHER>
        inline bool operator!=(const OTHER& right) const { 
            return mpNode != right.mpNode; }

        /*
         * Incr/decr, used to move through the list.
         */
        inline _Iter& operator++() {     // pre-increment
            mpNode = mpNode->getNext();
            return *this;
        }
        const _Iter operator++(int) {    // post-increment
            _Iter tmp(*this);
            mpNode = mpNode->getNext();
            return tmp;
        }
        inline _Iter& operator--() {     // pre-increment
            mpNode = mpNode->getPrev();
            return *this;
        }
        const _Iter operator--(int) {   // post-increment
            _Iter tmp(*this);
            mpNode = mpNode->getPrev();
            return tmp;
        }

        inline _NodePtr getNode() const { return mpNode; }

        _NodePtr mpNode;    /* should be private, but older gcc fails */
    private:
        friend class List;
    };

public:
    List() {
        prep();
    }
    List(const List<T>& src) {      // copy-constructor
        prep();
        insert(begin(), src.begin(), src.end());
    }
    virtual ~List() {
        clear();
        delete[] (unsigned char*) mpMiddle;
    }

    typedef _ListIterator<T, NON_CONST_ITERATOR> iterator;
    typedef _ListIterator<T, CONST_ITERATOR> const_iterator;

    List<T>& operator=(const List<T>& right);

    /* returns true if the list is empty */
    inline bool empty() const { return mpMiddle->getNext() == mpMiddle; }

    /* return #of elements in list */
    size_t size() const {
        return size_t(distance(begin(), end()));
    }

    /*
     * Return the first element or one past the last element.  The
     * _Node* we're returning is converted to an "iterator" by a
     * constructor in _ListIterator.
     */
    inline iterator begin() { 
        return iterator(mpMiddle->getNext()); 
    }
    inline const_iterator begin() const { 
        return const_iterator(const_cast<_Node const*>(mpMiddle->getNext())); 
    }
    inline iterator end() { 
        return iterator(mpMiddle); 
    }
    inline const_iterator end() const { 
        return const_iterator(const_cast<_Node const*>(mpMiddle)); 
    }

    /* add the object to the head or tail of the list */
    void push_front(const T& val) { insert(begin(), val); }
    void push_back(const T& val) { insert(end(), val); }

    /* insert before the current node; returns iterator at new node */
    iterator insert(iterator posn, const T& val) 
    {
        _Node* newNode = new(std::nothrow) _Node(val);        // alloc & copy-construct
        newNode->setNext(posn.getNode());
        newNode->setPrev(posn.getNode()->getPrev());
        posn.getNode()->getPrev()->setNext(newNode);
        posn.getNode()->setPrev(newNode);
        return iterator(newNode);
    }

    /* insert a range of elements before the current node */
    void insert(iterator posn, const_iterator first, const_iterator last) {
        for ( ; first != last; ++first)
            insert(posn, *first);
    }

    /* remove one entry; returns iterator at next node */
    iterator erase(iterator posn) {
        _Node* pNext = posn.getNode()->getNext();
        _Node* pPrev = posn.getNode()->getPrev();
        pPrev->setNext(pNext);
        pNext->setPrev(pPrev);
        delete posn.getNode();
        return iterator(pNext);
    }

    /* remove a range of elements */
    iterator erase(iterator first, iterator last) {
        while (first != last)
            erase(first++);     // don't erase than incr later!
        return iterator(last);
    }

    /* remove all contents of the list */
    void clear() {
        _Node* pCurrent = mpMiddle->getNext();
        _Node* pNext;

        while (pCurrent != mpMiddle) {
            pNext = pCurrent->getNext();
            delete pCurrent;
            pCurrent = pNext;
        }
        mpMiddle->setPrev(mpMiddle);
        mpMiddle->setNext(mpMiddle);
    }

    /*
     * Measure the distance between two iterators.  On exist, "first"
     * will be equal to "last".  The iterators must refer to the same
     * list.
     *
     * FIXME: This is actually a generic iterator function. It should be a 
     * template function at the top-level with specializations for things like
     * vector<>, which can just do pointer math). Here we limit it to
     * _ListIterator of the same type but different constness.
     */
    template<
        typename U,
        template <class> class CL,
        template <class> class CR
    > 
    ptrdiff_t distance(
            _ListIterator<U, CL> first, _ListIterator<U, CR> last) const 
    {
        ptrdiff_t count = 0;
        while (first != last) {
            ++first;
            ++count;
        }
        return count;
    }

private:
    /*
     * I want a _Node but don't need it to hold valid data.  More
     * to the point, I don't want T's constructor to fire, since it
     * might have side-effects or require arguments.  So, we do this
     * slightly uncouth storage alloc.
     */
    void prep() {
        mpMiddle = (_Node*) new(std::nothrow) unsigned char[sizeof(_Node)];
        mpMiddle->setPrev(mpMiddle);
        mpMiddle->setNext(mpMiddle);
    }

    /*
     * This node plays the role of "pointer to head" and "pointer to tail".
     * It sits in the middle of a circular list of nodes.  The iterator
     * runs around the circle until it encounters this one.
     */
    _Node*      mpMiddle;
};

/*
 * Assignment operator.
 *
 * The simplest way to do this would be to clear out the target list and
 * fill it with the source.  However, we can speed things along by
 * re-using existing elements.
 */
template<class T>
List<T>& List<T>::operator=(const List<T>& right)
{
    if (this == &right)
        return *this;       // self-assignment
    iterator firstDst = begin();
    iterator lastDst = end();
    const_iterator firstSrc = right.begin();
    const_iterator lastSrc = right.end();
    while (firstSrc != lastSrc && firstDst != lastDst)
        *firstDst++ = *firstSrc++;
    if (firstSrc == lastSrc)        // ran out of elements in source?
        erase(firstDst, lastDst);   // yes, erase any extras
    else
        insert(lastDst, firstSrc, lastSrc);     // copy remaining over
    return *this;
}

}; // namespace android

#endif // _LIBS_UTILS_LIST_H
