#ifndef  __RWSLIST_H__
#define  __RWSLIST_H__

/*
 * RWSlist: A singly linked list of pointers to void
 *
 * $Id: slist.h,v 2.9 1993/11/04 13:48:54 jims Exp $
 *
 ****************************************************************************
 *
 * Rogue Wave Software, Inc.
 * P.O. Box 2328
 * Corvallis, OR 97339
 * Voice: (503) 754-3010	FAX: (503) 757-6650
 *
 * Copyright (C) 1990, 1991, 1992, 1992, 1993.
 * This software is subject to copyright protection under the laws
 * of the United States and other countries.
 *
 ***************************************************************************
 *
 * $Log: slist.h,v $
 * Revision 2.9  1993/11/04  13:48:54  jims
 * Port to ObjectStore
 *
 * Revision 2.8  1993/09/10  02:56:53  keffer
 * Switched RCS idents to avoid spurious diffs
 *
 * Revision 2.7  1993/04/09  19:35:45  keffer
 * Indexing is now done using size_t
 *
 * Revision 2.6  1993/03/24  01:29:51  keffer
 * Indexing operations now used unsigned
 *
 * Revision 2.5  1993/02/13  21:49:01  keffer
 * Ported to Zortech; required public derivation.
 *
 * Revision 2.4  1993/02/11  22:47:20  keffer
 * Ported to IBM xlC compiler
 *
 * Revision 2.3  1993/01/25  18:21:06  keffer
 * Simplified, improving performance
 *
 * 
 */

#include "rw/islist.h"

/*
 * This is the actual link which includes a pointer
 */
class RWExport RWPSlink : public RWIsvSlink
{

public:

  RWPSlink(void* a) : info_(a) {;}
  RWPSlink*	next() const  {return (RWPSlink*)next_;}

  void*		info_;
};

/****************************************************************
 *								*
 *		Declarations for RWSlist			*
 *								*
 ****************************************************************/

#ifdef __ZTC__
// This derivation is formally intended to be private, but a bug
// in Zortech requires it to be public:
class RWExport RWSlist : public RWIsvSlist
#else
class RWExport RWSlist : private RWIsvSlist
#endif
{

public:

  RWSlist() {;}
  RWSlist(void* a) : 
      RWIsvSlist(new RWPSlink(a)) {;}
  RWSlist(const RWSlist&);
  ~RWSlist()		{clear();}

  // Operators:
  RWSlist&		operator=(const RWSlist& s);

  // Member functions:
  void*			append(void* a);
  void			apply(RWapplyGeneric, void*);
  void			applyReference(void (*apRef)(void*&, void*), void*);
  void*&		at(size_t n)	{return ((RWPSlink*)RWIsvSlist::at(n))->info_;}
#ifndef RW_NO_CONST_OVERLOAD
  const void*		at(size_t n) const	{return ((RWPSlink*)RWIsvSlist::at(n))->info_;}
#endif
  void			clear();
  RWBoolean		contains(RWtestGeneric tfun, const void* c) const
	{return find(tfun,c) != rwnil;}
  RWBoolean		containsReference(const void* c) const
	{return findReference(c) != rwnil;}
#ifdef RW_NO_ACCESS_ADJUSTMENT
  size_t		entries() const { return RWIsvSlist::entries(); }
#else
  RWIsvSlist::entries;
#endif
  void* 		find(RWtestGeneric, const void*) const;
  void* 		findReference(const void*) const; // First occurrence
  void*	 		first() const;
  void*			get()	{return peel((RWPSlink*)RWIsvSlist::get());}
  size_t		index(RWtestGeneric, const void*) const;
  void* 		insert(void* a) 	{ return append(a); }
  void*			insertAfter(int i, void* a); // For backwards compatibility
  void*			insertAt(size_t i, void* a);
#ifdef RW_NO_ACCESS_ADJUSTMENT
  RWBoolean		isEmpty() const { return RWIsvSlist::isEmpty(); }
#else
  RWIsvSlist::isEmpty;
#endif
  void*			last() const;
  size_t		occurrencesOf(RWtestGeneric, const void*) const;
  size_t		occurrencesOfReference(const void*) const;
  void*			prepend(void* a);
  void* 		remove(RWtestGeneric, const void*);
  void* 		removeReference(const void*);

protected:

  RWPSlink*		headLink()  const;
  RWPSlink*		tailLink()  const;
  RWPSlink*		firstLink() const {return (RWPSlink*)head_.next_;}
  RWPSlink*		lastLink()  const {return (RWPSlink*)last_;}

  // Type safe interfaces to base class:
  void			insertAfterLink(RWPSlink* p, RWPSlink* v)
	{RWIsvSlist::insertAfterLink(p,v);}
  RWPSlink*		removeRight(RWPSlink* p)
	{return (RWPSlink*)RWIsvSlist::removeRight(p);}

  static void*		peel(RWPSlink*);

private:

friend class RWExport RWSlistIterator;

};


/*
 * Declaration for iterator for singly linked list.
 */
class RWExport RWSlistIterator : private RWIsvSlistIterator
{

public:

  // Constructor: cast needed for Glock V2.0b:
  RWSlistIterator(RWSlist& s) : RWIsvSlistIterator((RWIsvSlist&)s) {;}
  
  void*			operator++();
  void*			operator+=(size_t n);
  void*	 		operator()();

#ifdef RW_NO_ACCESS_ADJUSTMENT
  RWBoolean		atFirst() const	{return RWIsvSlistIterator::atFirst();}
  RWBoolean		atLast() const	{return RWIsvSlistIterator::atLast(); }
  void			toFirst()	{RWIsvSlistIterator::toFirst();       }
  void			toLast()	{RWIsvSlistIterator::toLast();        }
#else
  RWIsvSlistIterator::atFirst;
  RWIsvSlistIterator::atLast;
  RWIsvSlistIterator::toFirst;
  RWIsvSlistIterator::toLast;
#endif

  // Methods:
  RWSlist*		container() const	{return (RWSlist*)slist_;}
  void*	 		findNext(RWtestGeneric, const void*);
  void*	 		findNextReference(const void*);
  void*	 		insertAfterPoint(void*);
  void*	 		key() const
	{return isActive() ? cursor()->info_ : rwnil;}
  void* 		remove()
	{return RWSlist::peel((RWPSlink*)RWIsvSlistIterator::remove());}
  void*	 		removeNext(RWtestGeneric, const void*);
  void*	 		removeNextReference(const void*);
  void			reset()			{RWIsvSlistIterator::reset();}
  void			reset(RWSlist& sl)	{RWIsvSlistIterator::reset((RWIsvSlist&)sl);}

protected:

  RWPSlink*		cursor() const		{return (RWPSlink*)shere_;}

private:

#ifndef RW_NO_POSTFIX
  // Disallow postfix increment.  Unless we hide it, some compilers will
  // substitute the prefix increment operator in its place. (or worse)
  void			operator++(int);
#endif  

};


//////////////////////////////////////////////////////////
//							//
//			INLINES				//
//							//
//////////////////////////////////////////////////////////

inline void*
RWSlist::first() const	{
  return isEmpty() ? rwnil : firstLink()->info_;
}

inline void*
RWSlist::last() const	{
  return isEmpty() ? rwnil : lastLink()->info_;
}

inline RWPSlink*
RWSlist::headLink() const {
  // Cast away constness to suppress unfounded cfront warning:
  return (RWPSlink*)&((RWSlist*)this)->head_;
}

inline RWPSlink*
RWSlist::tailLink() const {
  // Cast away constness to suppress unfounded cfront warning:
  return (RWPSlink*)&((RWSlist*)this)->tail_;
}

inline void*
RWSlistIterator::operator++()
{
  // Make sure tail link points to itself:
  RWPRECONDITION(container()->tailLink()->next()==container()->tailLink());
  advance();
  return cursor() == container()->tailLink() ? rwnil : cursor()->info_;
}

inline void*
RWSlistIterator::operator()()
{
  return ++(*this);
}

#endif /* __RWSLIST_H__ */
