OpenNI 1.5.7
XnHashT.h
Go to the documentation of this file.
00001 /*****************************************************************************
00002 *                                                                            *
00003 *  OpenNI 1.x Alpha                                                          *
00004 *  Copyright (C) 2012 PrimeSense Ltd.                                        *
00005 *                                                                            *
00006 *  This file is part of OpenNI.                                              *
00007 *                                                                            *
00008 *  Licensed under the Apache License, Version 2.0 (the "License");           *
00009 *  you may not use this file except in compliance with the License.          *
00010 *  You may obtain a copy of the License at                                   *
00011 *                                                                            *
00012 *      http://www.apache.org/licenses/LICENSE-2.0                            *
00013 *                                                                            *
00014 *  Unless required by applicable law or agreed to in writing, software       *
00015 *  distributed under the License is distributed on an "AS IS" BASIS,         *
00016 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
00017 *  See the License for the specific language governing permissions and       *
00018 *  limitations under the License.                                            *
00019 *                                                                            *
00020 *****************************************************************************/
00021 #ifndef _XN_HASH_T_H_
00022 #define _XN_HASH_T_H_ 
00023 
00024 //---------------------------------------------------------------------------
00025 // Includes
00026 //---------------------------------------------------------------------------
00027 #include <XnOS.h>
00028 #include <XnListT.h>
00029 
00030 //---------------------------------------------------------------------------
00031 // Defines
00032 //---------------------------------------------------------------------------
00033 typedef XnUInt8 XnHashCode;
00034 
00035 //---------------------------------------------------------------------------
00036 // Code
00037 //---------------------------------------------------------------------------
00038 template<class _TKey, class _TValue>
00039 struct XnKeyValuePair
00040 {
00041     typedef _TKey TKey;
00042     typedef _TValue TValue;
00043 
00044     XnKeyValuePair() : key(TKey()), value(TValue()) {}
00045     XnKeyValuePair(TKey key, TValue value) : key(key), value(value) {}
00046     XnKeyValuePair(const XnKeyValuePair& other) : key(other.key), value(other.value) {}
00047 
00048 public:
00049     TKey const& Key() const { return key; }
00050     TValue const& Value() const { return value; }
00051     TValue& Value() { return value; }
00052 
00053 private:
00054     TKey key;
00055     TValue value;
00056 };
00057 
00058 template<class TKey>
00059 class XnDefaultKeyManagerT
00060 {
00061 public:
00062     static XnHashCode Hash(TKey const& key)
00063     {
00064         return (((XnSizeT)key) & 0xff);
00065     }
00066 
00067     static XnInt32 Compare(TKey const& key1, TKey const& key2)
00068     {
00069         return XnInt32(XnSizeT(key1)-XnSizeT(key2));
00070     }
00071 };
00072 
00073 template<class TKey, 
00074         class TValue, 
00075         class TKeyManager = XnDefaultKeyManagerT<TKey>, 
00076         class TAlloc = XnLinkedNodeDefaultAllocatorT<XnKeyValuePair<TKey, TValue> > >
00077 class XnHashT
00078 {
00079 public:
00080     typedef XnKeyValuePair<TKey, TValue> TPair;
00081     typedef XnListT<TPair, TAlloc> TPairList;
00082 
00083     enum 
00084     { 
00085         LAST_BIN = (1 << (sizeof(XnHashCode)*8)),
00086         NUM_BINS = LAST_BIN + 1,
00087     };
00088 
00089     class ConstIterator
00090     {
00091     public:
00092         ConstIterator() : m_ppBins(NULL), m_nCurrBin(0)
00093         {}
00094 
00095         ConstIterator(TPairList* const* apBins, XnUInt32 nCurrBin, typename TPairList::ConstIterator currIt)
00096             : m_ppBins(apBins), m_nCurrBin(nCurrBin), m_currIt(currIt)
00097         {
00098             if (nCurrBin != LAST_BIN && m_currIt == m_ppBins[m_nCurrBin]->End())
00099             {
00100                 // this does not point to an actual entry. run to next one.
00101                 ++*this;
00102             }
00103         }
00104 
00105         ConstIterator(const ConstIterator& other)
00106             : m_ppBins(other.m_ppBins), m_nCurrBin(other.m_nCurrBin), m_currIt(other.m_currIt)
00107         {}
00108 
00112         ConstIterator& operator++()
00113         {
00114             XN_ASSERT(m_nCurrBin != LAST_BIN);
00115 
00116             // increment internal bin iterator
00117             if (m_currIt != m_ppBins[m_nCurrBin]->End())
00118             {
00119                 ++m_currIt;
00120             }
00121 
00122             // check if we need to move to next bin
00123             if (m_currIt == m_ppBins[m_nCurrBin]->End())
00124             {
00125                 // go forward through bins, until we either reach the end or a non-empty bin
00126                 do 
00127                 {
00128                     ++m_nCurrBin;
00129                 } while (m_nCurrBin < LAST_BIN && 
00130                         (m_ppBins[m_nCurrBin] == NULL || m_ppBins[m_nCurrBin]->IsEmpty()));
00131 
00132                 m_currIt = m_ppBins[m_nCurrBin]->Begin();
00133             }
00134 
00135             return *this;
00136         }
00137 
00141         ConstIterator operator++(int)
00142         {
00143             ConstIterator retVal(*this);
00144             ++*this;
00145             return retVal;
00146         }
00147 
00151         ConstIterator& operator--()
00152         {
00153             XN_ASSERT(m_nCurrBin != LAST_BIN);
00154 
00155             // decrement internal bin iterator
00156             if (m_currIt != m_ppBins[m_nCurrBin]->ReverseEnd())
00157             {
00158                 --m_currIt;
00159             }
00160 
00161             // check if we need to move to previous bin
00162             if (m_currIt == m_ppBins[m_nCurrBin]->ReverseEnd())
00163             {
00164                 // go backwards through bins, until we either reach the end or a non-empty bin
00165                 do 
00166                 {
00167                     if (m_nCurrBin == 0)
00168                     {
00169                         m_nCurrBin = LAST_BIN;
00170                         break;
00171                     }
00172                     else
00173                     {
00174                         --m_nCurrBin;
00175                     }
00176                 } while (m_ppBins[m_nCurrBin] == NULL || m_ppBins[m_nCurrBin]->IsEmpty());
00177 
00178                 m_currIt = m_ppBins[m_nCurrBin]->Begin();
00179             }
00180 
00181             return *this;
00182         }
00183 
00187         ConstIterator operator--(int)
00188         {
00189             ConstIterator retVal(*this);
00190             --*this;
00191             return retVal;
00192         }
00193 
00199         inline XnBool operator==(const ConstIterator& other) const
00200         {
00201             return m_currIt == other.m_currIt;
00202         }
00203 
00209         inline XnBool operator!=(const ConstIterator& other) const
00210         {
00211             return m_currIt != other.m_currIt;
00212         }
00213 
00217         inline TPair const& operator*() const
00218         {
00219             return *m_currIt;
00220         }
00221 
00225         inline TPair const* operator->() const
00226         {
00227             return m_currIt.operator->();
00228         }
00229 
00230     protected:
00231         friend class XnHashT;
00232 
00233         TPairList* const* m_ppBins;
00234         XnUInt32 m_nCurrBin;
00235         typename TPairList::ConstIterator m_currIt;
00236     };
00237 
00238     class Iterator : public ConstIterator
00239     {
00240     public:
00241         Iterator() : ConstIterator()
00242         {}
00243 
00244         Iterator(TPairList** apBins, XnUInt32 nCurrBin, typename TPairList::Iterator currIt)
00245             : ConstIterator(apBins, nCurrBin, currIt)
00246         {}
00247 
00248         Iterator(const Iterator& other) : ConstIterator(other)
00249         {}
00250 
00254         Iterator& operator++()
00255         {
00256             ++(*(ConstIterator*)this);
00257             return (*this);
00258         }
00259 
00263         inline Iterator operator++(int) 
00264         { 
00265             Iterator retVal(*this);
00266             ++*this;
00267             return (retVal);
00268         }
00269         
00273         inline Iterator& operator--() 
00274         { 
00275             --(*(ConstIterator*)this); 
00276             return (*this);
00277         }
00278 
00282         inline Iterator operator--(int)
00283         { 
00284             Iterator retVal(*this);
00285             --*this;
00286             return (retVal);
00287         }
00288 
00292         inline TPair& operator*() const 
00293         {
00294             return const_cast<TPair&>(*this->m_currIt);
00295         }
00296 
00300         inline TPair* operator->() const
00301         {
00302             return const_cast<TPair*>(this->m_currIt.operator->());
00303         }
00304     };
00305 
00306     XnHashT()
00307     {
00308         Init();
00309     }
00310 
00311     XnHashT(const XnHashT& other)
00312     {
00313         Init();
00314         *this = other;
00315     }
00316 
00317     XnHashT& operator=(const XnHashT& other)
00318     {
00319         Clear();
00320 
00321         XnStatus nRetVal = XN_STATUS_OK;
00322 
00323         for (ConstIterator it = other.Begin(); it != other.End(); ++it)
00324         {
00325             nRetVal = Set(it->Key(), it->Value());
00326             XN_ASSERT(nRetVal == XN_STATUS_OK);
00327         }
00328 
00329         return *this;
00330     }
00331 
00332     ~XnHashT()
00333     {
00334         // NOTE: we don't want to delete LAST_BIN (it points to the m_lastBin member)
00335         for (XnUInt32 i = 0; i < LAST_BIN; ++i)
00336         {
00337             if (m_apBins[i] != NULL)
00338             {
00339                 XN_DELETE(m_apBins[i]);
00340             }
00341         }
00342     }
00343 
00347     Iterator Begin()
00348     {
00349         return Iterator(m_apBins, m_nMinBin, m_apBins[m_nMinBin]->Begin());
00350     }
00351 
00355     ConstIterator Begin() const
00356     {
00357         return ConstIterator(m_apBins, m_nMinBin, m_apBins[m_nMinBin]->Begin());
00358     }
00359 
00363     Iterator End()
00364     {
00365         return Iterator(m_apBins, LAST_BIN, m_apBins[LAST_BIN]->Begin());
00366     }
00367 
00371     ConstIterator End() const
00372     {
00373         return ConstIterator(m_apBins, LAST_BIN, m_apBins[LAST_BIN]->Begin());
00374     }
00375 
00382     XnStatus Set(const TKey& key, const TValue& value)
00383     {
00384         XnHashCode nHash = TKeyManager::Hash(key);
00385 
00386         // check if bin exists
00387         if (m_apBins[nHash] == NULL)
00388         {
00389             // create it
00390             XN_VALIDATE_NEW(m_apBins[nHash], TPairList);
00391 
00392             if (nHash < m_nMinBin)
00393             {
00394                 m_nMinBin = nHash;
00395             }
00396         }
00397 
00398         // now check if key is already in the bin
00399         for (typename TPairList::Iterator it = m_apBins[nHash]->Begin(); it != m_apBins[nHash]->End(); ++it)
00400         {
00401             if (TKeyManager::Compare(it->Key(), key) == 0)
00402             {
00403                 // replace it
00404                 it->Value() = value;
00405                 return (XN_STATUS_OK);
00406             }
00407         }
00408 
00409         // if we got here, key is not in bin. Add it.
00410         return m_apBins[nHash]->AddLast(TPair(key, value));
00411     }
00412 
00420     ConstIterator Find(TKey const& key) const
00421     {
00422         XnUInt32 nBin = LAST_BIN;
00423         typename TPairList::ConstIterator it;
00424         if (TRUE == Find(key, nBin, it))
00425         {
00426             return ConstIterator(m_apBins, nBin, it);
00427         }
00428         else
00429         {
00430             return End();
00431         }
00432     }
00433 
00441     Iterator Find(TKey const& key)
00442     {
00443         XnUInt32 nBin = LAST_BIN;
00444         typename TPairList::Iterator it;
00445         if (TRUE == Find(key, nBin, it))
00446         {
00447             return Iterator(m_apBins, nBin, it);
00448         }
00449         else
00450         {
00451             return End();
00452         }
00453     }
00454 
00463     XnStatus Find(TKey const& key, ConstIterator& it) const
00464     {
00465         it = Find(key);
00466         return (it == End() ? XN_STATUS_NO_MATCH : XN_STATUS_OK);
00467     }
00468 
00477     XnStatus Find(TKey const& key, Iterator& it)
00478     {
00479         it = Find(key);
00480         return (it == End() ? XN_STATUS_NO_MATCH : XN_STATUS_OK);
00481     }
00482 
00491     XnStatus Get(TKey const& key, TValue& value) const
00492     {
00493         ConstIterator it = Find(key);
00494         if (it == End())
00495         {
00496             return XN_STATUS_NO_MATCH;
00497         }
00498         else
00499         {
00500             value = it->Value();
00501             return XN_STATUS_OK;
00502         }
00503     }
00504 
00513     XnStatus Get(TKey const& key, TValue const*& pValue) const
00514     {
00515         ConstIterator it = Find(key);
00516         if (it == End())
00517         {
00518             return XN_STATUS_NO_MATCH;
00519         }
00520         else
00521         {
00522             pValue = &it->Value();
00523             return XN_STATUS_OK;
00524         }
00525     }
00526 
00535     XnStatus Get(TKey const& key, TValue& value)
00536     {
00537         Iterator it = Find(key);
00538         if (it == End())
00539         {
00540             return XN_STATUS_NO_MATCH;
00541         }
00542         else
00543         {
00544             value = it->Value();
00545             return XN_STATUS_OK;
00546         }
00547     }
00548 
00557     XnStatus Get(TKey const& key, TValue*& pValue)
00558     {
00559         Iterator it = Find(key);
00560         if (it == End())
00561         {
00562             return XN_STATUS_NO_MATCH;
00563         }
00564         else
00565         {
00566             pValue = &it->Value();
00567             return XN_STATUS_OK;
00568         }
00569     }
00570 
00576     TValue& operator[](TKey const& key)
00577     {
00578         XnStatus nRetVal = XN_STATUS_OK;
00579         Iterator it = Find(key);
00580         if (it == End())
00581         {
00582             nRetVal = Set(key, TValue());
00583             XN_ASSERT(nRetVal == XN_STATUS_OK);
00584 
00585             it = Find(key);
00586             XN_ASSERT(it != End());
00587         }
00588 
00589         return it->Value();
00590     }
00591 
00592     XnStatus Remove(ConstIterator it)
00593     {
00594         // Verify iterator is valid
00595         if (it == End())
00596         {
00597             XN_ASSERT(FALSE);
00598             return XN_STATUS_ILLEGAL_POSITION;
00599         }
00600 
00601         XN_ASSERT(m_apBins == it.m_ppBins);
00602         XN_ASSERT(m_apBins[it.m_nCurrBin] != NULL);
00603 
00604         return m_apBins[it.m_nCurrBin]->Remove(it.m_currIt);
00605     }
00606 
00607     XnStatus Remove(TKey const& key)
00608     {
00609         ConstIterator it = Find(key);
00610         if (it != End())
00611         {
00612             return Remove(it);
00613         }
00614         else
00615         {
00616             return XN_STATUS_NO_MATCH;
00617         }
00618     }
00619 
00623     XnStatus Clear()
00624     {
00625         while (Begin() != End())
00626             Remove(Begin());
00627 
00628         return XN_STATUS_OK;
00629     }
00630 
00634     XnBool IsEmpty() const
00635     {
00636         return (Begin() == End());
00637     }
00638 
00642     XnUInt32 Size() const
00643     {
00644         XnUInt32 nSize = 0;
00645         for (ConstIterator iter = Begin(); iter != End(); ++iter, ++nSize)
00646             ;
00647 
00648         return nSize;
00649     }
00650 
00651 private:
00652     XnBool Find(TKey const& key, XnUInt32& nBin, typename TPairList::ConstIterator& currIt) const
00653     {
00654         XnHashCode nHash = TKeyManager::Hash(key);
00655 
00656         if (m_apBins[nHash] != NULL)
00657         {
00658             // look for value in bin
00659             for (typename TPairList::ConstIterator it = m_apBins[nHash]->Begin(); it != m_apBins[nHash]->End(); ++it)
00660             {
00661                 if (TKeyManager::Compare(it->Key(), key) == 0)
00662                 {
00663                     nBin = nHash;
00664                     currIt = it;
00665                     return TRUE;
00666                 }
00667             }
00668         }
00669 
00670         // if we got here, key wasn't found
00671         return FALSE;
00672     }
00673 
00674     void Init()
00675     {
00676         xnOSMemSet(m_apBins, 0, sizeof(m_apBins));
00677         m_apBins[LAST_BIN] = &m_lastBin;
00678         m_nMinBin = LAST_BIN;
00679     }
00680 
00681     TPairList* m_apBins[NUM_BINS];
00682     TPairList m_lastBin;
00683     XnUInt32 m_nMinBin;
00684 };
00685 
00686 
00687 
00688 #endif // _XN_HASH_T_H_