text: /*	see copyright notice in squirrel.h */
  #ifndef _SQOBJECT_H_
  #define _SQOBJECT_H_
  
  #include "squtils.h"
  
  #ifdef _SQ64
  #define UINT_MINUS_ONE (0xFFFFFFFFFFFFFFFF)
  #else
  #define UINT_MINUS_ONE (0xFFFFFFFF)
  #endif
  
  #define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))
  #define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))
  #define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))
  
  struct SQSharedState;
  
  enum SQMetaMethod{
  	MT_ADD=0,
  	MT_SUB=1,
  	MT_MUL=2,
  	MT_DIV=3,
  	MT_UNM=4,
  	MT_MODULO=5,
  	MT_SET=6,
  	MT_GET=7,
  	MT_TYPEOF=8,
  	MT_NEXTI=9,
  	MT_CMP=10,
  	MT_CALL=11,
  	MT_CLONED=12,
  	MT_NEWSLOT=13,
  	MT_DELSLOT=14,
  	MT_TOSTRING=15,
  	MT_NEWMEMBER=16,
  	MT_INHERITED=17,
  	MT_LAST = 18
  };
  
  #define MM_ADD		_SC("_add")
  #define MM_SUB		_SC("_sub")
  #define MM_MUL		_SC("_mul")
  #define MM_DIV		_SC("_div")
  #define MM_UNM		_SC("_unm")
  #define MM_MODULO	_SC("_modulo")
  #define MM_SET		_SC("_set")
  #define MM_GET		_SC("_get")
  #define MM_TYPEOF	_SC("_typeof")
  #define MM_NEXTI	_SC("_nexti")
  #define MM_CMP		_SC("_cmp")
  #define MM_CALL		_SC("_call")
  #define MM_CLONED	_SC("_cloned")
  #define MM_NEWSLOT	_SC("_newslot")
  #define MM_DELSLOT	_SC("_delslot")
  #define MM_TOSTRING	_SC("_tostring")
  #define MM_NEWMEMBER _SC("_newmember")
  #define MM_INHERITED _SC("_inherited")
  
  #define MINPOWER2 4
  
  struct SQRefCounted
  {
  	SQUnsignedInteger _uiRef;
  	struct SQWeakRef *_weakref;
  	SQRefCounted() { _uiRef = 0; _weakref = NULL; }
  	virtual ~SQRefCounted();
  	SQWeakRef *GetWeakRef(SQObjectType type);
  	virtual void Release()=0;
  	
  };
  
  struct SQWeakRef : SQRefCounted
  {
  	void Release();
  	SQObject _obj;
  };
  
  #define _realval(o) (type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj)
  
  struct SQObjectPtr;
  
  #define __AddRef(type,unval) if(ISREFCOUNTED(type))	\
  		{ \
  			unval.pRefCounted->_uiRef++; \
  		}  
  
  #define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)==0))	\
  		{	\
  			unval.pRefCounted->Release();	\
  		}
  
  #define __ObjRelease(obj) { \
  	if((obj)) {	\
  		(obj)->_uiRef--; \
  		if((obj)->_uiRef == 0) \
  			(obj)->Release(); \
  		(obj) = NULL;	\
  	} \
  }
  
  #define __ObjAddRef(obj) { \
  	(obj)->_uiRef++; \
  }
  
  #define type(obj) ((obj)._type)
  #define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE)
  #define raw_type(obj) _RAW_TYPE((obj)._type)
  
  #define _integer(obj) ((obj)._unVal.nInteger)
  #define _float(obj) ((obj)._unVal.fFloat)
  #define _string(obj) ((obj)._unVal.pString)
  #define _table(obj) ((obj)._unVal.pTable)
  #define _array(obj) ((obj)._unVal.pArray)
  #define _closure(obj) ((obj)._unVal.pClosure)
  #define _generator(obj) ((obj)._unVal.pGenerator)
  #define _nativeclosure(obj) ((obj)._unVal.pNativeClosure)
  #define _userdata(obj) ((obj)._unVal.pUserData)
  #define _userpointer(obj) ((obj)._unVal.pUserPointer)
  #define _thread(obj) ((obj)._unVal.pThread)
  #define _funcproto(obj) ((obj)._unVal.pFunctionProto)
  #define _class(obj) ((obj)._unVal.pClass)
  #define _instance(obj) ((obj)._unVal.pInstance)
  #define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable)
  #define _weakref(obj) ((obj)._unVal.pWeakRef)
  #define _outer(obj) ((obj)._unVal.pOuter)
  #define _refcounted(obj) ((obj)._unVal.pRefCounted)
  #define _rawval(obj) ((obj)._unVal.raw)
  
  #define _stringval(obj) (obj)._unVal.pString->_val
  #define _userdataval(obj) (obj)._unVal.pUserData->_val
  
  #define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))
  #define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))
  /////////////////////////////////////////////////////////////////////////////////////
  /////////////////////////////////////////////////////////////////////////////////////
  #if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64)
  #define SQ_REFOBJECT_INIT()	SQ_OBJECT_RAWINIT()
  #else
  #define SQ_REFOBJECT_INIT()
  #endif
  
  #define _REF_TYPE_DECL(type,_class,sym) \
  	SQObjectPtr(_class * x) \
  	{ \
  		SQ_OBJECT_RAWINIT() \
  		_type=type; \
  		_unVal.sym = x; \
  		assert(_unVal.pTable); \
  		_unVal.pRefCounted->_uiRef++; \
  	} \
  	inline SQObjectPtr& operator=(_class *x) \
  	{  \
  		SQObjectType tOldType; \
  		SQObjectValue unOldVal; \
  		tOldType=_type; \
  		unOldVal=_unVal; \
  		_type = type; \
  		SQ_REFOBJECT_INIT() \
  		_unVal.sym = x; \
  		_unVal.pRefCounted->_uiRef++; \
  		__Release(tOldType,unOldVal); \
  		return *this; \
  	}
  
  #define _SCALAR_TYPE_DECL(type,_class,sym) \
  	SQObjectPtr(_class x) \
  	{ \
  		SQ_OBJECT_RAWINIT() \
  		_type=type; \
  		_unVal.sym = x; \
  	} \
  	inline SQObjectPtr& operator=(_class x) \
  	{  \
  		__Release(_type,_unVal); \
  		_type = type; \
  		SQ_OBJECT_RAWINIT() \
  		_unVal.sym = x; \
  		return *this; \
  	}
  struct SQObjectPtr : public SQObject
  {
  	SQObjectPtr()
  	{
  		SQ_OBJECT_RAWINIT()
  		_type=OT_NULL;
  		_unVal.pUserPointer=NULL;
  	}
  	SQObjectPtr(const SQObjectPtr &o)
  	{
  		//SQ_OBJECT_RAWINIT()
  		_type=o._type;
  		_unVal=o._unVal;
  		__AddRef(_type,_unVal);
  	}
  	SQObjectPtr(const SQObject &o)
  	{
  		//SQ_OBJECT_RAWINIT()
  		_type=o._type;
  		_unVal=o._unVal;
  		__AddRef(_type,_unVal);
  	}
  	_REF_TYPE_DECL(OT_TABLE,SQTable,pTable)
  	_REF_TYPE_DECL(OT_CLASS,SQClass,pClass)
  	_REF_TYPE_DECL(OT_INSTANCE,SQInstance,pInstance)
  	_REF_TYPE_DECL(OT_ARRAY,SQArray,pArray)
  	_REF_TYPE_DECL(OT_CLOSURE,SQClosure,pClosure)
  	_REF_TYPE_DECL(OT_NATIVECLOSURE,SQNativeClosure,pNativeClosure)
  	_REF_TYPE_DECL(OT_OUTER,SQOuter,pOuter)
  	_REF_TYPE_DECL(OT_GENERATOR,SQGenerator,pGenerator)
  	_REF_TYPE_DECL(OT_STRING,SQString,pString)
  	_REF_TYPE_DECL(OT_USERDATA,SQUserData,pUserData)
  	_REF_TYPE_DECL(OT_WEAKREF,SQWeakRef,pWeakRef)
  	_REF_TYPE_DECL(OT_THREAD,SQVM,pThread)
  	_REF_TYPE_DECL(OT_FUNCPROTO,SQFunctionProto,pFunctionProto)
  	
  	_SCALAR_TYPE_DECL(OT_INTEGER,SQInteger,nInteger)
  	_SCALAR_TYPE_DECL(OT_FLOAT,SQFloat,fFloat)
  	_SCALAR_TYPE_DECL(OT_USERPOINTER,SQUserPointer,pUserPointer)
  
  	SQObjectPtr(bool bBool)
  	{
  		SQ_OBJECT_RAWINIT()
  		_type = OT_BOOL;
  		_unVal.nInteger = bBool?1:0;
  	}
  	inline SQObjectPtr& operator=(bool b)
  	{ 
  		__Release(_type,_unVal);
  		SQ_OBJECT_RAWINIT()
  		_type = OT_BOOL;
  		_unVal.nInteger = b?1:0;
  		return *this;
  	}
  
  	~SQObjectPtr()
  	{
  		__Release(_type,_unVal);
  	}
  			
  	inline SQObjectPtr& operator=(const SQObjectPtr& obj)
  	{ 
  		SQObjectType tOldType;
  		SQObjectValue unOldVal;
  		tOldType=_type;
  		unOldVal=_unVal;
  		_unVal = obj._unVal;
  		_type = obj._type;
  		__AddRef(_type,_unVal);
  		__Release(tOldType,unOldVal);
  		return *this;
  	}
  	inline SQObjectPtr& operator=(const SQObject& obj)
  	{ 
  		SQObjectType tOldType;
  		SQObjectValue unOldVal;
  		tOldType=_type;
  		unOldVal=_unVal;
  		_unVal = obj._unVal;
  		_type = obj._type;
  		__AddRef(_type,_unVal);
  		__Release(tOldType,unOldVal);
  		return *this;
  	}
  	inline void Null()
  	{
  		__Release(_type ,_unVal);
  		_type = OT_NULL;
  		_unVal.raw = NULL;
  	}
  	private:
  		SQObjectPtr(const SQChar *){} //safety
  };
  
  
  inline void _Swap(SQObject &a,SQObject &b)
  {
  	SQObjectType tOldType = a._type;
  	SQObjectValue unOldVal = a._unVal;
  	a._type = b._type;
  	a._unVal = b._unVal;
  	b._type = tOldType;
  	b._unVal = unOldVal;
  }
  
  /////////////////////////////////////////////////////////////////////////////////////
  #ifndef NO_GARBAGE_COLLECTOR
  #define MARK_FLAG 0x80000000
  struct SQCollectable : public SQRefCounted {
  	SQCollectable *_next;
  	SQCollectable *_prev;
  	SQSharedState *_sharedstate;
  	virtual SQObjectType GetType()=0;
  	virtual void Release()=0;
  	virtual void Mark(SQCollectable **chain)=0;
  	void UnMark();
  	virtual void Finalize()=0;
  	static void AddToChain(SQCollectable **chain,SQCollectable *c);
  	static void RemoveFromChain(SQCollectable **chain,SQCollectable *c);
  };
  
  
  #define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj)
  #define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);}
  #define CHAINABLE_OBJ SQCollectable
  #define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;}
  #else
  
  #define ADD_TO_CHAIN(chain,obj) ((void)0)
  #define REMOVE_FROM_CHAIN(chain,obj) ((void)0)
  #define CHAINABLE_OBJ SQRefCounted
  #define INIT_CHAIN() ((void)0)
  #endif
  
  struct SQDelegable : public CHAINABLE_OBJ {
  	bool SetDelegate(SQTable *m);
  	virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
  	SQTable *_delegate;
  };
  
  SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx);
  typedef sqvector<SQObjectPtr> SQObjectPtrVec;
  typedef sqvector<SQInteger> SQIntVec;
  const SQChar *GetTypeName(const SQObjectPtr &obj1);
  const SQChar *IdType2Name(SQObjectType type);
  
  
  
  #endif //_SQOBJECT_H_
  