mirror of https://github.com/qt/qtdatavis3d.git
1015 lines
30 KiB
C++
1015 lines
30 KiB
C++
/****************************************************************************
|
|
* *
|
|
* OpenNI 1.x Alpha *
|
|
* Copyright (C) 2011 PrimeSense Ltd. *
|
|
* *
|
|
* This file is part of OpenNI. *
|
|
* *
|
|
* OpenNI is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU Lesser General Public License as published *
|
|
* by the Free Software Foundation, either version 3 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* OpenNI is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Lesser General Public License *
|
|
* along with OpenNI. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
****************************************************************************/
|
|
#ifndef _XN_HASH_H
|
|
#define _XN_HASH_H
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Includes
|
|
//---------------------------------------------------------------------------
|
|
#include "XnList.h"
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Defines
|
|
//---------------------------------------------------------------------------
|
|
#define XN_HASH_LAST_BIN 256
|
|
#define XN_HASH_NUM_BINS (XN_HASH_LAST_BIN + 1)
|
|
//---------------------------------------------------------------------------
|
|
// Types
|
|
//---------------------------------------------------------------------------
|
|
/**
|
|
* The key to the hash
|
|
*/
|
|
typedef XnValue XnKey;
|
|
|
|
/**
|
|
* The hash value - the output of the hash function
|
|
*/
|
|
typedef XnUInt8 XnHashValue;
|
|
|
|
/**
|
|
* Default Hash function
|
|
*/
|
|
static XnHashValue XnDefaultHashFunction(const XnKey& key)
|
|
{
|
|
return (XnSizeT(key) & 0xff);
|
|
}
|
|
|
|
/**
|
|
* Default Compare function
|
|
*/
|
|
static XnInt32 XnDefaultCompareFunction(const XnKey& key1, const XnKey& key2)
|
|
{
|
|
return XnInt32(XnSizeT(key1)-XnSizeT(key2));
|
|
}
|
|
|
|
/**
|
|
* The hash - associative array
|
|
*/
|
|
class XnHash
|
|
{
|
|
public:
|
|
/**
|
|
* Iterator to the XnHash
|
|
*/
|
|
class ConstIterator
|
|
{
|
|
public:
|
|
friend class XnHash;
|
|
|
|
/**
|
|
* Copy constructor
|
|
*
|
|
* @param other [in] instance to copy from
|
|
*/
|
|
ConstIterator(const ConstIterator& other) :
|
|
m_pHash(other.m_pHash), m_nCurrentBin(other.m_nCurrentBin), m_Iterator(other.m_Iterator) {}
|
|
|
|
/**
|
|
* Support ++iterator, go to the next object in the hash
|
|
*/
|
|
ConstIterator& operator++()
|
|
{
|
|
++m_Iterator;
|
|
|
|
while (m_Iterator == m_pHash->m_Bins[m_nCurrentBin]->end() &&
|
|
m_Iterator != m_pHash->m_Bins[XN_HASH_LAST_BIN]->end())
|
|
{
|
|
do
|
|
{
|
|
m_nCurrentBin++;
|
|
} while (m_pHash->m_Bins[m_nCurrentBin] == NULL);
|
|
m_Iterator = m_pHash->m_Bins[m_nCurrentBin]->begin();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Support iterator++, go to the next object in the hash, returning the old value
|
|
*/
|
|
ConstIterator operator++(int)
|
|
{
|
|
XnHash::ConstIterator other(*this);
|
|
++*this;
|
|
return other;
|
|
}
|
|
|
|
/**
|
|
* Support --iterator, go to the previous object in the hash
|
|
*/
|
|
ConstIterator& operator--()
|
|
{
|
|
--m_Iterator;
|
|
|
|
while (m_Iterator == m_pHash->m_Bins[m_nCurrentBin]->end() &&
|
|
m_Iterator != m_pHash->m_Bins[XN_HASH_LAST_BIN]->end())
|
|
{
|
|
do
|
|
{
|
|
if (m_nCurrentBin == 0)
|
|
{
|
|
m_nCurrentBin = XN_HASH_LAST_BIN;
|
|
m_Iterator = m_pHash->m_Bins[XN_HASH_LAST_BIN]->end();
|
|
return *this;
|
|
}
|
|
m_nCurrentBin--;
|
|
} while (m_pHash->m_Bins[m_nCurrentBin] == NULL);
|
|
m_Iterator = m_pHash->m_Bins[m_nCurrentBin]->rbegin();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
/**
|
|
* Support iterator--, go to the previous object in the hash, returning the old value
|
|
*/
|
|
ConstIterator operator--(int)
|
|
{
|
|
ConstIterator other(*this);
|
|
--*this;
|
|
return other;
|
|
}
|
|
|
|
/**
|
|
* Operator to check if 2 iterators point to the same object
|
|
*
|
|
* @param other [in] instance to compare with
|
|
*/
|
|
XnBool operator==(const ConstIterator& other) const
|
|
{
|
|
return m_Iterator == other.m_Iterator;
|
|
}
|
|
|
|
/**
|
|
* Operator to check if 2 iterators point to different objects
|
|
*
|
|
* @param other [in] instance to compare with
|
|
*/
|
|
XnBool operator!=(const ConstIterator& other) const
|
|
{
|
|
return m_Iterator != other.m_Iterator;
|
|
}
|
|
|
|
/**
|
|
* Get the key of the current object (const version)
|
|
*/
|
|
const XnKey& Key() const
|
|
{
|
|
return ((XnNode*)(*m_Iterator))->Data();
|
|
}
|
|
|
|
/**
|
|
* Get the value of the current object (const version)
|
|
*/
|
|
const XnValue& Value() const
|
|
{
|
|
return ((XnNode*)(*m_Iterator))->Next()->Data();
|
|
}
|
|
|
|
/**
|
|
* Get the entire current object (non-const version)
|
|
*/
|
|
XnNode* GetNode()
|
|
{
|
|
return m_Iterator.GetNode();
|
|
}
|
|
|
|
/**
|
|
* Get the entire current object (const version)
|
|
*/
|
|
const XnNode* GetNode() const
|
|
{
|
|
return m_Iterator.GetNode();
|
|
}
|
|
|
|
protected:
|
|
/**
|
|
* constructor to be used from inside the XnHash
|
|
*
|
|
* @param pHash [in] The hash to which the iterator belongs
|
|
* @param nBin [in] The bin of the current object
|
|
* @param listIterator [in] Iterator on the bin (each bin is a XnList)
|
|
*/
|
|
ConstIterator(const XnHash* pHash, XnUInt16 nBin, XnList::Iterator listIterator) :
|
|
m_pHash(pHash), m_nCurrentBin(nBin), m_Iterator(listIterator)
|
|
{
|
|
// Find the first valid
|
|
while (m_Iterator == m_pHash->m_Bins[m_nCurrentBin]->end() &&
|
|
m_Iterator != m_pHash->m_Bins[XN_HASH_LAST_BIN]->end())
|
|
{
|
|
do
|
|
{
|
|
m_nCurrentBin++;
|
|
} while (m_pHash->m_Bins[m_nCurrentBin] == NULL);
|
|
m_Iterator = m_pHash->m_Bins[m_nCurrentBin]->begin();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* constructor to be used from inside the XnHash. It points to the first value in the hash.
|
|
*
|
|
* @param pHash [in] The hash to which the iterator belongs
|
|
*/
|
|
ConstIterator(const XnHash* pHash) :
|
|
m_pHash(pHash), m_nCurrentBin(0), m_Iterator(m_pHash->m_Bins[XN_HASH_LAST_BIN]->end()) {}
|
|
|
|
/** The hash to which the iterator belongs */
|
|
const XnHash* m_pHash;
|
|
/** The bin of the current object */
|
|
XnUInt16 m_nCurrentBin;
|
|
/** Iterator for the specific bin */
|
|
XnList::Iterator m_Iterator;
|
|
};
|
|
|
|
/**
|
|
* Iterator to the XnHash
|
|
*/
|
|
class Iterator : public ConstIterator
|
|
{
|
|
public:
|
|
friend class XnHash;
|
|
|
|
/**
|
|
* Copy constructor
|
|
*
|
|
* @param other [in] instance to copy from
|
|
*/
|
|
inline Iterator(const Iterator& other) : ConstIterator(other) {}
|
|
|
|
/**
|
|
* Support ++iterator, go to the next object in the list
|
|
*/
|
|
inline Iterator& operator++()
|
|
{
|
|
++(*(ConstIterator*)this);
|
|
return (*this);
|
|
}
|
|
/**
|
|
* Support iterator++, go to the next object in the list, returning the old value
|
|
*/
|
|
inline Iterator operator++(int)
|
|
{
|
|
Iterator result = *this;
|
|
++*this;
|
|
return (result);
|
|
}
|
|
|
|
/**
|
|
* Support --iterator, go to the next object in the list
|
|
*/
|
|
inline Iterator& operator--()
|
|
{
|
|
--(*(ConstIterator*)this);
|
|
return (*this);
|
|
}
|
|
/**
|
|
* Support iterator--, go to the next object in the list, returning the old value
|
|
*/
|
|
inline Iterator operator--(int)
|
|
{
|
|
Iterator result = *this;
|
|
--*this;
|
|
return (result);
|
|
}
|
|
|
|
/**
|
|
* Get the key of the current object (const version)
|
|
*/
|
|
XnKey& Key() const { return (XnKey&)ConstIterator::Key(); }
|
|
|
|
/**
|
|
* Get the value of the current object (const version)
|
|
*/
|
|
XnValue& Value() const { return (XnValue&)ConstIterator::Value(); }
|
|
|
|
protected:
|
|
/**
|
|
* constructor to be used from inside the XnHash
|
|
*
|
|
* @param pHash [in] The hash to which the iterator belongs
|
|
* @param nBin [in] The bin of the current object
|
|
* @param listIterator [in] Iterator on the bin (each bin is a XnList)
|
|
*/
|
|
Iterator(const XnHash* pHash, XnUInt16 nBin, XnList::Iterator listIterator) :
|
|
ConstIterator(pHash, nBin, listIterator)
|
|
{}
|
|
|
|
/**
|
|
* constructor to be used from inside the XnHash. It points to the first value in the hash.
|
|
*
|
|
* @param pHash [in] The hash to which the iterator belongs
|
|
*/
|
|
Iterator(const XnHash* pHash) : ConstIterator(pHash) {}
|
|
|
|
Iterator(const ConstIterator& other) : ConstIterator(other) {}
|
|
};
|
|
|
|
friend class ConstIterator;
|
|
|
|
public:
|
|
/**
|
|
* Definition of a hash function - receive key, and outputs HashValue
|
|
*/
|
|
typedef XnHashValue (*XnHashFunction)(const XnKey& key);
|
|
/**
|
|
* Definition of comparison function - receives 2 keys, returns 0 on equality
|
|
*/
|
|
typedef XnInt32 (*XnCompareFunction)(const XnKey& key1, const XnKey& key2);
|
|
|
|
/**
|
|
* Constructor. Initializes internal representations.
|
|
*/
|
|
XnHash()
|
|
{
|
|
m_nInitStatus = Init();
|
|
}
|
|
|
|
/**
|
|
* Destructor. Destroys internal representations.
|
|
*/
|
|
virtual ~XnHash()
|
|
{
|
|
if (m_Bins != NULL)
|
|
{
|
|
for (int i = 0; i < XN_HASH_NUM_BINS; ++i)
|
|
{
|
|
XN_DELETE(m_Bins[i]);
|
|
}
|
|
XN_DELETE_ARR(m_Bins);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the status of the initialization of the hash.
|
|
* @returns XN_STATUS_OK if the hash was initialized successfully, or an error code otherwise
|
|
* (e.g. if memory could not be allocated).
|
|
*/
|
|
XnStatus GetInitStatus() const
|
|
{
|
|
return m_nInitStatus;
|
|
}
|
|
|
|
/**
|
|
* Set a new key-value entry. If key exists, will replace value.
|
|
*
|
|
* @param key [in] The key to which to associate the value
|
|
* @param value [in] The value to add to the XnHash
|
|
*/
|
|
XnStatus Set(const XnKey& key, const XnValue& value)
|
|
{
|
|
XnHashValue HashValue = (*m_HashFunction)(key);
|
|
|
|
// Check if key already exists
|
|
if (m_Bins[HashValue] != NULL)
|
|
{
|
|
Iterator hiter(this);
|
|
if (Find(key, HashValue, hiter) == XN_STATUS_OK)
|
|
{
|
|
// Replace value
|
|
hiter.Value() = value;
|
|
return XN_STATUS_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// First time trying to access this bin, create it.
|
|
m_Bins[HashValue] = XN_NEW(XnList);
|
|
if (m_Bins[HashValue] == NULL)
|
|
{
|
|
return XN_STATUS_ALLOC_FAILED;
|
|
}
|
|
if (HashValue < m_nMinBin)
|
|
m_nMinBin = HashValue;
|
|
}
|
|
|
|
// Get a new node for the key
|
|
XnNode* pKeyNode = XnNode::Allocate();
|
|
if (pKeyNode == NULL)
|
|
{
|
|
return XN_STATUS_ALLOC_FAILED;
|
|
}
|
|
pKeyNode->Data() = key;
|
|
|
|
// Get a new node for the value
|
|
XnNode* pValueNode = XnNode::Allocate();
|
|
if (pValueNode == NULL)
|
|
{
|
|
XnNode::Deallocate(pKeyNode);
|
|
return XN_STATUS_ALLOC_FAILED;
|
|
}
|
|
pValueNode->Data() = value;
|
|
|
|
// Concatenate the value node to the key node
|
|
pKeyNode->Next() = pValueNode;
|
|
pValueNode->Next() = NULL;
|
|
|
|
// Add the 2 nodes as the value to the key's list
|
|
XnStatus ListStatus = m_Bins[HashValue]->AddLast(XnValue(pKeyNode));
|
|
if (ListStatus != XN_STATUS_OK)
|
|
{
|
|
// Add failed. return the 2 nodes to the pool
|
|
XnNode::Deallocate(pKeyNode);
|
|
XnNode::Deallocate(pValueNode);
|
|
return ListStatus;
|
|
}
|
|
|
|
return XN_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* Get the value associated with the supplied key
|
|
*
|
|
* @param key [in] The key of the entry
|
|
* @param value [out] The retrieved value
|
|
*
|
|
* @return XN_STATUS_NO_MATCH if no such key exists
|
|
*/
|
|
XnStatus Get(const XnKey& key, XnValue& value) const
|
|
{
|
|
// Check if key exists
|
|
Iterator hiter(this);
|
|
XnStatus FindStatus = Find(key, hiter);
|
|
if (FindStatus != XN_STATUS_OK)
|
|
{
|
|
// Key doesn't exist!
|
|
return FindStatus;
|
|
}
|
|
value = hiter.Value();
|
|
|
|
return XN_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* Remove a key-value entry from the XnHash
|
|
*
|
|
* @param key [in] The key of the entry
|
|
* @param value [out] The value that was in the removed entry
|
|
|
|
* @return XN_STATUS_NO_MATCH if no such key exists
|
|
*/
|
|
XnStatus Remove(const XnKey& key, XnValue& value)
|
|
{
|
|
// find the entry to which the key belongs
|
|
Iterator hiter(this);
|
|
|
|
XnStatus FindStatus = Find(key, hiter);
|
|
if (FindStatus != XN_STATUS_OK)
|
|
{
|
|
// no such entry!
|
|
return FindStatus;
|
|
}
|
|
|
|
// Remove by iterator
|
|
value = hiter.Value();
|
|
return Remove(hiter);
|
|
}
|
|
|
|
/**
|
|
* Remove an entry from the XnHash by iterator
|
|
*
|
|
* @param iter [in] Iterator pointing to an entry in the hash
|
|
* @param key [out] The key that was in the removed entry
|
|
* @param value [out] The value that was in the removed entry
|
|
*
|
|
* @return XN_STATUS_ILLEGAL_POSITION if iterator is invalid
|
|
*/
|
|
XnStatus Remove(ConstIterator iter, XnKey& key, XnValue& value)
|
|
{
|
|
if (iter == end())
|
|
{
|
|
// Can't remove invalid node
|
|
return XN_STATUS_ILLEGAL_POSITION;
|
|
}
|
|
|
|
// Get value and key, to return to the caller
|
|
value = iter.Value();
|
|
key = iter.Key();
|
|
|
|
return Remove(iter);
|
|
}
|
|
|
|
/**
|
|
* Remove an entry from the XnHash by iterator
|
|
*
|
|
* @param iter [in] Iterator pointing to an entry in the hash
|
|
*
|
|
* @return XN_STATUS_ILLEGAL_POSITION if iterator is invalid
|
|
*/
|
|
virtual XnStatus Remove(ConstIterator iter)
|
|
{
|
|
if (iter == end())
|
|
{
|
|
// Can't remove invalid node
|
|
return XN_STATUS_ILLEGAL_POSITION;
|
|
}
|
|
|
|
XnNode* pNode = iter.GetNode();
|
|
|
|
XnNode* pKeyNode = (XnNode*)(pNode->Data());
|
|
XnNode* pValueNode = pKeyNode->Next();
|
|
|
|
// Return the nodes to the pool
|
|
XnNode::Deallocate(pKeyNode);
|
|
XnNode::Deallocate(pValueNode);
|
|
|
|
pNode->Previous()->Next() = pNode->Next();
|
|
pNode->Next()->Previous() = pNode->Previous();
|
|
|
|
XnNode::Deallocate(pNode);
|
|
|
|
return XN_STATUS_OK;
|
|
}
|
|
|
|
|
|
/**
|
|
* Remove all entries from the XnHash.
|
|
*/
|
|
XnStatus Clear()
|
|
{
|
|
while (begin() != end())
|
|
Remove(begin());
|
|
|
|
return XN_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* Checks if hash is empty.
|
|
*/
|
|
XnBool IsEmpty() const
|
|
{
|
|
return (begin() == end());
|
|
}
|
|
|
|
/**
|
|
* Gets the number of entries in the hash.
|
|
*/
|
|
XnUInt32 Size() const
|
|
{
|
|
XnUInt32 nSize = 0;
|
|
for (Iterator iter = begin(); iter != end(); ++iter, ++nSize)
|
|
;
|
|
|
|
return nSize;
|
|
}
|
|
|
|
/**
|
|
* Get an iterator pointing to the entry to which the key belongs
|
|
*
|
|
* @param key [in] The key of the entry
|
|
* @param hiter [out] Iterator to the entry described by key
|
|
*
|
|
* @return XN_STATUS_NO_MATCH No such key in the XnHash
|
|
*/
|
|
XnStatus Find(const XnKey& key, ConstIterator& hiter) const
|
|
{
|
|
return ConstFind(key, hiter);
|
|
}
|
|
|
|
/**
|
|
* Get an iterator pointing to the entry to which the key belongs
|
|
*
|
|
* @param key [in] The key of the entry
|
|
* @param hiter [out] Iterator to the entry described by key
|
|
*
|
|
* @return XN_STATUS_NO_MATCH No such key in the XnHash
|
|
*/
|
|
XnStatus Find(const XnKey& key, Iterator& hiter)
|
|
{
|
|
XnStatus nRetVal = XN_STATUS_OK;
|
|
|
|
ConstIterator& it = hiter;
|
|
nRetVal = ConstFind(key, it);
|
|
XN_IS_STATUS_OK(nRetVal);
|
|
|
|
return (XN_STATUS_OK);
|
|
}
|
|
|
|
/**
|
|
* Get an iterator to the beginning of the XnHash (non-const version)
|
|
*/
|
|
Iterator begin()
|
|
{
|
|
return Iterator(this, m_nMinBin, m_Bins[m_nMinBin]->begin());
|
|
}
|
|
|
|
/**
|
|
* Get an iterator to the beginning of the XnHash (const version)
|
|
*/
|
|
ConstIterator begin() const
|
|
{
|
|
return ConstIterator(this, m_nMinBin, m_Bins[m_nMinBin]->begin());
|
|
}
|
|
|
|
/**
|
|
* Get an iterator to the end of the XnHash (position is invalid) (non-const version)
|
|
*/
|
|
Iterator end()
|
|
{
|
|
return Iterator(this, XN_HASH_LAST_BIN, m_Bins[XN_HASH_LAST_BIN]->end());
|
|
}
|
|
|
|
/**
|
|
* Get an iterator to the end of the XnHash (position is invalid) (const version)
|
|
*/
|
|
ConstIterator end() const
|
|
{
|
|
return ConstIterator(this, XN_HASH_LAST_BIN, m_Bins[XN_HASH_LAST_BIN]->end());
|
|
}
|
|
|
|
/**
|
|
* Change the hash function. The XnHash must be empty for this to succeed.
|
|
*
|
|
* @param hashFunction [in] The new hash function
|
|
*
|
|
* @return XN_STATUS_IS_NOT_EMPTY if the XnHash isn't empty
|
|
*/
|
|
XnStatus SetHashFunction(XnHashFunction hashFunction)
|
|
{
|
|
if (begin() != end())
|
|
{
|
|
return XN_STATUS_IS_NOT_EMPTY;
|
|
}
|
|
m_HashFunction = hashFunction;
|
|
return XN_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* Change the comparison function. The XnHash must be empty for this to succeed.
|
|
*
|
|
* @param compareFunction [in] The new hash function
|
|
*
|
|
* @return XN_STATUS_IS_NOT_EMPTY if the XnHash isn't empty
|
|
*/
|
|
XnStatus SetCompareFunction(XnCompareFunction compareFunction)
|
|
{
|
|
if (begin() != end())
|
|
{
|
|
return XN_STATUS_IS_NOT_EMPTY;
|
|
}
|
|
m_CompareFunction = compareFunction;
|
|
return XN_STATUS_OK;
|
|
}
|
|
|
|
protected:
|
|
|
|
XnStatus Init()
|
|
{
|
|
m_Bins = XN_NEW_ARR(XnList*, XN_HASH_NUM_BINS);
|
|
XN_VALIDATE_ALLOC_PTR(m_Bins);
|
|
|
|
for (int i = 0; i < XN_HASH_NUM_BINS; i++)
|
|
{
|
|
m_Bins[i] = NULL;
|
|
}
|
|
|
|
m_Bins[XN_HASH_LAST_BIN] = XN_NEW(XnList); // We need this for an end() iterator
|
|
m_nMinBin = XN_HASH_LAST_BIN;
|
|
|
|
XN_VALIDATE_ALLOC_PTR(m_Bins[XN_HASH_LAST_BIN]);
|
|
m_CompareFunction = &XnDefaultCompareFunction;
|
|
m_HashFunction = &XnDefaultHashFunction;
|
|
return XN_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* Get an iterator pointing to the entry to which the key belongs
|
|
*
|
|
* @param key [in] The key of the entry
|
|
* @param hashValue [in] The hash value of the key
|
|
* @param hiter [out] Iterator to the entry described by key
|
|
*
|
|
* @return XN_STATUS_NO_MATCH No such key in the XnHash
|
|
*/
|
|
XnStatus Find(const XnKey& key, XnHashValue hashValue, ConstIterator& hiter) const
|
|
{
|
|
if (m_Bins[hashValue] != NULL)
|
|
{
|
|
hiter = ConstIterator(this, hashValue, m_Bins[hashValue]->begin());
|
|
for (XnList::ConstIterator iter = m_Bins[hashValue]->begin();
|
|
iter != m_Bins[hashValue]->end(); ++iter, ++hiter)
|
|
{
|
|
if ((*m_CompareFunction)(key, hiter.Key()) == 0)
|
|
return XN_STATUS_OK;
|
|
}
|
|
}
|
|
|
|
return XN_STATUS_NO_MATCH;
|
|
}
|
|
|
|
|
|
/** Each bin is a XnList */
|
|
XnList** m_Bins;
|
|
|
|
XnUInt16 m_nMinBin;
|
|
|
|
/* Status of initialization - could be an error if memory could not be allocated. */
|
|
XnStatus m_nInitStatus;
|
|
|
|
/** The current hash function */
|
|
XnHashFunction m_HashFunction;
|
|
/** The current comparison function */
|
|
XnCompareFunction m_CompareFunction;
|
|
|
|
private:
|
|
XN_DISABLE_COPY_AND_ASSIGN(XnHash);
|
|
|
|
XnStatus ConstFind(const XnKey& key, ConstIterator& hiter) const
|
|
{
|
|
XnHashValue HashValue = (*m_HashFunction)(key);
|
|
return Find(key, HashValue, hiter);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Declares a default Key Manager for type @a KeyType. It is given the name @a ClassName.
|
|
* The manager uses the translator @a KeyTranslator, and is declared using the @a decl declspec.
|
|
*/
|
|
#define XN_DECLARE_DEFAULT_KEY_MANAGER_DECL(decl, KeyType, ClassName, KeyTranslator) \
|
|
class decl ClassName \
|
|
{ \
|
|
public: \
|
|
inline static XnHashValue Hash(KeyType const& key) \
|
|
{ \
|
|
const XnKey _key = KeyTranslator::GetAsValue(key); \
|
|
return XnDefaultHashFunction(_key); \
|
|
} \
|
|
inline static XnInt32 Compare(KeyType const& key1, KeyType const& key2) \
|
|
{ \
|
|
const XnKey _key1 = KeyTranslator::GetAsValue(key1); \
|
|
const XnKey _key2 = KeyTranslator::GetAsValue(key2); \
|
|
return XnDefaultCompareFunction(_key1, _key2); \
|
|
} \
|
|
};
|
|
|
|
/**
|
|
* Declares a default Key Manager for type @a KeyType. It is given the name @a ClassName.
|
|
* The manager uses the translator @a KeyTranslator.
|
|
*/
|
|
#define XN_DECLARE_DEFAULT_KEY_MANAGER(KeyType, ClassName, KeyTranslator) \
|
|
XN_DECLARE_DEFAULT_KEY_MANAGER_DECL(, KeyType, ClassName, KeyTranslator)
|
|
|
|
/**
|
|
* Declares a hash table from @a KeyType to @a ValueType named @a ClassName. The hash table uses
|
|
* @a KeyTranslator and @a ValueTranslator for storing keys and values, and @a KeyManager for managing the keys.
|
|
* It is declared using the @a decl declspec.
|
|
*/
|
|
#define XN_DECLARE_HASH_DECL(decl, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator, KeyManager) \
|
|
class decl ClassName : public XnHash \
|
|
{ \
|
|
public: \
|
|
class decl ConstIterator : public XnHash::ConstIterator \
|
|
{ \
|
|
public: \
|
|
friend class ClassName; \
|
|
inline ConstIterator(const ConstIterator& other) : XnHash::ConstIterator(other) {} \
|
|
inline ConstIterator& operator++() \
|
|
{ \
|
|
++(*(XnHash::ConstIterator*)this); \
|
|
return (*this); \
|
|
} \
|
|
inline ConstIterator operator++(int) \
|
|
{ \
|
|
ConstIterator result = *this; \
|
|
++*this; \
|
|
return result; \
|
|
} \
|
|
inline ConstIterator& operator--() \
|
|
{ \
|
|
--(*(XnHash::ConstIterator*)this); \
|
|
return (*this); \
|
|
} \
|
|
inline ConstIterator operator--(int) \
|
|
{ \
|
|
ConstIterator result = *this; \
|
|
--*this; \
|
|
return result; \
|
|
} \
|
|
inline KeyType const& Key() const \
|
|
{ \
|
|
return KeyTranslator::GetFromValue(XnHash::ConstIterator::Key()); \
|
|
} \
|
|
inline ValueType const& Value() const \
|
|
{ \
|
|
return ValueTranslator::GetFromValue(XnHash::ConstIterator::Value()); \
|
|
} \
|
|
protected: \
|
|
inline ConstIterator(const XnHash::ConstIterator& other) : \
|
|
XnHash::ConstIterator(other) {} \
|
|
}; \
|
|
class decl Iterator : public ConstIterator \
|
|
{ \
|
|
public: \
|
|
friend class ClassName; \
|
|
inline Iterator(const Iterator& other) : ConstIterator(other) {} \
|
|
inline Iterator& operator++() \
|
|
{ \
|
|
++(*(ConstIterator*)this); \
|
|
return (*this); \
|
|
} \
|
|
inline Iterator operator++(int) \
|
|
{ \
|
|
Iterator result = *this; \
|
|
++*this; \
|
|
return result; \
|
|
} \
|
|
inline Iterator& operator--() \
|
|
{ \
|
|
--(*(ConstIterator*)this); \
|
|
return (*this); \
|
|
} \
|
|
inline Iterator operator--(int) \
|
|
{ \
|
|
Iterator result = *this; \
|
|
--*this; \
|
|
return result; \
|
|
} \
|
|
inline KeyType& Key() const \
|
|
{ \
|
|
return (KeyType&)ConstIterator::Key(); \
|
|
} \
|
|
inline ValueType& Value() const \
|
|
{ \
|
|
return (ValueType&)ConstIterator::Value(); \
|
|
} \
|
|
protected: \
|
|
inline Iterator(const XnHash::Iterator& other) : ConstIterator(other) {} \
|
|
}; \
|
|
public: \
|
|
ClassName() \
|
|
{ \
|
|
SetHashFunction(Hash); \
|
|
SetCompareFunction(Compare); \
|
|
} \
|
|
virtual ~ClassName() \
|
|
{ \
|
|
while (!IsEmpty()) \
|
|
Remove(begin()); \
|
|
} \
|
|
XnStatus Set(KeyType const& key, ValueType const& value) \
|
|
{ \
|
|
Iterator oldIt = begin(); \
|
|
if (Find(key, oldIt) == XN_STATUS_OK) \
|
|
{ \
|
|
oldIt.Value() = value; \
|
|
} \
|
|
else \
|
|
{ \
|
|
XnKey _key = KeyTranslator::CreateValueCopy(key); \
|
|
XnValue _value = ValueTranslator::CreateValueCopy(value); \
|
|
XnStatus nRetVal = XnHash::Set(_key, _value); \
|
|
if (nRetVal != XN_STATUS_OK) \
|
|
{ \
|
|
KeyTranslator::FreeValue(_key); \
|
|
ValueTranslator::FreeValue(_value); \
|
|
return (nRetVal); \
|
|
} \
|
|
} \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
XnStatus Get(KeyType const& key, ValueType& value) const \
|
|
{ \
|
|
XnKey _key = KeyTranslator::GetAsValue(key); \
|
|
XnValue _value; \
|
|
XnStatus nRetVal = XnHash::Get(_key, _value); \
|
|
if (nRetVal != XN_STATUS_OK) return (nRetVal); \
|
|
value = ValueTranslator::GetFromValue(_value); \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
XnStatus Get(KeyType const& key, ValueType*& pValue) const \
|
|
{ \
|
|
XnKey _key = KeyTranslator::GetAsValue(key); \
|
|
XnValue _value; \
|
|
XnStatus nRetVal = XnHash::Get(_key, _value); \
|
|
if (nRetVal != XN_STATUS_OK) return (nRetVal); \
|
|
pValue = &ValueTranslator::GetFromValue(_value); \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
XnStatus Remove(KeyType const& key) \
|
|
{ \
|
|
ValueType dummy; \
|
|
return Remove(key, dummy); \
|
|
} \
|
|
XnStatus Remove(KeyType const& key, ValueType& value) \
|
|
{ \
|
|
ConstIterator it = end(); \
|
|
XnStatus nRetVal = Find(key, it); \
|
|
if (nRetVal != XN_STATUS_OK) return (nRetVal); \
|
|
value = it.Value(); \
|
|
return Remove(it); \
|
|
} \
|
|
inline XnStatus Remove(ConstIterator iter) \
|
|
{ \
|
|
XnKey key = KeyTranslator::GetAsValue(iter.Key()); \
|
|
XnValue value = ValueTranslator::GetAsValue(iter.Value()); \
|
|
XnStatus nRetVal = XnHash::Remove(iter); \
|
|
if (nRetVal != XN_STATUS_OK) return (nRetVal); \
|
|
KeyTranslator::FreeValue(key); \
|
|
ValueTranslator::FreeValue(value); \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
XnStatus Find(KeyType const& key, ConstIterator& hiter) const \
|
|
{ \
|
|
XnKey _key = KeyTranslator::GetAsValue(key); \
|
|
XnHash::ConstIterator it = XnHash::end(); \
|
|
XnStatus nRetVal = XnHash::Find(_key, it); \
|
|
if (nRetVal != XN_STATUS_OK) return (nRetVal); \
|
|
hiter = it; \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
XnStatus Find(KeyType const& key, Iterator& hiter) \
|
|
{ \
|
|
XnKey _key = KeyTranslator::GetAsValue(key); \
|
|
XnHash::Iterator it = XnHash::end(); \
|
|
XnStatus nRetVal = XnHash::Find(_key, it); \
|
|
if (nRetVal != XN_STATUS_OK) return (nRetVal); \
|
|
hiter = it; \
|
|
return XN_STATUS_OK; \
|
|
} \
|
|
inline Iterator begin() { return XnHash::begin(); } \
|
|
inline ConstIterator begin() const { return XnHash::begin(); } \
|
|
inline Iterator end() { return XnHash::end(); } \
|
|
inline ConstIterator end() const { return XnHash::end(); } \
|
|
protected: \
|
|
virtual XnStatus Remove(XnHash::ConstIterator iter) \
|
|
{ \
|
|
return Remove(ConstIterator(iter)); \
|
|
} \
|
|
inline static XnHashValue Hash(const XnKey& key) \
|
|
{ \
|
|
KeyType const& _key = KeyTranslator::GetFromValue(key); \
|
|
return KeyManager::Hash(_key); \
|
|
} \
|
|
inline static XnInt32 Compare(const XnKey& key1, const XnKey& key2) \
|
|
{ \
|
|
KeyType const _key1 = KeyTranslator::GetFromValue(key1); \
|
|
KeyType const _key2 = KeyTranslator::GetFromValue(key2); \
|
|
return KeyManager::Compare(_key1, _key2); \
|
|
} \
|
|
private: \
|
|
XN_DISABLE_COPY_AND_ASSIGN(ClassName); \
|
|
};
|
|
|
|
/**
|
|
* Declares a hash table from @a KeyType to @a ValueType named @a ClassName. The hash table uses
|
|
* @a KeyTranslator and @a ValueTranslator for storing keys and values, and @a KeyManager for managing the keys.
|
|
*/
|
|
#define XN_DECLARE_HASH(KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator, KeyManager) \
|
|
XN_DECLARE_HASH_DECL(, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator, KeyManager)
|
|
|
|
#define _XN_DEFAULT_KEY_MANAGER_NAME(ClassName) _##ClassName##Manager
|
|
|
|
/**
|
|
* Declares a hash table from @a KeyType to @a ValueType named @a ClassName. The hash table uses
|
|
* @a KeyTranslator and @a ValueTranslator for storing keys and values. It declares and uses a default manager.
|
|
* It is declared using the @a decl declspec.
|
|
*/
|
|
#define XN_DECLARE_DEFAULT_MANAGER_HASH_DECL(decl, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator) \
|
|
XN_DECLARE_DEFAULT_KEY_MANAGER_DECL(decl, KeyType, _XN_DEFAULT_KEY_MANAGER_NAME(ClassName), KeyTranslator) \
|
|
XN_DECLARE_HASH_DECL(decl, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator, _XN_DEFAULT_KEY_MANAGER_NAME(ClassName))
|
|
|
|
/**
|
|
* Declares a hash table from @a KeyType to @a ValueType named @a ClassName. The hash table uses
|
|
* @a KeyTranslator and @a ValueTranslator for storing keys and values. It declares and uses a default manager.
|
|
*/
|
|
#define XN_DECLARE_DEFAULT_MANAGER_HASH(decl, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator) \
|
|
XN_DECLARE_DEFAULT_MANAGER_HASH_DECL(, KeyType, ValueType, ClassName, KeyTranslator, ValueTranslator)
|
|
|
|
#define _XN_DEFAULT_KEY_TRANSLATOR(ClassName) _##ClassName##KeyTranslator
|
|
#define _XN_DEFAULT_VALUE_TRANSLATOR(ClassName) _##ClassName##ValueTranslator
|
|
|
|
/**
|
|
* Declares a hash table from @a KeyType to @a ValueType named @a ClassName. The hash table uses
|
|
* default translators for storing keys and values. It declares and uses a default manager.
|
|
* It is declared using the @a decl declspec.
|
|
*/
|
|
#define XN_DECLARE_DEFAULT_HASH_DECL(decl, KeyType, ValueType, ClassName) \
|
|
XN_DECLARE_DEFAULT_VALUE_TRANSLATOR_DECL(decl, KeyType, _XN_DEFAULT_KEY_TRANSLATOR(ClassName)) \
|
|
XN_DECLARE_DEFAULT_VALUE_TRANSLATOR_DECL(decl, ValueType, _XN_DEFAULT_VALUE_TRANSLATOR(ClassName)) \
|
|
XN_DECLARE_DEFAULT_MANAGER_HASH_DECL(decl, KeyType, ValueType, ClassName, _XN_DEFAULT_KEY_TRANSLATOR(ClassName), _XN_DEFAULT_VALUE_TRANSLATOR(ClassName))
|
|
|
|
/**
|
|
* Declares a hash table from @a KeyType to @a ValueType named @a ClassName. The hash table uses
|
|
* default translators for storing keys and values. It declares and uses a default manager.
|
|
*/
|
|
#define XN_DECLARE_DEFAULT_HASH(KeyType, ValueType, ClassName) \
|
|
XN_DECLARE_DEFAULT_HASH_DECL(, KeyType, ValueType, ClassName)
|
|
|
|
#endif // _XN_HASH_H
|