00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _XN_HASH_H
00023 #define _XN_HASH_H
00024
00025
00026
00027
00028 #include "XnList.h"
00029
00030
00031
00032
00033 #define XN_HASH_LAST_BIN 256
00034 #define XN_HASH_NUM_BINS (XN_HASH_LAST_BIN + 1)
00035
00036
00037
00041 typedef XnValue XnKey;
00042
00046 typedef XnUInt8 XnHashValue;
00047
00051 static XnHashValue XnDefaultHashFunction(const XnKey& key)
00052 {
00053 return (XnSizeT(key) & 0xff);
00054 }
00055
00059 static XnInt32 XnDefaultCompareFunction(const XnKey& key1, const XnKey& key2)
00060 {
00061 return XnInt32(XnSizeT(key1)-XnSizeT(key2));
00062 }
00063
00067 class XnHash
00068 {
00069 public:
00073 class ConstIterator
00074 {
00075 public:
00076 friend class XnHash;
00077
00083 ConstIterator(const ConstIterator& other) :
00084 m_pHash(other.m_pHash), m_nCurrentBin(other.m_nCurrentBin), m_Iterator(other.m_Iterator) {}
00085
00089 ConstIterator& operator++()
00090 {
00091 ++m_Iterator;
00092
00093 while (m_Iterator == m_pHash->m_Bins[m_nCurrentBin]->end() &&
00094 m_Iterator != m_pHash->m_Bins[XN_HASH_LAST_BIN]->end())
00095 {
00096 do
00097 {
00098 m_nCurrentBin++;
00099 } while (m_pHash->m_Bins[m_nCurrentBin] == NULL);
00100 m_Iterator = m_pHash->m_Bins[m_nCurrentBin]->begin();
00101 }
00102 return *this;
00103 }
00104
00108 ConstIterator operator++(int)
00109 {
00110 XnHash::ConstIterator other(*this);
00111 ++*this;
00112 return other;
00113 }
00114
00118 ConstIterator& operator--()
00119 {
00120 --m_Iterator;
00121
00122 while (m_Iterator == m_pHash->m_Bins[m_nCurrentBin]->end() &&
00123 m_Iterator != m_pHash->m_Bins[XN_HASH_LAST_BIN]->end())
00124 {
00125 do
00126 {
00127 if (m_nCurrentBin == 0)
00128 {
00129 m_nCurrentBin = XN_HASH_LAST_BIN;
00130 m_Iterator = m_pHash->m_Bins[XN_HASH_LAST_BIN]->end();
00131 return *this;
00132 }
00133 m_nCurrentBin--;
00134 } while (m_pHash->m_Bins[m_nCurrentBin] == NULL);
00135 m_Iterator = m_pHash->m_Bins[m_nCurrentBin]->rbegin();
00136 }
00137 return *this;
00138 }
00139
00143 ConstIterator operator--(int)
00144 {
00145 ConstIterator other(*this);
00146 --*this;
00147 return other;
00148 }
00149
00155 XnBool operator==(const ConstIterator& other) const
00156 {
00157 return m_Iterator == other.m_Iterator;
00158 }
00159
00165 XnBool operator!=(const ConstIterator& other) const
00166 {
00167 return m_Iterator != other.m_Iterator;
00168 }
00169
00173 const XnKey& Key() const
00174 {
00175 return ((XnNode*)(*m_Iterator))->Data();
00176 }
00177
00181 const XnValue& Value() const
00182 {
00183 return ((XnNode*)(*m_Iterator))->Next()->Data();
00184 }
00185
00189 XnNode* GetNode()
00190 {
00191 return m_Iterator.GetNode();
00192 }
00193
00197 const XnNode* GetNode() const
00198 {
00199 return m_Iterator.GetNode();
00200 }
00201
00202 protected:
00210 ConstIterator(const XnHash* pHash, XnUInt16 nBin, XnList::Iterator listIterator) :
00211 m_pHash(pHash), m_nCurrentBin(nBin), m_Iterator(listIterator)
00212 {
00213
00214 while (m_Iterator == m_pHash->m_Bins[m_nCurrentBin]->end() &&
00215 m_Iterator != m_pHash->m_Bins[XN_HASH_LAST_BIN]->end())
00216 {
00217 do
00218 {
00219 m_nCurrentBin++;
00220 } while (m_pHash->m_Bins[m_nCurrentBin] == NULL);
00221 m_Iterator = m_pHash->m_Bins[m_nCurrentBin]->begin();
00222 }
00223 }
00224
00230 ConstIterator(const XnHash* pHash) :
00231 m_pHash(pHash), m_nCurrentBin(0), m_Iterator(m_pHash->m_Bins[XN_HASH_LAST_BIN]->end()) {}
00232
00234 const XnHash* m_pHash;
00236 XnUInt16 m_nCurrentBin;
00238 XnList::Iterator m_Iterator;
00239 };
00240
00244 class Iterator : public ConstIterator
00245 {
00246 public:
00247 friend class XnHash;
00248
00254 inline Iterator(const Iterator& other) : ConstIterator(other) {}
00255
00259 inline Iterator& operator++()
00260 {
00261 ++(*(ConstIterator*)this);
00262 return (*this);
00263 }
00267 inline Iterator operator++(int)
00268 {
00269 Iterator result = *this;
00270 ++*this;
00271 return (result);
00272 }
00273
00277 inline Iterator& operator--()
00278 {
00279 --(*(ConstIterator*)this);
00280 return (*this);
00281 }
00285 inline Iterator operator--(int)
00286 {
00287 Iterator result = *this;
00288 --*this;
00289 return (result);
00290 }
00291
00295 XnKey& Key() const { return (XnKey&)ConstIterator::Key(); }
00296
00300 XnValue& Value() const { return (XnValue&)ConstIterator::Value(); }
00301
00302 protected:
00310 Iterator(const XnHash* pHash, XnUInt16 nBin, XnList::Iterator listIterator) :
00311 ConstIterator(pHash, nBin, listIterator)
00312 {}
00313
00319 Iterator(const XnHash* pHash) : ConstIterator(pHash) {}
00320
00321 Iterator(const ConstIterator& other) : ConstIterator(other) {}
00322 };
00323
00324 friend class ConstIterator;
00325
00326 public:
00330 typedef XnHashValue (*XnHashFunction)(const XnKey& key);
00334 typedef XnInt32 (*XnCompareFunction)(const XnKey& key1, const XnKey& key2);
00335
00339 XnHash()
00340 {
00341 m_nInitStatus = Init();
00342 }
00343
00347 virtual ~XnHash()
00348 {
00349 if (m_Bins != NULL)
00350 {
00351 for (int i = 0; i < XN_HASH_NUM_BINS; ++i)
00352 {
00353 XN_DELETE(m_Bins[i]);
00354 }
00355 XN_DELETE_ARR(m_Bins);
00356 }
00357 }
00358
00364 XnStatus GetInitStatus() const
00365 {
00366 return m_nInitStatus;
00367 }
00368
00375 XnStatus Set(const XnKey& key, const XnValue& value)
00376 {
00377 XnHashValue HashValue = (*m_HashFunction)(key);
00378
00379
00380 if (m_Bins[HashValue] != NULL)
00381 {
00382 Iterator hiter(this);
00383 if (Find(key, HashValue, hiter) == XN_STATUS_OK)
00384 {
00385
00386 hiter.Value() = value;
00387 return XN_STATUS_OK;
00388 }
00389 }
00390 else
00391 {
00392
00393 m_Bins[HashValue] = XN_NEW(XnList);
00394 if (m_Bins[HashValue] == NULL)
00395 {
00396 return XN_STATUS_ALLOC_FAILED;
00397 }
00398 if (HashValue < m_nMinBin)
00399 m_nMinBin = HashValue;
00400 }
00401
00402
00403 XnNode* pKeyNode = XnNode::Allocate();
00404 if (pKeyNode == NULL)
00405 {
00406 return XN_STATUS_ALLOC_FAILED;
00407 }
00408 pKeyNode->Data() = key;
00409
00410
00411 XnNode* pValueNode = XnNode::Allocate();
00412 if (pValueNode == NULL)
00413 {
00414 XnNode::Deallocate(pKeyNode);
00415 return XN_STATUS_ALLOC_FAILED;
00416 }
00417 pValueNode->Data() = value;
00418
00419
00420 pKeyNode->Next() = pValueNode;
00421 pValueNode->Next() = NULL;
00422
00423
00424 XnStatus ListStatus = m_Bins[HashValue]->AddLast(XnValue(pKeyNode));
00425 if (ListStatus != XN_STATUS_OK)
00426 {
00427
00428 XnNode::Deallocate(pKeyNode);
00429 XnNode::Deallocate(pValueNode);
00430 return ListStatus;
00431 }
00432
00433 return XN_STATUS_OK;
00434 }
00435
00444 XnStatus Get(const XnKey& key, XnValue& value) const
00445 {
00446
00447 Iterator hiter(this);
00448 XnStatus FindStatus = Find(key, hiter);
00449 if (FindStatus != XN_STATUS_OK)
00450 {
00451
00452 return FindStatus;
00453 }
00454 value = hiter.Value();
00455
00456 return XN_STATUS_OK;
00457 }
00458
00467 XnStatus Remove(const XnKey& key, XnValue& value)
00468 {
00469
00470 Iterator hiter(this);
00471
00472 XnStatus FindStatus = Find(key, hiter);
00473 if (FindStatus != XN_STATUS_OK)
00474 {
00475
00476 return FindStatus;
00477 }
00478
00479
00480 value = hiter.Value();
00481 return Remove(hiter);
00482 }
00483
00493 XnStatus Remove(ConstIterator iter, XnKey& key, XnValue& value)
00494 {
00495 if (iter == end())
00496 {
00497
00498 return XN_STATUS_ILLEGAL_POSITION;
00499 }
00500
00501
00502 value = iter.Value();
00503 key = iter.Key();
00504
00505 return Remove(iter);
00506 }
00507
00515 virtual XnStatus Remove(ConstIterator iter)
00516 {
00517 if (iter == end())
00518 {
00519
00520 return XN_STATUS_ILLEGAL_POSITION;
00521 }
00522
00523 XnNode* pNode = iter.GetNode();
00524
00525 XnNode* pKeyNode = (XnNode*)(pNode->Data());
00526 XnNode* pValueNode = pKeyNode->Next();
00527
00528
00529 XnNode::Deallocate(pKeyNode);
00530 XnNode::Deallocate(pValueNode);
00531
00532 pNode->Previous()->Next() = pNode->Next();
00533 pNode->Next()->Previous() = pNode->Previous();
00534
00535 XnNode::Deallocate(pNode);
00536
00537 return XN_STATUS_OK;
00538 }
00539
00540
00544 XnStatus Clear()
00545 {
00546 while (begin() != end())
00547 Remove(begin());
00548
00549 return XN_STATUS_OK;
00550 }
00551
00555 XnBool IsEmpty() const
00556 {
00557 return (begin() == end());
00558 }
00559
00563 XnUInt32 Size() const
00564 {
00565 XnUInt32 nSize = 0;
00566 for (Iterator iter = begin(); iter != end(); ++iter, ++nSize)
00567 ;
00568
00569 return nSize;
00570 }
00571
00580 XnStatus Find(const XnKey& key, ConstIterator& hiter) const
00581 {
00582 return ConstFind(key, hiter);
00583 }
00584
00593 XnStatus Find(const XnKey& key, Iterator& hiter)
00594 {
00595 XnStatus nRetVal = XN_STATUS_OK;
00596
00597 ConstIterator& it = hiter;
00598 nRetVal = ConstFind(key, it);
00599 XN_IS_STATUS_OK(nRetVal);
00600
00601 return (XN_STATUS_OK);
00602 }
00603
00607 Iterator begin()
00608 {
00609 return Iterator(this, m_nMinBin, m_Bins[m_nMinBin]->begin());
00610 }
00611
00615 ConstIterator begin() const
00616 {
00617 return ConstIterator(this, m_nMinBin, m_Bins[m_nMinBin]->begin());
00618 }
00619
00623 Iterator end()
00624 {
00625 return Iterator(this, XN_HASH_LAST_BIN, m_Bins[XN_HASH_LAST_BIN]->end());
00626 }
00627
00631 ConstIterator end() const
00632 {
00633 return ConstIterator(this, XN_HASH_LAST_BIN, m_Bins[XN_HASH_LAST_BIN]->end());
00634 }
00635
00643 XnStatus SetHashFunction(XnHashFunction hashFunction)
00644 {
00645 if (begin() != end())
00646 {
00647 return XN_STATUS_IS_NOT_EMPTY;
00648 }
00649 m_HashFunction = hashFunction;
00650 return XN_STATUS_OK;
00651 }
00652
00660 XnStatus SetCompareFunction(XnCompareFunction compareFunction)
00661 {
00662 if (begin() != end())
00663 {
00664 return XN_STATUS_IS_NOT_EMPTY;
00665 }
00666 m_CompareFunction = compareFunction;
00667 return XN_STATUS_OK;
00668 }
00669
00670 protected:
00671
00672 XnStatus Init()
00673 {
00674 m_Bins = XN_NEW_ARR(XnList*, XN_HASH_NUM_BINS);
00675 XN_VALIDATE_ALLOC_PTR(m_Bins);
00676
00677 for (int i = 0; i < XN_HASH_NUM_BINS; i++)
00678 {
00679 m_Bins[i] = NULL;
00680 }
00681
00682 m_Bins[XN_HASH_LAST_BIN] = XN_NEW(XnList);
00683 m_nMinBin = XN_HASH_LAST_BIN;
00684
00685 XN_VALIDATE_ALLOC_PTR(m_Bins[XN_HASH_LAST_BIN]);
00686 m_CompareFunction = &XnDefaultCompareFunction;
00687 m_HashFunction = &XnDefaultHashFunction;
00688 return XN_STATUS_OK;
00689 }
00690
00700 XnStatus Find(const XnKey& key, XnHashValue hashValue, ConstIterator& hiter) const
00701 {
00702 if (m_Bins[hashValue] != NULL)
00703 {
00704 hiter = ConstIterator(this, hashValue, m_Bins[hashValue]->begin());
00705 for (XnList::ConstIterator iter = m_Bins[hashValue]->begin();
00706 iter != m_Bins[hashValue]->end(); ++iter, ++hiter)
00707 {
00708 if ((*m_CompareFunction)(key, hiter.Key()) == 0)
00709 return XN_STATUS_OK;
00710 }
00711 }
00712
00713 return XN_STATUS_NO_MATCH;
00714 }
00715
00716
00718 XnList** m_Bins;
00719
00720 XnUInt16 m_nMinBin;
00721
00722
00723 XnStatus m_nInitStatus;
00724
00726 XnHashFunction m_HashFunction;
00728 XnCompareFunction m_CompareFunction;
00729
00730 private:
00731 XN_DISABLE_COPY_AND_ASSIGN(XnHash);
00732
00733 XnStatus ConstFind(const XnKey& key, ConstIterator& hiter) const
00734 {
00735 XnHashValue HashValue = (*m_HashFunction)(key);
00736 return Find(key, HashValue, hiter);
00737 }
00738 };
00739
00744 #define XN_DECLARE_DEFAULT_KEY_MANAGER_DECL(decl, KeyType, ClassName, KeyTranslator) \
00745 class decl ClassName \
00746 { \
00747 public: \
00748 inline static XnHashValue Hash(KeyType const& key) \
00749 { \
00750 const XnKey _key = KeyTranslator::GetAsValue(key); \
00751 return XnDefaultHashFunction(_key); \
00752 } \
00753 inline static XnInt32 Compare(KeyType const& key1, KeyType const& key2) \
00754 { \
00755 const XnKey _key1 = KeyTranslator::GetAsValue(key1); \
00756 const XnKey _key2 = KeyTranslator::GetAsValue(key2); \
00757 return XnDefaultCompareFunction(_key1, _key2); \
00758 } \
00759 };
00760
00765 #define XN_DECLARE_DEFAULT_KEY_MANAGER(KeyType, ClassName, KeyTranslator) \
00766 XN_DECLARE_DEFAULT_KEY_MANAGER_DECL(, KeyType, ClassName, KeyTranslator)
00767
00773 #define XN_DECLARE_HASH_DECL(decl, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator, KeyManager) \
00774 class decl ClassName : public XnHash \
00775 { \
00776 public: \
00777 class decl ConstIterator : public XnHash::ConstIterator \
00778 { \
00779 public: \
00780 friend class ClassName; \
00781 inline ConstIterator(const ConstIterator& other) : XnHash::ConstIterator(other) {} \
00782 inline ConstIterator& operator++() \
00783 { \
00784 ++(*(XnHash::ConstIterator*)this); \
00785 return (*this); \
00786 } \
00787 inline ConstIterator operator++(int) \
00788 { \
00789 ConstIterator result = *this; \
00790 ++*this; \
00791 return result; \
00792 } \
00793 inline ConstIterator& operator--() \
00794 { \
00795 --(*(XnHash::ConstIterator*)this); \
00796 return (*this); \
00797 } \
00798 inline ConstIterator operator--(int) \
00799 { \
00800 ConstIterator result = *this; \
00801 --*this; \
00802 return result; \
00803 } \
00804 inline KeyType const& Key() const \
00805 { \
00806 return KeyTranslator::GetFromValue(XnHash::ConstIterator::Key()); \
00807 } \
00808 inline ValueType const& Value() const \
00809 { \
00810 return ValueTranslator::GetFromValue(XnHash::ConstIterator::Value()); \
00811 } \
00812 protected: \
00813 inline ConstIterator(const XnHash::ConstIterator& other) : \
00814 XnHash::ConstIterator(other) {} \
00815 }; \
00816 class decl Iterator : public ConstIterator \
00817 { \
00818 public: \
00819 friend class ClassName; \
00820 inline Iterator(const Iterator& other) : ConstIterator(other) {} \
00821 inline Iterator& operator++() \
00822 { \
00823 ++(*(ConstIterator*)this); \
00824 return (*this); \
00825 } \
00826 inline Iterator operator++(int) \
00827 { \
00828 Iterator result = *this; \
00829 ++*this; \
00830 return result; \
00831 } \
00832 inline Iterator& operator--() \
00833 { \
00834 --(*(ConstIterator*)this); \
00835 return (*this); \
00836 } \
00837 inline Iterator operator--(int) \
00838 { \
00839 Iterator result = *this; \
00840 --*this; \
00841 return result; \
00842 } \
00843 inline KeyType& Key() const \
00844 { \
00845 return (KeyType&)ConstIterator::Key(); \
00846 } \
00847 inline ValueType& Value() const \
00848 { \
00849 return (ValueType&)ConstIterator::Value(); \
00850 } \
00851 protected: \
00852 inline Iterator(const XnHash::Iterator& other) : ConstIterator(other) {} \
00853 }; \
00854 public: \
00855 ClassName() \
00856 { \
00857 SetHashFunction(Hash); \
00858 SetCompareFunction(Compare); \
00859 } \
00860 virtual ~ClassName() \
00861 { \
00862 while (!IsEmpty()) \
00863 Remove(begin()); \
00864 } \
00865 XnStatus Set(KeyType const& key, ValueType const& value) \
00866 { \
00867 Iterator oldIt = begin(); \
00868 if (Find(key, oldIt) == XN_STATUS_OK) \
00869 { \
00870 oldIt.Value() = value; \
00871 } \
00872 else \
00873 { \
00874 XnKey _key = KeyTranslator::CreateValueCopy(key); \
00875 XnValue _value = ValueTranslator::CreateValueCopy(value); \
00876 XnStatus nRetVal = XnHash::Set(_key, _value); \
00877 if (nRetVal != XN_STATUS_OK) \
00878 { \
00879 KeyTranslator::FreeValue(_key); \
00880 ValueTranslator::FreeValue(_value); \
00881 return (nRetVal); \
00882 } \
00883 } \
00884 return XN_STATUS_OK; \
00885 } \
00886 XnStatus Get(KeyType const& key, ValueType& value) const \
00887 { \
00888 XnKey _key = KeyTranslator::GetAsValue(key); \
00889 XnValue _value; \
00890 XnStatus nRetVal = XnHash::Get(_key, _value); \
00891 if (nRetVal != XN_STATUS_OK) return (nRetVal); \
00892 value = ValueTranslator::GetFromValue(_value); \
00893 return XN_STATUS_OK; \
00894 } \
00895 XnStatus Get(KeyType const& key, ValueType*& pValue) const \
00896 { \
00897 XnKey _key = KeyTranslator::GetAsValue(key); \
00898 XnValue _value; \
00899 XnStatus nRetVal = XnHash::Get(_key, _value); \
00900 if (nRetVal != XN_STATUS_OK) return (nRetVal); \
00901 pValue = &ValueTranslator::GetFromValue(_value); \
00902 return XN_STATUS_OK; \
00903 } \
00904 XnStatus Remove(KeyType const& key) \
00905 { \
00906 ValueType dummy; \
00907 return Remove(key, dummy); \
00908 } \
00909 XnStatus Remove(KeyType const& key, ValueType& value) \
00910 { \
00911 ConstIterator it = end(); \
00912 XnStatus nRetVal = Find(key, it); \
00913 if (nRetVal != XN_STATUS_OK) return (nRetVal); \
00914 value = it.Value(); \
00915 return Remove(it); \
00916 } \
00917 inline XnStatus Remove(ConstIterator iter) \
00918 { \
00919 XnKey key = KeyTranslator::GetAsValue(iter.Key()); \
00920 XnValue value = ValueTranslator::GetAsValue(iter.Value()); \
00921 XnStatus nRetVal = XnHash::Remove(iter); \
00922 if (nRetVal != XN_STATUS_OK) return (nRetVal); \
00923 KeyTranslator::FreeValue(key); \
00924 ValueTranslator::FreeValue(value); \
00925 return XN_STATUS_OK; \
00926 } \
00927 XnStatus Find(KeyType const& key, ConstIterator& hiter) const \
00928 { \
00929 XnKey _key = KeyTranslator::GetAsValue(key); \
00930 XnHash::ConstIterator it = XnHash::end(); \
00931 XnStatus nRetVal = XnHash::Find(_key, it); \
00932 if (nRetVal != XN_STATUS_OK) return (nRetVal); \
00933 hiter = it; \
00934 return XN_STATUS_OK; \
00935 } \
00936 XnStatus Find(KeyType const& key, Iterator& hiter) \
00937 { \
00938 XnKey _key = KeyTranslator::GetAsValue(key); \
00939 XnHash::Iterator it = XnHash::end(); \
00940 XnStatus nRetVal = XnHash::Find(_key, it); \
00941 if (nRetVal != XN_STATUS_OK) return (nRetVal); \
00942 hiter = it; \
00943 return XN_STATUS_OK; \
00944 } \
00945 inline Iterator begin() { return XnHash::begin(); } \
00946 inline ConstIterator begin() const { return XnHash::begin(); } \
00947 inline Iterator end() { return XnHash::end(); } \
00948 inline ConstIterator end() const { return XnHash::end(); } \
00949 protected: \
00950 virtual XnStatus Remove(XnHash::ConstIterator iter) \
00951 { \
00952 return Remove(ConstIterator(iter)); \
00953 } \
00954 inline static XnHashValue Hash(const XnKey& key) \
00955 { \
00956 KeyType const& _key = KeyTranslator::GetFromValue(key); \
00957 return KeyManager::Hash(_key); \
00958 } \
00959 inline static XnInt32 Compare(const XnKey& key1, const XnKey& key2) \
00960 { \
00961 KeyType const _key1 = KeyTranslator::GetFromValue(key1); \
00962 KeyType const _key2 = KeyTranslator::GetFromValue(key2); \
00963 return KeyManager::Compare(_key1, _key2); \
00964 } \
00965 private: \
00966 XN_DISABLE_COPY_AND_ASSIGN(ClassName); \
00967 };
00968
00973 #define XN_DECLARE_HASH(KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator, KeyManager) \
00974 XN_DECLARE_HASH_DECL(, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator, KeyManager)
00975
00976 #define _XN_DEFAULT_KEY_MANAGER_NAME(ClassName) _##ClassName##Manager
00977
00983 #define XN_DECLARE_DEFAULT_MANAGER_HASH_DECL(decl, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator) \
00984 XN_DECLARE_DEFAULT_KEY_MANAGER_DECL(decl, KeyType, _XN_DEFAULT_KEY_MANAGER_NAME(ClassName), KeyTranslator) \
00985 XN_DECLARE_HASH_DECL(decl, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator, _XN_DEFAULT_KEY_MANAGER_NAME(ClassName))
00986
00991 #define XN_DECLARE_DEFAULT_MANAGER_HASH(decl, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator) \
00992 XN_DECLARE_DEFAULT_MANAGER_HASH_DECL(, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator)
00993
00994 #define _XN_DEFAULT_KEY_TRANSLATOR(ClassName) _##ClassName##KeyTranslator
00995 #define _XN_DEFAULT_VALUE_TRANSLATOR(ClassName) _##ClassName##ValueTranslator
00996
01002 #define XN_DECLARE_DEFAULT_HASH_DECL(decl, KeyType, ValueType, ClassName) \
01003 XN_DECLARE_DEFAULT_VALUE_TRANSLATOR_DECL(decl, KeyType, _XN_DEFAULT_KEY_TRANSLATOR(ClassName)) \
01004 XN_DECLARE_DEFAULT_VALUE_TRANSLATOR_DECL(decl, ValueType, _XN_DEFAULT_VALUE_TRANSLATOR(ClassName)) \
01005 XN_DECLARE_DEFAULT_MANAGER_HASH_DECL(decl, KeyType, ValueType, ClassName, _XN_DEFAULT_KEY_TRANSLATOR(ClassName), _XN_DEFAULT_VALUE_TRANSLATOR(ClassName))
01006
01011 #define XN_DECLARE_DEFAULT_HASH(KeyType, ValueType, ClassName) \
01012 XN_DECLARE_DEFAULT_HASH_DECL(, KeyType, ValueType, ClassName)
01013
01014 #endif // _XN_HASH_H