#ifndef __RWCOLLECT_H__
#define __RWCOLLECT_H__

/*
 * Declarations for RWCollectables: an abstract base class.
 *
 * $Id: collect.h,v 2.14 1993/09/03 02:08:13 keffer Exp $
 *
 ****************************************************************************
 *
 * Rogue Wave Software, Inc.
 * P.O. Box 2328
 * Corvallis, OR 97339
 * Voice: (503) 754-3010	FAX: (503) 757-6650
 *
 * Copyright (C) 1989, 1990, 1991.
 * This software is subject to copyright protection under the laws of
 * the United States and other countries.
 *
 ***************************************************************************
 *
 * $Log: collect.h,v $
 * Revision 2.14  1993/09/03  02:08:13  keffer
 * Macro _CLASSDLL is now named _RWTOOLSDLL
 *
 * Revision 2.13  1993/08/05  11:49:12  jims
 * Distinguish between using a WIN16 DLL from a WIN32 DLL by
 * checking for __WIN16__
 *
 * Revision 2.12  1993/08/03  18:40:35  dealys
 * Ported to MPW C++ 3.3 -- RW_BROKEN_TOKEN_PASTE
 *
 * Revision 2.11  1993/04/22  20:38:48  keffer
 * Persistence operators now store and restore nil pointers.
 *
 * Revision 2.10  1993/04/12  12:28:28  jims
 * Use global nil object for MULTI_THREAD, but not for Windows 3.x DLL
 *
 * Revision 2.9  1993/04/09  19:35:45  keffer
 * Indexing is now done using size_t
 *
 * Revision 2.8  1993/04/09  02:50:00  keffer
 * Added support for operator<< and >> for virtual streams and RWFile.
 *
 * Revision 2.7  1993/04/08  16:44:42  keffer
 * Cleanup and removed V4.X support.
 *
 * Revision 2.6  1993/03/17  21:07:06  keffer
 * Return type of binaryStoreSize() is now RWspace
 *
 * Revision 2.3  1993/03/13  00:17:34  keffer
 * UNDEFINED_REFERENCE_BUG becomes RW_UNDEFINED_REFERENCE_BUG
 *
 * Revision 2.2  1993/02/03  00:01:56  jims
 * Removed #include directive for procinit.h
 *
 *    Rev 1.12   09 Sep 1992 12:47:10   KEFFER
 * Changed macro "Init" to "RWInit" to avoid conflict with JPI header.
 * 
 *    Rev 1.6   21 Feb 1992 12:29:26   KEFFER
 * nil collectable now defined when using the DLL.
 * 
 *    Rev 1.4   13 Nov 1991 11:07:42   keffer
 * More robust DLL code; No longer declares GVector(RWCollectable); store and
 * read tables now maintained by a separate manager.
 * 
 */

#ifndef __RWTOOLDEFS_H__
#  include "rw/tooldefs.h"
#endif
#ifndef __RWMEMPOOL_H__
#  include "rw/mempool.h"
#endif
#ifndef __RWGENERIC_H__
#  include "rw/generic.h"		/* Looking for name2() */
#endif
#ifdef RW_UNDEFINED_REFERENCE_BUG
#  include "rw/rstream.h"
#endif

/************************************************************************
 *									*
 * The macro RWDECLARE_COLLECTABLE should be included in the declaration*
 * of any class that derives from RWCollectable.			*
 *									*
 ************************************************************************/

#define RWDECLARE_COLLECTABLE(className)				\
  public:								\
    virtual RWCollectable*	newSpecies() const;			\
    virtual RWCollectable*	copy() const;				\
    virtual RWClassID		isA() const;				\
    friend RWvistream& operator>>(RWvistream& s, className*& pCl)	\
      { pCl = (className*)RWCollectable::recursiveRestoreFrom(s); return s; } \
    friend RWFile&     operator>>(RWFile& f,     className*& pCl)             \
      { pCl = (className*)RWCollectable::recursiveRestoreFrom(f); return f; }




/************************************************************************
 *									*
 * The macro RWDEFINE_COLLECTABLE should be included in one ".cpp"	*
 * file to implement various functions for classing deriving from	*
 * RWCollectable.  It presently serves four purposes:			*
 * 1) To provide a definition for newSpecies().				*
 * 2) To provide a definition for copy().				*
 * 3) To provide a definition for isA().				*
 * 4) To define a "creator function" to be inserted into the 		*
 *    one-of-a-kind global RWFactory pointed to by theFactory.		*
 *									*
 ************************************************************************/

#ifdef RW_BROKEN_TOKEN_PASTE
#  define RWInit(className)       RWInitCtor##className
#  define rwCreateFN(className)   rwCreate##className
#else
#  define RWInit(className)	name2(RWInitCtor,className)
#  define rwCreateFN(className)	name2(rwCreate,className)
#endif

#define RWDEFINE_COLLECTABLE(className, id)			\
  RWCollectable* className::newSpecies() const			\
    { return new className; }					\
  RWCollectable* className::copy() const			\
    { return new className(*this); }				\
  RWClassID      className::isA() const				\
    { return id; }						\
								\
  /* Global function to create an instance of the class:*/	\
  RWCollectable* rwCreateFN(className)()			\
    { return new className; }					\
								\
  /* Static constructor to insert above into factory: */	\
  struct RWInit(className) {					\
    RWInit(className)();					\
    ~RWInit(className)();					\
  };								\
  RWInit(className)::RWInit(className)()			\
    { rwAddToFactory(rwCreateFN(className), id); }		\
  RWInit(className)::~RWInit(className)()			\
    { rwRemoveFromFactory(id); }				\
  RWInit(className) name2(rwDummy,className);



/////////////////////////////////////////////////////////////////
//                                                             //
//                       RWCollectable                         //
//                                                             //
/////////////////////////////////////////////////////////////////


class RWExport RWCollectable
{

  RWDECLARE_COLLECTABLE(RWCollectable)

public:

  RWCollectable();
  virtual			~RWCollectable();

  virtual RWspace		binaryStoreSize() const;
  virtual int			compareTo(const RWCollectable*) const;
  virtual unsigned		hash() const;
  virtual RWBoolean		isEqual(const RWCollectable*) const;
  virtual void			restoreGuts(RWFile&);
  virtual void			restoreGuts(RWvistream&);
  virtual void			saveGuts(RWFile&) const;
  virtual void			saveGuts(RWvostream&) const;
  RWspace			recursiveStoreSize() const;
  static RWCollectable*		recursiveRestoreFrom(RWFile&       file,
                                                     RWCollectable*p = 0);
  static RWCollectable*		recursiveRestoreFrom(RWvistream&   vstream,
                                                     RWCollectable*p = 0);
  void				recursiveSaveOn(RWFile&) const;
  void				recursiveSaveOn(RWvostream&) const;

};

RWvostream& rwexport operator<<(RWvostream& vstream, const RWCollectable* p);
RWFile&     rwexport operator<<(RWFile& file,        const RWCollectable* p);

inline RWvostream& operator<<(RWvostream& vstream, const RWCollectable& rc)
	{ rc.recursiveSaveOn(vstream); return vstream; }

inline RWFile&     operator<<(RWFile& file, const RWCollectable& rc)
	{ rc.recursiveSaveOn(file);    return file;    }

inline RWvistream& operator>>(RWvistream& vstream, RWCollectable& r)
	{ RWCollectable::recursiveRestoreFrom(vstream, &r); return vstream; }

inline RWFile&     operator>>(RWFile& file,        RWCollectable& r)
	{ RWCollectable::recursiveRestoreFrom(file, &r);    return file; }

extern void                rwexport rwDestroy(RWCollectable*, void*);
extern RWBoolean           rwexport rwIsEqualFun(const void* a, const void* b);
extern void                rwexport rwAddToFactory(RWuserCreator fn, RWClassID id);
extern RWCollectable*      rwexport rwCreateFromFactory(RWClassID);
extern void                rwexport rwRemoveFromFactory(RWClassID);

#if defined(_RWTOOLSDLL) && defined(__WIN16__)
  // DLL situation; get nil object from the instance mgr.
  extern RWCollectable* getRWNilCollectable();
# define RWnilCollectable (getRWNilCollectable())
#else
   // Use a global nil object.
   extern RWCollectable* RWnilCollectable;
#endif



#endif /* __RWCOLLECT_H__ */

