sqclass.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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),_udsize(0),_constructoridx(-1),_destructoridx(-1),_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 (_members->CountUsed() >= MEMBER_MAX_COUNT) {
  54. return false;
  55. }
  56. if(belongs_to_static_table) {
  57. SQInteger mmidx;
  58. if((sq_type(val) == OT_CLOSURE || sq_type(val) == OT_NATIVECLOSURE) &&
  59. (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
  60. _metamethods[mmidx] = val;
  61. }
  62. else {
  63. SQObjectPtr theval = val;
  64. if(_base && sq_type(val) == OT_CLOSURE) {
  65. theval = _closure(val)->Clone();
  66. _closure(theval)->_base = _base;
  67. __ObjAddRef(_base); //ref for the closure
  68. }
  69. if(sq_type(temp) == OT_NULL) {
  70. if(SQVM::IsEqual(ss->_constructoridx, key)) {
  71. _constructoridx = (SQInteger)_methods.size();
  72. }
  73. else if(SQVM::IsEqual(ss->_destructoridx, key)) {
  74. _destructoridx = (SQInteger)_methods.size();
  75. }
  76. SQClassMember m;
  77. m.val = theval;
  78. _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
  79. _methods.push_back(m);
  80. }
  81. else {
  82. _methods[_member_idx(temp)].val = theval;
  83. }
  84. }
  85. return true;
  86. }
  87. SQClassMember m;
  88. m.val = val;
  89. _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
  90. _defaultvalues.push_back(m);
  91. return true;
  92. }
  93. SQInstance *SQClass::CreateInstance()
  94. {
  95. if(!_locked) Lock();
  96. return SQInstance::Create(_opt_ss(this),this);
  97. }
  98. SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
  99. {
  100. SQObjectPtr oval;
  101. SQInteger idx = _members->Next(false,refpos,outkey,oval);
  102. if(idx != -1) {
  103. if(_ismethod(oval)) {
  104. outval = _methods[_member_idx(oval)].val;
  105. }
  106. else {
  107. SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
  108. outval = _realval(o);
  109. }
  110. }
  111. return idx;
  112. }
  113. bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
  114. {
  115. SQObjectPtr idx;
  116. if(_members->Get(key,idx)) {
  117. if(_isfield(idx))
  118. _defaultvalues[_member_idx(idx)].attrs = val;
  119. else
  120. _methods[_member_idx(idx)].attrs = val;
  121. return true;
  122. }
  123. return false;
  124. }
  125. bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
  126. {
  127. SQObjectPtr idx;
  128. if(_members->Get(key,idx)) {
  129. outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
  130. return true;
  131. }
  132. return false;
  133. }
  134. ///////////////////////////////////////////////////////////////////////
  135. void SQInstance::Init(SQSharedState *ss)
  136. {
  137. _userpointer = NULL;
  138. _hook = NULL;
  139. __ObjAddRef(_class);
  140. _delegate = _class->_members;
  141. INIT_CHAIN();
  142. ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
  143. }
  144. SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
  145. {
  146. _memsize = memsize;
  147. _class = c;
  148. SQUnsignedInteger nvalues = _class->_defaultvalues.size();
  149. for(SQUnsignedInteger n = 0; n < nvalues; n++) {
  150. new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);
  151. }
  152. Init(ss);
  153. }
  154. SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
  155. {
  156. _memsize = memsize;
  157. _class = i->_class;
  158. SQUnsignedInteger nvalues = _class->_defaultvalues.size();
  159. for(SQUnsignedInteger n = 0; n < nvalues; n++) {
  160. new (&_values[n]) SQObjectPtr(i->_values[n]);
  161. }
  162. Init(ss);
  163. }
  164. void SQInstance::Finalize()
  165. {
  166. SQUnsignedInteger nvalues = _class->_defaultvalues.size();
  167. __ObjRelease(_class);
  168. _NULL_SQOBJECT_VECTOR(_values,nvalues);
  169. //for(SQUnsignedInteger i = 0; i < nvalues; i++) {
  170. // _values[i].Null();
  171. // }
  172. }
  173. SQInstance::~SQInstance()
  174. {
  175. REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
  176. if(_class){ Finalize(); } //if _class is null it was already finalized by the GC
  177. }
  178. bool SQInstance::GetMetaMethod(SQVM* SQ_UNUSED_ARG(v),SQMetaMethod mm,SQObjectPtr &res)
  179. {
  180. if(sq_type(_class->_metamethods[mm]) != OT_NULL) {
  181. res = _class->_metamethods[mm];
  182. return true;
  183. }
  184. return false;
  185. }
  186. bool SQInstance::InstanceOf(SQClass *trg)
  187. {
  188. SQClass *parent = _class;
  189. while(parent != NULL) {
  190. if(parent == trg)
  191. return true;
  192. parent = parent->_base;
  193. }
  194. return false;
  195. }