Program Listing for File DoublyLinkedList.h

Program Listing for File DoublyLinkedList.h#

↰ Return to documentation for file (src/util/support/DoublyLinkedList.h)

#ifndef DOUBLYLINKEDLIST_H
#define DOUBLYLINKEDLIST_H

#include <stdlib.h>
#include <assert.h>
#include <FunctionObject.h>
#include <iostream>

template <class T> class DoublyLinkedListWrap;

template <class T>
class DoublyLinkedEntryWrap
{
   T *o;
   DoublyLinkedEntryWrap<T>* next, *prev;
 public:
   DoublyLinkedEntryWrap<T>() : o(0), next(0), prev(0) {}
   DoublyLinkedEntryWrap( const T& _o) : o(new T(_o)), next(0), prev(0) {}
   DoublyLinkedEntryWrap& operator = ( const T& _o)
         {
           if (o == 0)
              o = new T(_o);
           else
              *o = _o;
           return *this;
         }
   ~DoublyLinkedEntryWrap() { if (o != 0) delete o; }
   T& GetEntry() { return *o; }
 friend class DoublyLinkedListWrap<T>;
};

template <class T>
class DoublyLinkedListWrap
{
   DoublyLinkedEntryWrap<T> head;
   unsigned count;
 public:
   void LinkBefore( DoublyLinkedEntryWrap<T> *e, DoublyLinkedEntryWrap<T>* pos)
     {
       assert(e->prev == 0 && e->next == 0 && e->o != 0);
       ++count;
       e->next = pos;
       e->prev = pos->prev;
       pos->prev->next = e;
       pos->prev = e;
     }
   void LinkAfter( DoublyLinkedEntryWrap<T> *e, DoublyLinkedEntryWrap<T>* pos)
     {
       assert(e->prev == 0 && e->next == 0 && e->o != 0);
       ++count;
       e->prev = pos;
       e->next = pos->next;
       pos->next->prev = e;
       pos->next = e;
     }
    void Unlink( DoublyLinkedEntryWrap<T>* e)
     {
       --count;
       if (e->prev != 0)
           e->prev->next = e->next;
       if (e->next != 0)
          e->next->prev = e->prev;
       e->prev = e->next = 0;
     }
    DoublyLinkedListWrap() : count(0)
         { head.prev = head.next = &head; }
    DoublyLinkedListWrap(const DoublyLinkedListWrap<T> & that)
      : count(0)
    {
      head.prev = head.next = &head;
      for (iterator iter(that); !iter.ReachEnd(); iter++) {
         T &c = iter.Current();
         AppendLast(c);
      }
    }
    void operator = (const DoublyLinkedListWrap<T> & that)
     {
      DeleteAll();
      for (const_iterator iter(that); !iter.ReachEnd(); iter++) {
         const T &c = iter.Current();
         AppendLast(c);
      }
     }
    ~DoublyLinkedListWrap() { DeleteAll(); }

    DoublyLinkedEntryWrap<T>* InsertBefore( const T& o , DoublyLinkedEntryWrap<T>* pos)
     {
       DoublyLinkedEntryWrap<T> *e = new DoublyLinkedEntryWrap<T>( o );
       LinkBefore(e, pos);
       return e;
     }
    DoublyLinkedEntryWrap<T>* InsertAfter( const T& o , DoublyLinkedEntryWrap<T>* pos)
     {
       DoublyLinkedEntryWrap<T> *e = new DoublyLinkedEntryWrap<T>( o );
       LinkAfter(e, pos);
       return e;
     }
    DoublyLinkedEntryWrap<T>* AppendLast( const T& o )
     {
       DoublyLinkedEntryWrap<T> *e = new DoublyLinkedEntryWrap<T>( o );
       LinkAfter(e, head.prev);
       return e;
     }
    DoublyLinkedEntryWrap<T>* PushFirst( const T& o )
     {
       DoublyLinkedEntryWrap<T> *e = new DoublyLinkedEntryWrap<T>( o );
       LinkBefore(e, head.next);
       return e;
     }
    void push_front(const T& o) { PushFirst(o); }

    void Sort( MapObject<T, int>& f)
     {
       DoublyLinkedEntryWrap<T> **buf = new DoublyLinkedEntryWrap<T>*[count];
       for (size_t i = 0; i < count; ++i)
            buf[i] = 0;
       for (DoublyLinkedEntryWrap<T> *p = First(); p; p = Next(p)) {
           unsigned index = f(p->GetEntry());
           while (index < count && buf[index] != 0)
               ++index;
           assert( index < count);
           buf[index] = p;
       }
       DoublyLinkedEntryWrap<T> *cur = buf[count-1];
       for ( int j = count-2; j >= 0; --j) {
          Unlink(buf[j]);
          LinkBefore( buf[j], cur);
          cur = buf[j];
       }
       delete [] buf;
     }

    void Sort( CompareObject<T> & f)
     { bool done = false;
       DoublyLinkedEntryWrap<T> *h = head.next;
       while (!done) {
         done = true;
         DoublyLinkedEntryWrap<T> *p = head.prev, *p1 = p->prev;
         while (p != h) {
           if ( f (p->GetEntry(), p1->GetEntry()) < 0 ) {
              Unlink(p);
              LinkBefore(p, p1);
              done = false;
              if (p1 == h)
                 break;
           }
           else
              p = p1;
           p1 = p->prev;
         }
         h = p->next;
       }
     }

    void Delete( DoublyLinkedEntryWrap<T>* e)
     {
       Unlink(e);
       delete e;
     }
    void DeleteAll()
    {
       while (count)
           Delete(head.next);
    }
    void clear() { DeleteAll(); }

    unsigned NumberOfEntries() const { return count; }
    unsigned size() const { return count; }
    DoublyLinkedEntryWrap<T>* First() const
          {
            DoublyLinkedEntryWrap<T>* r = (count == 0)? 0 : head.next;
            assert( r == 0 || r->o != 0);
            return r;
          }
    T& front() const { return First()->GetEntry(); }
    DoublyLinkedEntryWrap<T>* Last() const
          {
            DoublyLinkedEntryWrap<T>* r = (count == 0)? 0 : head.prev;
            assert( r == 0 || r->o != 0); return r;
          }
    T& back() const { return Last()->GetEntry(); }

    DoublyLinkedEntryWrap<T>* Next(const DoublyLinkedEntryWrap<T>* cur) const
          {
            DoublyLinkedEntryWrap<T>* r = (cur == head.prev)? 0 : cur->next;
            assert( r == 0 || r->o != 0); return r;
          }
    DoublyLinkedEntryWrap<T>* Prev(DoublyLinkedEntryWrap<T>* cur) const
          { DoublyLinkedEntryWrap<T>* r = (cur == head.next)? 0 : cur->prev;
            assert( r == 0 || r->o != 0); return r;
          }

    void Reverse()
     {  if (count == 0)
              return;
        DoublyLinkedEntryWrap<T>* tmp = &head, *tmp1 = tmp->next;
        head.next = head.prev;
        head.prev = tmp1;
        while (tmp != head.next) {
          DoublyLinkedEntryWrap<T>* tmp2 = tmp;
          tmp = tmp1;
          tmp1 = tmp1->next;
          tmp->next = tmp2;
          tmp->prev = tmp1;
        }
     }
    void reverse() { Reverse(); }

    class Iterator
    {
      const DoublyLinkedListWrap<T> *list;
      DoublyLinkedEntryWrap<T> *cur;
     public:
      Iterator(const DoublyLinkedListWrap<T> &l)
          : list(&l) { cur = l.First(); }
      Iterator(const DoublyLinkedListWrap<T> &l, DoublyLinkedEntryWrap<T>* c)
          : list(&l), cur(c) {}
      bool operator == (const Iterator& that) const
            { return list == that.list && cur == that.cur; }
      bool operator != (const Iterator& that) const
             { return !operator ==(that); }
      Iterator(const Iterator& that) : list(that.list), cur(that.cur) {}
      Iterator() : list(0), cur(0) {}
      DoublyLinkedEntryWrap<T>* CurrentPtr() const { return cur; }
      bool ReachEnd() const
        { return cur == 0; }
      void Reset() { if (list != 0) cur = list->First(); }
      void Advance() { if (cur != 0) cur = list->Next(cur); }
      void operator++() { Advance(); }
      void operator ++(int) { Advance(); }
    };
    class const_iterator : public Iterator
    { public:
      using Iterator::CurrentPtr;
      const_iterator(const Iterator& that) : Iterator(that) {}
      const_iterator() : Iterator() {}
      const_iterator(const DoublyLinkedListWrap<T> &l) : Iterator(l) {}
      const_iterator(const DoublyLinkedListWrap<T> &l,
                    DoublyLinkedEntryWrap<T>* c) : Iterator(l,c) {}
      bool operator == (const const_iterator& that) const
            { return Iterator::operator==(that); }
      bool operator != (const const_iterator& that) const
             { return !operator ==(that); }
      const T& Current() const { return CurrentPtr()->GetEntry(); }
      const T& operator *() const { return Current(); }
    };
    class iterator : public Iterator
    { public:
      using Iterator::CurrentPtr;
      iterator(const Iterator& that) : Iterator(that) {}
      iterator() : Iterator() {}
      iterator(const DoublyLinkedListWrap<T> &l) : Iterator(l) {}
      iterator(const DoublyLinkedListWrap<T> &l,
                    DoublyLinkedEntryWrap<T>* c) : Iterator(l,c) {}
      bool operator == (const iterator& that) const
            { return Iterator::operator==(that); }
      bool operator != (const iterator& that) const
             { return !operator ==(that); }
      T& Current() const { return CurrentPtr()->GetEntry(); }
      T& operator *() const { return Current(); }
    };

    const_iterator begin() const { return Iterator(*this); }
    const_iterator end() const { return Iterator(*this, 0); }
    iterator begin() { return Iterator(*this); }
    iterator end() { return Iterator(*this, 0); }

    void erase( iterator& p) { Delete(p.CurrentPtr()); }
    void push_back( const T& o ) { AppendLast(o); }
};

template <class T>
void writeList( const DoublyLinkedListWrap<T>& list, std::ostream& out)
{ for ( typename DoublyLinkedListWrap<T>::Iterator iter(list); !iter.ReachEnd();
       iter.Advance())
     iter.Current().write(out);
}

template <class T>
class CollectDoublyLinkedList : public CollectObject<T>
{
  DoublyLinkedListWrap<T>& res;
 public:
  CollectDoublyLinkedList(DoublyLinkedListWrap<T>& r) : res(r) {}
  bool operator()(const T& cur)
   {
      res.AppendLast(cur);
      return true;
   }
};

#endif