windows-nt/Source/XPSP1/NT/inetsrv/iis/admin/wmiprov_dynamic/hashtable.h

302 lines
6.6 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
hashtable.h
Abstract:
Definition of:
CPool<T>, CStringPool, CHashTableElement<T>
Implementation of:
CHashTable<T>
Author:
Mohit Srivastava 10-Nov-2000
Revision History:
--*/
#ifndef _hashtable_h_
#define _hashtable_h_
#include <lkrhash.h>
const ULONG POOL_ARRAY_SIZE = 10;
const ULONG HASH_TABLE_POOL_SIZE = 10;
const ULONG STRING_POOL_STRING_SIZE = 64;
//
// This is an array of pointers to arrays (aka buckets).
// -You pass the size of the first bucket to Initialize.
// -When first bucket is full, a new bucket is created
// that is twice as big as the last one.
// -When the array itself is full, it is doubled and the
// bucket pointers from the old array are copied. Then
// the old array is cleaned up.
//
template <class T> class CPool
{
public:
CPool() :
m_bInitCalled(false),
m_bInitSuccessful(false),
m_apBuckets(NULL),
m_iArrayPosition(0),
m_iArraySize(0),
m_iCurrentBucketPosition(0),
m_iCurrentBucketSize(0),
m_iFirstBucketSize(0) {}
~CPool()
{
for(ULONG i = 0; i < m_iArrayPosition; i++)
{
delete [] m_apBuckets[i];
}
delete [] m_apBuckets;
}
HRESULT Initialize(ULONG i_iFirstBucketSize);
HRESULT GetNewElement(T** o_ppElement);
T* Lookup(ULONG i_idx) const;
ULONG GetUsed() const
{
return (GetSize() - m_iCurrentBucketSize) + m_iCurrentBucketPosition;
}
ULONG GetSize() const
{
return (2 * m_iCurrentBucketSize - m_iFirstBucketSize);
}
private:
//
// Change this as necessary for best performance.
//
static const ULONG ARRAY_SIZE = ::POOL_ARRAY_SIZE;
bool m_bInitCalled;
bool m_bInitSuccessful;
ULONG m_iCurrentBucketPosition;
ULONG m_iCurrentBucketSize;
ULONG m_iFirstBucketSize;
ULONG m_iArraySize;
ULONG m_iArrayPosition;
T** m_apBuckets;
};
//
// CArrayPool contains two pools.
// If a user calls GetNewArray with i <= size, then we serve request from fixedsize pool.
// If i > size, then we serve request from dynamic pool. In this case, we need to perform
// a new since the dynamic pool is a pool of ptrs to T.
//
template <class T, ULONG size>
struct CArrayPoolEntry
{
T m_data[size];
};
template <class T, ULONG size> class CArrayPool
{
public:
CArrayPool() {}
virtual ~CArrayPool()
{
T* pElem;
for(ULONG i = 0; i < m_PoolDynamic.GetUsed(); i++)
{
pElem = *m_PoolDynamic.Lookup(i);
delete [] pElem;
}
}
HRESULT Initialize();
HRESULT GetNewArray(ULONG i_cElem, T** o_ppElem);
T* Lookup(ULONG i_idx) const;
protected:
CPool< CArrayPoolEntry<T, size> > m_PoolFixedSize;
CPool< T * > m_PoolDynamic;
private:
//
// This is passed to constructor of the embedded CPools.
//
static const FIRST_BUCKET_SIZE = 10;
};
class CStringPool: public CArrayPool<wchar_t, ::STRING_POOL_STRING_SIZE>
{
public:
void ToConsole() const;
HRESULT GetNewString(LPCWSTR i_wsz, LPWSTR* o_pwsz);
HRESULT GetNewString(LPCWSTR i_wsz, ULONG i_cch, LPWSTR* o_pwsz);
};
template <class T> class CHashTableElement
{
public:
LPWSTR m_wszKey;
T m_data;
ULONG m_idx;
};
template <class T>
class CHashTable : public CTypedHashTable<CHashTable, const CHashTableElement<T>, const WCHAR*>
{
public:
CHashTable() : CTypedHashTable<CHashTable, const CHashTableElement<T>, const WCHAR*>("n")
{
m_idxCur = 0;
}
~CHashTable()
{
}
public:
//
// These 4 functions are callbacks and must be implemented.
// The user of CHashTable should NOT call these explicitly.
//
static const WCHAR* ExtractKey(
const CHashTableElement<T>* i_pElem)
{
return i_pElem->m_wszKey;
}
static DWORD CalcKeyHash(
const WCHAR* i_wszKey)
{
return HashStringNoCase(i_wszKey);
}
static bool EqualKeys(
const WCHAR* i_wszKey1,
const WCHAR* i_wszKey2)
{
return ( _wcsicmp( i_wszKey1, i_wszKey2 ) == 0 );
}
static void AddRefRecord(
const CHashTableElement<T>* i_pElem,
int i_iIncrementAmount)
{
//
// do nothing
//
}
//
// The following functions are the functions that the user should
// actually call.
//
HRESULT Wmi_Initialize()
{
return m_pool.Initialize(HASH_TABLE_POOL_SIZE);
}
HRESULT Wmi_Insert(LPWSTR i_wszKey, T i_DataNew)
{
DBG_ASSERT(i_wszKey != NULL);
HRESULT hr = WBEM_S_NO_ERROR;
LK_RETCODE lkrc;
CHashTableElement<T>* pElementNew;
hr = m_pool.GetNewElement(&pElementNew);
if(FAILED(hr))
{
goto exit;
}
pElementNew->m_data = i_DataNew;
pElementNew->m_wszKey = i_wszKey;
pElementNew->m_idx = m_idxCur;
lkrc = InsertRecord(pElementNew);
if(lkrc != LK_SUCCESS)
{
hr = Wmi_LKRToHR(lkrc);
goto exit;
}
exit:
if(SUCCEEDED(hr))
{
m_idxCur++;
}
return hr;
}
HRESULT Wmi_GetByKey(LPCWSTR i_wszKey, T* o_pData, ULONG *o_idx)
{
DBG_ASSERT(i_wszKey != NULL);
DBG_ASSERT(o_pData != NULL);
*o_pData = NULL;
HRESULT hr = WBEM_S_NO_ERROR;
LK_RETCODE lkrc;
const CHashTableElement<T>* pElem = NULL;
lkrc = FindKey(i_wszKey, &pElem);
if(lkrc != LK_SUCCESS)
{
hr = Wmi_LKRToHR(lkrc);
return hr;
}
*o_pData = pElem->m_data;
if(o_idx != NULL)
{
*o_idx = pElem->m_idx;
}
return hr;
}
HRESULT Wmi_GetByKey(LPCWSTR i_wszKey, T* o_pData)
{
return Wmi_GetByKey(i_wszKey, o_pData, NULL);
}
HRESULT Wmi_LKRToHR(LK_RETCODE i_lkrc)
{
if(i_lkrc == LK_SUCCESS)
{
return WBEM_S_NO_ERROR;
}
switch(i_lkrc)
{
case LK_ALLOC_FAIL:
return WBEM_E_OUT_OF_MEMORY;
default:
return E_FAIL;
}
}
ULONG Wmi_GetNumElements()
{
CLKRHashTableStats stats;
stats = GetStatistics();
DBG_ASSERT(stats.RecordCount == m_idxCur);
return m_idxCur;
}
private:
CPool< CHashTableElement<T> > m_pool;
ULONG m_idxCur;
};
//
#endif // _hashtable_h_