sqclass.cpp 5.7 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. {
  12. _base = base;
  13. _typetag = 0;
  14. _hook = NULL;
  15. _udsize = 0;
  16. _locked = false;
  17. _constructoridx = -1;
  18. if(_base) {
  19. _constructoridx = _base->_constructoridx;
  20. _udsize = _base->_udsize;
  21. _defaultvalues.copy(base->_defaultvalues);
  22. _methods.copy(base->_methods);
  23. _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);
  24. __ObjAddRef(_base);
  25. }
  26. _members = base?base->_members->Clone() : SQTable::Create(ss,0);
  27. __ObjAddRef(_members);
  28. INIT_CHAIN();
  29. ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
  30. }
  31. void SQClass::Finalize() {
  32. _attributes.Null();
  33. _NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
  34. _methods.resize(0);
  35. _NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST);
  36. __ObjRelease(_members);
  37. if(_base) {
  38. __ObjRelease(_base);
  39. }
  40. }
  41. SQClass::~SQClass()
  42. {
  43. REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
  44. Finalize();
  45. }
  46. bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
  47. {
  48. SQObjectPtr temp;
  49. bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic;
  50. if(_locked && !belongs_to_static_table)
  51. return false; //the class already has an instance so cannot be modified
  52. if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value
  53. {
  54. _defaultvalues[_member_idx(temp)].val = val;
  55. return true;
  56. }
  57. if(belongs_to_static_table) {
  58. SQInteger mmidx;
  59. if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) &&
  60. (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
  61. _metamethods[mmidx] = val;
  62. }
  63. else {
  64. SQObjectPtr theval = val;
  65. if(_base && type(val) == OT_CLOSURE) {
  66. theval = _closure(val)->Clone();
  67. _closure(theval)->_base = _base;
  68. __ObjAddRef(_base); //ref for the closure
  69. }
  70. if(type(temp) == OT_NULL) {
  71. bool isconstructor;
  72. SQVM::IsEqual(ss->_constructoridx, key, isconstructor);
  73. if(isconstructor) {
  74. _constructoridx = (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. }
  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 *v,SQMetaMethod mm,SQObjectPtr &res)
  176. {
  177. if(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. }