/* 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 _CONSTRUCT_VECTOR(type,size,ptr) { \ for(SQInteger n = 0; n < ((SQInteger)size); n++) { \ new (&ptr[n]) type(); \ } \ } #define _DESTRUCT_VECTOR(type,size,ptr) { \ for(SQInteger nl = 0; nl < ((SQInteger)size); nl++) { \ ptr[nl].~type(); \ } \ } #define _COPY_VECTOR(dest,src,size) { \ for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \ dest[_n_] = src[_n_]; \ } \ } #define _NULL_SQOBJECT_VECTOR(vec,size) { \ for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \ vec[_n_].Null(); \ } \ } #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) (sq_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 is_delegable(t) (sq_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) ((SQUserPointer)sq_aligning((obj)._unVal.pUserData + 1)) #define tofloat(num) ((sq_type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num)) #define tointeger(num) ((sq_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) { _type = o._type; _unVal = o._unVal; __AddRef(_type,_unVal); } SQObjectPtr(const SQObject &o) { _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() { SQObjectType tOldType = _type; SQObjectValue unOldVal = _unVal; _type = OT_NULL; _unVal.raw = (SQRawObjectVal)NULL; __Release(tOldType ,unOldVal); } 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 SQObjectPtrVec; typedef sqvector SQIntVec; const SQChar *GetTypeName(const SQObjectPtr &obj1); const SQChar *IdType2Name(SQObjectType type); #endif //_SQOBJECT_H_