Class Hierarchy   Class Index   Method Index  

CHMrefHashTable.h

00001 #ifndef __CHM_REF_HASH_TABLE__
00002 #define __CHM_REF_HASH_TABLE__
00003 #include <CHM/CHMvector.h>
00004 #include <CHM/CHMstring.h>
00005 
00006 template<class PKey, class PValue>
00007 class CHMpair : public CHMinstanceHeap
00008 {
00009 public:
00010    CHMpair() {}
00011    CHMpair(const PKey& nKey, const PValue& nValue)
00012            : Key(nKey), Value(nValue) {}
00013    ~CHMpair() {}
00014    PKey   Key;
00015    PValue Value;
00016 };
00017 
00018 size_t CHMhashFunc(size_t Item);
00019 
00020 template<class PKey, class PValue> class CHMrefHashTableIterator;
00021 
00022 template<class PKey, class PValue>
00023 class CHMrefHashTable : public CHMinstanceHeap
00024 {
00025 public:
00026    CHMrefHashTable(size_t CountOfBucket=10);
00027    virtual ~CHMrefHashTable();
00028 
00029    //void showBuckets() const;
00030 
00031    PValue& operator[](const PKey& Key);
00032    const PValue& operator[](const PKey& Key) const;
00033 
00034    CHMpair<PKey,PValue>* findPair(const PKey& Key) const;
00035    CHMboolean has(const PKey& Key) const;
00036 
00037    PValue* getValue(const PKey& Key) const;
00038    void clear();
00039 
00040    void remove(const PKey& Key);
00041 
00042    void insert(const PKey& Key, const PValue& Value);
00043 
00044    size_t size() const { return m_Size; }
00045 
00046    friend class CHMrefHashTableIterator<PKey, PValue>;
00047    typedef CHMrefHashTableIterator<PKey, PValue> Iterator;
00048 private:
00049    void removeAll();
00050    void init(size_t CountOfBucket);
00051 
00052    typedef CHMvector< CHMpair<PKey, PValue>* > CHMbucket;
00053 
00054    CHMvector<CHMbucket*> m_Bucket;
00055 
00056    void findIndex(const PKey& Key, size_t& BucketIndex, size_t& ItemIndex) const;
00057    size_t m_Size;
00058 
00059    CHMrefHashTable(const CHMrefHashTable<PKey,PValue>& Original) {}
00060    CHMrefHashTable<PKey,PValue>& operator=(const CHMrefHashTable<PKey,PValue>& Original) { return *this;}
00061 };
00062 
00063 template<class PKey, class PValue>
00064 class CHMrefHashTableIterator
00065 {
00066 public:
00067    CHMrefHashTableIterator(const CHMrefHashTable<PKey, PValue>& Table);
00068    ~CHMrefHashTableIterator() {}
00069 
00070    void resetIterator();
00071    CHMboolean iterateNext(PKey& Key, PValue& Value);
00072 private:
00073    size_t m_IterBucketIndex;
00074    size_t m_IterItemIndex;
00075    const CHMrefHashTable<PKey, PValue>* m_pTable;
00076 };
00077 
00078 template<class PKey, class PValue>
00079 CHMrefHashTableIterator<PKey, PValue>::CHMrefHashTableIterator
00080 (
00081    const CHMrefHashTable<PKey, PValue>& Table
00082 )
00083 {
00084    m_pTable = &Table;
00085    resetIterator();
00086 }
00087 
00088 template<class PKey, class PValue>
00089 void CHMrefHashTableIterator<PKey, PValue>::resetIterator()
00090 {
00091    m_IterBucketIndex=npos;
00092    m_IterItemIndex=0;
00093 }
00094 
00095 template<class PKey, class PValue>
00096 CHMboolean CHMrefHashTableIterator<PKey,PValue>::iterateNext
00097 (
00098     PKey& Key, 
00099     PValue& Value
00100 )
00101 {
00102    if (m_IterBucketIndex == npos)
00103    {
00104       m_IterBucketIndex = 0;
00105    }
00106    while (m_IterBucketIndex < m_pTable->m_Bucket.size() && 
00107            m_pTable->m_Bucket[m_IterBucketIndex]->size() <= m_IterItemIndex )
00108    {
00109       m_IterBucketIndex++;
00110       m_IterItemIndex = 0;
00111    }
00112    if (m_IterBucketIndex == m_pTable->m_Bucket.size())
00113    {
00114       return false;
00115    }
00116    else
00117    {
00118       Key = m_pTable->m_Bucket[m_IterBucketIndex]->operator[](m_IterItemIndex)->Key;
00119       Value = m_pTable->m_Bucket[m_IterBucketIndex]->operator[](m_IterItemIndex)->Value;
00120       m_IterItemIndex++;
00121       return true;
00122    }
00123 }
00124 
00125 size_t CHMhashFunc(const CHMstring& String);
00126 
00127 template<class PKey, class PValue>
00128 CHMrefHashTable<PKey, PValue>::CHMrefHashTable
00129 (
00130    size_t CountOfBucket
00131 ) : m_Bucket(CountOfBucket)
00132 {
00133    init(CountOfBucket);
00134 }
00135 
00136 template<class PKey, class PValue>
00137 void CHMrefHashTable<PKey, PValue>::init(size_t CountOfBucket)
00138 {
00139    removeAll();
00140    m_Size = 0;
00141    m_Bucket.resize(CountOfBucket);
00142    for(size_t BucketIndex=0; BucketIndex < m_Bucket.size(); ++BucketIndex)
00143    {
00144       m_Bucket[BucketIndex] = new CHMvector< CHMpair<PKey,PValue>* >(2, 0, true);
00145       // initial size of 0 grow by doubling.
00146    }
00147 }
00148 
00149 template<class PKey, class PValue>
00150 CHMrefHashTable<PKey, PValue>::~CHMrefHashTable()
00151 {
00152    removeAll();
00153 }
00154 
00155 template<class PKey, class PValue>
00156 void CHMrefHashTable<PKey, PValue>::removeAll()
00157 {
00158    for(size_t BucketIndex = 0;
00159        BucketIndex < m_Bucket.size();
00160        ++BucketIndex)
00161    {
00162       for(size_t ItemIndex = 0; ItemIndex < m_Bucket[BucketIndex]->size();
00163           ++ItemIndex)
00164       {
00165          delete m_Bucket[BucketIndex]->operator[](ItemIndex);
00166       }
00167       delete m_Bucket[BucketIndex];
00168    }
00169    m_Size = 0;
00170 }
00171 
00172 template<class PKey, class PValue>
00173 CHMpair<PKey,PValue>* CHMrefHashTable<PKey, PValue>::findPair(const PKey& Key) const
00174 {
00175    size_t BucketIndex;
00176    size_t ItemIndex;
00177    findIndex(Key, BucketIndex, ItemIndex);
00178 
00179    if (ItemIndex == npos)
00180    {
00181       return NULL;
00182    }
00183    else
00184    {
00185       return m_Bucket[BucketIndex]->operator[](ItemIndex);
00186    }
00187 }
00188 
00189 template<class PKey, class PValue>
00190 PValue& CHMrefHashTable<PKey, PValue>::operator[](const PKey& Key)
00191 {
00192    CHMpair<PKey, PValue>* pPair = findPair(Key);
00193 
00194    if (!pPair)
00195    {
00196       insert(Key, PValue());
00197       pPair = findPair(Key);
00198    }
00199    CHMPRECONDITION(pPair != NULL)
00200    return pPair->Value;
00201 }
00202 
00203 template<class PKey, class PValue>
00204 const PValue& CHMrefHashTable<PKey, PValue>::operator[](const PKey& Key) const
00205 {
00206    CHMpair<PKey, PValue>* pPair = findPair(Key);
00207 
00208    if (!pPair)
00209    {
00210       throw CHMerror(CHM_TEXT("Key does not exist."),0);
00211    }
00212 
00213    return pPair->Value;
00214 }
00215 
00216 
00217 template<class PKey, class PValue>
00218 CHMboolean CHMrefHashTable<PKey, PValue>::has(const PKey& Key) const
00219 {
00220    CHMpair<PKey, PValue>* pPair = findPair(Key);
00221    if (!pPair)
00222       return false;
00223    else
00224       return true;
00225 }
00226 
00227 template<class PKey, class PValue>
00228 PValue* CHMrefHashTable<PKey, PValue>::getValue(const PKey& Key) const
00229 {
00230    CHMpair<PKey, PValue>* pPair = findPair(Key);
00231    if (pPair)
00232       return &pPair->Value;
00233    else
00234       return NULL;
00235 }
00236 
00237 template<class PKey, class PValue>
00238 void CHMrefHashTable<PKey, PValue>::clear()
00239 {
00240    size_t CountOfBucket = m_Bucket.size();
00241    init(CountOfBucket);
00242 }
00243 
00244 template<class PKey, class PValue>
00245 void CHMrefHashTable<PKey, PValue>::findIndex
00246 (
00247    const PKey& Key,
00248    size_t& BucketIndex,
00249    size_t& ItemIndex
00250 ) const
00251 {
00252    BucketIndex = CHMhashFunc(Key) % m_Bucket.size();
00253    ItemIndex = 0;
00254    while (ItemIndex < m_Bucket[BucketIndex]->size()
00255           && Key != m_Bucket[BucketIndex]->operator[](ItemIndex)->Key)
00256    {
00257       ItemIndex++;
00258    }
00259    if (m_Bucket[BucketIndex]->size() == ItemIndex)
00260    {
00261       ItemIndex = npos;
00262    }
00263 }
00264 
00265 template<class PKey, class PValue>
00266 void CHMrefHashTable<PKey, PValue>::remove(const PKey& Key)
00267 {
00268    size_t BucketIndex;
00269    size_t ItemIndex;
00270    findIndex(Key, BucketIndex, ItemIndex);
00271 
00272    if (ItemIndex == npos)
00273    {
00274       return;
00275    }
00276    else
00277    {
00278       delete m_Bucket[BucketIndex]->operator[](ItemIndex);
00279       m_Bucket[BucketIndex]->remove(ItemIndex);
00280       m_Size--;
00281    }
00282 }
00283 
00284 template<class PKey, class PValue>
00285 void CHMrefHashTable<PKey,PValue>::insert(const PKey& Key, const PValue& Value)
00286 {
00287    size_t BucketIndex;
00288    size_t ItemIndex;
00289    findIndex(Key, BucketIndex, ItemIndex);
00290    if (ItemIndex != npos)
00291    {
00292       //CHM_LOG3("Over-riding old entry " << Key);
00293       m_Bucket[BucketIndex]->operator[](ItemIndex)->Value = Value;
00294    }
00295    else
00296    {
00297       m_Size +=1;
00298       m_Bucket[BucketIndex]->push_back(new CHMpair<PKey,PValue>(Key,Value));
00299    }
00300 }
00301 /*
00302 template<class PKey, class PValue>
00303 void CHMrefHashTable<PKey,PValue>::showBuckets() const
00304 {
00305    for (size_t BucketIndex = 0; BucketIndex < m_Bucket.size(); BucketIndex++)
00306    {
00307       cout << "Bucket " << BucketIndex << " contains " << m_Bucket[BucketIndex]->size() << " entries\n";
00308    }
00309 }*/
00310 
00311 #endif // end of defensive include