1 /*  see copyright notice in squirrel.h */
2 #ifndef _SQOBJECT_H_
3 #define _SQOBJECT_H_
4 
5 #include "squtils.h"
6 
7 #ifdef _SQ64
8 #define UINT_MINUS_ONE (0xFFFFFFFFFFFFFFFF)
9 #else
10 #define UINT_MINUS_ONE (0xFFFFFFFF)
11 #endif
12 
13 #define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))
14 #define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))
15 #define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))
16 
17 struct SQSharedState;
18 
19 enum SQMetaMethod{
20     MT_ADD=0,
21     MT_SUB=1,
22     MT_MUL=2,
23     MT_DIV=3,
24     MT_UNM=4,
25     MT_MODULO=5,
26     MT_SET=6,
27     MT_GET=7,
28     MT_TYPEOF=8,
29     MT_NEXTI=9,
30     MT_CMP=10,
31     MT_CALL=11,
32     MT_CLONED=12,
33     MT_NEWSLOT=13,
34     MT_DELSLOT=14,
35     MT_TOSTRING=15,
36     MT_NEWMEMBER=16,
37     MT_INHERITED=17,
38     MT_LAST = 18
39 };
40 
41 #define MM_ADD      _SC("_add")
42 #define MM_SUB      _SC("_sub")
43 #define MM_MUL      _SC("_mul")
44 #define MM_DIV      _SC("_div")
45 #define MM_UNM      _SC("_unm")
46 #define MM_MODULO   _SC("_modulo")
47 #define MM_SET      _SC("_set")
48 #define MM_GET      _SC("_get")
49 #define MM_TYPEOF   _SC("_typeof")
50 #define MM_NEXTI    _SC("_nexti")
51 #define MM_CMP      _SC("_cmp")
52 #define MM_CALL     _SC("_call")
53 #define MM_CLONED   _SC("_cloned")
54 #define MM_NEWSLOT  _SC("_newslot")
55 #define MM_DELSLOT  _SC("_delslot")
56 #define MM_TOSTRING _SC("_tostring")
57 #define MM_NEWMEMBER _SC("_newmember")
58 #define MM_INHERITED _SC("_inherited")
59 
60 
61 #define _CONSTRUCT_VECTOR(type,size,ptr) { \
62     for(SQInteger n = 0; n < ((SQInteger)size); n++) { \
63             new (&ptr[n]) type(); \
64         } \
65 }
66 
67 #define _DESTRUCT_VECTOR(type,size,ptr) { \
68     for(SQInteger nl = 0; nl < ((SQInteger)size); nl++) { \
69             ptr[nl].~type(); \
70     } \
71 }
72 
73 #define _COPY_VECTOR(dest,src,size) { \
74     for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \
75         dest[_n_] = src[_n_]; \
76     } \
77 }
78 
79 #define _NULL_SQOBJECT_VECTOR(vec,size) { \
80     for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \
81         vec[_n_].Null(); \
82     } \
83 }
84 
85 #define MINPOWER2 4
86 
87 struct SQRefCounted
88 {
89     SQUnsignedInteger _uiRef;
90     struct SQWeakRef *_weakref;
SQRefCountedSQRefCounted91     SQRefCounted() { _uiRef = 0; _weakref = NULL; }
92     virtual ~SQRefCounted();
93     SQWeakRef *GetWeakRef(SQObjectType type);
94     virtual void Release()=0;
95 
96 };
97 
98 struct SQWeakRef : SQRefCounted
99 {
100     void Release();
101     SQObject _obj;
102 };
103 
104 #define _realval(o) (sqtype((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj)
105 
106 struct SQObjectPtr;
107 
108 #define __AddRef(type,unval) if(ISREFCOUNTED(type)) \
109         { \
110             unval.pRefCounted->_uiRef++; \
111         }
112 
113 #define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)==0))  \
114         {   \
115             unval.pRefCounted->Release();   \
116         }
117 
118 #define __ObjRelease(obj) { \
119     if((obj)) { \
120         (obj)->_uiRef--; \
121         if((obj)->_uiRef == 0) \
122             (obj)->Release(); \
123         (obj) = NULL;   \
124     } \
125 }
126 
127 #define __ObjAddRef(obj) { \
128     (obj)->_uiRef++; \
129 }
130 
131 #define sqtype(obj) ((obj)._type)
132 #define is_delegable(t) (sqtype(t)&SQOBJECT_DELEGABLE)
133 #define raw_type(obj) _RAW_TYPE((obj)._type)
134 
135 #define _integer(obj) ((obj)._unVal.nInteger)
136 #define _float(obj) ((obj)._unVal.fFloat)
137 #define _string(obj) ((obj)._unVal.pString)
138 #define _table(obj) ((obj)._unVal.pTable)
139 #define _array(obj) ((obj)._unVal.pArray)
140 #define _closure(obj) ((obj)._unVal.pClosure)
141 #define _generator(obj) ((obj)._unVal.pGenerator)
142 #define _nativeclosure(obj) ((obj)._unVal.pNativeClosure)
143 #define _userdata(obj) ((obj)._unVal.pUserData)
144 #define _userpointer(obj) ((obj)._unVal.pUserPointer)
145 #define _thread(obj) ((obj)._unVal.pThread)
146 #define _funcproto(obj) ((obj)._unVal.pFunctionProto)
147 #define _class(obj) ((obj)._unVal.pClass)
148 #define _instance(obj) ((obj)._unVal.pInstance)
149 #define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable)
150 #define _weakref(obj) ((obj)._unVal.pWeakRef)
151 #define _outer(obj) ((obj)._unVal.pOuter)
152 #define _refcounted(obj) ((obj)._unVal.pRefCounted)
153 #define _rawval(obj) ((obj)._unVal.raw)
154 
155 #define _stringval(obj) (obj)._unVal.pString->_val
156 #define _userdataval(obj) ((SQUserPointer)sq_aligning((obj)._unVal.pUserData + 1))
157 
158 #define tofloat(num) ((sqtype(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))
159 #define tointeger(num) ((sqtype(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))
160 /////////////////////////////////////////////////////////////////////////////////////
161 /////////////////////////////////////////////////////////////////////////////////////
162 #if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64)
163 #define SQ_REFOBJECT_INIT() SQ_OBJECT_RAWINIT()
164 #else
165 #define SQ_REFOBJECT_INIT()
166 #endif
167 
168 #define _REF_TYPE_DECL(type,_class,sym) \
169     SQObjectPtr(_class * x) \
170     { \
171         SQ_OBJECT_RAWINIT() \
172         _type=type; \
173         _unVal.sym = x; \
174         assert(_unVal.pTable); \
175         _unVal.pRefCounted->_uiRef++; \
176     } \
177     inline SQObjectPtr& operator=(_class *x) \
178     {  \
179         SQObjectType tOldType; \
180         SQObjectValue unOldVal; \
181         tOldType=_type; \
182         unOldVal=_unVal; \
183         _type = type; \
184         SQ_REFOBJECT_INIT() \
185         _unVal.sym = x; \
186         _unVal.pRefCounted->_uiRef++; \
187         __Release(tOldType,unOldVal); \
188         return *this; \
189     }
190 
191 #define _SCALAR_TYPE_DECL(type,_class,sym) \
192     SQObjectPtr(_class x) \
193     { \
194         SQ_OBJECT_RAWINIT() \
195         _type=type; \
196         _unVal.sym = x; \
197     } \
198     inline SQObjectPtr& operator=(_class x) \
199     {  \
200         __Release(_type,_unVal); \
201         _type = type; \
202         SQ_OBJECT_RAWINIT() \
203         _unVal.sym = x; \
204         return *this; \
205     }
206 struct SQObjectPtr : public SQObject
207 {
SQObjectPtrSQObjectPtr208     SQObjectPtr()
209     {
210         SQ_OBJECT_RAWINIT()
211         _type=OT_NULL;
212         _unVal.pUserPointer=NULL;
213     }
SQObjectPtrSQObjectPtr214     SQObjectPtr(const SQObjectPtr &o)
215     {
216         _type = o._type;
217         _unVal = o._unVal;
218         __AddRef(_type,_unVal);
219     }
SQObjectPtrSQObjectPtr220     SQObjectPtr(const SQObject &o)
221     {
222         _type = o._type;
223         _unVal = o._unVal;
224         __AddRef(_type,_unVal);
225     }
_REF_TYPE_DECLSQObjectPtr226     _REF_TYPE_DECL(OT_TABLE,SQTable,pTable)
227     _REF_TYPE_DECL(OT_CLASS,SQClass,pClass)
228     _REF_TYPE_DECL(OT_INSTANCE,SQInstance,pInstance)
229     _REF_TYPE_DECL(OT_ARRAY,SQArray,pArray)
230     _REF_TYPE_DECL(OT_CLOSURE,SQClosure,pClosure)
231     _REF_TYPE_DECL(OT_NATIVECLOSURE,SQNativeClosure,pNativeClosure)
232     _REF_TYPE_DECL(OT_OUTER,SQOuter,pOuter)
233     _REF_TYPE_DECL(OT_GENERATOR,SQGenerator,pGenerator)
234     _REF_TYPE_DECL(OT_STRING,SQString,pString)
235     _REF_TYPE_DECL(OT_USERDATA,SQUserData,pUserData)
236     _REF_TYPE_DECL(OT_WEAKREF,SQWeakRef,pWeakRef)
237     _REF_TYPE_DECL(OT_THREAD,SQVM,pThread)
238     _REF_TYPE_DECL(OT_FUNCPROTO,SQFunctionProto,pFunctionProto)
239 
240     _SCALAR_TYPE_DECL(OT_INTEGER,SQInteger,nInteger)
241     _SCALAR_TYPE_DECL(OT_FLOAT,SQFloat,fFloat)
242     _SCALAR_TYPE_DECL(OT_USERPOINTER,SQUserPointer,pUserPointer)
243 
244     SQObjectPtr(bool bBool)
245     {
246         SQ_OBJECT_RAWINIT()
247         _type = OT_BOOL;
248         _unVal.nInteger = bBool?1:0;
249     }
250     inline SQObjectPtr& operator=(bool b)
251     {
252         __Release(_type,_unVal);
253         SQ_OBJECT_RAWINIT()
254         _type = OT_BOOL;
255         _unVal.nInteger = b?1:0;
256         return *this;
257     }
258 
~SQObjectPtrSQObjectPtr259     ~SQObjectPtr()
260     {
261         __Release(_type,_unVal);
262     }
263 
264     inline SQObjectPtr& operator=(const SQObjectPtr& obj)
265     {
266         SQObjectType tOldType;
267         SQObjectValue unOldVal;
268         tOldType=_type;
269         unOldVal=_unVal;
270         _unVal = obj._unVal;
271         _type = obj._type;
272         __AddRef(_type,_unVal);
273         __Release(tOldType,unOldVal);
274         return *this;
275     }
276     inline SQObjectPtr& operator=(const SQObject& obj)
277     {
278         SQObjectType tOldType;
279         SQObjectValue unOldVal;
280         tOldType=_type;
281         unOldVal=_unVal;
282         _unVal = obj._unVal;
283         _type = obj._type;
284         __AddRef(_type,_unVal);
285         __Release(tOldType,unOldVal);
286         return *this;
287     }
NullSQObjectPtr288     inline void Null()
289     {
290         SQObjectType tOldType = _type;
291         SQObjectValue unOldVal = _unVal;
292         _type = OT_NULL;
293         _unVal.raw = (SQRawObjectVal)NULL;
294         __Release(tOldType ,unOldVal);
295     }
296     private:
SQObjectPtrSQObjectPtr297         SQObjectPtr(const SQChar *){} //safety
298 };
299 
300 
_Swap(SQObject & a,SQObject & b)301 inline void _Swap(SQObject &a,SQObject &b)
302 {
303     SQObjectType tOldType = a._type;
304     SQObjectValue unOldVal = a._unVal;
305     a._type = b._type;
306     a._unVal = b._unVal;
307     b._type = tOldType;
308     b._unVal = unOldVal;
309 }
310 
311 /////////////////////////////////////////////////////////////////////////////////////
312 #ifndef NO_GARBAGE_COLLECTOR
313 #define MARK_FLAG 0x80000000
314 struct SQCollectable : public SQRefCounted {
315     SQCollectable *_next;
316     SQCollectable *_prev;
317     SQSharedState *_sharedstate;
318     virtual SQObjectType GetType()=0;
319     virtual void Release()=0;
320     virtual void Mark(SQCollectable **chain)=0;
321     void UnMark();
322     virtual void Finalize()=0;
323     static void AddToChain(SQCollectable **chain,SQCollectable *c);
324     static void RemoveFromChain(SQCollectable **chain,SQCollectable *c);
325 };
326 
327 
328 #define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj)
329 #define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);}
330 #define CHAINABLE_OBJ SQCollectable
331 #define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;}
332 #else
333 
334 #define ADD_TO_CHAIN(chain,obj) ((void)0)
335 #define REMOVE_FROM_CHAIN(chain,obj) ((void)0)
336 #define CHAINABLE_OBJ SQRefCounted
337 #define INIT_CHAIN() ((void)0)
338 #endif
339 
340 struct SQDelegable : public CHAINABLE_OBJ {
341     bool SetDelegate(SQTable *m);
342     virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
343     SQTable *_delegate;
344 };
345 
346 SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx);
347 typedef sqvector<SQObjectPtr> SQObjectPtrVec;
348 typedef sqvector<SQInteger> SQIntVec;
349 const SQChar *GetTypeName(const SQObjectPtr &obj1);
350 const SQChar *IdType2Name(SQObjectType type);
351 
352 
353 
354 #endif //_SQOBJECT_H_
355