fix cr/lfs and remove trailing whitespaces...
[supertux.git] / src / squirrel / squirrel / sqstate.cpp
index db8e5b2..85da8c8 100644 (file)
 SQObjectPtr _null_;
 SQObjectPtr _true_(true);
 SQObjectPtr _false_(false);
-SQObjectPtr _one_(1);
-SQObjectPtr _minusone_(-1);
+SQObjectPtr _one_((SQInteger)1);
+SQObjectPtr _minusone_((SQInteger)-1);
 
 SQSharedState::SQSharedState()
 {
        _compilererrorhandler = NULL;
        _printfunc = NULL;
        _debuginfo = false;
+       _notifyallexceptions = false;
 }
 
 #define newsysstring(s) {      \
@@ -36,11 +37,11 @@ SQSharedState::SQSharedState()
 
 bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
 {
-       int i = 0;
-       
-       int mask = 0;
+       SQInteger i = 0;
+
+       SQInteger mask = 0;
        while(typemask[i] != 0) {
-               
+
                switch(typemask[i]){
                                case 'o': mask |= _RT_NULL; break;
                                case 'i': mask |= _RT_INTEGER; break;
@@ -57,28 +58,29 @@ bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
                                case 'v': mask |= _RT_THREAD; break;
                                case 'x': mask |= _RT_INSTANCE; break;
                                case 'y': mask |= _RT_CLASS; break;
+                               case 'r': mask |= _RT_WEAKREF; break;
                                case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;
                                case ' ': i++; continue; //ignores spaces
                                default:
                                        return false;
                }
                i++;
-               if(typemask[i] == '|') { 
-                       i++; 
+               if(typemask[i] == '|') {
+                       i++;
                        if(typemask[i] == 0)
                                return false;
-                       continue; 
+                       continue;
                }
                res.push_back(mask);
                mask = 0;
-               
+
        }
        return true;
 }
 
 SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
 {
-       int i=0;
+       SQInteger i=0;
        SQTable *t=SQTable::Create(ss,0);
        while(funcz[i].name!=0){
                SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);
@@ -93,7 +95,7 @@ SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
 }
 
 void SQSharedState::Init()
-{      
+{
        _scratchpad=NULL;
        _scratchpadsize=0;
 #ifndef NO_GARBAGE_COLLECTOR
@@ -137,9 +139,11 @@ void SQSharedState::Init()
        newmetamethod(MM_CLONED);
        newmetamethod(MM_NEWSLOT);
        newmetamethod(MM_DELSLOT);
+       newmetamethod(MM_TOSTRING);
+       newmetamethod(MM_NEWMEMBER);
+       newmetamethod(MM_INHERITED);
 
        _constructoridx = SQString::Create(this,_SC("constructor"));
-       _refs_table = SQTable::Create(this,0);
        _registry = SQTable::Create(this,0);
        _table_default_delegate=CreateDefaultDelegate(this,_table_default_delegate_funcz);
        _array_default_delegate=CreateDefaultDelegate(this,_array_default_delegate_funcz);
@@ -150,16 +154,17 @@ void SQSharedState::Init()
        _thread_default_delegate=CreateDefaultDelegate(this,_thread_default_delegate_funcz);
        _class_default_delegate=CreateDefaultDelegate(this,_class_default_delegate_funcz);
        _instance_default_delegate=CreateDefaultDelegate(this,_instance_default_delegate_funcz);
+       _weakref_default_delegate=CreateDefaultDelegate(this,_weakref_default_delegate_funcz);
 
 }
 
 SQSharedState::~SQSharedState()
 {
        _constructoridx = _null_;
-       _table(_refs_table)->Finalize();
+       _refs_table.Finalize();
        _table(_registry)->Finalize();
        _table(_metamethodsmap)->Finalize();
-       _refs_table = _null_;
+//     _refs_table = _null_;
        _registry = _null_;
        _metamethodsmap = _null_;
        while(!_systemstrings->empty()){
@@ -177,10 +182,11 @@ SQSharedState::~SQSharedState()
        _thread_default_delegate=_null_;
        _class_default_delegate=_null_;
        _instance_default_delegate=_null_;
-       
+       _weakref_default_delegate=_null_;
+
 #ifndef NO_GARBAGE_COLLECTOR
-       
-       
+
+
        SQCollectable *t=_gc_chain;
        SQCollectable *nx=NULL;
        while(t){
@@ -230,19 +236,20 @@ void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
        case OT_THREAD:_thread(o)->Mark(chain);break;
        case OT_CLASS:_class(o)->Mark(chain);break;
        case OT_INSTANCE:_instance(o)->Mark(chain);break;
+       default: break; //shutup compiler
        }
 }
 
 
-int SQSharedState::CollectGarbage(SQVM *vm)
+SQInteger SQSharedState::CollectGarbage(SQVM *vm)
 {
-       int n=0;
+       SQInteger n=0;
        SQCollectable *tchain=NULL;
        SQVM *vms=_thread(_root_vm);
-       
+
        vms->Mark(&tchain);
-       int x = _table(_thread(_root_vm)->_roottable)->CountUsed();
-       MarkObject(_refs_table,&tchain);
+       SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed();
+       _refs_table.Mark(&tchain);
        MarkObject(_registry,&tchain);
        MarkObject(_metamethodsmap,&tchain);
        MarkObject(_table_default_delegate,&tchain);
@@ -254,7 +261,8 @@ int SQSharedState::CollectGarbage(SQVM *vm)
        MarkObject(_closure_default_delegate,&tchain);
        MarkObject(_class_default_delegate,&tchain);
        MarkObject(_instance_default_delegate,&tchain);
-       
+       MarkObject(_weakref_default_delegate,&tchain);
+
        SQCollectable *t=_gc_chain;
        SQCollectable *nx=NULL;
        while(t){
@@ -273,7 +281,7 @@ int SQSharedState::CollectGarbage(SQVM *vm)
                t=t->_next;
        }
        _gc_chain=tchain;
-       int z = _table(_thread(_root_vm)->_roottable)->CountUsed();
+       SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed();
        assert(z == x);
        return n;
 }
@@ -299,9 +307,9 @@ void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
 }
 #endif
 
-SQChar* SQSharedState::GetScratchPad(int size)
+SQChar* SQSharedState::GetScratchPad(SQInteger size)
 {
-       int newsize;
+       SQInteger newsize;
        if(size>0){
                if(_scratchpadsize<size){
                        newsize=size+(size>>1);
@@ -317,6 +325,147 @@ SQChar* SQSharedState::GetScratchPad(int size)
        return _scratchpad;
 }
 
+RefTable::RefTable()
+{
+       AllocNodes(4);
+}
+
+void RefTable::Finalize()
+{
+       RefNode *nodes = (RefNode *)&_buckets[_numofslots];
+       for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
+               nodes->obj = _null_;
+               nodes++;
+       }
+}
+
+RefTable::~RefTable()
+{
+       SQ_FREE(_buckets,_buffersize);
+}
+#ifndef NO_GARBAGE_COLLECTOR
+void RefTable::Mark(SQCollectable **chain)
+{
+       RefNode *nodes = (RefNode *)&_buckets[_numofslots];
+       for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
+               if(type(nodes->obj) != OT_NULL) {
+                       SQSharedState::MarkObject(nodes->obj,chain);
+               }
+               nodes++;
+       }
+}
+#endif
+void RefTable::AddRef(SQObject &obj)
+{
+       SQHash mainpos;
+       RefNode *prev;
+       RefNode *ref = Get(obj,mainpos,&prev,true);
+       ref->refs++;
+}
+
+SQBool RefTable::Release(SQObject &obj)
+{
+       SQHash mainpos;
+       RefNode *prev;
+       RefNode *ref = Get(obj,mainpos,&prev,false);
+       if(ref) {
+               if(--ref->refs == 0) {
+                       ref->obj = _null_;
+                       if(prev) {
+                               prev->next = ref->next;
+                       }
+                       else {
+                               _buckets[mainpos] = ref->next;
+                       }
+                       ref->next = _freelist;
+                       _freelist = ref;
+                       _slotused--;
+                       //<<FIXME>>test for shrink?
+                       return SQTrue;
+               }
+       }
+       return SQFalse;
+}
+
+void RefTable::Resize(SQUnsignedInteger size)
+{
+       RefNode **oldbuffer = _buckets;
+       RefNode *oldnodes = (RefNode *)&_buckets[_numofslots];
+       SQUnsignedInteger oldnumofslots = _numofslots;
+       SQUnsignedInteger oldbuffersize = _buffersize;
+       AllocNodes(size);
+       //rehash
+       for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
+               if(type(oldnodes->obj) != OT_NULL) {
+                       //add back;
+                       assert(oldnodes->refs != 0);
+                       RefNode *nn = Add(::HashObj(oldnodes->obj)&(_numofslots-1),oldnodes->obj);
+                       nn->refs = oldnodes->refs;
+                       oldnodes->obj = _null_;
+               }
+               oldnodes++;
+       }
+       SQ_FREE(oldbuffer,oldbuffersize);
+}
+
+RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)
+{
+       RefNode *t = _buckets[mainpos];
+       RefNode *newnode = _freelist;
+       newnode->obj = obj;
+       _buckets[mainpos] = newnode;
+       _freelist = _freelist->next;
+       newnode->next = t;
+       assert(newnode->refs == 0);
+       _slotused++;
+       return newnode;
+}
+
+RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add)
+{
+       RefNode *ref;
+       mainpos = ::HashObj(obj)&(_numofslots-1);
+       *prev = NULL;
+       for (ref = _buckets[mainpos]; ref; ) {
+               if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))
+                       break;
+               *prev = ref;
+               ref = ref->next;
+       }
+       if(ref == NULL && add) {
+               if(_numofslots == _slotused) {
+                       Resize(_numofslots*2);
+               }
+               ref = Add(mainpos,obj);
+       }
+       return ref;
+}
+
+void RefTable::AllocNodes(SQUnsignedInteger size)
+{
+       RefNode **bucks;
+       RefNode *firstnode;
+       _buffersize = size * sizeof(RefNode *) + size * sizeof(RefNode);
+       bucks = (RefNode **)SQ_MALLOC(_buffersize);
+       firstnode = (RefNode *)&bucks[size];
+       RefNode *temp = firstnode;
+       SQUnsignedInteger n;
+       for(n = 0; n < size - 1; n++) {
+               bucks[n] = NULL;
+               temp->refs = 0;
+               new (&temp->obj) SQObjectPtr;
+               temp->next = temp+1;
+               temp++;
+       }
+       bucks[n] = NULL;
+       temp->refs = 0;
+       new (&temp->obj) SQObjectPtr;
+       temp->next = NULL;
+       _freelist = firstnode;
+       _buckets = bucks;
+       _slotused = 0;
+       _numofslots = size;
+}
 //////////////////////////////////////////////////////////////////////////
 //StringTable
 /*
@@ -325,19 +474,6 @@ SQChar* SQSharedState::GetScratchPad(int size)
 * http://www.lua.org/source/4.0.1/src_lstring.c.html
 */
 
-int SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
-{
-       int idx = (int)TranslateIndex(refpos);
-       while(idx < _len){
-               outkey = (SQInteger)idx;
-               outval = SQInteger(_val[idx]);
-               //return idx for the next iteration
-               return ++idx;
-       }
-       //nothing to iterate anymore
-       return -1;
-}
-
 StringTable::StringTable()
 {
        AllocNodes(4);
@@ -350,7 +486,7 @@ StringTable::~StringTable()
        _strings=NULL;
 }
 
-void StringTable::AllocNodes(int size)
+void StringTable::AllocNodes(SQInteger size)
 {
        _numofslots=size;
        //_slotused=0;
@@ -358,11 +494,11 @@ void StringTable::AllocNodes(int size)
        memset(_strings,0,sizeof(SQString*)*_numofslots);
 }
 
-SQString *StringTable::Add(const SQChar *news,int len)
+SQString *StringTable::Add(const SQChar *news,SQInteger len)
 {
        if(len<0)
-               len=scstrlen(news);
-       unsigned int h=::_hashstr(news,len)&(_numofslots-1);
+               len = (SQInteger)scstrlen(news);
+       SQHash h = ::_hashstr(news,len)&(_numofslots-1);
        SQString *s;
        for (s = _strings[h]; s; s = s->_next){
                if(s->_len == len && (!memcmp(news,s->_val,rsl(len))))
@@ -372,31 +508,30 @@ SQString *StringTable::Add(const SQChar *news,int len)
        SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));
        new (t) SQString;
        memcpy(t->_val,news,rsl(len));
-       t->_val[len]=_SC('\0');
-       t->_len=len;
-       t->_hash=::_hashstr(news,len);
-       t->_next=_strings[h];
-       t->_uiRef=0;
-       _strings[h]=t;
+       t->_val[len] = _SC('\0');
+       t->_len = len;
+       t->_hash = ::_hashstr(news,len);
+       t->_next = _strings[h];
+       _strings[h] = t;
        _slotused++;
        if (_slotused > _numofslots)  /* too crowded? */
                Resize(_numofslots*2);
        return t;
 }
 
-void StringTable::Resize(int size)
+void StringTable::Resize(SQInteger size)
 {
-       int oldsize=_numofslots;
+       SQInteger oldsize=_numofslots;
        SQString **oldtable=_strings;
        AllocNodes(size);
-       for (int i=0; i<oldsize; i++){
+       for (SQInteger i=0; i<oldsize; i++){
                SQString *p = oldtable[i];
                while(p){
                        SQString *next = p->_next;
-                       unsigned int h=p->_hash&(_numofslots-1);
-                       p->_next=_strings[h];
+                       SQHash h = p->_hash&(_numofslots-1);
+                       p->_next = _strings[h];
                        _strings[h] = p;
-                       p=next;
+                       p = next;
                }
        }
        SQ_FREE(oldtable,oldsize*sizeof(SQString*));
@@ -406,8 +541,8 @@ void StringTable::Remove(SQString *bs)
 {
        SQString *s;
        SQString *prev=NULL;
-       unsigned int h=bs->_hash&(_numofslots-1);
-       
+       SQHash h = bs->_hash&(_numofslots - 1);
+
        for (s = _strings[h]; s; ){
                if(s == bs){
                        if(prev)
@@ -415,9 +550,9 @@ void StringTable::Remove(SQString *bs)
                        else
                                _strings[h] = s->_next;
                        _slotused--;
-                       int slen=s->_len;
+                       SQInteger slen = s->_len;
                        s->~SQString();
-                       SQ_FREE(s,sizeof(SQString)+rsl(slen));
+                       SQ_FREE(s,sizeof(SQString) + rsl(slen));
                        return;
                }
                prev = s;