OpenNI 1.5.4: XnHashT.h Source File

OpenNI

OpenNI 1.5.4
XnHashT.h
Go to the documentation of this file.
00001 #ifndef _XN_HASH_T_H_
00002 #define _XN_HASH_T_H_ 
00003 
00004 //---------------------------------------------------------------------------
00005 // Includes
00006 //---------------------------------------------------------------------------
00007 #include <XnOS.h>
00008 #include <XnListT.h>
00009 
00010 //---------------------------------------------------------------------------
00011 // Defines
00012 //---------------------------------------------------------------------------
00013 typedef XnUInt8 XnHashCode;
00014 
00015 //---------------------------------------------------------------------------
00016 // Code
00017 //---------------------------------------------------------------------------
00018 template<class _TKey, class _TValue>
00019 struct XnKeyValuePair
00020 {
00021     typedef _TKey TKey;
00022     typedef _TValue TValue;
00023 
00024     XnKeyValuePair() : key(TKey()), value(TValue()) {}
00025     XnKeyValuePair(TKey key, TValue value) : key(key), value(value) {}
00026     XnKeyValuePair(const XnKeyValuePair& other) : key(other.key), value(other.value) {}
00027 
00028 public:
00029     TKey const& Key() const { return key; }
00030     TValue const& Value() const { return value; }
00031     TValue& Value() { return value; }
00032 
00033 private:
00034     TKey key;
00035     TValue value;
00036 };
00037 
00038 template<class TKey>
00039 class XnDefaultKeyManagerT
00040 {
00041 public:
00042     static XnHashCode Hash(TKey const& key)
00043     {
00044         return (((XnSizeT)key) & 0xff);
00045     }
00046 
00047     static XnInt32 Compare(TKey const& key1, TKey const& key2)
00048     {
00049         return XnInt32(XnSizeT(key1)-XnSizeT(key2));
00050     }
00051 };
00052 
00053 template<class TKey, 
00054         class TValue, 
00055         class TKeyManager = XnDefaultKeyManagerT<TKey>, 
00056         class TAlloc = XnLinkedNodeDefaultAllocatorT<XnKeyValuePair<TKey, TValue> > >
00057 class XnHashT
00058 {
00059 public:
00060     typedef XnKeyValuePair<TKey, TValue> TPair;
00061     typedef XnListT<TPair, TAlloc> TPairList;
00062 
00063     enum 
00064     { 
00065         LAST_BIN = (1 << (sizeof(XnHashCode)*8)),
00066         NUM_BINS = LAST_BIN + 1,
00067     };
00068 
00069     class ConstIterator
00070     {
00071     public:
00072         ConstIterator() : m_ppBins(NULL), m_nCurrBin(0)
00073         {}
00074 
00075         ConstIterator(TPairList* const* apBins, XnUInt32 nCurrBin, typename TPairList::ConstIterator currIt)
00076             : m_ppBins(apBins), m_nCurrBin(nCurrBin), m_currIt(currIt)
00077         {
00078             if (nCurrBin != LAST_BIN && m_currIt == m_ppBins[m_nCurrBin]->End())
00079             {
00080                 // this does not point to an actual entry. run to next one.
00081                 ++*this;
00082             }
00083         }
00084 
00085         ConstIterator(const ConstIterator& other)
00086             : m_ppBins(other.m_ppBins), m_nCurrBin(other.m_nCurrBin), m_currIt(other.m_currIt)
00087         {}
00088 
00092         ConstIterator& operator++()
00093         {
00094             XN_ASSERT(m_nCurrBin != LAST_BIN);
00095 
00096             // increment internal bin iterator
00097             if (m_currIt != m_ppBins[m_nCurrBin]->End())
00098             {
00099                 ++m_currIt;
00100             }
00101 
00102             // check if we need to move to next bin
00103             if (m_currIt == m_ppBins[m_nCurrBin]->End())
00104             {
00105                 // go forward through bins, until we either reach the end or a non-empty bin
00106                 do 
00107                 {
00108                     ++m_nCurrBin;
00109                 } while (m_nCurrBin < LAST_BIN && 
00110                         (m_ppBins[m_nCurrBin] == NULL || m_ppBins[m_nCurrBin]->IsEmpty()));
00111 
00112                 m_currIt = m_ppBins[m_nCurrBin]->Begin();
00113             }
00114 
00115             return *this;
00116         }
00117 
00121         ConstIterator operator++(int)
00122         {
00123             ConstIterator retVal(*this);
00124             ++*this;
00125             return retVal;
00126         }
00127 
00131         ConstIterator& operator--()
00132         {
00133             XN_ASSERT(m_nCurrBin != LAST_BIN);
00134 
00135             // decrement internal bin iterator
00136             if (m_currIt != m_ppBins[m_nCurrBin]->ReverseEnd())
00137             {
00138                 --m_currIt;
00139             }
00140 
00141             // check if we need to move to previous bin
00142             if (m_currIt == m_ppBins[m_nCurrBin]->ReverseEnd())
00143             {
00144                 // go backwards through bins, until we either reach the end or a non-empty bin
00145                 do 
00146                 {
00147                     if (m_nCurrBin == 0)
00148                     {
00149                         m_nCurrBin = LAST_BIN;
00150                         break;
00151                     }
00152                     else
00153                     {
00154                         --m_nCurrBin;
00155                     }
00156                 } while (m_ppBins[m_nCurrBin] == NULL || m_ppBins[m_nCurrBin]->IsEmpty());
00157 
00158                 m_currIt = m_ppBins[m_nCurrBin]->Begin();
00159             }
00160 
00161             return *this;
00162         }
00163 
00167         ConstIterator operator--(int)
00168         {
00169             ConstIterator retVal(*this);
00170             --*this;
00171             return retVal;
00172         }
00173 
00179         inline XnBool operator==(const ConstIterator& other) const
00180         {
00181             return m_currIt == other.m_currIt;
00182         }
00183 
00189         inline XnBool operator!=(const ConstIterator& other) const
00190         {
00191             return m_currIt != other.m_currIt;
00192         }
00193 
00197         inline TPair const& operator*() const
00198         {
00199             return *m_currIt;
00200         }
00201 
00205         inline TPair const* operator->() const
00206         {
00207             return m_currIt.operator->();
00208         }
00209 
00210     protected:
00211         friend class XnHashT;
00212 
00213         TPairList* const* m_ppBins;
00214         XnUInt32 m_nCurrBin;
00215         typename TPairList::ConstIterator m_currIt;
00216     };
00217 
00218     class Iterator : public ConstIterator
00219     {
00220     public:
00221         Iterator() : ConstIterator()
00222         {}
00223 
00224         Iterator(TPairList** apBins, XnUInt32 nCurrBin, typename TPairList::Iterator currIt)
00225             : ConstIterator(apBins, nCurrBin, currIt)
00226         {}
00227 
00228         Iterator(const Iterator& other) : ConstIterator(other)
00229         {}
00230 
00234         Iterator& operator++()
00235         {
00236             ++(*(ConstIterator*)this);
00237             return (*this);
00238         }
00239 
00243         inline Iterator operator++(int) 
00244         { 
00245             Iterator retVal(*this);
00246             ++*this;
00247             return (retVal);
00248         }
00249         
00253         inline Iterator& operator--() 
00254         { 
00255             --(*(ConstIterator*)this); 
00256             return (*this);
00257         }
00258 
00262         inline Iterator operator--(int)
00263         { 
00264             Iterator retVal(*this);
00265             --*this;
00266             return (retVal);
00267         }
00268 
00272         inline TPair& operator*() const 
00273         {
00274             return const_cast<TPair&>(*this->m_currIt);
00275         }
00276 
00280         inline TPair* operator->() const
00281         {
00282             return const_cast<TPair*>(this->m_currIt.operator->());
00283         }
00284     };
00285 
00286     XnHashT()
00287     {
00288         Init();
00289     }
00290 
00291     XnHashT(const XnHashT& other)
00292     {
00293         Init();
00294         *this = other;
00295     }
00296 
00297     XnHashT& operator=(const XnHashT& other)
00298     {
00299         Clear();
00300 
00301         XnStatus nRetVal = XN_STATUS_OK;
00302 
00303         for (ConstIterator it = other.Begin(); it != other.End(); ++it)
00304         {
00305             nRetVal = Set(it->Key(), it->Value());
00306             XN_ASSERT(nRetVal == XN_STATUS_OK);
00307         }
00308 
00309         return *this;
00310     }
00311 
00312     ~XnHashT()
00313     {
00314         // NOTE: we don't want to delete LAST_BIN (it points to the m_lastBin member)
00315         for (XnUInt32 i = 0; i < LAST_BIN; ++i)
00316         {
00317             if (m_apBins[i] != NULL)
00318             {
00319                 XN_DELETE(m_apBins[i]);
00320             }
00321         }
00322     }
00323 
00327     Iterator Begin()
00328     {
00329         return Iterator(m_apBins, m_nMinBin, m_apBins[m_nMinBin]->Begin());
00330     }
00331 
00335     ConstIterator Begin() const
00336     {
00337         return ConstIterator(m_apBins, m_nMinBin, m_apBins[m_nMinBin]->Begin());
00338     }
00339 
00343     Iterator End()
00344     {
00345         return Iterator(m_apBins, LAST_BIN, m_apBins[LAST_BIN]->Begin());
00346     }
00347 
00351     ConstIterator End() const
00352     {
00353         return ConstIterator(m_apBins, LAST_BIN, m_apBins[LAST_BIN]->Begin());
00354     }
00355 
00362     XnStatus Set(const TKey& key, const TValue& value)
00363     {
00364         XnHashCode nHash = TKeyManager::Hash(key);
00365 
00366         // check if bin exists
00367         if (m_apBins[nHash] == NULL)
00368         {
00369             // create it
00370             XN_VALIDATE_NEW(m_apBins[nHash], TPairList);
00371 
00372             if (nHash < m_nMinBin)
00373             {
00374                 m_nMinBin = nHash;
00375             }
00376         }
00377 
00378         // now check if key is already in the bin
00379         for (typename TPairList::Iterator it = m_apBins[nHash]->Begin(); it != m_apBins[nHash]->End(); ++it)
00380         {
00381             if (TKeyManager::Compare(it->Key(), key) == 0)
00382             {
00383                 // replace it
00384                 it->Value() = value;
00385                 return (XN_STATUS_OK);
00386             }
00387         }
00388 
00389         // if we got here, key is not in bin. Add it.
00390         return m_apBins[nHash]->AddLast(TPair(key, value));
00391     }
00392 
00400     ConstIterator Find(TKey const& key) const
00401     {
00402         XnUInt32 nBin = LAST_BIN;
00403         typename TPairList::ConstIterator it;
00404         if (TRUE == Find(key, nBin, it))
00405         {
00406             return ConstIterator(m_apBins, nBin, it);
00407         }
00408         else
00409         {
00410             return End();
00411         }
00412     }
00413 
00421     Iterator Find(TKey const& key)
00422     {
00423         XnUInt32 nBin = LAST_BIN;
00424         typename TPairList::Iterator it;
00425         if (TRUE == Find(key, nBin, it))
00426         {
00427             return Iterator(m_apBins, nBin, it);
00428         }
00429         else
00430         {
00431             return End();
00432         }
00433     }
00434 
00443     XnStatus Find(TKey const& key, ConstIterator& it) const
00444     {
00445         it = Find(key);
00446         return (it == End() ? XN_STATUS_NO_MATCH : XN_STATUS_OK);
00447     }
00448 
00457     XnStatus Find(TKey const& key, Iterator& it)
00458     {
00459         it = Find(key);
00460         return (it == End() ? XN_STATUS_NO_MATCH : XN_STATUS_OK);
00461     }
00462 
00471     XnStatus Get(TKey const& key, TValue& value) const
00472     {
00473         ConstIterator it = Find(key);
00474         if (it == End())
00475         {
00476             return XN_STATUS_NO_MATCH;
00477         }
00478         else
00479         {
00480             value = it->Value();
00481             return XN_STATUS_OK;
00482         }
00483     }
00484 
00493     XnStatus Get(TKey const& key, TValue const*& pValue) const
00494     {
00495         ConstIterator it = Find(key);
00496         if (it == End())
00497         {
00498             return XN_STATUS_NO_MATCH;
00499         }
00500         else
00501         {
00502             pValue = &it->Value();
00503             return XN_STATUS_OK;
00504         }
00505     }
00506 
00515     XnStatus Get(TKey const& key, TValue& value)
00516     {
00517         Iterator it = Find(key);
00518         if (it == End())
00519         {
00520             return XN_STATUS_NO_MATCH;
00521         }
00522         else
00523         {
00524             value = it->Value();
00525             return XN_STATUS_OK;
00526         }
00527     }
00528 
00537     XnStatus Get(TKey const& key, TValue*& pValue)
00538     {
00539         Iterator it = Find(key);
00540         if (it == End())
00541         {
00542             return XN_STATUS_NO_MATCH;
00543         }
00544         else
00545         {
00546             pValue = &it->Value();
00547             return XN_STATUS_OK;
00548         }
00549     }
00550 
00556     TValue& operator[](TKey const& key)
00557     {
00558         XnStatus nRetVal = XN_STATUS_OK;
00559         Iterator it = Find(key);
00560         if (it == End())
00561         {
00562             nRetVal = Set(key, TValue());
00563             XN_ASSERT(nRetVal == XN_STATUS_OK);
00564 
00565             it = Find(key);
00566             XN_ASSERT(it != End());
00567         }
00568 
00569         return it->Value();
00570     }
00571 
00572     XnStatus Remove(ConstIterator it)
00573     {
00574         // Verify iterator is valid
00575         if (it == End())
00576         {
00577             XN_ASSERT(FALSE);
00578             return XN_STATUS_ILLEGAL_POSITION;
00579         }
00580 
00581         XN_ASSERT(m_apBins == it.m_ppBins);
00582         XN_ASSERT(m_apBins[it.m_nCurrBin] != NULL);
00583 
00584         return m_apBins[it.m_nCurrBin]->Remove(it.m_currIt);
00585     }
00586 
00587     XnStatus Remove(TKey const& key)
00588     {
00589         ConstIterator it = Find(key);
00590         if (it != End())
00591         {
00592             return Remove(it);
00593         }
00594         else
00595         {
00596             return XN_STATUS_NO_MATCH;
00597         }
00598     }
00599 
00603     XnStatus Clear()
00604     {
00605         while (Begin() != End())
00606             Remove(Begin());
00607 
00608         return XN_STATUS_OK;
00609     }
00610 
00614     XnBool IsEmpty() const
00615     {
00616         return (Begin() == End());
00617     }
00618 
00622     XnUInt32 Size() const
00623     {
00624         XnUInt32 nSize = 0;
00625         for (ConstIterator iter = Begin(); iter != End(); ++iter, ++nSize)
00626             ;
00627 
00628         return nSize;
00629     }
00630 
00631 private:
00632     XnBool Find(TKey const& key, XnUInt32& nBin, typename TPairList::ConstIterator& currIt) const
00633     {
00634         XnHashCode nHash = TKeyManager::Hash(key);
00635 
00636         if (m_apBins[nHash] != NULL)
00637         {
00638             // look for value in bin
00639             for (typename TPairList::ConstIterator it = m_apBins[nHash]->Begin(); it != m_apBins[nHash]->End(); ++it)
00640             {
00641                 if (TKeyManager::Compare(it->Key(), key) == 0)
00642                 {
00643                     nBin = nHash;
00644                     currIt = it;
00645                     return TRUE;
00646                 }
00647             }
00648         }
00649 
00650         // if we got here, key wasn't found
00651         return FALSE;
00652     }
00653 
00654     void Init()
00655     {
00656         xnOSMemSet(m_apBins, 0, sizeof(m_apBins));
00657         m_apBins[LAST_BIN] = &m_lastBin;
00658         m_nMinBin = LAST_BIN;
00659     }
00660 
00661     TPairList* m_apBins[NUM_BINS];
00662     TPairList m_lastBin;
00663     XnUInt32 m_nMinBin;
00664 };
00665 
00666 
00667 
00668 #endif // _XN_HASH_T_H_
Generated on Wed May 16 2012 10:16:05 for OpenNI 1.5.4 by   doxygen 1.7.5.1