502 lines
12 KiB
C++
502 lines
12 KiB
C++
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ARRTEMPL.H
|
|
|
|
Abstract:
|
|
|
|
This file defines a simple template for an array of arbitrary pointers.
|
|
Actual growing array functionality is provided by CFlexArray.
|
|
|
|
Classes defined:
|
|
|
|
template CPointerArray
|
|
|
|
History:
|
|
|
|
11/27/96 a-levn Compiles.
|
|
|
|
--*/
|
|
|
|
#ifndef __ARRAY_TEMPLATE__H_
|
|
#define __ARRAY_TEMPLATE__H_
|
|
|
|
#pragma warning(disable:4786)
|
|
|
|
#include <map>
|
|
#include <strutils.h>
|
|
|
|
|
|
using namespace std;
|
|
class wcsless : public binary_function<LPWSTR, LPWSTR, bool>
|
|
{
|
|
public:
|
|
bool operator()(const LPWSTR& wcs1, const LPWSTR& wcs2) const
|
|
{return wcscmp(wcs1, wcs2) < 0;}
|
|
};
|
|
|
|
class wcsiless : public binary_function<LPWSTR, LPWSTR, bool>
|
|
{
|
|
public:
|
|
bool operator()(const LPWSTR& wcs1, const LPWSTR& wcs2) const
|
|
{return wbem_wcsicmp(wcs1, wcs2) < 0;}
|
|
};
|
|
|
|
|
|
class CReleaseMe
|
|
{
|
|
protected:
|
|
IUnknown* m_pUnk;
|
|
|
|
public:
|
|
CReleaseMe(IUnknown* pUnk) : m_pUnk(pUnk){}
|
|
~CReleaseMe() { release();}
|
|
void release() { if(m_pUnk) m_pUnk->Release(); m_pUnk=0;}
|
|
};
|
|
|
|
template<class T>
|
|
class CTemplateReleaseMe
|
|
{
|
|
protected:
|
|
T* m_p;
|
|
|
|
public:
|
|
CTemplateReleaseMe(T* p) : m_p(p){}
|
|
~CTemplateReleaseMe() { release();}
|
|
void release(){ if(m_p) m_p->Release();m_p=0;}
|
|
};
|
|
|
|
template<class T>
|
|
class CDeleteMe
|
|
{
|
|
protected:
|
|
T* m_p;
|
|
|
|
public:
|
|
CDeleteMe(T* p = NULL) : m_p(p){}
|
|
~CDeleteMe() {delete m_p;}
|
|
|
|
// overwrites the previous pointer, does NOT delete it
|
|
void operator= (T* p) {m_p = p;}
|
|
};
|
|
|
|
class CCloseMe
|
|
{
|
|
protected:
|
|
HANDLE m_h;
|
|
public:
|
|
CCloseMe(HANDLE hToClose){m_h = hToClose;};
|
|
~CCloseMe(){if(m_h && m_h != INVALID_HANDLE_VALUE)CloseHandle(m_h);};
|
|
};
|
|
|
|
class CfcloseMe
|
|
{
|
|
protected:
|
|
FILE * m_h;
|
|
public:
|
|
CfcloseMe(FILE * ToClose){m_h = ToClose;};
|
|
~CfcloseMe(){if(m_h != NULL)fclose(m_h);};
|
|
};
|
|
|
|
typedef CCloseMe CCloseHandle;
|
|
|
|
class CRegCloseMe
|
|
{
|
|
protected:
|
|
HKEY m_h;
|
|
public:
|
|
CRegCloseMe(HKEY hToClose){m_h = hToClose;};
|
|
~CRegCloseMe(){if(m_h)RegCloseKey(m_h);};
|
|
};
|
|
|
|
template<class T>
|
|
class CVectorDeleteMe
|
|
{
|
|
protected:
|
|
T* m_p;
|
|
T** m_pp;
|
|
|
|
public:
|
|
CVectorDeleteMe(T* p) : m_p(p), m_pp(NULL){}
|
|
CVectorDeleteMe(T** pp) : m_p(NULL), m_pp(pp){}
|
|
~CVectorDeleteMe() {if(m_p) delete [] m_p; else if(m_pp) delete [] *m_pp;}
|
|
};
|
|
|
|
class CClearMe
|
|
{
|
|
protected:
|
|
VARIANT* m_pv;
|
|
|
|
public:
|
|
CClearMe(VARIANT* pv) : m_pv(pv){}
|
|
~CClearMe() {VariantClear(m_pv);}
|
|
};
|
|
|
|
class CSysFreeMe
|
|
{
|
|
protected:
|
|
BSTR m_str;
|
|
|
|
public:
|
|
CSysFreeMe(BSTR str) : m_str(str){}
|
|
~CSysFreeMe() { if ( NULL != m_str ) SysFreeString(m_str);}
|
|
};
|
|
|
|
class CUnaccessMe
|
|
{
|
|
protected:
|
|
SAFEARRAY* m_psa;
|
|
public:
|
|
CUnaccessMe(SAFEARRAY* psa) : m_psa(psa){}
|
|
~CUnaccessMe() {SafeArrayUnaccessData(m_psa);}
|
|
};
|
|
|
|
class CMemFreeMe
|
|
{
|
|
protected:
|
|
void* m_pMem;
|
|
public:
|
|
CMemFreeMe( void* pMem ) : m_pMem(pMem){}
|
|
~CMemFreeMe() { if ( NULL != m_pMem ) CoTaskMemFree(m_pMem);}
|
|
};
|
|
|
|
#include <arena.h>
|
|
#include <flexarry.h>
|
|
#include <flexq.h>
|
|
#include <smallarr.h>
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// class CPointerArray
|
|
//
|
|
// Array of pointers to TMember, where TMember is any class. See CFlexArray
|
|
// in coredll\flexarry.h/cpp for documentation.
|
|
//
|
|
//*****************************************************************************
|
|
|
|
template <class TMember>
|
|
class CNullManager
|
|
{
|
|
public:
|
|
void AddRefElement(TMember*){}
|
|
void ReleaseElement(TMember*){}
|
|
};
|
|
|
|
template <class TMember, class TManager = CNullManager<TMember>,
|
|
class TArray = CFlexArray>
|
|
class CPointerArray
|
|
{
|
|
protected:
|
|
TArray m_Array;
|
|
TManager m_Manager;
|
|
public:
|
|
CPointerArray(const TManager& Manager = TManager())
|
|
: m_Manager(Manager){}
|
|
~CPointerArray();
|
|
|
|
int GetSize() const
|
|
{return m_Array.Size();}
|
|
void SetSize(int nNewSize)
|
|
{m_Array.SetSize(nNewSize);}
|
|
const TMember* GetAt(int nIndex) const
|
|
{return (TMember*)m_Array.GetAt(nIndex);}
|
|
TMember* GetAt(int nIndex)
|
|
{return (TMember*)m_Array.GetAt(nIndex);}
|
|
const TMember* operator[](int nIndex) const
|
|
{return (TMember*)m_Array.GetAt(nIndex);}
|
|
TMember* operator[](int nIndex)
|
|
{return (TMember*)m_Array.GetAt(nIndex);}
|
|
void SetAt(int nIndex, TMember* pElement, TMember** ppOld = NULL);
|
|
void Discard(int nIndex);
|
|
bool RemoveAt(int nIndex, TMember** ppOld = NULL);
|
|
bool InsertAt(int nIndex, TMember* pElement);
|
|
int Add(TMember* pElement);
|
|
TMember** GetArrayPtr();
|
|
TMember** UnbindPtr();
|
|
void RemoveAll();
|
|
void Swap(int nIndex1, int nIndex2);
|
|
void Trim() {m_Array.Trim();}
|
|
|
|
protected:
|
|
void AddRefElement(TMember* p){m_Manager.AddRefElement(p);}
|
|
void ReleaseElement(TMember* p){m_Manager.ReleaseElement(p);}
|
|
};
|
|
|
|
template<class TMember>
|
|
class CPointerSmallArray :
|
|
public CPointerArray<TMember, CNullManager<TMember>, CSmallArray>
|
|
{
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// class CPointerQueue
|
|
//
|
|
// Queue of pointers to TMember, where TMember is any class. See CFlexQueue
|
|
// in coredll\flexq.h/cpp for documentation.
|
|
//
|
|
//*****************************************************************************
|
|
template <class TMember, class TManager = CNullManager<TMember> >
|
|
class CPointerQueue
|
|
{
|
|
protected:
|
|
CFlexQueue m_Queue;
|
|
TManager m_Manager;
|
|
public:
|
|
CPointerQueue(int nInitialSize = 1, const TManager& Manager = TManager())
|
|
: m_Manager(Manager), m_Queue(nInitialSize){}
|
|
void Clear();
|
|
~CPointerQueue()
|
|
{Clear();}
|
|
|
|
inline int GetQueueSize() const
|
|
{return m_Queue.GetQueueSize();}
|
|
|
|
bool Enqueue(TMember* pNew)
|
|
{
|
|
AddRefElement(pNew);
|
|
return m_Queue.Enqueue(pNew);
|
|
}
|
|
TMember* Dequeue()
|
|
{
|
|
TMember* p = (TMember*)m_Queue.Dequeue();
|
|
return p;
|
|
}
|
|
bool Requeue(TMember* pNew)
|
|
{
|
|
AddRefElement(pNew);
|
|
return m_Queue.Requeue(pNew);
|
|
}
|
|
TMember* Unqueue()
|
|
{
|
|
TMember* p = (TMember*)m_Queue.Unqueue();
|
|
AddRefElement(p);
|
|
return p;
|
|
}
|
|
protected:
|
|
void AddRefElement(TMember* p){m_Manager.AddRefElement(p);}
|
|
void ReleaseElement(TMember* p){m_Manager.ReleaseElement(p);}
|
|
};
|
|
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// UNIQUE POINTER ARRAY
|
|
//
|
|
//*****************************************************************************
|
|
|
|
template <class TMember>
|
|
class CUniqueManager
|
|
{
|
|
public:
|
|
void AddRefElement(TMember*){}
|
|
void ReleaseElement(TMember* pMember) {delete pMember;}
|
|
};
|
|
|
|
template<class TMember>
|
|
class CUniquePointerArray :
|
|
public CPointerArray<TMember, CUniqueManager<TMember> >
|
|
{
|
|
};
|
|
|
|
template<class TMember>
|
|
class CUniquePointerSmallArray :
|
|
public CPointerArray<TMember, CUniqueManager<TMember>, CSmallArray>
|
|
{
|
|
};
|
|
|
|
template<class TMember>
|
|
class CUniquePointerQueue :
|
|
public CPointerQueue<TMember, CUniqueManager<TMember> >
|
|
{
|
|
public:
|
|
CUniquePointerQueue<TMember>(int nInitialSize = 1)
|
|
: CPointerQueue<TMember, CUniqueManager<TMember> >(nInitialSize)
|
|
{}
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// REFED POINTER ARRAY
|
|
//
|
|
//*****************************************************************************
|
|
template <class TMember>
|
|
class CReferenceManager
|
|
{
|
|
public:
|
|
void AddRefElement(TMember* pMember) {if(pMember)pMember->AddRef();}
|
|
void ReleaseElement(TMember* pMember) {if(pMember)pMember->Release();}
|
|
};
|
|
|
|
template<class TMember>
|
|
class CRefedPointerArray :
|
|
public CPointerArray<TMember, CReferenceManager<TMember> >
|
|
{
|
|
};
|
|
|
|
template<class TMember>
|
|
class CRefedPointerSmallArray :
|
|
public CPointerArray<TMember, CReferenceManager<TMember>, CSmallArray>
|
|
{
|
|
};
|
|
|
|
template<class TMember>
|
|
class CRefedPointerQueue :
|
|
public CPointerQueue<TMember, CReferenceManager<TMember> >
|
|
{
|
|
public:
|
|
CRefedPointerQueue(int nInitialSize = 1)
|
|
: CPointerQueue<TMember, CReferenceManager<TMember> >(nInitialSize)
|
|
{}
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// ARRAY OF UNIQUE ARRAYS
|
|
//
|
|
//*****************************************************************************
|
|
|
|
template <class TMember>
|
|
class CUniqueArrayManager
|
|
{
|
|
void AddRefElement(TMember**){}
|
|
void ReleaseElement(TMember** pMember) {delete [] pMember;}
|
|
};
|
|
template<class TMember>
|
|
class CUniqueArrayArray : public CPointerArray<TMember,
|
|
CUniqueArrayManager<TMember> >
|
|
{
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// IMPLEMENTATION
|
|
//
|
|
//*****************************************************************************
|
|
|
|
template <class TMember, class TManager, class TArray>
|
|
CPointerArray<TMember, TManager, TArray>::~CPointerArray()
|
|
{
|
|
RemoveAll();
|
|
}
|
|
|
|
template <class TMember, class TManager, class TArray>
|
|
void CPointerArray<TMember, TManager, TArray>::RemoveAll()
|
|
{
|
|
for(int i = 0; i < m_Array.Size(); i++)
|
|
{
|
|
//
|
|
// Remove it from array before releasing --- otherwise for a moment
|
|
// there we have a garbage pointer in array!
|
|
//
|
|
|
|
TMember* p = GetAt(i);
|
|
m_Array.SetAt(i, NULL);
|
|
ReleaseElement(p);
|
|
}
|
|
m_Array.Empty();
|
|
}
|
|
|
|
template <class TMember, class TManager, class TArray>
|
|
void CPointerArray<TMember, TManager, TArray>::SetAt(int nIndex,
|
|
TMember* pElement, TMember** ppOld)
|
|
{
|
|
AddRefElement(pElement);
|
|
|
|
//
|
|
// Remove it from array before releasing --- otherwise for a moment
|
|
// there we have a garbage pointer in array!
|
|
//
|
|
|
|
TMember* pOld = GetAt(nIndex);
|
|
m_Array.SetAt(nIndex, (void*)pElement);
|
|
|
|
if(ppOld == NULL)
|
|
ReleaseElement(pOld);
|
|
else
|
|
*ppOld = pOld;
|
|
}
|
|
|
|
template <class TMember, class TManager, class TArray>
|
|
void CPointerArray<TMember, TManager, TArray>::Discard(int nIndex)
|
|
{
|
|
m_Array.SetAt(nIndex, NULL);
|
|
}
|
|
|
|
template <class TMember, class TManager, class TArray>
|
|
bool CPointerArray<TMember, TManager, TArray>::RemoveAt(int nIndex,
|
|
TMember** ppOld)
|
|
{
|
|
//
|
|
// Remove it from array before releasing --- otherwise for a moment
|
|
// there we have a garbage pointer in array!
|
|
//
|
|
|
|
TMember* pOld = GetAt(nIndex);
|
|
if(m_Array.RemoveAt(nIndex) != CFlexArray::no_error)
|
|
return false;
|
|
|
|
if(ppOld == NULL)
|
|
ReleaseElement(pOld);
|
|
else
|
|
*ppOld = pOld;
|
|
|
|
return true;
|
|
}
|
|
|
|
template <class TMember, class TManager, class TArray>
|
|
bool CPointerArray<TMember, TManager, TArray>::InsertAt(int nIndex,
|
|
TMember* pElement)
|
|
{
|
|
if(m_Array.InsertAt(nIndex, (void*)pElement) != CFlexArray::no_error)
|
|
return false;
|
|
|
|
AddRefElement(pElement);
|
|
return true;
|
|
}
|
|
|
|
template <class TMember, class TManager, class TArray>
|
|
int CPointerArray<TMember, TManager, TArray>::Add(TMember* pElement)
|
|
{
|
|
if(m_Array.Add((void*)pElement) != CFlexArray::no_error)
|
|
return -1;
|
|
|
|
AddRefElement(pElement);
|
|
return m_Array.Size()-1;
|
|
}
|
|
|
|
template <class TMember, class TManager, class TArray>
|
|
TMember** CPointerArray<TMember, TManager, TArray>::GetArrayPtr()
|
|
{
|
|
return (TMember**)m_Array.GetArrayPtr();
|
|
}
|
|
|
|
template <class TMember, class TManager, class TArray>
|
|
TMember** CPointerArray<TMember, TManager, TArray>::UnbindPtr()
|
|
{
|
|
return (TMember**)m_Array.UnbindPtr();
|
|
}
|
|
|
|
template <class TMember, class TManager, class TArray>
|
|
void CPointerArray<TMember, TManager, TArray>::Swap(int nIndex1, int nIndex2)
|
|
{
|
|
void* pTemp = m_Array[nIndex1];
|
|
m_Array.SetAt(nIndex1, m_Array[nIndex2]);
|
|
m_Array.SetAt(nIndex2, pTemp);
|
|
}
|
|
|
|
template <class TMember, class TManager>
|
|
void CPointerQueue<TMember, TManager>::Clear()
|
|
{
|
|
TMember* p;
|
|
while(p = (TMember*)m_Queue.Dequeue())
|
|
{
|
|
ReleaseElement(p);
|
|
}
|
|
}
|
|
|
|
#endif
|