Update SQUIRREL to 2.2.5
[supertux.git] / external / squirrel / squirrel / sqtable.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 1b3acd0..87f8cbf
-/*
-see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include "sqvm.h"
-#include "sqtable.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-
-SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize)
-{
-       SQInteger pow2size=MINPOWER2;
-       while(nInitialSize>pow2size)pow2size=pow2size<<1;
-       AllocNodes(pow2size);
-       _usednodes = 0;
-       _delegate = NULL;
-       INIT_CHAIN();
-       ADD_TO_CHAIN(&_sharedstate->_gc_chain,this);
-}
-
-void SQTable::Remove(const SQObjectPtr &key)
-{
-       
-       _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
-       if (n) {
-               n->val = n->key = _null_;
-               _usednodes--;
-               Rehash(false);
-       }
-}
-
-void SQTable::AllocNodes(SQInteger nSize)
-{
-       _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);
-       for(SQInteger i=0;i<nSize;i++){
-               new (&nodes[i]) _HashNode;
-               nodes[i].next=NULL;
-       }
-       _numofnodes=nSize;
-       _nodes=nodes;
-       _firstfree=&_nodes[_numofnodes-1];
-}
-
-void SQTable::Rehash(bool force)
-{
-       SQInteger oldsize=_numofnodes;
-       //prevent problems with the integer division
-       if(oldsize<4)oldsize=4;
-       _HashNode *nold=_nodes;
-       SQInteger nelems=CountUsed();
-       if (nelems >= oldsize-oldsize/4)  /* using more than 3/4? */
-               AllocNodes(oldsize*2);
-       else if (nelems <= oldsize/4 &&  /* less than 1/4? */
-               oldsize > MINPOWER2)
-               AllocNodes(oldsize/2);
-       else if(force)
-               AllocNodes(oldsize);
-       else
-               return;
-       _usednodes = 0;
-       for (SQInteger i=0; i<oldsize; i++) {
-               _HashNode *old = nold+i;
-               if (type(old->key) != OT_NULL)
-                       NewSlot(old->key,old->val);
-       }
-       for(SQInteger k=0;k<oldsize;k++) 
-               nold[k].~_HashNode();
-       SQ_FREE(nold,oldsize*sizeof(_HashNode));
-}
-
-SQTable *SQTable::Clone()
-{
-       SQTable *nt=Create(_opt_ss(this),_numofnodes);
-       SQInteger ridx=0;
-       SQObjectPtr key,val;
-       while((ridx=Next(true,ridx,key,val))!=-1){
-               nt->NewSlot(key,val);
-       }
-       nt->SetDelegate(_delegate);
-       return nt;
-}
-
-bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)
-{
-       if(type(key) == OT_NULL)
-               return false;
-       _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
-       if (n) {
-               val = _realval(n->val);
-               return true;
-       }
-       return false;
-}
-bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)
-{
-       assert(type(key) != OT_NULL);
-       SQHash h = HashObj(key) & (_numofnodes - 1);
-       _HashNode *n = _Get(key, h);
-       if (n) {
-               n->val = val;
-               return false;
-       }
-       _HashNode *mp = &_nodes[h];
-       n = mp;
-
-
-       //key not found I'll insert it
-       //main pos is not free
-
-       if(type(mp->key) != OT_NULL) {
-               n = _firstfree;  /* get a free place */
-               SQHash mph = HashObj(mp->key) & (_numofnodes - 1);
-               _HashNode *othern;  /* main position of colliding node */
-               
-               if (mp > n && (othern = &_nodes[mph]) != mp){
-                       /* yes; move colliding node into free position */
-                       while (othern->next != mp){
-                               assert(othern->next != NULL);
-                               othern = othern->next;  /* find previous */
-                       }
-                       othern->next = n;  /* redo the chain with `n' in place of `mp' */
-                       n->key = mp->key;
-                       n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */
-                       n->next = mp->next;
-                       mp->key = _null_;
-                       mp->val = _null_;
-                       mp->next = NULL;  /* now `mp' is free */
-               }
-               else{
-                       /* new node will go into free position */
-                       n->next = mp->next;  /* chain new position */
-                       mp->next = n;
-                       mp = n;
-               }
-       }
-       mp->key = key;
-
-       for (;;) {  /* correct `firstfree' */
-               if (type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) {
-                       mp->val = val;
-                       _usednodes++;
-                       return true;  /* OK; table still has a free place */
-               }
-               else if (_firstfree == _nodes) break;  /* cannot decrement from here */
-               else (_firstfree)--;
-       }
-       Rehash(true);
-       return NewSlot(key, val);
-}
-
-SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
-{
-       SQInteger idx = (SQInteger)TranslateIndex(refpos);
-       while (idx < _numofnodes) {
-               if(type(_nodes[idx].key) != OT_NULL) {
-                       //first found
-                       _HashNode &n = _nodes[idx];
-                       outkey = n.key;
-                       outval = getweakrefs?(SQObject)n.val:_realval(n.val);
-                       //return idx for the next iteration
-                       return ++idx;
-               }
-               ++idx;
-       }
-       //nothing to iterate anymore
-       return -1;
-}
-
-
-bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)
-{
-       _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
-       if (n) {
-               n->val = val;
-               return true;
-       }
-       return false;
-}
-
-void SQTable::_ClearNodes()
-{
-       for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; }
-}
-
-void SQTable::Finalize()
-{
-       _ClearNodes();
-       SetDelegate(NULL);
-}
-
-void SQTable::Clear()
-{
-       _ClearNodes();
-       _usednodes = 0;
-       Rehash(true);
-}
+/*\r
+see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include "sqvm.h"\r
+#include "sqtable.h"\r
+#include "sqfuncproto.h"\r
+#include "sqclosure.h"\r
+\r
+SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize)\r
+{\r
+       SQInteger pow2size=MINPOWER2;\r
+       while(nInitialSize>pow2size)pow2size=pow2size<<1;\r
+       AllocNodes(pow2size);\r
+       _usednodes = 0;\r
+       _delegate = NULL;\r
+       INIT_CHAIN();\r
+       ADD_TO_CHAIN(&_sharedstate->_gc_chain,this);\r
+}\r
+\r
+void SQTable::Remove(const SQObjectPtr &key)\r
+{\r
+       \r
+       _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));\r
+       if (n) {\r
+               n->val = n->key = _null_;\r
+               _usednodes--;\r
+               Rehash(false);\r
+       }\r
+}\r
+\r
+void SQTable::AllocNodes(SQInteger nSize)\r
+{\r
+       _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);\r
+       for(SQInteger i=0;i<nSize;i++){\r
+               new (&nodes[i]) _HashNode;\r
+               nodes[i].next=NULL;\r
+       }\r
+       _numofnodes=nSize;\r
+       _nodes=nodes;\r
+       _firstfree=&_nodes[_numofnodes-1];\r
+}\r
+\r
+void SQTable::Rehash(bool force)\r
+{\r
+       SQInteger oldsize=_numofnodes;\r
+       //prevent problems with the integer division\r
+       if(oldsize<4)oldsize=4;\r
+       _HashNode *nold=_nodes;\r
+       SQInteger nelems=CountUsed();\r
+       if (nelems >= oldsize-oldsize/4)  /* using more than 3/4? */\r
+               AllocNodes(oldsize*2);\r
+       else if (nelems <= oldsize/4 &&  /* less than 1/4? */\r
+               oldsize > MINPOWER2)\r
+               AllocNodes(oldsize/2);\r
+       else if(force)\r
+               AllocNodes(oldsize);\r
+       else\r
+               return;\r
+       _usednodes = 0;\r
+       for (SQInteger i=0; i<oldsize; i++) {\r
+               _HashNode *old = nold+i;\r
+               if (type(old->key) != OT_NULL)\r
+                       NewSlot(old->key,old->val);\r
+       }\r
+       for(SQInteger k=0;k<oldsize;k++) \r
+               nold[k].~_HashNode();\r
+       SQ_FREE(nold,oldsize*sizeof(_HashNode));\r
+}\r
+\r
+SQTable *SQTable::Clone()\r
+{\r
+       SQTable *nt=Create(_opt_ss(this),_numofnodes);\r
+       SQInteger ridx=0;\r
+       SQObjectPtr key,val;\r
+       while((ridx=Next(true,ridx,key,val))!=-1){\r
+               nt->NewSlot(key,val);\r
+       }\r
+       nt->SetDelegate(_delegate);\r
+       return nt;\r
+}\r
+\r
+bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)\r
+{\r
+       if(type(key) == OT_NULL)\r
+               return false;\r
+       _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));\r
+       if (n) {\r
+               val = _realval(n->val);\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
+bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)\r
+{\r
+       assert(type(key) != OT_NULL);\r
+       SQHash h = HashObj(key) & (_numofnodes - 1);\r
+       _HashNode *n = _Get(key, h);\r
+       if (n) {\r
+               n->val = val;\r
+               return false;\r
+       }\r
+       _HashNode *mp = &_nodes[h];\r
+       n = mp;\r
+\r
+\r
+       //key not found I'll insert it\r
+       //main pos is not free\r
+\r
+       if(type(mp->key) != OT_NULL) {\r
+               n = _firstfree;  /* get a free place */\r
+               SQHash mph = HashObj(mp->key) & (_numofnodes - 1);\r
+               _HashNode *othern;  /* main position of colliding node */\r
+               \r
+               if (mp > n && (othern = &_nodes[mph]) != mp){\r
+                       /* yes; move colliding node into free position */\r
+                       while (othern->next != mp){\r
+                               assert(othern->next != NULL);\r
+                               othern = othern->next;  /* find previous */\r
+                       }\r
+                       othern->next = n;  /* redo the chain with `n' in place of `mp' */\r
+                       n->key = mp->key;\r
+                       n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */\r
+                       n->next = mp->next;\r
+                       mp->key = _null_;\r
+                       mp->val = _null_;\r
+                       mp->next = NULL;  /* now `mp' is free */\r
+               }\r
+               else{\r
+                       /* new node will go into free position */\r
+                       n->next = mp->next;  /* chain new position */\r
+                       mp->next = n;\r
+                       mp = n;\r
+               }\r
+       }\r
+       mp->key = key;\r
+\r
+       for (;;) {  /* correct `firstfree' */\r
+               if (type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) {\r
+                       mp->val = val;\r
+                       _usednodes++;\r
+                       return true;  /* OK; table still has a free place */\r
+               }\r
+               else if (_firstfree == _nodes) break;  /* cannot decrement from here */\r
+               else (_firstfree)--;\r
+       }\r
+       Rehash(true);\r
+       return NewSlot(key, val);\r
+}\r
+\r
+SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
+{\r
+       SQInteger idx = (SQInteger)TranslateIndex(refpos);\r
+       while (idx < _numofnodes) {\r
+               if(type(_nodes[idx].key) != OT_NULL) {\r
+                       //first found\r
+                       _HashNode &n = _nodes[idx];\r
+                       outkey = n.key;\r
+                       outval = getweakrefs?(SQObject)n.val:_realval(n.val);\r
+                       //return idx for the next iteration\r
+                       return ++idx;\r
+               }\r
+               ++idx;\r
+       }\r
+       //nothing to iterate anymore\r
+       return -1;\r
+}\r
+\r
+\r
+bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)\r
+{\r
+       _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));\r
+       if (n) {\r
+               n->val = val;\r
+               return true;\r
+       }\r
+       return false;\r
+}\r
+\r
+void SQTable::_ClearNodes()\r
+{\r
+       for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; }\r
+}\r
+\r
+void SQTable::Finalize()\r
+{\r
+       _ClearNodes();\r
+       SetDelegate(NULL);\r
+}\r
+\r
+void SQTable::Clear()\r
+{\r
+       _ClearNodes();\r
+       _usednodes = 0;\r
+       Rehash(true);\r
+}\r