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