# sqclass.cpp

    00001 /*
    00002   see copyright notice in squirrel.h
    00003 */
    00004 #include "sqpcheader.h"
    00005 #include "sqvm.h"
    00006 #include "sqtable.h"
    00007 #include "sqclass.h"
    00008 #include "sqclosure.h"
    00009
    00010 SQClass::SQClass(SQSharedState *ss,SQClass *base)
    00011 {
    00012   _base = base;
    00013   _typetag = 0;
    00014   _hook = NULL;
    00015   _udsize = 0;
    00016   _metamethods.resize(MT_LAST); //size it to max size
    00017   if(_base) {
    00018     _defaultvalues.copy(base->_defaultvalues);
    00019     _methods.copy(base->_methods);
    00020     _metamethods.copy(base->_metamethods);
    00021     __ObjAddRef(_base);
    00022   }
    00023   _members = base?base->_members->Clone() : SQTable::Create(ss,0);
    00024   __ObjAddRef(_members);
    00025   _locked = false;
    00026   INIT_CHAIN();
    00027   ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
    00028 }
    00029
    00030 void SQClass::Finalize() {
    00031   _attributes = _null_;
    00032   _defaultvalues.resize(0);
    00033   _methods.resize(0);
    00034   _metamethods.resize(0);
    00035   __ObjRelease(_members);
    00036   if(_base) {
    00037     __ObjRelease(_base);
    00038   }
    00039 }
    00040
    00041 SQClass::~SQClass()
    00042 {
    00043   REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
    00044   Finalize();
    00045 }
    00046
    00047 bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
    00048 {
    00049   SQObjectPtr temp;
    00050   if(_locked)
    00051     return false; //the class already has an instance so cannot be modified
    00052   if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value
    00053   {
    00054     _defaultvalues[_member_idx(temp)].val = val;
    00055     return true;
    00056   }
    00057   if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) {
    00058     SQInteger mmidx;
    00059     if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) &&
    00060       (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
    00061       _metamethods[mmidx] = val;
    00062     }
    00063     else {
    00064       if(type(temp) == OT_NULL) {
    00065         SQClassMember m;
    00066         m.val = val;
    00067         _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
    00068         _methods.push_back(m);
    00069       }
    00070       else {
    00071         _methods[_member_idx(temp)].val = val;
    00072       }
    00073     }
    00074     return true;
    00075   }
    00076   SQClassMember m;
    00077   m.val = val;
    00078   _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
    00079   _defaultvalues.push_back(m);
    00080   return true;
    00081 }
    00082
    00083 SQInstance *SQClass::CreateInstance()
    00084 {
    00085   if(!_locked) Lock();
    00086   return SQInstance::Create(_opt_ss(this),this);
    00087 }
    00088
    00089 SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
    00090 {
    00091   SQObjectPtr oval;
    00092   SQInteger idx = _members->Next(false,refpos,outkey,oval);
    00093   if(idx != -1) {
    00094     if(_ismethod(oval)) {
    00095       outval = _methods[_member_idx(oval)].val;
    00096     }
    00097     else {
    00098       SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
    00099       outval = _realval(o);
    00100     }
    00101   }
    00102   return idx;
    00103 }
    00104
    00105 bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
    00106 {
    00107   SQObjectPtr idx;
    00108   if(_members->Get(key,idx)) {
    00109     if(_isfield(idx))
    00110       _defaultvalues[_member_idx(idx)].attrs = val;
    00111     else
    00112       _methods[_member_idx(idx)].attrs = val;
    00113     return true;
    00114   }
    00115   return false;
    00116 }
    00117
    00118 bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
    00119 {
    00120   SQObjectPtr idx;
    00121   if(_members->Get(key,idx)) {
    00122     outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
    00123     return true;
    00124   }
    00125   return false;
    00126 }
    00127
    00129 void SQInstance::Init(SQSharedState *ss)
    00130 {
    00131   _userpointer = NULL;
    00132   _hook = NULL;
    00133   __ObjAddRef(_class);
    00134   _delegate = _class->_members;
    00135   INIT_CHAIN();
    00136   ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
    00137 }
    00138
    00139 SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
    00140 {
    00141   _memsize = memsize;
    00142   _class = c;
    00143   SQUnsignedInteger nvalues = _class->_defaultvalues.size();
    00144   for(SQUnsignedInteger n = 0; n < nvalues; n++) {
    00145     new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);
    00146   }
    00147   Init(ss);
    00148 }
    00149
    00150 SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
    00151 {
    00152   _memsize = memsize;
    00153   _class = i->_class;
    00154   SQUnsignedInteger nvalues = _class->_defaultvalues.size();
    00155   for(SQUnsignedInteger n = 0; n < nvalues; n++) {
    00156     new (&_values[n]) SQObjectPtr(i->_values[n]);
    00157   }
    00158   Init(ss);
    00159 }
    00160
    00161 void SQInstance::Finalize()
    00162 {
    00163   SQUnsignedInteger nvalues = _class->_defaultvalues.size();
    00164   __ObjRelease(_class);
    00165   for(SQUnsignedInteger i = 0; i < nvalues; i++) {
    00166     _values[i] = _null_;
    00167   }
    00168 }
    00169
    00170 SQInstance::~SQInstance()
    00171 {
    00172   REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
    00173   if(_class){ Finalize(); } //if _class is null it was already finalized by the GC
    00174 }
    00175
    00176 bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res)
    00177 {
    00178   if(type(_class->_metamethods[mm]) != OT_NULL) {
    00179     res = _class->_metamethods[mm];
    00180     return true;
    00181   }
    00182   return false;
    00183 }
    00184
    00185 bool SQInstance::InstanceOf(SQClass *trg)
    00186 {
    00187   SQClass *parent = _class;
    00188   while(parent != NULL) {
    00189     if(parent == trg)
    00190       return true;
    00191     parent = parent->_base;
    00192   }
    00193   return false;
    00194 }