Back to home page

Enduro/X

 
 

    


0001 /*  see copyright notice in pscript.h */
0002 #ifndef _PSTABLE_H_
0003 #define _PSTABLE_H_
0004 /*

0005 * The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)

0006 * http://www.lua.org/copyright.html#4

0007 * http://www.lua.org/source/4.0.1/src_ltable.c.html

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     //for compiler use

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     //returns true if a new slot has been created false if it was already present

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 //_PSTABLE_H_