sqstate.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. /*
  2. see copyright notice in squirrel.h
  3. */
  4. #include "sqpcheader.h"
  5. #include "sqopcodes.h"
  6. #include "sqvm.h"
  7. #include "sqfuncproto.h"
  8. #include "sqclosure.h"
  9. #include "sqstring.h"
  10. #include "sqtable.h"
  11. #include "sqarray.h"
  12. #include "squserdata.h"
  13. #include "sqclass.h"
  14. //SQObjectPtr _null_;
  15. //SQObjectPtr _true_(true);
  16. //SQObjectPtr _false_(false);
  17. //SQObjectPtr _one_((SQInteger)1);
  18. //SQObjectPtr _minusone_((SQInteger)-1);
  19. SQSharedState::SQSharedState()
  20. {
  21. _compilererrorhandler = NULL;
  22. _printfunc = NULL;
  23. _errorfunc = NULL;
  24. _debuginfo = false;
  25. _notifyallexceptions = false;
  26. _foreignptr = NULL;
  27. _releasehook = NULL;
  28. }
  29. #define newsysstring(s) { \
  30. _systemstrings->push_back(SQString::Create(this,s)); \
  31. }
  32. #define newmetamethod(s) { \
  33. _metamethods->push_back(SQString::Create(this,s)); \
  34. _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \
  35. }
  36. bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
  37. {
  38. SQInteger i = 0;
  39. SQInteger mask = 0;
  40. while(typemask[i] != 0) {
  41. switch(typemask[i]){
  42. case 'o': mask |= _RT_NULL; break;
  43. case 'i': mask |= _RT_INTEGER; break;
  44. case 'f': mask |= _RT_FLOAT; break;
  45. case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;
  46. case 's': mask |= _RT_STRING; break;
  47. case 't': mask |= _RT_TABLE; break;
  48. case 'a': mask |= _RT_ARRAY; break;
  49. case 'u': mask |= _RT_USERDATA; break;
  50. case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;
  51. case 'b': mask |= _RT_BOOL; break;
  52. case 'g': mask |= _RT_GENERATOR; break;
  53. case 'p': mask |= _RT_USERPOINTER; break;
  54. case 'v': mask |= _RT_THREAD; break;
  55. case 'x': mask |= _RT_INSTANCE; break;
  56. case 'y': mask |= _RT_CLASS; break;
  57. case 'r': mask |= _RT_WEAKREF; break;
  58. case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;
  59. case ' ': i++; continue; //ignores spaces
  60. default:
  61. return false;
  62. }
  63. i++;
  64. if(typemask[i] == '|') {
  65. i++;
  66. if(typemask[i] == 0)
  67. return false;
  68. continue;
  69. }
  70. res.push_back(mask);
  71. mask = 0;
  72. }
  73. return true;
  74. }
  75. SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
  76. {
  77. SQInteger i=0;
  78. SQTable *t=SQTable::Create(ss,0);
  79. while(funcz[i].name!=0){
  80. SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f,0);
  81. nc->_nparamscheck = funcz[i].nparamscheck;
  82. nc->_name = SQString::Create(ss,funcz[i].name);
  83. if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))
  84. return NULL;
  85. t->NewSlot(SQString::Create(ss,funcz[i].name),nc);
  86. i++;
  87. }
  88. return t;
  89. }
  90. void SQSharedState::Init()
  91. {
  92. _scratchpad=NULL;
  93. _scratchpadsize=0;
  94. #ifndef NO_GARBAGE_COLLECTOR
  95. _gc_chain=NULL;
  96. #endif
  97. _stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable));
  98. new (_stringtable) SQStringTable(this);
  99. sq_new(_metamethods,SQObjectPtrVec);
  100. sq_new(_systemstrings,SQObjectPtrVec);
  101. sq_new(_types,SQObjectPtrVec);
  102. _metamethodsmap = SQTable::Create(this,MT_LAST-1);
  103. //adding type strings to avoid memory trashing
  104. //types names
  105. newsysstring(_SC("null"));
  106. newsysstring(_SC("table"));
  107. newsysstring(_SC("array"));
  108. newsysstring(_SC("closure"));
  109. newsysstring(_SC("string"));
  110. newsysstring(_SC("userdata"));
  111. newsysstring(_SC("integer"));
  112. newsysstring(_SC("float"));
  113. newsysstring(_SC("userpointer"));
  114. newsysstring(_SC("function"));
  115. newsysstring(_SC("generator"));
  116. newsysstring(_SC("thread"));
  117. newsysstring(_SC("class"));
  118. newsysstring(_SC("instance"));
  119. newsysstring(_SC("bool"));
  120. //meta methods
  121. newmetamethod(MM_ADD);
  122. newmetamethod(MM_SUB);
  123. newmetamethod(MM_MUL);
  124. newmetamethod(MM_DIV);
  125. newmetamethod(MM_UNM);
  126. newmetamethod(MM_MODULO);
  127. newmetamethod(MM_SET);
  128. newmetamethod(MM_GET);
  129. newmetamethod(MM_TYPEOF);
  130. newmetamethod(MM_NEXTI);
  131. newmetamethod(MM_CMP);
  132. newmetamethod(MM_CALL);
  133. newmetamethod(MM_CLONED);
  134. newmetamethod(MM_NEWSLOT);
  135. newmetamethod(MM_DELSLOT);
  136. newmetamethod(MM_TOSTRING);
  137. newmetamethod(MM_NEWMEMBER);
  138. newmetamethod(MM_INHERITED);
  139. _constructoridx = SQString::Create(this,_SC("constructor"));
  140. _registry = SQTable::Create(this,0);
  141. _consts = SQTable::Create(this,0);
  142. _table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz);
  143. _array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz);
  144. _string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz);
  145. _number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz);
  146. _closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz);
  147. _generator_default_delegate = CreateDefaultDelegate(this,_generator_default_delegate_funcz);
  148. _thread_default_delegate = CreateDefaultDelegate(this,_thread_default_delegate_funcz);
  149. _class_default_delegate = CreateDefaultDelegate(this,_class_default_delegate_funcz);
  150. _instance_default_delegate = CreateDefaultDelegate(this,_instance_default_delegate_funcz);
  151. _weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz);
  152. }
  153. SQSharedState::~SQSharedState()
  154. {
  155. if(_releasehook) { _releasehook(_foreignptr,0); _releasehook = NULL; }
  156. _constructoridx.Null();
  157. _table(_registry)->Finalize();
  158. _table(_consts)->Finalize();
  159. _table(_metamethodsmap)->Finalize();
  160. _registry.Null();
  161. _consts.Null();
  162. _metamethodsmap.Null();
  163. while(!_systemstrings->empty()) {
  164. _systemstrings->back().Null();
  165. _systemstrings->pop_back();
  166. }
  167. _thread(_root_vm)->Finalize();
  168. _root_vm.Null();
  169. _table_default_delegate.Null();
  170. _array_default_delegate.Null();
  171. _string_default_delegate.Null();
  172. _number_default_delegate.Null();
  173. _closure_default_delegate.Null();
  174. _generator_default_delegate.Null();
  175. _thread_default_delegate.Null();
  176. _class_default_delegate.Null();
  177. _instance_default_delegate.Null();
  178. _weakref_default_delegate.Null();
  179. _refs_table.Finalize();
  180. #ifndef NO_GARBAGE_COLLECTOR
  181. SQCollectable *t = _gc_chain;
  182. SQCollectable *nx = NULL;
  183. if(t) {
  184. t->_uiRef++;
  185. while(t) {
  186. t->Finalize();
  187. nx = t->_next;
  188. if(nx) nx->_uiRef++;
  189. if(--t->_uiRef == 0)
  190. t->Release();
  191. t = nx;
  192. }
  193. }
  194. assert(_gc_chain==NULL); //just to proove a theory
  195. while(_gc_chain){
  196. _gc_chain->_uiRef++;
  197. _gc_chain->Release();
  198. }
  199. #endif
  200. sq_delete(_types,SQObjectPtrVec);
  201. sq_delete(_systemstrings,SQObjectPtrVec);
  202. sq_delete(_metamethods,SQObjectPtrVec);
  203. sq_delete(_stringtable,SQStringTable);
  204. if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
  205. }
  206. SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)
  207. {
  208. if(type(name) != OT_STRING)
  209. return -1;
  210. SQObjectPtr ret;
  211. if(_table(_metamethodsmap)->Get(name,ret)) {
  212. return _integer(ret);
  213. }
  214. return -1;
  215. }
  216. #ifndef NO_GARBAGE_COLLECTOR
  217. void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
  218. {
  219. switch(type(o)){
  220. case OT_TABLE:_table(o)->Mark(chain);break;
  221. case OT_ARRAY:_array(o)->Mark(chain);break;
  222. case OT_USERDATA:_userdata(o)->Mark(chain);break;
  223. case OT_CLOSURE:_closure(o)->Mark(chain);break;
  224. case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;
  225. case OT_GENERATOR:_generator(o)->Mark(chain);break;
  226. case OT_THREAD:_thread(o)->Mark(chain);break;
  227. case OT_CLASS:_class(o)->Mark(chain);break;
  228. case OT_INSTANCE:_instance(o)->Mark(chain);break;
  229. case OT_OUTER:_outer(o)->Mark(chain);break;
  230. case OT_FUNCPROTO:_funcproto(o)->Mark(chain);break;
  231. default: break; //shutup compiler
  232. }
  233. }
  234. void SQSharedState::RunMark(SQVM *vm,SQCollectable **tchain)
  235. {
  236. SQVM *vms = _thread(_root_vm);
  237. vms->Mark(tchain);
  238. _refs_table.Mark(tchain);
  239. MarkObject(_registry,tchain);
  240. MarkObject(_consts,tchain);
  241. MarkObject(_metamethodsmap,tchain);
  242. MarkObject(_table_default_delegate,tchain);
  243. MarkObject(_array_default_delegate,tchain);
  244. MarkObject(_string_default_delegate,tchain);
  245. MarkObject(_number_default_delegate,tchain);
  246. MarkObject(_generator_default_delegate,tchain);
  247. MarkObject(_thread_default_delegate,tchain);
  248. MarkObject(_closure_default_delegate,tchain);
  249. MarkObject(_class_default_delegate,tchain);
  250. MarkObject(_instance_default_delegate,tchain);
  251. MarkObject(_weakref_default_delegate,tchain);
  252. }
  253. SQInteger SQSharedState::ResurrectUnreachable(SQVM *vm)
  254. {
  255. SQInteger n=0;
  256. SQCollectable *tchain=NULL;
  257. RunMark(vm,&tchain);
  258. SQCollectable *resurrected = _gc_chain;
  259. SQCollectable *t = resurrected;
  260. //SQCollectable *nx = NULL;
  261. _gc_chain = tchain;
  262. SQArray *ret = NULL;
  263. if(resurrected) {
  264. ret = SQArray::Create(this,0);
  265. SQCollectable *rlast = NULL;
  266. while(t) {
  267. rlast = t;
  268. SQObjectType type = t->GetType();
  269. if(type != OT_FUNCPROTO && type != OT_OUTER) {
  270. SQObject sqo;
  271. sqo._type = type;
  272. sqo._unVal.pRefCounted = t;
  273. ret->Append(sqo);
  274. }
  275. t = t->_next;
  276. n++;
  277. }
  278. assert(rlast->_next == NULL);
  279. rlast->_next = _gc_chain;
  280. if(_gc_chain)
  281. {
  282. _gc_chain->_prev = rlast;
  283. }
  284. _gc_chain = resurrected;
  285. }
  286. t = _gc_chain;
  287. while(t) {
  288. t->UnMark();
  289. t = t->_next;
  290. }
  291. if(ret) {
  292. SQObjectPtr temp = ret;
  293. vm->Push(temp);
  294. }
  295. else {
  296. vm->PushNull();
  297. }
  298. return n;
  299. }
  300. SQInteger SQSharedState::CollectGarbage(SQVM *vm)
  301. {
  302. SQInteger n = 0;
  303. SQCollectable *tchain = NULL;
  304. RunMark(vm,&tchain);
  305. SQCollectable *t = _gc_chain;
  306. SQCollectable *nx = NULL;
  307. if(t) {
  308. t->_uiRef++;
  309. while(t) {
  310. t->Finalize();
  311. nx = t->_next;
  312. if(nx) nx->_uiRef++;
  313. if(--t->_uiRef == 0)
  314. t->Release();
  315. t = nx;
  316. n++;
  317. }
  318. }
  319. t = tchain;
  320. while(t) {
  321. t->UnMark();
  322. t = t->_next;
  323. }
  324. _gc_chain = tchain;
  325. return n;
  326. }
  327. #endif
  328. #ifndef NO_GARBAGE_COLLECTOR
  329. void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)
  330. {
  331. c->_prev = NULL;
  332. c->_next = *chain;
  333. if(*chain) (*chain)->_prev = c;
  334. *chain = c;
  335. }
  336. void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
  337. {
  338. if(c->_prev) c->_prev->_next = c->_next;
  339. else *chain = c->_next;
  340. if(c->_next)
  341. c->_next->_prev = c->_prev;
  342. c->_next = NULL;
  343. c->_prev = NULL;
  344. }
  345. #endif
  346. SQChar* SQSharedState::GetScratchPad(SQInteger size)
  347. {
  348. SQInteger newsize;
  349. if(size>0) {
  350. if(_scratchpadsize < size) {
  351. newsize = size + (size>>1);
  352. _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
  353. _scratchpadsize = newsize;
  354. }else if(_scratchpadsize >= (size<<5)) {
  355. newsize = _scratchpadsize >> 1;
  356. _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
  357. _scratchpadsize = newsize;
  358. }
  359. }
  360. return _scratchpad;
  361. }
  362. RefTable::RefTable()
  363. {
  364. AllocNodes(4);
  365. }
  366. void RefTable::Finalize()
  367. {
  368. RefNode *nodes = _nodes;
  369. for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
  370. nodes->obj.Null();
  371. nodes++;
  372. }
  373. }
  374. RefTable::~RefTable()
  375. {
  376. SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode)));
  377. }
  378. #ifndef NO_GARBAGE_COLLECTOR
  379. void RefTable::Mark(SQCollectable **chain)
  380. {
  381. RefNode *nodes = (RefNode *)_nodes;
  382. for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
  383. if(type(nodes->obj) != OT_NULL) {
  384. SQSharedState::MarkObject(nodes->obj,chain);
  385. }
  386. nodes++;
  387. }
  388. }
  389. #endif
  390. void RefTable::AddRef(SQObject &obj)
  391. {
  392. SQHash mainpos;
  393. RefNode *prev;
  394. RefNode *ref = Get(obj,mainpos,&prev,true);
  395. ref->refs++;
  396. }
  397. SQUnsignedInteger RefTable::GetRefCount(SQObject &obj)
  398. {
  399. SQHash mainpos;
  400. RefNode *prev;
  401. RefNode *ref = Get(obj,mainpos,&prev,true);
  402. return ref->refs;
  403. }
  404. SQBool RefTable::Release(SQObject &obj)
  405. {
  406. SQHash mainpos;
  407. RefNode *prev;
  408. RefNode *ref = Get(obj,mainpos,&prev,false);
  409. if(ref) {
  410. if(--ref->refs == 0) {
  411. SQObjectPtr o = ref->obj;
  412. if(prev) {
  413. prev->next = ref->next;
  414. }
  415. else {
  416. _buckets[mainpos] = ref->next;
  417. }
  418. ref->next = _freelist;
  419. _freelist = ref;
  420. _slotused--;
  421. ref->obj.Null();
  422. //<<FIXME>>test for shrink?
  423. return SQTrue;
  424. }
  425. }
  426. else {
  427. assert(0);
  428. }
  429. return SQFalse;
  430. }
  431. void RefTable::Resize(SQUnsignedInteger size)
  432. {
  433. RefNode **oldbucks = _buckets;
  434. RefNode *t = _nodes;
  435. SQUnsignedInteger oldnumofslots = _numofslots;
  436. AllocNodes(size);
  437. //rehash
  438. SQUnsignedInteger nfound = 0;
  439. for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
  440. if(type(t->obj) != OT_NULL) {
  441. //add back;
  442. assert(t->refs != 0);
  443. RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);
  444. nn->refs = t->refs;
  445. t->obj.Null();
  446. nfound++;
  447. }
  448. t++;
  449. }
  450. assert(nfound == oldnumofslots);
  451. SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode)));
  452. }
  453. RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)
  454. {
  455. RefNode *t = _buckets[mainpos];
  456. RefNode *newnode = _freelist;
  457. newnode->obj = obj;
  458. _buckets[mainpos] = newnode;
  459. _freelist = _freelist->next;
  460. newnode->next = t;
  461. assert(newnode->refs == 0);
  462. _slotused++;
  463. return newnode;
  464. }
  465. RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add)
  466. {
  467. RefNode *ref;
  468. mainpos = ::HashObj(obj)&(_numofslots-1);
  469. *prev = NULL;
  470. for (ref = _buckets[mainpos]; ref; ) {
  471. if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))
  472. break;
  473. *prev = ref;
  474. ref = ref->next;
  475. }
  476. if(ref == NULL && add) {
  477. if(_numofslots == _slotused) {
  478. assert(_freelist == 0);
  479. Resize(_numofslots*2);
  480. mainpos = ::HashObj(obj)&(_numofslots-1);
  481. }
  482. ref = Add(mainpos,obj);
  483. }
  484. return ref;
  485. }
  486. void RefTable::AllocNodes(SQUnsignedInteger size)
  487. {
  488. RefNode **bucks;
  489. RefNode *nodes;
  490. bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode)));
  491. nodes = (RefNode *)&bucks[size];
  492. RefNode *temp = nodes;
  493. SQUnsignedInteger n;
  494. for(n = 0; n < size - 1; n++) {
  495. bucks[n] = NULL;
  496. temp->refs = 0;
  497. new (&temp->obj) SQObjectPtr;
  498. temp->next = temp+1;
  499. temp++;
  500. }
  501. bucks[n] = NULL;
  502. temp->refs = 0;
  503. new (&temp->obj) SQObjectPtr;
  504. temp->next = NULL;
  505. _freelist = nodes;
  506. _nodes = nodes;
  507. _buckets = bucks;
  508. _slotused = 0;
  509. _numofslots = size;
  510. }
  511. //////////////////////////////////////////////////////////////////////////
  512. //SQStringTable
  513. /*
  514. * The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
  515. * http://www.lua.org/copyright.html#4
  516. * http://www.lua.org/source/4.0.1/src_lstring.c.html
  517. */
  518. SQStringTable::SQStringTable(SQSharedState *ss)
  519. {
  520. _sharedstate = ss;
  521. AllocNodes(4);
  522. _slotused = 0;
  523. }
  524. SQStringTable::~SQStringTable()
  525. {
  526. SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
  527. _strings = NULL;
  528. }
  529. void SQStringTable::AllocNodes(SQInteger size)
  530. {
  531. _numofslots = size;
  532. _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
  533. memset(_strings,0,sizeof(SQString*)*_numofslots);
  534. }
  535. SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
  536. {
  537. if(len<0)
  538. len = (SQInteger)scstrlen(news);
  539. SQHash newhash = ::_hashstr(news,len);
  540. SQHash h = newhash&(_numofslots-1);
  541. SQString *s;
  542. for (s = _strings[h]; s; s = s->_next){
  543. if(s->_len == len && (!memcmp(news,s->_val,sq_rsl(len))))
  544. return s; //found
  545. }
  546. SQString *t = (SQString *)SQ_MALLOC(sq_rsl(len)+sizeof(SQString));
  547. new (t) SQString;
  548. t->_sharedstate = _sharedstate;
  549. memcpy(t->_val,news,sq_rsl(len));
  550. t->_val[len] = _SC('\0');
  551. t->_len = len;
  552. t->_hash = newhash;
  553. t->_next = _strings[h];
  554. _strings[h] = t;
  555. _slotused++;
  556. if (_slotused > _numofslots) /* too crowded? */
  557. Resize(_numofslots*2);
  558. return t;
  559. }
  560. void SQStringTable::Resize(SQInteger size)
  561. {
  562. SQInteger oldsize=_numofslots;
  563. SQString **oldtable=_strings;
  564. AllocNodes(size);
  565. for (SQInteger i=0; i<oldsize; i++){
  566. SQString *p = oldtable[i];
  567. while(p){
  568. SQString *next = p->_next;
  569. SQHash h = p->_hash&(_numofslots-1);
  570. p->_next = _strings[h];
  571. _strings[h] = p;
  572. p = next;
  573. }
  574. }
  575. SQ_FREE(oldtable,oldsize*sizeof(SQString*));
  576. }
  577. void SQStringTable::Remove(SQString *bs)
  578. {
  579. SQString *s;
  580. SQString *prev=NULL;
  581. SQHash h = bs->_hash&(_numofslots - 1);
  582. for (s = _strings[h]; s; ){
  583. if(s == bs){
  584. if(prev)
  585. prev->_next = s->_next;
  586. else
  587. _strings[h] = s->_next;
  588. _slotused--;
  589. SQInteger slen = s->_len;
  590. s->~SQString();
  591. SQ_FREE(s,sizeof(SQString) + sq_rsl(slen));
  592. return;
  593. }
  594. prev = s;
  595. s = s->_next;
  596. }
  597. assert(0);//if this fail something is wrong
  598. }