//
//      $$   class Thing V.1.01  --  2/27/91   $$
//
//	Michael Kelly  --  Author
//
//	Turbo C++ V.1.0
//
//	Your basic "thing" is a base class for
//	data elements of any type.  Derived classes
//	must overload the comparison operators and
//	virtual functions so that sorts and prints
//	will work.  The Thing class is not a virtual
//	base class so that functions that operate on
//	derived classes may create temporary instances
//	of class Thing.
//
//	The virtual function type() is worth a note:
//	the enum TypeOfThing value is returned in the
//	upper 16 bits of the long int.  The lower 16
//	bits contains the size of the Thing.  This
//	is intended to help the programmer to use
//	more than one struct-based Thing, for example,
//	in a program.  If the two structs are the same
//	size, the creator of the struct type Thing will
//	have to devise some other way to differentiate
//	the structs.  See one of the derived types,
//	such as LongThing ( th_long.cpp and th_long.hpp ).
//
//	$$   See HSort.Cpp and TryThing.Cpp   $$
//


#if !defined(THING_HPP)
#define THING_HPP
#include <mem.h>

enum TypeOfThing { 	 
	CharType, 
	IntType,
	LongType,
	FloatType,
	DoubleType,
	StructType,
	CharPtrType,
	IntPtrType,
	LongPtrType,
	FloatPtrType,
	DoublePtrType,
	StructPtrType,
	UnknownType
};

class Thing  {
  protected:
    void    	*thing;

  public:

    Thing()
    {
	thing = NULL; 
    }
    virtual ~Thing()
    { 
	if( thing )  {
	    delete thing;
	    thing = NULL;
	}
    }

    void    	*ptr() 	{ return thing; }
    
  virtual long type()	
  { 
    return ( (long)UnknownType << 16 );
  }
  virtual unsigned data_size()
  {
    return (unsigned)type();
  }
  virtual void print()		{}	
  virtual int  printable() 	{ return 0; }
  virtual int  sortable()  	{ return 0; }
  virtual int  storable()  	{ return 0; }

// turn off "parameter not used" warning
// for now.
//
#pragma warn -par
/*
    Thing& operator =( Thing &some_thing )
    {
	unsigned size = some_thing.data_size();

	thing = new char[ size ];
	if( thing )
	    memmove( ptr(), some_thing.ptr(), size );
	return *this;
    }
*/      
    virtual operator ==(Thing &some_thing) 
    {
	return ( type() == some_thing.type() );
    }
    virtual operator !=(Thing &some_thing) 
    { 
	return !( *this == some_thing); 
    }
    virtual operator < (Thing &some_thing) { return 0; }
    virtual operator <=(Thing &some_thing) { return 0; }
    virtual operator > (Thing &some_thing) { return 0; }
    virtual operator >=(Thing &some_thing) { return 0; }
};

// restore "parameter not used" warning
// to default state.
//
#pragma warn .par

extern const Thing TheNullThing;

#endif
