sqclass.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. see copyright notice in squirrel.h
  3. */
  4. #include "sqpcheader.h"
  5. #include "sqvm.h"
  6. #include "sqtable.h"
  7. #include "sqclass.h"
  8. #include "sqfuncproto.h"
  9. #include "sqclosure.h"
  10. SQClass::SQClass(SQSharedState *ss,SQClass *base):
  11. _base(base),_typetag(0),_hook(NULL),_constructoridx(-1),_destructoridx(-1),_udsize(0),_locked(false)
  12. {
  13. if(_base) {
  14. _constructoridx = _base->_constructoridx;
  15. _destructoridx = _base->_destructoridx;
  16. _udsize = _base->_udsize;
  17. _defaultvalues.copy(base->_defaultvalues);
  18. _methods.copy(base->_methods);
  19. _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);
  20. __ObjAddRef(_base);
  21. }
  22. _members = base?base->_members->Clone() : SQTable::Create(ss,0);
  23. __ObjAddRef(_members);
  24. INIT_CHAIN();
  25. ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
  26. }
  27. void SQClass::Finalize() {
  28. _attributes.Null();
  29. _NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
  30. _methods.resize(0);
  31. _NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST);
  32. __ObjRelease(_members);
  33. if(_base) {
  34. __ObjRelease(_base);
  35. }
  36. }
  37. SQClass::~SQClass()
  38. {
  39. REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
  40. Finalize();
  41. }
  42. bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
  43. {
  44. SQObjectPtr temp;
  45. bool belongs_to_static_table = sq_type(val) == OT_CLOSURE || sq_type(val) == OT_NATIVECLOSURE || bstatic;
  46. if(_locked && !belongs_to_static_table)
  47. return false; //the class already has an instance so cannot be modified
  48. if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value
  49. {
  50. _defaultvalues[_member_idx(temp)].val = val;
  51. return true;
  52. }
  53. if(belongs_to_static_table) {
  54. SQInteger mmidx;
  55. if((sq_type(val) == OT_CLOSURE || sq_type(val) == OT_NATIVECLOSURE) &&
  56. (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
  57. _metamethods[mmidx] = val;
  58. }
  59. else {
  60. SQObjectPtr theval = val;
  61. if(_base && sq_type(val) == OT_CLOSURE) {
  62. theval = _closure(val)->Clone();
  63. _closure(theval)->_base = _base;
  64. __ObjAddRef(_base); //ref for the closure
  65. }
  66. if(sq_type(temp) == OT_NULL) {
  67. if(SQVM::IsEqual(ss->_constructoridx, key)) {
  68. _constructoridx = (SQInteger)_methods.size();
  69. }
  70. else if(SQVM::IsEqual(ss->_destructoridx, key)) {
  71. _destructoridx = (SQInteger)_methods.size();
  72. }
  73. SQClassMember m;
  74. m.val = theval;
  75. _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
  76. _methods.push_back(m);
  77. }
  78. else {
  79. _methods[_member_idx(temp)].val = theval;
  80. }
  81. }
  82. return true;
  83. }
  84. SQClassMember m;
  85. m.val = val;
  86. _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
  87. _defaultvalues.push_back(m);
  88. return true;
  89. }
  90. SQInstance *SQClass::CreateInstance()
  91. {
  92. if(!_locked) Lock();
  93. return SQInstance::Create(_opt_ss(this),this);
  94. }
  95. SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
  96. {
  97. SQObjectPtr oval;
  98. SQInteger idx = _members->Next(false,refpos,outkey,oval);
  99. if(idx != -1) {
  100. if(_ismethod(oval)) {
  101. outval = _methods[_member_idx(oval)].val;
  102. }
  103. else {
  104. SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
  105. outval = _realval(o);
  106. }
  107. }
  108. return idx;
  109. }
  110. bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
  111. {
  112. SQObjectPtr idx;
  113. if(_members->Get(key,idx)) {
  114. if(_isfield(idx))
  115. _defaultvalues[_member_idx(idx)].attrs = val;
  116. else
  117. _methods[_member_idx(idx)].attrs = val;
  118. return true;
  119. }
  120. return false;
  121. }
  122. bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
  123. {
  124. SQObjectPtr idx;
  125. if(_members->Get(key,idx)) {
  126. outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
  127. return true;
  128. }
  129. return false;
  130. }
  131. ///////////////////////////////////////////////////////////////////////
  132. void SQInstance::Init(SQSharedState *ss)
  133. {
  134. _userpointer = NULL;
  135. _hook = NULL;
  136. __ObjAddRef(_class);
  137. _delegate = _class->_members;
  138. INIT_CHAIN();
  139. ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
  140. }
  141. SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
  142. {
  143. _memsize = memsize;
  144. _class = c;
  145. SQUnsignedInteger nvalues = _class->_defaultvalues.size();
  146. for(SQUnsignedInteger n = 0; n < nvalues; n++) {
  147. new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);
  148. }
  149. Init(ss);
  150. }
  151. SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
  152. {
  153. _memsize = memsize;
  154. _class = i->_class;
  155. SQUnsignedInteger nvalues = _class->_defaultvalues.size();
  156. for(SQUnsignedInteger n = 0; n < nvalues; n++) {
  157. new (&_values[n]) SQObjectPtr(i->_values[n]);
  158. }
  159. Init(ss);
  160. }
  161. void SQInstance::Finalize()
  162. {
  163. SQUnsignedInteger nvalues = _class->_defaultvalues.size();
  164. __ObjRelease(_class);
  165. _NULL_SQOBJECT_VECTOR(_values,nvalues);
  166. //for(SQUnsignedInteger i = 0; i < nvalues; i++) {
  167. // _values[i].Null();
  168. // }
  169. }
  170. SQInstance::~SQInstance()
  171. {
  172. REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
  173. if(_class){ Finalize(); } //if _class is null it was already finalized by the GC
  174. }
  175. bool SQInstance::GetMetaMethod(SQVM* SQ_UNUSED_ARG(v),SQMetaMethod mm,SQObjectPtr &res)
  176. {
  177. if(sq_type(_class->_metamethods[mm]) != OT_NULL) {
  178. res = _class->_metamethods[mm];
  179. return true;
  180. }
  181. return false;
  182. }
  183. bool SQInstance::InstanceOf(SQClass *trg)
  184. {
  185. SQClass *parent = _class;
  186. while(parent != NULL) {
  187. if(parent == trg)
  188. return true;
  189. parent = parent->_base;
  190. }
  191. return false;
  192. }