- Avoid some expensive SDL_GetTicks() calls
[supertux.git] / src / squirrel / squirrel / sqclass.h
1 /*      see copyright notice in squirrel.h */\r
2 #ifndef _SQCLASS_H_\r
3 #define _SQCLASS_H_\r
4 \r
5 struct SQInstance;\r
6 \r
7 struct SQClassMemeber {\r
8         SQClassMemeber(){}\r
9         SQClassMemeber(const SQClassMemeber &o) {\r
10                 val = o.val;\r
11                 attrs = o.attrs;\r
12         }\r
13         SQObjectPtr val;\r
14         SQObjectPtr attrs;\r
15 };\r
16 \r
17 typedef sqvector<SQClassMemeber> SQClassMemeberVec;\r
18 \r
19 #define MEMBER_TYPE_METHOD 0x01000000\r
20 #define MEMBER_TYPE_FIELD 0x02000000\r
21 \r
22 #define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD)\r
23 #define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD)\r
24 #define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i))\r
25 #define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i))\r
26 #define _member_type(o) (_integer(o)&0xFF000000)\r
27 #define _member_idx(o) (_integer(o)&0x00FFFFFF)\r
28 \r
29 struct SQClass : public CHAINABLE_OBJ\r
30 {\r
31         SQClass(SQSharedState *ss,SQClass *base);\r
32 public:\r
33         static SQClass* Create(SQSharedState *ss,SQClass *base) {\r
34                 SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));\r
35                 new (newclass) SQClass(ss, base);\r
36                 return newclass;\r
37         }\r
38         ~SQClass();\r
39         bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic);\r
40         bool Get(const SQObjectPtr &key,SQObjectPtr &val) {\r
41                 if(_members->Get(key,val)) {\r
42                         if(_isfield(val)) {\r
43                                 SQObjectPtr &o = _defaultvalues[_member_idx(val)].val;\r
44                                 val = _realval(o);\r
45                         }\r
46                         else {\r
47                                 val = _methods[_member_idx(val)].val;\r
48                         }\r
49                         return true;\r
50                 }\r
51                 return false;\r
52         }\r
53         bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val);\r
54         bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval);\r
55         void Lock() { _locked = true; if(_base) _base->Lock(); }\r
56         void Release() { \r
57                 if (_hook) { _hook(_typetag,0);}\r
58                 sq_delete(this, SQClass);       \r
59         }\r
60         void Finalize();\r
61 #ifndef NO_GARBAGE_COLLECTOR\r
62         void Mark(SQCollectable ** );\r
63 #endif\r
64         SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
65         SQInstance *CreateInstance();\r
66         SQTable *_members;\r
67         SQClass *_base;\r
68         SQClassMemeberVec _defaultvalues;\r
69         SQClassMemeberVec _methods;\r
70         SQObjectPtrVec _metamethods;\r
71         SQObjectPtr _attributes;\r
72         SQUserPointer _typetag;\r
73         SQRELEASEHOOK _hook;\r
74         bool _locked;\r
75 };\r
76 \r
77 #define calcinstancesize(_theclass_) \\r
78         (sizeof(SQInstance)+(sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0)))\r
79 struct SQInstance : public SQDelegable \r
80 {\r
81         void Init(SQSharedState *ss);\r
82         SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize);\r
83         SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize);\r
84 public:\r
85         static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {\r
86                 \r
87                 SQInteger size = calcinstancesize(theclass);\r
88                 SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);\r
89                 new (newinst) SQInstance(ss, theclass,size);\r
90                 return newinst;\r
91         }\r
92         SQInstance *Clone(SQSharedState *ss)\r
93         {\r
94                 SQInteger size = calcinstancesize(_class);\r
95                 SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);\r
96                 new (newinst) SQInstance(ss, this,size);\r
97                 return newinst;\r
98         }\r
99         ~SQInstance();\r
100         bool Get(const SQObjectPtr &key,SQObjectPtr &val)  {\r
101                 if(_class->_members->Get(key,val)) {\r
102                         if(_isfield(val)) {\r
103                                 SQObjectPtr &o = _values[_member_idx(val)];\r
104                                 val = _realval(o);\r
105                         }\r
106                         else {\r
107                                 val = _class->_methods[_member_idx(val)].val;\r
108                         }\r
109                         return true;\r
110                 }\r
111                 return false;\r
112         }\r
113         bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {\r
114                 SQObjectPtr idx;\r
115                 if(_class->_members->Get(key,idx) && _isfield(idx)) {\r
116             _values[_member_idx(idx)] = val;\r
117                         return true;\r
118                 }\r
119                 return false;\r
120         }\r
121         void Release() { \r
122                 if (_hook) { _hook(_userpointer,0);}\r
123                 SQInteger size = _memsize;\r
124                 this->~SQInstance();\r
125                 SQ_FREE(this, size);\r
126         }\r
127         void Finalize();\r
128 #ifndef NO_GARBAGE_COLLECTOR \r
129         void Mark(SQCollectable ** );\r
130 #endif\r
131         bool InstanceOf(SQClass *trg);\r
132         bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);\r
133 \r
134         SQClass *_class;\r
135         SQUserPointer _userpointer;\r
136         SQRELEASEHOOK _hook;\r
137         SQUnsignedInteger _nvalues;\r
138         SQInteger _memsize;\r
139         SQObjectPtr _values[1];\r
140 };\r
141 \r
142 #endif //_SQCLASS_H_\r