2
see copyright notice in squirrel.h
4
#include "sqpcheader.h"
7
#include "sqfuncproto.h"
10
SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize)
12
SQInteger pow2size=MINPOWER2;
13
while(nInitialSize>pow2size)pow2size=pow2size<<1;
18
ADD_TO_CHAIN(&_sharedstate->_gc_chain,this);
21
void SQTable::Remove(const SQObjectPtr &key)
24
_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
26
n->val = n->key = _null_;
32
void SQTable::AllocNodes(SQInteger nSize)
34
_HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);
35
for(SQInteger i=0;i<nSize;i++){
36
new (&nodes[i]) _HashNode;
41
_firstfree=&_nodes[_numofnodes-1];
44
void SQTable::Rehash(bool force)
46
SQInteger oldsize=_numofnodes;
47
//prevent problems with the integer division
48
if(oldsize<4)oldsize=4;
49
_HashNode *nold=_nodes;
50
SQInteger nelems=CountUsed();
51
if (nelems >= oldsize-oldsize/4) /* using more than 3/4? */
52
AllocNodes(oldsize*2);
53
else if (nelems <= oldsize/4 && /* less than 1/4? */
55
AllocNodes(oldsize/2);
61
for (SQInteger i=0; i<oldsize; i++) {
62
_HashNode *old = nold+i;
63
if (type(old->key) != OT_NULL)
64
NewSlot(old->key,old->val);
66
for(SQInteger k=0;k<oldsize;k++)
68
SQ_FREE(nold,oldsize*sizeof(_HashNode));
71
SQTable *SQTable::Clone()
73
SQTable *nt=Create(_opt_ss(this),_numofnodes);
76
while((ridx=Next(true,ridx,key,val))!=-1){
79
nt->SetDelegate(_delegate);
83
bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)
85
if(type(key) == OT_NULL)
87
_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
89
val = _realval(n->val);
94
bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)
96
assert(type(key) != OT_NULL);
97
SQHash h = HashObj(key) & (_numofnodes - 1);
98
_HashNode *n = _Get(key, h);
103
_HashNode *mp = &_nodes[h];
107
//key not found I'll insert it
108
//main pos is not free
110
if(type(mp->key) != OT_NULL) {
111
n = _firstfree; /* get a free place */
112
SQHash mph = HashObj(mp->key) & (_numofnodes - 1);
113
_HashNode *othern; /* main position of colliding node */
115
if (mp > n && (othern = &_nodes[mph]) != mp){
116
/* yes; move colliding node into free position */
117
while (othern->next != mp){
118
assert(othern->next != NULL);
119
othern = othern->next; /* find previous */
121
othern->next = n; /* redo the chain with `n' in place of `mp' */
123
n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */
127
mp->next = NULL; /* now `mp' is free */
130
/* new node will go into free position */
131
n->next = mp->next; /* chain new position */
138
for (;;) { /* correct `firstfree' */
139
if (type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) {
142
return true; /* OK; table still has a free place */
144
else if (_firstfree == _nodes) break; /* cannot decrement from here */
148
return NewSlot(key, val);
151
SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
153
SQInteger idx = (SQInteger)TranslateIndex(refpos);
154
while (idx < _numofnodes) {
155
if(type(_nodes[idx].key) != OT_NULL) {
157
_HashNode &n = _nodes[idx];
159
outval = getweakrefs?(SQObject)n.val:_realval(n.val);
160
//return idx for the next iteration
165
//nothing to iterate anymore
170
bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)
172
_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
180
void SQTable::_ClearNodes()
182
for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; }
185
void SQTable::Finalize()
191
void SQTable::Clear()