sqclass.cpp 5.2 KB

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