#ifndef _SLIST_H
#define _SLIST_H
static char SList_h_id[] = "$Header: /usr/tiburon/xPlatform/utils/RCS/SList.h,v 1.5 1997/06/16 16:04:11 oreilly Exp pean $";

/*
$Log: SList.h,v $
Revision 1.5  1997/06/16 16:04:11  oreilly
Make clear() publicly available

 * Revision 1.4  97/03/20  12:26:58  12:26:58  oreilly (Thomas C. O'Reilly)
 * *** empty log message ***
 * 
 * Revision 1.3  96/07/22  10:20:45  10:20:45  oreilly (Thomas C. O'Reilly)
 * Added RCS stuff
 * 
*/

#include <mbari/types.h>
#include <mbari/const.h>

struct SLink 
{
  SLink *next;
  SLink() 
  {
    next = 0;
  }

  SLink(SLink *p) 
  {
    next = p;
  }
};


class SListBase 
{
  SLink *last;      // last->next is head of list
  
  public:
  void insert(SLink *);     // add at head of list
  void append(SLink *);     // add at end of list
  SLink *get();             // return and remove head
  int remove(SLink *a);     // delete specified link
  int length();             // return number of links in list
  
  void clear() {last = 0;}

  SListBase() 
  {
    last = 0;
  }

  SListBase(SLink *a)
  {
    last = a->next = a;
  }
  
  friend class SListBaseIter;
};



template<class T>
struct TLink : public SLink 
{
  T info;
  TLink(const T& a) : info(a) {} 
};

template<class T> class SListIter;

template<class T>
class SList : private SListBase
{
  friend class SListIter<T>;
  
  public:

  void insert(const T& a)
  {
    SListBase::insert(new TLink<T>(a));
  }
  
  void append(const T& a)
  {
    SListBase::append(new TLink<T>(a));
  }
  
  void clear()
  {
    SListBase::clear();
  }
  
      
  T get();
  int remove(TLink<T> *lnk);

  int length() 
  {  
    return SListBase::length();
  }
  
};


template<class T>
T SList<T>::get()
{
  TLink<T> *lnk = (TLink<T> *)SListBase::get();
  T i = lnk->info ;
  delete lnk;
  return i;
}

template<class T>    
int SList<T>::remove(TLink<T> *lnk)
{
  if (SListBase::remove(lnk) == 0)
  {
    delete lnk;
    return 0;
  }
  else
    return -1;
}


class SListBaseIter
{
  SLink *ce;
  SListBase *cs;
  MBool atEnd;
  
  public:
  SListBaseIter(SListBase &s);
  SLink *operator() ();
  int remove();
  
  void reset() 
  {
    atEnd = FALSE;
    ce = cs->last;
  }
};
      
      
template<class T>
class SListIter : private SListBaseIter {

  public:

  SListIter(SList<T> &s) : SListBaseIter(s) 
  {
  }

  void reset() 
  {
    SListBaseIter::reset();
  }

  int remove()
  {  
    return SListBaseIter::remove();
  }
  
  T* next()
  {
    TLink<T>* lnk = (TLink<T> *)SListBaseIter::operator()();
    return lnk ? &lnk->info : 0;
  }
  
  T* operator()()
  {
    return next();
  }      
};




#endif
