286 lines
6.6 KiB
C
286 lines
6.6 KiB
C
|
// Copyright (c) 1992 - 1997 Microsoft Corporation. All Rights Reserved.
|
||
|
/* Dynamic arrays */
|
||
|
|
||
|
#ifndef __AMUTIL_H__
|
||
|
#define __AMUTIL_H__
|
||
|
|
||
|
/* Dynamic array support */
|
||
|
template <class _TInterface, class _TArray>
|
||
|
class CDynamicArray
|
||
|
{
|
||
|
public:
|
||
|
CDynamicArray(int iIncrement) : m_pArray(NULL),
|
||
|
m_nElements(0),
|
||
|
m_iIncrement(iIncrement),
|
||
|
m_nSize(0) {}
|
||
|
CDynamicArray() : m_pArray(NULL),
|
||
|
m_nElements(0),
|
||
|
m_iIncrement(4),
|
||
|
m_nSize(0) {}
|
||
|
~CDynamicArray() { delete [] m_pArray; }
|
||
|
|
||
|
_TInterface Element(int i) const {
|
||
|
_ASSERTE(i < m_nElements);
|
||
|
return m_pArray[i];
|
||
|
}
|
||
|
|
||
|
_TInterface operator [] (int i)
|
||
|
{
|
||
|
return m_pArray[i];
|
||
|
}
|
||
|
|
||
|
int Size() const {
|
||
|
return m_nElements;
|
||
|
}
|
||
|
|
||
|
BOOL Add(_TInterface Element)
|
||
|
{
|
||
|
_ASSERTE(m_nSize >= m_nElements);
|
||
|
if (m_nSize == m_nElements) {
|
||
|
_TArray *pNewArray = new _TArray[m_nSize + m_iIncrement];
|
||
|
if (pNewArray == NULL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
for (int i = 0; i < m_nElements; i++) {
|
||
|
pNewArray[i] = m_pArray[i];
|
||
|
}
|
||
|
delete [] m_pArray;
|
||
|
m_pArray = pNewArray;
|
||
|
m_nSize = m_nSize + m_iIncrement;
|
||
|
}
|
||
|
m_pArray[m_nElements++] = Element;
|
||
|
return TRUE;
|
||
|
}
|
||
|
BOOL Remove(_TInterface Element)
|
||
|
{
|
||
|
for (int i = 0; m_pArray[i] != Element; i++ ) {
|
||
|
if (i >= m_nElements) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
Remove(i);
|
||
|
return TRUE;
|
||
|
}
|
||
|
void Remove(int i)
|
||
|
{
|
||
|
_ASSERTE(i < m_nElements);
|
||
|
m_nElements--;
|
||
|
for (; i < m_nElements; i++) {
|
||
|
m_pArray[i] = m_pArray[i + 1];
|
||
|
}
|
||
|
m_pArray[m_nElements] = NULL;
|
||
|
}
|
||
|
void RemoveAll()
|
||
|
{
|
||
|
for (int i = 0; i < m_nElements; i++) {
|
||
|
m_pArray[i] = NULL;
|
||
|
}
|
||
|
m_nElements = 0;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
_TArray *m_pArray;
|
||
|
int m_nSize;
|
||
|
int m_nElements;
|
||
|
const int m_iIncrement;
|
||
|
};
|
||
|
|
||
|
template <class Base, const IID *piid, class T>
|
||
|
class CAMEnumInterfaceImpl :
|
||
|
public Base,
|
||
|
public CDynamicArray<T*, CComPtr<T> >
|
||
|
{
|
||
|
public:
|
||
|
CAMEnumInterfaceImpl() : m_iter(0) {}
|
||
|
|
||
|
/* The actual interface we support */
|
||
|
STDMETHOD(Next)(ULONG celt, T** rgelt, ULONG* pceltFetched);
|
||
|
STDMETHOD(Skip)(ULONG celt);
|
||
|
STDMETHOD(Reset)(void){m_iter = 0;return S_OK;}
|
||
|
STDMETHOD(Clone)(Base** ppEnum);
|
||
|
|
||
|
int m_iter;
|
||
|
};
|
||
|
|
||
|
template <class Base, const IID* piid, class T>
|
||
|
STDMETHODIMP CAMEnumInterfaceImpl<Base, piid, T>::Next(ULONG celt, T** rgelt,
|
||
|
ULONG* pceltFetched)
|
||
|
{
|
||
|
if (rgelt == NULL || (celt != 1 && pceltFetched == NULL))
|
||
|
return E_POINTER;
|
||
|
ULONG nRem = (ULONG)(Size() - m_iter);
|
||
|
HRESULT hRes = S_OK;
|
||
|
if (nRem < celt)
|
||
|
hRes = S_FALSE;
|
||
|
ULONG nMin = min(celt, nRem);
|
||
|
if (pceltFetched != NULL)
|
||
|
*pceltFetched = nMin;
|
||
|
while(nMin--) {
|
||
|
Element(m_iter)->AddRef();
|
||
|
*(rgelt++) = Element(m_iter++);
|
||
|
}
|
||
|
return hRes;
|
||
|
}
|
||
|
|
||
|
template <class Base, const IID* piid, class T>
|
||
|
STDMETHODIMP CAMEnumInterfaceImpl<Base, piid, T>::Skip(ULONG celt)
|
||
|
{
|
||
|
m_iter += celt;
|
||
|
if (m_iter < Size())
|
||
|
return S_OK;
|
||
|
m_iter = Size();
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
template <class Base, const IID* piid, class T>
|
||
|
STDMETHODIMP CAMEnumInterfaceImpl<Base, piid, T>::Clone(Base** ppEnum)
|
||
|
{
|
||
|
typedef CComObject<CAMEnumInterface<Base, piid, T> > _class;
|
||
|
HRESULT hRes = E_POINTER;
|
||
|
if (ppEnum != NULL)
|
||
|
{
|
||
|
_class* p = NULL;
|
||
|
ATLTRY(p = new _class)
|
||
|
if (p == NULL)
|
||
|
{
|
||
|
*ppEnum = NULL;
|
||
|
hRes = E_OUTOFMEMORY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = 0; i < Size(); i++) {
|
||
|
if (!p->Add(Element(i))) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (i != Size()) {
|
||
|
delete p;
|
||
|
hRes = E_OUTOFMEMORY;
|
||
|
*ppEnum = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
p->m_iter = m_iter;
|
||
|
hRes = p->_InternalQueryInterface(*piid, (void**)ppEnum);
|
||
|
if (FAILED(hRes))
|
||
|
delete p;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return hRes;
|
||
|
}
|
||
|
|
||
|
template <class Base, const IID* piid, class T>
|
||
|
class CAMEnumInterface : public CAMEnumInterfaceImpl<Base, piid, T>, public CComObjectRoot
|
||
|
{
|
||
|
public:
|
||
|
typedef CComObjectRoot _BaseClass ;
|
||
|
typedef CAMEnumInterface<Base, piid, T> _CComEnum;
|
||
|
typedef CAMEnumInterfaceImpl<Base, piid, T> _CComEnumBase;
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
ULONG InternalAddRef()
|
||
|
{
|
||
|
return _BaseClass::InternalAddRef();
|
||
|
}
|
||
|
ULONG InternalRelease()
|
||
|
{
|
||
|
return _BaseClass::InternalRelease();
|
||
|
}
|
||
|
#endif
|
||
|
BEGIN_COM_MAP(_CComEnum)
|
||
|
COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase)
|
||
|
END_COM_MAP()
|
||
|
};
|
||
|
|
||
|
#ifndef __WXUTIL__
|
||
|
|
||
|
// wrapper for whatever critical section we have
|
||
|
class CCritSec {
|
||
|
|
||
|
// make copy constructor and assignment operator inaccessible
|
||
|
|
||
|
CCritSec(const CCritSec &refCritSec);
|
||
|
CCritSec &operator=(const CCritSec &refCritSec);
|
||
|
|
||
|
CRITICAL_SECTION m_CritSec;
|
||
|
|
||
|
public:
|
||
|
CCritSec() {
|
||
|
InitializeCriticalSection(&m_CritSec);
|
||
|
};
|
||
|
|
||
|
~CCritSec() {
|
||
|
DeleteCriticalSection(&m_CritSec);
|
||
|
};
|
||
|
|
||
|
void Lock() {
|
||
|
EnterCriticalSection(&m_CritSec);
|
||
|
};
|
||
|
|
||
|
void Unlock() {
|
||
|
LeaveCriticalSection(&m_CritSec);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
// locks a critical section, and unlocks it automatically
|
||
|
// when the lock goes out of scope
|
||
|
class CAutoLock {
|
||
|
|
||
|
// make copy constructor and assignment operator inaccessible
|
||
|
|
||
|
CAutoLock(const CAutoLock &refAutoLock);
|
||
|
CAutoLock &operator=(const CAutoLock &refAutoLock);
|
||
|
|
||
|
protected:
|
||
|
CCritSec * m_pLock;
|
||
|
|
||
|
public:
|
||
|
CAutoLock(CCritSec * plock)
|
||
|
{
|
||
|
m_pLock = plock;
|
||
|
m_pLock->Lock();
|
||
|
};
|
||
|
|
||
|
~CAutoLock() {
|
||
|
m_pLock->Unlock();
|
||
|
};
|
||
|
};
|
||
|
|
||
|
// locks a critical section, and unlocks it automatically
|
||
|
// when the lock goes out of scope
|
||
|
class CAutoObjectLock {
|
||
|
|
||
|
// make copy constructor and assignment operator inaccessible
|
||
|
|
||
|
CAutoObjectLock(const CAutoObjectLock &refAutoLock);
|
||
|
CAutoObjectLock &operator=(const CAutoObjectLock &refAutoLock);
|
||
|
|
||
|
protected:
|
||
|
CComObjectRoot * m_pObject;
|
||
|
|
||
|
public:
|
||
|
CAutoObjectLock(CComObjectRoot * pobject)
|
||
|
{
|
||
|
m_pObject = pobject;
|
||
|
m_pObject->Lock();
|
||
|
};
|
||
|
|
||
|
~CAutoObjectLock() {
|
||
|
m_pObject->Unlock();
|
||
|
};
|
||
|
};
|
||
|
|
||
|
#define AUTO_CRIT_LOCK CAutoObjectLock lck(this);
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define EXECUTE_ASSERT(_x_) _ASSERTE(_x_)
|
||
|
#else
|
||
|
#define EXECUTE_ASSERT(_x_) _x_
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#endif // __AMUTIL_H__
|