1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00
SqMod/external/Squirrel/sqtable.h

111 lines
3.2 KiB
C++

/* see copyright notice in squirrel.h */
#ifndef _SQTABLE_H_
#define _SQTABLE_H_
/*
* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
* http://www.lua.org/copyright.html#4
* http://www.lua.org/source/4.0.1/src_ltable.c.html
*/
#include "sqstring.h"
#define hashptr(p) ((SQHash)(((SQInteger)p) >> 3))
inline SQHash HashObj(const SQObjectPtr &key)
{
switch(sq_type(key)) {
case OT_STRING: return _string(key)->_hash;
case OT_FLOAT: return (SQHash)((SQInteger)_float(key));
case OT_BOOL: case OT_INTEGER: return (SQHash)((SQInteger)_integer(key));
default: return hashptr(key._unVal.pRefCounted);
}
}
struct SQTable : public SQDelegable
{
private:
struct _HashNode
{
_HashNode() { next = NULL; }
SQObjectPtr val;
SQObjectPtr key;
_HashNode *next;
};
_HashNode *_firstfree;
_HashNode *_nodes;
SQInteger _numofnodes;
SQInteger _usednodes;
///////////////////////////
void AllocNodes(SQInteger nSize);
void Rehash(bool force);
SQTable(SQSharedState *ss, SQInteger nInitialSize);
void _ClearNodes();
public:
static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize)
{
SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));
new (newtable) SQTable(ss, nInitialSize);
newtable->_delegate = NULL;
return newtable;
}
void Finalize();
SQTable *Clone();
~SQTable()
{
SetDelegate(NULL);
REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));
}
#ifndef NO_GARBAGE_COLLECTOR
void Mark(SQCollectable **chain);
SQObjectType GetType() {return OT_TABLE;}
#endif
inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash)
{
_HashNode *n = &_nodes[hash];
do{
if(_rawval(n->key) == _rawval(key) && sq_type(n->key) == sq_type(key)){
return n;
}
}while((n = n->next));
return NULL;
}
//for compiler use
inline bool GetStr(const SQChar* key,SQInteger keylen,SQObjectPtr &val)
{
SQHash hash = _hashstr(key,keylen);
_HashNode *n = &_nodes[hash & (_numofnodes - 1)];
_HashNode *res = NULL;
do{
if(sq_type(n->key) == OT_STRING && (scstrcmp(_stringval(n->key),key) == 0)){
res = n;
break;
}
}while((n = n->next));
if (res) {
val = _realval(res->val);
return true;
}
return false;
}
bool Get(const SQObjectPtr &key,SQObjectPtr &val);
void Remove(const SQObjectPtr &key);
bool Set(const SQObjectPtr &key, const SQObjectPtr &val);
//returns true if a new slot has been created false if it was already present
bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);
SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
SQInteger CountUsed(){ return _usednodes;}
void Clear();
void Release()
{
sq_delete(this, SQTable);
}
};
#endif //_SQTABLE_H_