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