1 /*  see copyright notice in squirrel.h */
2 #ifndef _SQTABLE_H_
3 #define _SQTABLE_H_
4 /*
5 * The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
6 * http://www.lua.org/copyright.html#4
7 * http://www.lua.org/source/4.0.1/src_ltable.c.html
8 */
9 
10 #include "sqstring.h"
11 
12 
13 #define hashptr(p)  ((SQHash)(((SQInteger)p) >> 3))
14 
HashObj(const SQObjectPtr & key)15 inline SQHash HashObj(const SQObjectPtr &key)
16 {
17     switch(sqtype(key)) {
18         case OT_STRING:     return _string(key)->_hash;
19         case OT_FLOAT:      return (SQHash)((SQInteger)_float(key));
20         case OT_BOOL: case OT_INTEGER:  return (SQHash)((SQInteger)_integer(key));
21         default:            return hashptr(key._unVal.pRefCounted);
22     }
23 }
24 
25 struct SQTable : public SQDelegable
26 {
27 private:
28     struct _HashNode
29     {
_HashNodeSQTable::_HashNode30         _HashNode() { next = NULL; }
31         SQObjectPtr val;
32         SQObjectPtr key;
33         _HashNode *next;
34     };
35     _HashNode *_firstfree;
36     _HashNode *_nodes;
37     SQInteger _numofnodes;
38     SQInteger _usednodes;
39 
40 ///////////////////////////
41     void AllocNodes(SQInteger nSize);
42     void Rehash(bool force);
43     SQTable(SQSharedState *ss, SQInteger nInitialSize);
44     void _ClearNodes();
45 public:
CreateSQTable46     static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize)
47     {
48         SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));
49         new (newtable) SQTable(ss, nInitialSize);
50         newtable->_delegate = NULL;
51         return newtable;
52     }
53     void Finalize();
54     SQTable *Clone();
~SQTableSQTable55     ~SQTable()
56     {
57         SetDelegate(NULL);
58         REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
59         for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
60         SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));
61     }
62 #ifndef NO_GARBAGE_COLLECTOR
63     void Mark(SQCollectable **chain);
GetTypeSQTable64     SQObjectType GetType() {return OT_TABLE;}
65 #endif
_GetSQTable66     inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash)
67     {
68         _HashNode *n = &_nodes[hash];
69         do{
70             if(_rawval(n->key) == _rawval(key) && sqtype(n->key) == sqtype(key)){
71                 return n;
72             }
73         }while((n = n->next));
74         return NULL;
75     }
76     //for compiler use
GetStrSQTable77     inline bool GetStr(const SQChar* key,SQInteger keylen,SQObjectPtr &val)
78     {
79         SQHash hash = _hashstr(key,keylen);
80         _HashNode *n = &_nodes[hash & (_numofnodes - 1)];
81         _HashNode *res = NULL;
82         do{
83             if(sqtype(n->key) == OT_STRING && (scstrcmp(_stringval(n->key),key) == 0)){
84                 res = n;
85                 break;
86             }
87         }while((n = n->next));
88         if (res) {
89             val = _realval(res->val);
90             return true;
91         }
92         return false;
93     }
94     bool Get(const SQObjectPtr &key,SQObjectPtr &val);
95     void Remove(const SQObjectPtr &key);
96     bool Set(const SQObjectPtr &key, const SQObjectPtr &val);
97     //returns true if a new slot has been created false if it was already present
98     bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);
99     SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
100 
CountUsedSQTable101     SQInteger CountUsed(){ return _usednodes;}
102     void Clear();
ReleaseSQTable103     void Release()
104     {
105         sq_delete(this, SQTable);
106     }
107 
108 };
109 
110 #endif //_SQTABLE_H_
111