// ----------------------------------------------------------------------------
//
// Copyright (C) Columbia University, 1994. All Rights Reserved.
// Sameer A. Nene, Shree K. Nayar, Hiroshi Murase
//
// See file LICENSE for details of software license agreement.
//
// ----------------------------------------------------------------------------
//
// list.C
//
// Author:               Sameer Nene
// Date:                 05/24/94
// Version:              1.0
// Modification History:
// Bugs:
//
// Classes:
//   Link
//   List
//   ListIter
//   ListManip
//
// Notes:
//   This module contains implementation of classes declared in list.h
//   
// ----------------------------------------------------------------------------

#ifdef __GNUC__

#pragma implementation

#endif

#include <iostream.h>
#include "list.h"

template<class Type> Link<Type>::Link(Link<Type> **addLinkPtr, const Type &data) : d_next_p(*addLinkPtr), d_data(data)
{
  *addLinkPtr = this;
}

template<class Type> void Link<Type>::setData(const Type &data)
{
  d_data = data;
}

template<class Type> void Link<Type>::setNext(Link<Type> *link)
{
  d_next_p = link;
}

template<class Type> Link<Type>*& Link<Type>::getNextRef()
{
  return d_next_p;
}

template<class Type> Type Link<Type>::getData() const
{
  return d_data;
}

template<class Type> Link<Type>* Link<Type>::getNext() const
{
  return d_next_p;
}

template<class Type> List<Type>::List() : d_head_p(0), d_length(0)
{
}

template<class Type> List<Type>::List(const List<Type>& list) : d_head_p(0)
{
  ListManip<Type> m(this);
  ListIter<Type> l(list);

  while(l) {
    m.insert(l());
    ++l;
    ++m;
  }
}

template<class Type> List<Type>::~List()
{
  ListManip<Type> m(this);

  while(m)
    m.remove();
}

template<class Type> List<Type>& List<Type>::operator=(const List<Type>& list)
{
  ListManip<Type> m(this);
  ListIter<Type> l(list);

  if(this != &list) {
    while(m)
      m.remove();
    while(l) {
      m.insert(l());
      ++l;
      ++m;
    }
  }
  return *this;
}

template<class Type> List<Type>& List<Type>::operator+=(const Type &i)
{
  ListManip<Type> m(this);

  while(m)
    ++m;
  m.insert(i);
  return *this;
}

template<class Type> List<Type>& List<Type>::operator+=(const List<Type>& list)
{
  unsigned i, s;
  ListIter<Type> l(list);
  ListManip<Type> m(this);
  
  while(m)
    ++m;
  s = list.d_length;
  for(i = 0; i < s; ++i) {
    m.insert(l());
    ++m;
    ++l;
  }
  return *this;
}

template<class Type> List<Type>& List<Type>::prepend(const Type &i)
{
  ListManip<Type> m(this);

  m.insert(i);
  return *this;
}

template<class Type> List<Type>& List<Type>::prepend(const List<Type> &list)
{
  ListIter<Type> l(list);
  ListManip<Type> m(this);

  while(l) {
    m.insert(l());
    ++m;
    ++l;
  }
  return *this;
}

template<class Type> int List<Type>::length() const
{
  return d_length;
}

template<class Type> ostream& operator<<(ostream &o, const List<Type>& list)
{
  ListIter<Type> l(list);

  o << "[ ";
  while(l) {
    o << l();
    o << " ";
    ++l;
  }
  return o << "]";
}

template<class Type> ListIter<Type>::ListIter(const List<Type> &list) : d_current_p(list.d_head_p)
{
}

template<class Type> ListIter<Type>::ListIter(const ListIter<Type> &iter) : d_current_p(iter.d_current_p)
{
}

template<class Type> ListIter<Type>& ListIter<Type>::operator=(const ListIter<Type> &iter)
{
  d_current_p = iter.d_current_p;
  return *this;
}

template<class Type> void ListIter<Type>::operator++()
{
  d_current_p = d_current_p -> getNext();
}

template<class Type> Type ListIter<Type>::operator()() const
{
  return d_current_p -> getData();
}

template<class Type> ListIter<Type>::operator const void* () const
{
  return (d_current_p == 0) ? 0 : this;
}

template<class Type> ListManip<Type>::ListManip(List<Type> *list) : d_current_p(&(list -> d_head_p)), d_list_p(list)
{
}

template<class Type> void ListManip<Type>::operator++()
{
  d_current_p = &((*d_current_p) -> getNextRef());
}

template<class Type> void ListManip<Type>::insert(const Type &data)
{
  new Link<Type>(d_current_p, data);
  ++(d_list_p -> d_length);
}

template<class Type> void ListManip<Type>::remove()
{
  Link<Type> *t = *d_current_p;

  *d_current_p = (*d_current_p) -> getNext();
  delete t;
  --(d_list_p -> d_length);
}

template<class Type> ListManip<Type>::operator const void* () const
{
  return (*d_current_p == 0) ? 0 : this;
}

template<class Type> Type ListManip<Type>::operator()() const
{
  return (*d_current_p) -> getData();
}

#ifdef __DECCXX // Instantiate Templates for DEC C++

class NamedDataSet;
class NamedInterpolation;
class VectAry;
class FileInfo;

#pragma define_template Link<char*>
#pragma define_template Link<NamedDataSet*>
#pragma define_template Link<NamedInterpolation*>
#pragma define_template Link<VectAry*>
#pragma define_template Link<FileInfo*>

#pragma define_template List<char*>
#pragma define_template List<NamedDataSet*>
#pragma define_template List<NamedInterpolation*>
#pragma define_template List<VectAry*>
#pragma define_template List<FileInfo*>

#pragma define_template ListIter<char*>
#pragma define_template ListIter<NamedDataSet*>
#pragma define_template ListIter<NamedInterpolation*>
#pragma define_template ListIter<VectAry*>
#pragma define_template ListIter<FileInfo*>

#pragma define_template ListManip<char*>
#pragma define_template ListManip<NamedDataSet*>
#pragma define_template ListManip<NamedInterpolation*>
#pragma define_template ListManip<VectAry*>
#pragma define_template ListManip<FileInfo*>

#endif

#ifdef __GNUC__ // Instantiate Templates for gnu c++

class NamedDataSet;
class NamedInterpolation;
class VectAry;
class FileInfo;

typedef Link<char*> LinkCharP;
typedef Link<NamedDataSet*> LinkNamedDataSetP;
typedef Link<NamedInterpolation*> LinkNamedInterpolationP;
typedef Link<VectAry*> LinkVectAryP;
typedef Link<FileInfo*> LinkFileInfoP;

typedef List<char*> ListCharP;
typedef List<NamedDataSet*> ListNamedDataSetP;
typedef List<NamedInterpolation*> ListNamedInterpolationP;
typedef List<VectAry*> ListVectAryP;
typedef List<FileInfo*> ListFileInfoP;

typedef ListIter<char*> ListIterCharP;
typedef ListIter<NamedDataSet*> ListIterNamedDataSetP;
typedef ListIter<NamedInterpolation*> ListIterNamedInterpolationP;
typedef ListIter<VectAry*> ListIterVectAryP;
typedef ListIter<FileInfo*> ListIterFileInfoP;

typedef ListManip<char*> ListManipCharP;
typedef ListManip<NamedDataSet*> ListManipNamedDataSetP;
typedef ListManip<NamedInterpolation*> ListManipNamedInterpolationP;
typedef ListManip<VectAry*> ListManipVectAryP;
typedef ListManip<FileInfo*> ListManipFileInfoP;

#endif
