# sqclass.h

    00001 /*  see copyright notice in squirrel.h */
    00002 #ifndef _SQCLASS_H_
    00003 #define _SQCLASS_H_
    00004
    00005 struct SQInstance;
    00006
    00007 struct SQClassMember {
    00008   SQClassMember(){}
    00009   SQClassMember(const SQClassMember &o) {
    00010     val = o.val;
    00011     attrs = o.attrs;
    00012   }
    00013   SQObjectPtr val;
    00014   SQObjectPtr attrs;
    00015 };
    00016
    00017 typedef sqvector<SQClassMember> SQClassMemberVec;
    00018
    00019 #define MEMBER_TYPE_METHOD 0x01000000
    00020 #define MEMBER_TYPE_FIELD 0x02000000
    00021
    00022 #define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD)
    00023 #define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD)
    00024 #define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i))
    00025 #define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i))
    00026 #define _member_type(o) (_integer(o)&0xFF000000)
    00027 #define _member_idx(o) (_integer(o)&0x00FFFFFF)
    00028
    00029 struct SQClass : public CHAINABLE_OBJ
    00030 {
    00031   SQClass(SQSharedState *ss,SQClass *base);
    00032 public:
    00033   static SQClass* Create(SQSharedState *ss,SQClass *base) {
    00034     SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));
    00035     new (newclass) SQClass(ss, base);
    00036     return newclass;
    00037   }
    00038   ~SQClass();
    00039   bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic);
    00040   bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
    00041     if(_members->Get(key,val)) {
    00042       if(_isfield(val)) {
    00043         SQObjectPtr &o = _defaultvalues[_member_idx(val)].val;
    00044         val = _realval(o);
    00045       }
    00046       else {
    00047         val = _methods[_member_idx(val)].val;
    00048       }
    00049       return true;
    00050     }
    00051     return false;
    00052   }
    00053   bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val);
    00054   bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval);
    00055   void Lock() { _locked = true; if(_base) _base->Lock(); }
    00056   void Release() {
    00057     if (_hook) { _hook(_typetag,0);}
    00058     sq_delete(this, SQClass);
    00059   }
    00060   void Finalize();
    00061 #ifndef NO_GARBAGE_COLLECTOR
    00062   void Mark(SQCollectable ** );
    00063 #endif
    00064   SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
    00065   SQInstance *CreateInstance();
    00066   SQTable *_members;
    00067   SQClass *_base;
    00068   SQClassMemberVec _defaultvalues;
    00069   SQClassMemberVec _methods;
    00070   SQObjectPtrVec _metamethods;
    00071   SQObjectPtr _attributes;
    00072   SQUserPointer _typetag;
    00073   SQRELEASEHOOK _hook;
    00074   bool _locked;
    00075   SQInteger _udsize;
    00076 };
    00077
    00078 #define calcinstancesize(_theclass_) \
    00079   (_theclass_->_udsize + sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0)))
    00080
    00081 struct SQInstance : public SQDelegable
    00082 {
    00083   void Init(SQSharedState *ss);
    00084   SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize);
    00085   SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize);
    00086 public:
    00087   static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {
    00088
    00089     SQInteger size = calcinstancesize(theclass);
    00090     SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
    00091     new (newinst) SQInstance(ss, theclass,size);
    00092     if(theclass->_udsize) {
    00093       newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);
    00094     }
    00095     return newinst;
    00096   }
    00097   SQInstance *Clone(SQSharedState *ss)
    00098   {
    00099     SQInteger size = calcinstancesize(_class);
    00100     SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
    00101     new (newinst) SQInstance(ss, this,size);
    00102     if(_class->_udsize) {
    00103       newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);
    00104     }
    00105     return newinst;
    00106   }
    00107   ~SQInstance();
    00108   bool Get(const SQObjectPtr &key,SQObjectPtr &val)  {
    00109     if(_class->_members->Get(key,val)) {
    00110       if(_isfield(val)) {
    00111         SQObjectPtr &o = _values[_member_idx(val)];
    00112         val = _realval(o);
    00113       }
    00114       else {
    00115         val = _class->_methods[_member_idx(val)].val;
    00116       }
    00117       return true;
    00118     }
    00119     return false;
    00120   }
    00121   bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {
    00122     SQObjectPtr idx;
    00123     if(_class->_members->Get(key,idx) && _isfield(idx)) {
    00124             _values[_member_idx(idx)] = val;
    00125       return true;
    00126     }
    00127     return false;
    00128   }
    00129   void Release() {
    00130     _uiRef++;
    00131     try {
    00132       if (_hook) { _hook(_userpointer,0);}
    00133     } catch (...) {
    00134       _uiRef--;
    00135       if (_uiRef == 0) {
    00136         SQInteger size = _memsize;
    00137         this->~SQInstance();
    00138         SQ_FREE(this, size);
    00139       }
    00140       throw;
    00141     }
    00142     _uiRef--;
    00143     if(_uiRef > 0) return;
    00144     SQInteger size = _memsize;
    00145     this->~SQInstance();
    00146     SQ_FREE(this, size);
    00147   }
    00148   void Finalize();
    00149 #ifndef NO_GARBAGE_COLLECTOR
    00150   void Mark(SQCollectable ** );
    00151 #endif
    00152   bool InstanceOf(SQClass *trg);
    00153   bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
    00154
    00155   SQClass *_class;
    00156   SQUserPointer _userpointer;
    00157   SQRELEASEHOOK _hook;
    00158   SQInteger _memsize;
    00159   SQObjectPtr _values[1];
    00160 };
    00161
    00162 #endif //_SQCLASS_H_