New grow and skid sounds from remaxim
[supertux.git] / src / squirrel / squirrel / sqtable.h
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
15 inline SQHash HashObj(const SQObjectPtr &key)
16 {
17         switch(type(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         {
30                 _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:
46         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();
55         ~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);
64 #endif
65         inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash)
66         {
67                 _HashNode *n = &_nodes[hash];
68                 do{
69                         if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){
70                                 return n;
71                         }
72                 }while((n = n->next));
73                 return NULL;
74         }
75         bool Get(const SQObjectPtr &key,SQObjectPtr &val);
76         void Remove(const SQObjectPtr &key);
77         bool Set(const SQObjectPtr &key, const SQObjectPtr &val);
78         //returns true if a new slot has been created false if it was already present
79         bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);
80         SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
81         
82         SQInteger CountUsed(){ return _usednodes;}
83         void Clear();
84         void Release()
85         {
86                 sq_delete(this, SQTable);
87         }
88         
89 };
90
91 #endif //_SQTABLE_H_