
/* ------------------------------------------------------------------------- */

/*
 * Copyright (c) 1999
 *      GMRS Software GmbH, Innsbrucker Ring 159, 81669 Munich, Germany.
 *      http://www.gmrs.de
 *      All rights reserved.
 *      Author: Arno Unkrig (arno.unkrig@gmrs.de)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by GMRS Software GmbH.
 * 4. The name of GMRS Software GmbH may not be used to endorse or promote
 *    products derived from this software without specific prior written
 *    permission.
 *
 * THIS SOFTWARE IS PROVIDED BY GMRS SOFTWARE GMBH ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GMRS SOFTWARE GMBH BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

/* ------------------------------------------------------------------------- */

#ifndef __list_INCLUDED__ /* { */
#define __list_INCLUDED__

/* ------------------------------------------------------------------------- */

#ident "$Id: list,v 1.7 1999/10/26 10:57:33 arno Exp $"

#include <sys/types.h>       // For "size_t".

#ifdef BOOL_DEFINITION
BOOL_DEFINITION
#undef BOOL_DEFINITION
#endif

/* ------------------------------------------------------------------------- */

/*
 * This is a simplified, but otherwise correct implementation of the "list"
 * class as specified by the ANSI C++ library.
 *
 * Missing features:
 * (1) "list::Allocator" is missing ("list" uses "operator new()" instead).
 * (2) Several "unimportant" methods are not implemented (but they are
 *     "declared" in comments).
 */

/* ------------------------------------------------------------------------- */

template <class T>
class list {

private:
  struct Node {
    T    value;
    Node *prev;
    Node *next;

    Node(Node *p, Node *n) : prev(p), next(n) {}
    Node(const T &v, Node *p, Node *n) : value(v), prev(p), next(n) {}
  } root;

public:

  // Types

  class           iterator;
  class           const_iterator;
  class           reverse_iterator;
  class           const_reverse_iterator;
  typedef T       &reference;
  typedef const T &const_reference;
  typedef size_t  size_type;
//typedef         difference_type;
  typedef T       value_type;
//typedef         allocator_type;

  // Construct/Copy/Destroy

  list() : root(&root, &root) {}
//list(size_type);
//list(size_type, const T &);
//list(const_iterator, const_iterator);
  list(const list<T> &x) : root(&root, &root) {
    insert(begin(), x.begin(), x.end());
  }
  ~list() {
    Node *n, *nn;
    for (n = root.next; n != &root; n = nn) { nn = n->next; delete n; }
  }
  const list<T>  &operator=(const list<T> &x) {
    clear();
    insert(begin(), x.begin(), x.end());
    return *this;
  }
//void           assign(...);

//allocator_type get_allocator() const;

  // Iterators

  iterator begin()
  { return iterator(root.next); }
  const_iterator begin() const
  { return const_iterator(root.next); }
  iterator end()
  { return iterator(&root); }
  const_iterator end() const
  { return const_iterator(&root); }
  reverse_iterator rbegin()
  { return reverse_iterator(&root); }
  const_reverse_iterator rbegin() const
  { return const_reverse_iterator(&root); }
  reverse_iterator rend()
  { return reverse_iterator(root.next); }
  const_reverse_iterator rend() const
  { return const_reverse_iterator(root.next); }

  // Capacity

  bool      empty() const { return root.next == &root; }
  size_type size() const {
    size_type res = 0;
    for (const Node *n = root.next; n != &root; n = n->next) res++;
    return res;
  }
//size_type max_size() const;
//void      resize(...);

  // Element access

  reference       front()       { return root.next->value; }
  const_reference front() const { return root.next->value; }
  reference       back()        { return root.prev->value; }
  const_reference back() const  { return root.prev->value; }

  // Modifiers

  void push_front(const T &x) {
    Node *n = new Node(x, &root, root.next);
    root.next->prev = n;
    root.next = n;
  }
  void pop_front() {
    Node *f = root.next;
    if (f != &root) { f->next->prev = &root; root.next = f->next; delete f; }
  }
  void push_back(const T &x) {
    Node *n = new Node(x, root.prev, &root);
    root.prev->next = n;
    root.prev = n;
  }
  void pop_back() {
    Node *f = root.prev;
    if (f != &root) { f->prev->next = &root; root.prev = f->prev; delete f; }
  }

  iterator insert(iterator pos) {
    Node *n = new Node(pos.node->prev, pos.node);
    pos.node->prev->next = n;
    pos.node->prev       = n;
    return iterator(n);
  }
  iterator insert(iterator pos, const T &value) {
    Node *n = new Node(value, pos.node->prev, pos.node);
    pos.node->prev->next = n;
    pos.node->prev       = n;
    return iterator(n);
  }
//void insert(iterator, size_type, const T&);
  void insert(iterator pos, const_iterator from, const_iterator to) {
    while (from != to) { insert(pos, *from); ++from; }
  }

//iterator erase(iterator);
//iterator erase(iterator, iterator);
//void     swap(list<T> &);
  void     clear() {
    Node *n, *nn;
    for (n = root.next; n != &root; n = nn) { nn = n->next; delete n; }
    root.prev = root.next = &root;
  }

  // Special mutative operations on list

  void splice(iterator pos, list<T> &x) {
    Node *n, *nn;
    for (n = x.root.next; n != &x.root; n = nn) {
      nn = n->next;
      pos.node->prev->next = n;
      n->prev = pos.node->prev;
      n->next = pos.node;
      pos.node->prev = n;
    }
    x.root.prev = x.root.next = &x.root;
  }
  void splice(iterator pos1, list<T> & /*x*/ , iterator pos2) {
    pos1.node->prev->next = pos2.node;
    pos2.node->prev->next = pos2.node->next;
    pos2.node->next->prev = pos2.node->prev;
    pos2.node->prev = pos1.node->prev;
    pos2.node->next = pos1.node;
    pos1.node->prev = pos2.node;
  }
  void splice(iterator pos1, list<T> & /*x*/ , iterator pos2, iterator pos3) {
    pos1.node->prev->next = pos2.node;
    pos2.node->prev->next = pos3.node;
    pos3.node->prev->next = pos1.node;
    Node *tmp = pos2.node->prev;
    pos2.node->prev = pos1.node->prev;
    pos1.node->prev = pos3.node->prev;
    pos3.node->prev = tmp;
  }

//void remove(const T &);
//void remove_is(Predicate);
//void unique();
//void unique(BinaryPredicate);
//void merge(list<T> &);
//void merge(list<T> &, Compare);

//void sort();
//void sort(Compare);
//void reverse();

  class iterator {

  public:
    iterator() : node((Node *) 0xa3a3a3a3) {}

    iterator operator++() { return node = node->next; }       // Prefix ++
    iterator operator--() { return node = node->prev; }       // Prefix --
    iterator operator++(int)                                  // Postfix ++
	  { iterator i(node); node = node->next; return i; }
    iterator operator--(int)                                  // Postfix --
	  { iterator i(node); node = node->prev; return i; }
    T &operator*() const { return node->value; }
    bool operator==(const iterator x) { return node == x.node; }
    bool operator!=(const iterator x) { return node != x.node; }

  protected:
    iterator(Node *n) : node(n) {}
    Node *node;
    friend list<T>;
  };

  class const_iterator {

  public:
    const_iterator() : node((Node *) 0xa3a3a3a3) {}
    // Can convert "iterator" to "const_iterator", but not the other way round.
    const_iterator(iterator x) : node(x.node) {}

    const_iterator operator++() { return node = node->next; } // Prefix ++
    const_iterator operator--() { return node = node->prev; } // Prefix --
    const_iterator operator++(int)                            // Postfix ++
	  { const_iterator i(node); node = node->next; return i; }
    const_iterator operator--(int)                            // Postfix --
	  { const_iterator i(node); node = node->prev; return i; }
    const T &operator*() const { return node->value; }
    bool operator==(const const_iterator x) { return node == x.node; }
    bool operator!=(const const_iterator x) { return node != x.node; }

  protected:
    const_iterator(const Node *n) : node(n) {}
    const Node *node;
    friend list<T>;
  };

  class reverse_iterator : public iterator {

  public:
    reverse_iterator() {}
    reverse_iterator(const iterator &x) : iterator(x) {}

    iterator operator++()    { return iterator::operator--();  } // Prefix ++
    iterator operator--()    { return iterator::operator++();  } // Prefix --
    iterator operator++(int) { return iterator::operator--(0); } // Postfix ++
    iterator operator--(int) { return iterator::operator++(0); } // Postfix --
    T &operator*() const { return node->prev->value; }

  protected:
    reverse_iterator(Node *n) : iterator(n) {}

  private:
    friend list<T>;
  };

  class const_reverse_iterator : public const_iterator {

  public:
    const_reverse_iterator() {}
    const_reverse_iterator(const const_iterator &x) : const_iterator(x) {}

    const_iterator operator++()                               // Prefix ++
            { return const_iterator::operator--(); }
    const_iterator operator--()                               // Prefix --
            { return const_iterator::operator++(); }
    const_iterator operator++(int)                            // Postfix ++
            { return const_iterator::operator--(0); }
    const_iterator operator--(int)                            // Postfix --
            { return const_iterator::operator++(0); }
    const T &operator*() const { return node->prev->value; }

  protected:
    const_reverse_iterator(const Node *n) : const_iterator(n) {}

  private:
    friend list<T>;
  };
};

/* ------------------------------------------------------------------------- */

#endif /* } */

/* ------------------------------------------------------------------------- */

