/*++ 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 #include using namespace std; class wcsless : public binary_function { public: bool operator()(const LPWSTR& wcs1, const LPWSTR& wcs2) const {return wcscmp(wcs1, wcs2) < 0;} }; class wcsiless : public binary_function { 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;} IUnknown* dismiss(){ IUnknown* p_ = m_pUnk; m_pUnk = NULL; return p_;} }; template class CReleaseMeRef { protected: T & m_pUnkRef; public: CReleaseMeRef(T& pUnkRef) : m_pUnkRef(pUnkRef){} ~CReleaseMeRef() { release();} void release() { if(m_pUnkRef) m_pUnkRef->Release(); m_pUnkRef=0;} T dismiss(){ T p_ = m_pUnkRef; m_pUnkRef = NULL; return p_;} }; template 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 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 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 CSysFreeMeRef { protected: BSTR & m_str; public: CSysFreeMeRef(BSTR & str) : m_str(str){} ~CSysFreeMeRef() { 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 #include #include #include //***************************************************************************** // // class CPointerArray // // Array of pointers to TMember, where TMember is any class. See CFlexArray // in coredll\flexarry.h/cpp for documentation. // //***************************************************************************** template class CNullManager { public: void AddRefElement(TMember*){} void ReleaseElement(TMember*){} }; template , 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();} TArray & GetArray(){ return m_Array; }; protected: void AddRefElement(TMember* p){m_Manager.AddRefElement(p);} void ReleaseElement(TMember* p){m_Manager.ReleaseElement(p);} }; template class CPointerSmallArray : public CPointerArray, CSmallArray> { }; //***************************************************************************** // // class CPointerQueue // // Queue of pointers to TMember, where TMember is any class. See CFlexQueue // in coredll\flexq.h/cpp for documentation. // //***************************************************************************** template > 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 CUniqueManager { public: void AddRefElement(TMember*){} void ReleaseElement(TMember* pMember) {delete pMember;} }; template class CUniquePointerArray : public CPointerArray > { }; template class CUniquePointerSmallArray : public CPointerArray, CSmallArray> { }; template class CUniquePointerQueue : public CPointerQueue > { public: CUniquePointerQueue(int nInitialSize = 1) : CPointerQueue >(nInitialSize) {} }; //***************************************************************************** // // REFED POINTER ARRAY // //***************************************************************************** template class CReferenceManager { public: void AddRefElement(TMember* pMember) {if(pMember)pMember->AddRef();} void ReleaseElement(TMember* pMember) {if(pMember)pMember->Release();} }; template class CRefedPointerArray : public CPointerArray > { }; template class CRefedPointerSmallArray : public CPointerArray, CSmallArray> { }; template class CRefedPointerQueue : public CPointerQueue > { public: CRefedPointerQueue(int nInitialSize = 1) : CPointerQueue >(nInitialSize) {} }; //***************************************************************************** // // ARRAY OF UNIQUE ARRAYS // //***************************************************************************** template class CUniqueArrayManager { void AddRefElement(TMember**){} void ReleaseElement(TMember** pMember) {delete [] pMember;} }; template class CUniqueArrayArray : public CPointerArray > { }; //***************************************************************************** // // IMPLEMENTATION // //***************************************************************************** template CPointerArray::~CPointerArray() { RemoveAll(); } template void CPointerArray::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 void CPointerArray::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 void CPointerArray::Discard(int nIndex) { m_Array.SetAt(nIndex, NULL); } template bool CPointerArray::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 bool CPointerArray::InsertAt(int nIndex, TMember* pElement) { if(m_Array.InsertAt(nIndex, (void*)pElement) != CFlexArray::no_error) return false; AddRefElement(pElement); return true; } template int CPointerArray::Add(TMember* pElement) { if(m_Array.Add((void*)pElement) != CFlexArray::no_error) return -1; AddRefElement(pElement); return m_Array.Size()-1; } template TMember** CPointerArray::GetArrayPtr() { return (TMember**)m_Array.GetArrayPtr(); } template TMember** CPointerArray::UnbindPtr() { return (TMember**)m_Array.UnbindPtr(); } template void CPointerArray::Swap(int nIndex1, int nIndex2) { void* pTemp = m_Array[nIndex1]; m_Array.SetAt(nIndex1, m_Array[nIndex2]); m_Array.SetAt(nIndex2, pTemp); } template void CPointerQueue::Clear() { TMember* p; while(p = (TMember*)m_Queue.Dequeue()) { ReleaseElement(p); } } #endif