156 lines
4 KiB
C
156 lines
4 KiB
C
|
// Helper funcs for string maps
|
||
|
|
||
|
#ifndef _BSTRHASH_INC
|
||
|
#define _BSTRHASH_INC
|
||
|
|
||
|
#pragma warning( disable : 4786 )
|
||
|
|
||
|
#include <map>
|
||
|
using namespace std;
|
||
|
|
||
|
#include "lkrhash.h"
|
||
|
|
||
|
template <class _Key, class _Val>
|
||
|
class CLKWrap
|
||
|
{
|
||
|
public:
|
||
|
#ifdef MEM_DBG
|
||
|
char m_id[8];
|
||
|
#endif
|
||
|
_Key m_k;
|
||
|
_Val m_v;
|
||
|
mutable LONG m_cRefs;
|
||
|
|
||
|
CLKWrap(_Key k, _Val v, char* id = "CLKWrap") : m_k(k), m_v(v), m_cRefs(0)
|
||
|
{
|
||
|
#ifdef MEM_DBG
|
||
|
memcpy(m_id, id, 8);
|
||
|
#endif
|
||
|
}
|
||
|
~CLKWrap()
|
||
|
{
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template <class _Val>
|
||
|
class CRawCIBstrHash
|
||
|
: public CTypedHashTable<CRawCIBstrHash<_Val>, const CLKWrap<BSTR,_Val>, BSTR>
|
||
|
{
|
||
|
public:
|
||
|
typedef CLKWrap<BSTR,_Val> ValueType;
|
||
|
|
||
|
CRawCIBstrHash(LPCSTR name) :
|
||
|
CTypedHashTable<CRawCIBstrHash, const CLKWrap<BSTR,_Val>, BSTR>(name)
|
||
|
{}
|
||
|
|
||
|
CRawCIBstrHash(LPCSTR name, double maxload, DWORD initsize, DWORD num_subtbls) :
|
||
|
CTypedHashTable<CRawCIBstrHash, const CLKWrap<BSTR,_Val>, BSTR>(name,maxload,initsize,num_subtbls)
|
||
|
{}
|
||
|
|
||
|
static BSTR ExtractKey(const CLKWrap<BSTR,_Val> *pEntry)
|
||
|
{ return pEntry->m_k; }
|
||
|
static DWORD CalcKeyHash(BSTR pstrKey)
|
||
|
{ return HashStringNoCase(pstrKey); }
|
||
|
static bool EqualKeys(BSTR x, BSTR y)
|
||
|
{
|
||
|
if (x == NULL)
|
||
|
{
|
||
|
return (y==NULL ? TRUE : FALSE);
|
||
|
}
|
||
|
if (!y) return FALSE;
|
||
|
|
||
|
return (_wcsicmp(x,y) == 0);
|
||
|
}
|
||
|
|
||
|
static void AddRefRecord(const CLKWrap<BSTR,_Val>* pTest, int nIncr)
|
||
|
{
|
||
|
IRTLTRACE(_TEXT("AddRef(%p, %s) %d, cRefs == %d\n"),
|
||
|
pTest, pTest->m_k, nIncr, pTest->m_cRefs);
|
||
|
|
||
|
if (nIncr == +1)
|
||
|
{
|
||
|
// or, perhaps, pIFoo->AddRef() (watch out for marshalling)
|
||
|
// or ++pTest->m_cRefs (single-threaded only)
|
||
|
InterlockedIncrement(&pTest->m_cRefs);
|
||
|
}
|
||
|
else if (nIncr == -1)
|
||
|
{
|
||
|
// or, perhaps, pIFoo->Release() or --pTest->m_cRefs;
|
||
|
LONG l = InterlockedDecrement(&pTest->m_cRefs);
|
||
|
|
||
|
// For some hashtables, it may also make sense to add the following
|
||
|
if (l == 0) delete pTest;
|
||
|
// but that would typically only apply when InsertRecord was
|
||
|
// used thus
|
||
|
// lkrc = ht.InsertRecord(new CTest(foo, bar));
|
||
|
}
|
||
|
else
|
||
|
IRTLASSERT(0);
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
// For normal built in types as keys
|
||
|
template <class _Key,class _Val>
|
||
|
class CGenericHash
|
||
|
: public CTypedHashTable<CGenericHash<_Key,_Val>, const CLKWrap<_Key,_Val>, _Key>
|
||
|
{
|
||
|
public:
|
||
|
typedef CLKWrap<_Key,_Val> ValueType;
|
||
|
|
||
|
CGenericHash(LPCSTR name) :
|
||
|
CTypedHashTable<CGenericHash, const ValueType, _Key>(name)
|
||
|
{}
|
||
|
|
||
|
CGenericHash(LPCSTR name, double maxload, DWORD initsize, DWORD num_subtbls) :
|
||
|
CTypedHashTable<CGenericHash, const ValueType, _Key>(name,maxload,initsize,num_subtbls)
|
||
|
{}
|
||
|
|
||
|
static _Key ExtractKey(const CLKWrap<_Key,_Val> *pEntry)
|
||
|
{ return pEntry->m_k; }
|
||
|
static DWORD CalcKeyHash(_Key psKey)
|
||
|
{ return Hash(psKey); }
|
||
|
static bool EqualKeys(_Key x, _Key y)
|
||
|
{ return (x==y); }
|
||
|
|
||
|
static void AddRefRecord(const CLKWrap<_Key,_Val>* pTest, int nIncr)
|
||
|
{
|
||
|
IRTLTRACE(_TEXT("AddRef(%p, %s) %d, cRefs == %d\n"),
|
||
|
pTest, pTest->m_k, nIncr, pTest->m_cRefs);
|
||
|
|
||
|
if (nIncr == +1)
|
||
|
{
|
||
|
// or, perhaps, pIFoo->AddRef() (watch out for marshalling)
|
||
|
// or ++pTest->m_cRefs (single-threaded only)
|
||
|
InterlockedIncrement(&pTest->m_cRefs);
|
||
|
}
|
||
|
else if (nIncr == -1)
|
||
|
{
|
||
|
// or, perhaps, pIFoo->Release() or --pTest->m_cRefs;
|
||
|
LONG l = InterlockedDecrement(&pTest->m_cRefs);
|
||
|
|
||
|
// For some hashtables, it may also make sense to add the following
|
||
|
if (l == 0) delete pTest;
|
||
|
// but that would typically only apply when InsertRecord was
|
||
|
// used thus
|
||
|
// lkrc = ht.InsertRecord(new CTest(foo, bar));
|
||
|
}
|
||
|
else
|
||
|
IRTLASSERT(0);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#include <map>
|
||
|
using namespace std;
|
||
|
|
||
|
class RawBstrLT
|
||
|
{
|
||
|
public:
|
||
|
bool operator()(const BSTR& x, const BSTR& y) const
|
||
|
{
|
||
|
return (_wcsicmp(x,y) < 0);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#endif
|