/*

          Alternative CONTAINER template library
Copyright (C) Andrey V. Stolyarov <croco@croco.net> 1997,98,99

First compiled with Borland C++ 4.52, Mar 1997
Ported to GNU C++ (g++) / Linux       Feb 1999

*/


#ifndef _A_LIST_HPP_
#define _A_LIST_HPP_


#ifndef NULL
#define NULL 0
#endif

////////////////////////////////////////////////////////////////////////////////
// "List Of Nothing" - the only use of this class is to derive some
// real lists from it.
class TAbstractList {

  public:

    class AbstractElem {
        friend class TAbstractList;
        AbstractElem *Prev, *Next;
//      protected:
      public:
        AbstractElem() { Prev = Next = NULL; }
        virtual ~AbstractElem() {}
        AbstractElem* operator +(int i)
        {
          if (i==0) return this;
          AbstractElem *el = this;
          if (i>0) {
            for (int j = 0; j < i && el; j++, el = el -> Next);
          } else {
            for (int j = 0; j > i && el; j--, el = el -> Prev);
          }
          return el;
        }
        AbstractElem* operator -(int i)
        {
          return operator +(-i);
        }
    };

    private:
        AbstractElem *First, *Last;
    public:

    TAbstractList()
    {
       First = Last = NULL;
    }
    void Clear()
    {
       while(First)
       {
          AbstractElem *p = First;
          UnlinkElem(First);
          delete p;
       }
    }
    void UnlinkElem( AbstractElem *el )
    {
       if ( el->Prev ) {
         el->Prev->Next = el->Next;
       } else {
         First = el->Next;
       }
       if ( el->Next ) {
         el->Next->Prev = el->Prev;
       } else {
         Last = el->Prev;
       }
    }
    void LinkElemToBegin( AbstractElem *el )
    {
       el->Prev = NULL;
       el->Next = First;
       if (First)
         First->Prev = el;
       else
         Last = el;
       First = el;
    }
    void LinkElemToEnd( AbstractElem *el )
    {
       el->Next = NULL;
       el->Prev = Last;
       if (Last)
         Last->Next=el;
       else
         First = el;
       Last = el;
    }
    void LinkElemBefore( AbstractElem *el, AbstractElem *newEl )
    {
       if (!el->Prev) {
         LinkElemToBegin(newEl);
       } else {
         newEl->Prev = el->Prev;
         newEl->Next = el;
         el->Prev->Next = newEl;
         el->Prev = newEl;
       }
    }
    void LinkElemAfter( AbstractElem *el, AbstractElem *newEl )
    {
       if (!el->Next) {
         LinkElemToEnd(newEl);
       } else {
         newEl->Next = el->Next;
         newEl->Prev = el;
         el->Next->Prev = newEl;
         el->Next = newEl;
       }
    }
    int MoveElemForward( AbstractElem *el ) {
       if (!el->Next) {
         return 0;
       } else {
         AbstractElem *el2 = el->Next;
         UnlinkElem(el);
         LinkElemAfter(el2, el);
         return 1;
       }
    }
    int MoveElemBackward( AbstractElem *el ) {
       if (!el->Prev) {
         return 0;
       } else {
         AbstractElem *el2 = el->Prev;
         UnlinkElem(el);
         LinkElemBefore(el2, el);
         return 1;
       }
    }
    void MoveElemToBegin( AbstractElem *el ) {
       UnlinkElem(el);
       LinkElemToBegin(el);
    }
    void MoveElemToEnd( AbstractElem *el ) {
       UnlinkElem(el);
       LinkElemToEnd(el);
    }
    AbstractElem *GetFirst() { return First; }
    AbstractElem *GetLast() { return Last; }
    ~TAbstractList()
    {
       Clear();
    }
};

////////////////////////////////////////////////////////////////////////////////
// Direct list. Useful for classes for which it's no loose to copy them.
// For example, it's very good idea to use this particular template with
// int, long, float, char etc.
// Objects are stored directly in Elements of the list, so actually they are
// copies of objects you passed to the methods of the class. This requires T
// to have a COPY CONSTRUCTOR.
template <class T>
class BiList : protected TAbstractList
{
  public:

    class ElemPtr;

  protected:

    class Elem : public AbstractElem {
        friend class BiList<T>;
        friend class ElemPtr;
      public:
        T data;
        operator T&() { return data; }
        Elem* operator +(int i) {
          return (Elem*)((*(AbstractElem*)this)+i);
        }
        Elem* operator -(int i) {
          return (Elem*)((*(AbstractElem*)this)-i);
        }
      protected:
        Elem(T &t) : data(t) {}
        virtual ~Elem() {}
    };

    Elem *GetFirstElem() {
       return (Elem*)TAbstractList::GetFirst();
    }
    Elem *GetLastElem() {
       return (Elem*)TAbstractList::GetLast();
    }

  public:

    class ElemPtr {
        friend class BiList<T>;
        Elem *p;
        ElemPtr(Elem *e) { p = e; }
      protected:
        Elem* GetP() { return p; }
      public:
        ElemPtr() { p = NULL; }
        ElemPtr(const ElemPtr &e2) { p = e2.p; }
        ~ElemPtr() {}

        ElemPtr  operator ++()            // Preincrement
               { p = p ? (*p)+1 : 0; return *this; }
        ElemPtr  operator --()            // Predecrement
               { p = p ? (*p)-1 : 0; return *this; }
        ElemPtr  operator ++(int)         // Postincrement
               { Elem *p2 = p; p = p ? (*p)+1 : 0; return ElemPtr(p2); }
        ElemPtr  operator --(int)         // Postdecrement
               { Elem *p2 = p; p = p ? (*p)-1 : 0; return ElemPtr(p2); }
        ElemPtr  operator +(int i) { return ElemPtr((*p)+i); }
        ElemPtr  operator -(int i) { return ElemPtr((*p)-i); }
        operator T* () { return p ? &(p->data) : NULL; }
    };


  public:

    BiList() : TAbstractList() {}
    ~BiList() { Clear(); }
    ElemPtr AddToBegin( T &t ) {
              Elem *el = new Elem(t);
              LinkElemToBegin(el);
              return ElemPtr(el);
            }
    ElemPtr AddToEnd( T &t ){
              Elem *el = new Elem(t);
              LinkElemToEnd(el);
              return ElemPtr(el);
            }
    ElemPtr InsertBefore( ElemPtr &elp, T &t) {
              Elem *el = elp.GetP();
              Elem *nel = new Elem(t);
              LinkElemBefore(el, nel);
              return ElemPtr(nel);
            }
    ElemPtr InsertAfter( ElemPtr &elp, T &t){
              Elem *el = elp.GetP();
              Elem *nel = new Elem(t);
              LinkElemAfter(el,nel);
              return ElemPtr(nel);
            }
    ElemPtr GetFirst() {
            return ElemPtr(GetFirstElem());
         }
    ElemPtr GetLast() {
            return ElemPtr(GetLastElem());
         }
    void Remove( ElemPtr &elp ) {
           Elem *el = elp.GetP();
           UnlinkElem(el);
           delete el;
         }
    void PlaceToBegin( ElemPtr &elp ) {
           Elem *el = elp.GetP();
           MoveElemToBegin(el);
         }
    void PlaceToEnd( ElemPtr &elp ) {
           Elem *el = elp.GetP();
           MoveElemToEnd(el);
         }
    void Clear() {
           TAbstractList::Clear();
         }
    int IsEmpty() { return GetFirstElem() == NULL; }
    int ElemCount() {
           int c = 0;
           ElemPtr p(GetFirstElem());
           while (p) { c++; p++; }
           return c;
         }
};


#define BILIST_FOREACH(bclass,list,itname)\
   for (BiList<bclass>::ElemPtr itname = list->GetFirst(); itname; itname++)


////////////////////////////////////////////////////////////////////////////////
// This template assumes that T is a (small?) structure or class or unit.
// The only difference from previous class is that there is operator->()
// for ElemPtr which makes it more like a real pointer to an object of T
template <class T>
class StrBiList : public BiList<T> {
  public:
  class ElemPtr : public BiList<T>::ElemPtr {
    public:
    ElemPtr(typename BiList<T>::ElemPtr &e) : BiList<T>::ElemPtr(e){}
    T* operator->() { return BiList<T>::ElemPtr::operator T*(); }
  };
  ElemPtr AddToBegin( T &t ) {
             return (ElemPtr)BiList<T>::AddToBegin(t);
          }
  ElemPtr AddToEnd( T &t ) {
             return (ElemPtr)BiList<T>::AddToEnd(t);
          }
  ElemPtr InsertBefore( ElemPtr &elp, T &t) {
             return (ElemPtr)BiList<T>::InsertBefore(elp,t);
          }
  ElemPtr InsertAfter( ElemPtr &elp, T &t) {
             return (ElemPtr)BiList<T>::InsertAfter(elp,t);
          }
  ElemPtr GetFirst() {
             return (ElemPtr)BiList<T>::GetFirst();
          }
  ElemPtr GetLast() {
             return (ElemPtr)BiList<T>::GetLast();
          }


};

#define STRBILIST_FOREACH(bclass,list,itname)\
   for (StrBiList<bclass>::ElemPtr itname = list->GetFirst(); itname; itname++)

////////////////////////////////////////////////////////////////////////////////
// This class is "Indirect" double-linked list. We assume that it's elements
// are classes or structures (please no arrays ;-) to define operator->() to
// access them.

template <class T>
class IndBiList : protected TAbstractList
{
  public:

    class ElemPtr;

  protected:

    class Elem : public AbstractElem {
        friend class IndBiList<T>;
        friend class ElemPtr;
        char Owner;
      public:
        T *data;
        operator T*() { return data; }
        Elem* operator +(int i) {
          return (Elem*)((*(AbstractElem*)this)+i);
        }
        Elem* operator -(int i) {
          return (Elem*)((*(AbstractElem*)this)-i);
        }
      protected:
        Elem(T *t, char own = 1) { data = t; Owner = own; }
        virtual ~Elem() { if (Owner) delete data; }
    };

    Elem *GetFirstElem() {
       return (Elem*)TAbstractList::GetFirst();
    }
    Elem *GetLastElem() {
       return (Elem*)TAbstractList::GetLast();
    }

  public:

    class ElemPtr {
        friend class IndBiList<T>;
        Elem *p;
        ElemPtr(Elem *e) { p = e; }
      protected:
        Elem* GetP() { return p; }
      public:
        ElemPtr() { p = NULL; }
        ElemPtr(const ElemPtr &e2) { p = e2.p; }
        ~ElemPtr() {}

        ElemPtr  operator ++()            // Preincrement
               { p = p ? (*p)+1 : 0; return *this; }
        ElemPtr  operator --()            // Predecrement
               { p = p ? (*p)-1 : 0; return *this; }
        ElemPtr  operator ++(int)         // Postincrement
               { Elem *p2 = p; p = p ? (*p)+1 : 0; return ElemPtr(p2); }
        ElemPtr  operator --(int)         // Postdecrement
               { Elem *p2 = p; p = p ? (*p)-1 : 0; return ElemPtr(p2); }
        ElemPtr  operator +(int i) { return ElemPtr((*p)+i); }
        ElemPtr  operator -(int i) { return ElemPtr((*p)-i); }
	T* operator -> () const { return p ? (T*) p->data : (T*) NULL; }
	operator T* () const { return operator ->(); }
//        operator T* () const { return p ? (T*) p->data : (T*) NULL; }
//        T* operator -> () const { return (operator T*()); }
    };


  public:

    IndBiList() : TAbstractList() {}
    ~IndBiList() { Clear(); }
    ElemPtr AddToBegin( T *t, char own=1 ) {
              Elem *el = new Elem(t,own);
              LinkElemToBegin(el);
              return ElemPtr(el);
            }
    ElemPtr AddToEnd( T *t, char own=1 ){
              Elem *el = new Elem(t,own);
              LinkElemToEnd(el);
              return ElemPtr(el);
            }
    ElemPtr InsertBefore( ElemPtr &elp, T *t, char own=1 ) {
              Elem *el = elp.GetP();
              Elem *nel = new Elem(t,own);
              LinkElemBefore(el, nel);
              return ElemPtr(nel);
            }
    ElemPtr InsertAfter( ElemPtr &elp, T *t, char own=1 ){
              Elem *el = elp.GetP();
              Elem *nel = new Elem(t,own);
              LinkElemAfter(el,nel);
              return ElemPtr(nel);
            }
    ElemPtr AddToBegin( T &t ) {
              return AddToBegin(&t,0);
            }
    ElemPtr AddToEnd( T &t ) {
              return AddToEnd(&t,0);
            }
    ElemPtr InsertBefore( ElemPtr &elp, T &t ) {
              return InsertBefore(elp, &t, 0);
            }
    ElemPtr InsertAfter( ElemPtr &elp, T &t ) {
              return InsertAfter(elp, &t, 0);
            }
    ElemPtr GetFirst() {
            return ElemPtr(GetFirstElem());
         }
    ElemPtr GetLast() {
            return ElemPtr(GetLastElem());
         }
    void Remove( ElemPtr &elp ) {
           Elem *el = elp.GetP();
           UnlinkElem(el);
           delete el;
         }
    void PlaceToBegin( ElemPtr &elp ) {
           Elem *el = elp.GetP();
           MoveElemToBegin(el);
         }
    void PlaceToEnd( ElemPtr &elp ) {
           Elem *el = elp.GetP();
           MoveElemToEnd(el);
         }
    void Clear() {
           TAbstractList::Clear();
         }
    int IsEmpty() { return GetFirstElem() == NULL; }
    int ElemCount() {
           int c = 0;
           ElemPtr p(GetFirstElem());
           while (p) { c++; p++; }
           return c;
         }
};


#define INDBILIST_FOREACH(bclass,list,itname)\
   for (IndBiList<bclass>::ElemPtr itname = list.GetFirst(); itname; itname++)


#endif // sentry


syntax highlighted by Code2HTML, v. 0.9.1