# sqtable.h

    00001 /*  see copyright notice in squirrel.h */
    00002 #ifndef _SQTABLE_H_
    00003 #define _SQTABLE_H_
    00004 /*
    00005 * The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
    00006 * http://www.lua.org/copyright.html#4
    00007 * http://www.lua.org/source/4.0.1/src_ltable.c.html
    00008 */
    00009
    00010 #include "sqstring.h"
    00011
    00012
    00013 #define hashptr(p)  ((SQHash)(((SQInteger)p) >> 3))
    00014
    00015 inline SQHash HashObj(const SQObjectPtr &key)
    00016 {
    00017   switch(type(key)) {
    00018     case OT_STRING:   return _string(key)->_hash;
    00019     case OT_FLOAT:    return (SQHash)((SQInteger)_float(key));
    00020     case OT_BOOL: case OT_INTEGER:  return (SQHash)((SQInteger)_integer(key));
    00021     default:      return hashptr(key._unVal.pRefCounted);
    00022   }
    00023 }
    00024
    00025 struct SQTable : public SQDelegable
    00026 {
    00027 private:
    00028   struct _HashNode
    00029   {
    00030     _HashNode() { next = NULL; }
    00031     SQObjectPtr val;
    00032     SQObjectPtr key;
    00033     _HashNode *next;
    00034   };
    00035   _HashNode *_firstfree;
    00036   _HashNode *_nodes;
    00037   SQInteger _numofnodes;
    00038   SQInteger _usednodes;
    00039
    00041   void AllocNodes(SQInteger nSize);
    00042   void Rehash(bool force);
    00043   SQTable(SQSharedState *ss, SQInteger nInitialSize);
    00044   void _ClearNodes();
    00045 public:
    00046   static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize)
    00047   {
    00048     SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));
    00049     new (newtable) SQTable(ss, nInitialSize);
    00050     newtable->_delegate = NULL;
    00051     return newtable;
    00052   }
    00053   void Finalize();
    00054   SQTable *Clone();
    00055   ~SQTable()
    00056   {
    00057     SetDelegate(NULL);
    00058     REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
    00059     for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
    00060     SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));
    00061   }
    00062 #ifndef NO_GARBAGE_COLLECTOR
    00063   void Mark(SQCollectable **chain);
    00064 #endif
    00065   inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash)
    00066   {
    00067     _HashNode *n = &_nodes[hash];
    00068     do{
    00069       if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){
    00070         return n;
    00071       }
    00072     }while((n = n->next));
    00073     return NULL;
    00074   }
    00075   bool Get(const SQObjectPtr &key,SQObjectPtr &val);
    00076   void Remove(const SQObjectPtr &key);
    00077   bool Set(const SQObjectPtr &key, const SQObjectPtr &val);
    00078   //returns true if a new slot has been created false if it was already present
    00079   bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);
    00080   SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
    00081
    00082   SQInteger CountUsed(){ return _usednodes;}
    00083   void Clear();
    00084   void Release()
    00085   {
    00086     sq_delete(this, SQTable);
    00087   }
    00088
    00089 };
    00090
    00091 #endif //_SQTABLE_H_