The Squirrel interpreter. See http://www.squirrel-lang.org/

Dependents:   Squirrel

Committer:
jhnwkmn
Date:
Tue Dec 16 10:20:34 2014 +0000
Revision:
0:97a4f8cc534c
Initial import of Squirrel.

Who changed what in which revision?

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