0001
0002 #ifndef _PSTABLE_H_
0003 #define _PSTABLE_H_
0004
0005
0006
0007
0008
0009
0010 #include "psstring.h"
0011
0012
0013 #define hashptr(p) ((PSHash)(((PSInteger)p) >> 3))
0014
0015 inline PSHash HashObj(const PSObjectPtr &key)
0016 {
0017 switch(type(key)) {
0018 case OT_STRING: return _string(key)->_hash;
0019 case OT_FLOAT: return (PSHash)((PSInteger)_float(key));
0020 case OT_BOOL: case OT_INTEGER: return (PSHash)((PSInteger)_integer(key));
0021 default: return hashptr(key._unVal.pRefCounted);
0022 }
0023 }
0024
0025 struct PSTable : public PSDelegable
0026 {
0027 private:
0028 struct _HashNode
0029 {
0030 _HashNode() { next = NULL; }
0031 PSObjectPtr val;
0032 PSObjectPtr key;
0033 _HashNode *next;
0034 };
0035 _HashNode *_firstfree;
0036 _HashNode *_nodes;
0037 PSInteger _numofnodes;
0038 PSInteger _usednodes;
0039
0040
0041 void AllocNodes(PSInteger nSize);
0042 void Rehash(bool force);
0043 PSTable(PSSharedState *ss, PSInteger nInitialSize);
0044 void _ClearNodes();
0045 public:
0046 static PSTable* Create(PSSharedState *ss,PSInteger nInitialSize)
0047 {
0048 PSTable *newtable = (PSTable*)PS_MALLOC(sizeof(PSTable));
0049 new (newtable) PSTable(ss, nInitialSize);
0050 newtable->_delegate = NULL;
0051 return newtable;
0052 }
0053 void Finalize();
0054 PSTable *Clone();
0055 ~PSTable()
0056 {
0057 SetDelegate(NULL);
0058 REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
0059 for (PSInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
0060 PS_FREE(_nodes, _numofnodes * sizeof(_HashNode));
0061 }
0062 #ifndef NO_GARBAGE_COLLECTOR
0063 void Mark(PSCollectable **chain);
0064 PSObjectType GetType() {return OT_TABLE;}
0065 #endif
0066 inline _HashNode *_Get(const PSObjectPtr &key,PSHash hash)
0067 {
0068 _HashNode *n = &_nodes[hash];
0069 do{
0070 if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){
0071 return n;
0072 }
0073 }while((n = n->next));
0074 return NULL;
0075 }
0076
0077 inline bool GetStr(const PSChar* key,PSInteger keylen,PSObjectPtr &val)
0078 {
0079 PSHash hash = _hashstr(key,keylen);
0080 _HashNode *n = &_nodes[hash & (_numofnodes - 1)];
0081 _HashNode *res = NULL;
0082 do{
0083 if(type(n->key) == OT_STRING && (scstrcmp(_stringval(n->key),key) == 0)){
0084 res = n;
0085 break;
0086 }
0087 }while((n = n->next));
0088 if (res) {
0089 val = _realval(res->val);
0090 return true;
0091 }
0092 return false;
0093 }
0094 bool Get(const PSObjectPtr &key,PSObjectPtr &val);
0095 void Remove(const PSObjectPtr &key);
0096 bool Set(const PSObjectPtr &key, const PSObjectPtr &val);
0097
0098 bool NewSlot(const PSObjectPtr &key,const PSObjectPtr &val);
0099 PSInteger Next(bool getweakrefs,const PSObjectPtr &refpos, PSObjectPtr &outkey, PSObjectPtr &outval);
0100
0101 PSInteger CountUsed(){ return _usednodes;}
0102 void Clear();
0103 void Release()
0104 {
0105 ps_delete(this, PSTable);
0106 }
0107
0108 };
0109
0110 #endif