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