Update to Squirrel 3.0.6
[supertux.git] / external / 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 SQClassMember {\r
8         SQObjectPtr val;\r
9         SQObjectPtr attrs;\r
10         void Null() {\r
11                 val.Null();\r
12                 attrs.Null();\r
13         }\r
14 };\r
15 \r
16 typedef sqvector<SQClassMember> SQClassMemberVec;\r
17 \r
18 #define MEMBER_TYPE_METHOD 0x01000000\r
19 #define MEMBER_TYPE_FIELD 0x02000000\r
20 \r
21 #define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD)\r
22 #define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD)\r
23 #define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i))\r
24 #define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i))\r
25 #define _member_type(o) (_integer(o)&0xFF000000)\r
26 #define _member_idx(o) (_integer(o)&0x00FFFFFF)\r
27 \r
28 struct SQClass : public CHAINABLE_OBJ\r
29 {\r
30         SQClass(SQSharedState *ss,SQClass *base);\r
31 public:\r
32         static SQClass* Create(SQSharedState *ss,SQClass *base) {\r
33                 SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));\r
34                 new (newclass) SQClass(ss, base);\r
35                 return newclass;\r
36         }\r
37         ~SQClass();\r
38         bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic);\r
39         bool Get(const SQObjectPtr &key,SQObjectPtr &val) {\r
40                 if(_members->Get(key,val)) {\r
41                         if(_isfield(val)) {\r
42                                 SQObjectPtr &o = _defaultvalues[_member_idx(val)].val;\r
43                                 val = _realval(o);\r
44                         }\r
45                         else {\r
46                                 val = _methods[_member_idx(val)].val;\r
47                         }\r
48                         return true;\r
49                 }\r
50                 return false;\r
51         }\r
52         bool GetConstructor(SQObjectPtr &ctor)\r
53         {\r
54                 if(_constructoridx != -1) {\r
55                         ctor = _methods[_constructoridx].val;\r
56                         return true;\r
57                 }\r
58                 return false;\r
59         }\r
60         bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val);\r
61         bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval);\r
62         void Lock() { _locked = true; if(_base) _base->Lock(); }\r
63         void Release() { \r
64                 if (_hook) { _hook(_typetag,0);}\r
65                 sq_delete(this, SQClass);       \r
66         }\r
67         void Finalize();\r
68 #ifndef NO_GARBAGE_COLLECTOR\r
69         void Mark(SQCollectable ** );\r
70         SQObjectType GetType() {return OT_CLASS;}\r
71 #endif\r
72         SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
73         SQInstance *CreateInstance();\r
74         SQTable *_members;\r
75         SQClass *_base;\r
76         SQClassMemberVec _defaultvalues;\r
77         SQClassMemberVec _methods;\r
78         SQObjectPtr _metamethods[MT_LAST];\r
79         SQObjectPtr _attributes;\r
80         SQUserPointer _typetag;\r
81         SQRELEASEHOOK _hook;\r
82         bool _locked;\r
83         SQInteger _constructoridx;\r
84         SQInteger _udsize;\r
85 };\r
86 \r
87 #define calcinstancesize(_theclass_) \\r
88         (_theclass_->_udsize + sq_aligning(sizeof(SQInstance) +  (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))))\r
89 \r
90 struct SQInstance : public SQDelegable \r
91 {\r
92         void Init(SQSharedState *ss);\r
93         SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize);\r
94         SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize);\r
95 public:\r
96         static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {\r
97                 \r
98                 SQInteger size = calcinstancesize(theclass);\r
99                 SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);\r
100                 new (newinst) SQInstance(ss, theclass,size);\r
101                 if(theclass->_udsize) {\r
102                         newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);\r
103                 }\r
104                 return newinst;\r
105         }\r
106         SQInstance *Clone(SQSharedState *ss)\r
107         {\r
108                 SQInteger size = calcinstancesize(_class);\r
109                 SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);\r
110                 new (newinst) SQInstance(ss, this,size);\r
111                 if(_class->_udsize) {\r
112                         newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);\r
113                 }\r
114                 return newinst;\r
115         }\r
116         ~SQInstance();\r
117         bool Get(const SQObjectPtr &key,SQObjectPtr &val)  {\r
118                 if(_class->_members->Get(key,val)) {\r
119                         if(_isfield(val)) {\r
120                                 SQObjectPtr &o = _values[_member_idx(val)];\r
121                                 val = _realval(o);\r
122                         }\r
123                         else {\r
124                                 val = _class->_methods[_member_idx(val)].val;\r
125                         }\r
126                         return true;\r
127                 }\r
128                 return false;\r
129         }\r
130         bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {\r
131                 SQObjectPtr idx;\r
132                 if(_class->_members->Get(key,idx) && _isfield(idx)) {\r
133             _values[_member_idx(idx)] = val;\r
134                         return true;\r
135                 }\r
136                 return false;\r
137         }\r
138         void Release() {\r
139                 _uiRef++;\r
140                 if (_hook) { _hook(_userpointer,0);}\r
141                 _uiRef--;\r
142                 if(_uiRef > 0) return;\r
143                 SQInteger size = _memsize;\r
144                 this->~SQInstance();\r
145                 SQ_FREE(this, size);\r
146         }\r
147         void Finalize();\r
148 #ifndef NO_GARBAGE_COLLECTOR \r
149         void Mark(SQCollectable ** );\r
150         SQObjectType GetType() {return OT_INSTANCE;}\r
151 #endif\r
152         bool InstanceOf(SQClass *trg);\r
153         bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);\r
154 \r
155         SQClass *_class;\r
156         SQUserPointer _userpointer;\r
157         SQRELEASEHOOK _hook;\r
158         SQInteger _memsize;\r
159         SQObjectPtr _values[1];\r
160 };\r
161 \r
162 #endif //_SQCLASS_H_\r