![]() |
OpenNI 1.5.7
|
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_