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