|
|
/*
Copyright (c) 1997-1999 Microsoft Corporation
*/
#ifndef __SDP_SAFEARRAY__
#define __SDP_SAFEARRAY__
#include <afxdisp.h>
#include "sdpcommo.h"
#include "sdpdef.h"
inline BOOL ValidateSafeArray( IN VARTYPE VarType, IN VARIANT *Variant ) { ASSERT(NULL != Variant);
// check if its a safearray and the type of elements in the safe array is whats expected
if ( !(V_VT(Variant) & (VT_ARRAY | VarType)) ) { return FALSE; }
// check number of dimensions, cannot handle more than one dimension
if ( V_ARRAY(Variant)->cDims != 1 ) { return FALSE; }
return TRUE; }
class _DllDecl SDP_SAFEARRAY : public COleSafeArray { public:
inline SDP_SAFEARRAY();
BOOL CreateAndAttach( IN ULONG MinSize, IN VARTYPE VarType, IN OUT VARIANT &Variant, OUT HRESULT &HResult );
inline void Attach( IN VARIANT &Variant );
inline void Detach();
inline BOOL Free( OUT HRESULT &HResult );
inline BOOL IsAllocated() const;
inline ~SDP_SAFEARRAY();
protected:
VARIANT *m_Variant; };
inline SDP_SAFEARRAY::SDP_SAFEARRAY( ) : m_Variant(NULL) { }
inline void SDP_SAFEARRAY::Attach( IN VARIANT &Variant ) { m_Variant = &Variant;
// because of the way attach is implemented, the variant vt type field is set to VT_EMPTY
// and the ptr is set to null
// if the instance is destroyed without calling free, the vt type and the safe array are assigned
// back to the member variant
COleSafeArray::Attach(Variant); }
inline void SDP_SAFEARRAY::Detach( ) { ASSERT(NULL != m_Variant);
if ( NULL != m_Variant ) { *m_Variant = COleSafeArray::Detach(); m_Variant = NULL; } }
inline BOOL SDP_SAFEARRAY::Free( OUT HRESULT &HResult ) { if (NULL == m_Variant) { HResult = S_OK; return TRUE; } // destroy the underlying safearray
Clear();
// set the member variant ptr to null so that we are no longer attached to it
m_Variant = NULL;
return TRUE; }
inline BOOL SDP_SAFEARRAY::IsAllocated( ) const { return (NULL != m_Variant) ? TRUE : FALSE; }
inline SDP_SAFEARRAY::~SDP_SAFEARRAY( ) { if ( NULL != m_Variant ) { *m_Variant = COleSafeArray::Detach(); } }
template <class T> class DYNAMIC_ARRAY { public:
inline DYNAMIC_ARRAY( IN ULONG NumElements );
inline T &operator[]( IN ULONG Index );
inline T *operator()();
virtual ~DYNAMIC_ARRAY();
protected:
T *m_Array; };
template <class T> inline DYNAMIC_ARRAY<T>::DYNAMIC_ARRAY( IN ULONG NumElements ) { ASSERT(0 != NumElements); m_Array = new T[NumElements]; }
template <class T> inline T & DYNAMIC_ARRAY<T>::operator[]( IN ULONG Index ) { return m_Array[Index]; }
template <class T> inline T * DYNAMIC_ARRAY<T>::operator ()( ) { return m_Array; }
template <class T> DYNAMIC_ARRAY<T>::~DYNAMIC_ARRAY( ) { ASSERT( NULL != m_Array ); delete[] m_Array; }
template <class T> class DYNAMIC_POINTER_ARRAY : public DYNAMIC_ARRAY<T *> { public:
inline DYNAMIC_POINTER_ARRAY( IN ULONG NumElements );
inline T &operator[]( IN ULONG Index );
virtual ~DYNAMIC_POINTER_ARRAY();
protected:
ULONG m_NumElements;
// should not be called
inline T *operator()() { ASSERT(FALSE); return NULL; } };
template <class T> inline DYNAMIC_POINTER_ARRAY<T>::DYNAMIC_POINTER_ARRAY( IN ULONG NumElements ) : DYNAMIC_ARRAY<T *>(NumElements), m_NumElements(NumElements) { for (UINT i=0; i < NumElements; i++) { m_Array[i] = new T(); } }
template <class T> inline T & DYNAMIC_POINTER_ARRAY<T>::operator[]( IN ULONG Index ) { return *m_Array[Index]; }
template <class T> DYNAMIC_POINTER_ARRAY<T>::~DYNAMIC_POINTER_ARRAY( ) { ASSERT( NULL != m_Array ); for (UINT i=0; i < m_NumElements; i++) { delete m_Array[i]; } }
class _DllDecl SDP_SAFEARRAY_WRAP { public:
HRESULT GetSafeArrays( IN const ULONG NumElements, IN const ULONG NumSafeArrays, IN VARTYPE VarType[], OUT VARIANT *Variant[] );
HRESULT SetSafeArrays( IN const ULONG NumSafeArrays, IN VARTYPE VarType[], IN VARIANT *Variant[] );
protected:
virtual BOOL GetElement( IN ULONG Index, IN ULONG NumEntries, IN void **Element, OUT HRESULT &HResult ) = 0;
virtual BOOL SetElement( IN ULONG Index, IN ULONG NumEntries, IN void ***Element, OUT HRESULT &HResult ) = 0;
virtual void RemoveExcessElements( IN ULONG StartIndex ) = 0; };
template <class T, class TLIST> class _DllDecl SDP_SAFEARRAY_WRAP_EX : public SDP_SAFEARRAY_WRAP { public:
inline SDP_SAFEARRAY_WRAP_EX( IN TLIST &TList );
protected:
TLIST &m_TList;
T *GetListMember( IN ULONG Index, OUT HRESULT &HResult );
virtual BOOL Get( IN T &ListMember, IN ULONG NumEntries, IN void **Element, OUT HRESULT &HResult ) = 0;
virtual BOOL GetElement( IN ULONG Index, IN ULONG NumEntries, IN void **Element, OUT HRESULT &HResult );
T *CreateListMemberIfRequired( IN ULONG Index, OUT HRESULT &HResult );
virtual BOOL Set( IN T &ListMember, IN ULONG NumEntries, IN void ***Element, OUT HRESULT &HResult ) = 0;
virtual BOOL SetElement( IN ULONG Index, IN ULONG NumEntries, IN void ***Element, OUT HRESULT &HResult );
virtual void RemoveExcessElements( IN ULONG StartIndex ); };
template <class T, class TLIST> inline SDP_SAFEARRAY_WRAP_EX<T, TLIST>::SDP_SAFEARRAY_WRAP_EX( IN TLIST &TList ) : m_TList(TList) {}
template <class T, class TLIST> T * SDP_SAFEARRAY_WRAP_EX<T, TLIST>::GetListMember( IN ULONG Index, OUT HRESULT &HResult ) { T *ToReturn = dynamic_cast<T *>(m_TList[Index]);
if ( NULL == ToReturn ) { HResult = HRESULT_FROM_ERROR_CODE(SDP_INTERNAL_ERROR); }
return ToReturn; }
template <class T, class TLIST> BOOL SDP_SAFEARRAY_WRAP_EX<T, TLIST>::GetElement( IN ULONG Index, IN ULONG NumEntries, IN void **Element, OUT HRESULT &HResult ) { T *ListMember = GetListMember(Index, HResult); if ( NULL == ListMember ) { return FALSE; }
ASSERT(ListMember->IsValid()); if ( !Get(*ListMember, NumEntries, Element, HResult) ) { return FALSE; }
return TRUE; }
template <class T, class TLIST> T * SDP_SAFEARRAY_WRAP_EX<T, TLIST>::CreateListMemberIfRequired( IN ULONG Index, OUT HRESULT &HResult ) { // assert that the index is atmost 1 more than the size of the list
ASSERT(0 <= m_TList.GetSize()); ASSERT(Index <= (ULONG)(m_TList.GetSize() + 1));
if ( Index >= (ULONG)m_TList.GetSize() ) {
T *NewElement = dynamic_cast<T *>(m_TList.CreateElement()); if ( NULL == NewElement ) { HResult = HRESULT_FROM_ERROR_CODE(SDP_INTERNAL_ERROR); } return NewElement; } else { return GetListMember(Index, HResult); }
// should never reach here
ASSERT(FALSE); }
template <class T, class TLIST> BOOL SDP_SAFEARRAY_WRAP_EX<T, TLIST>::SetElement( IN ULONG Index, IN ULONG NumEntries, IN void ***Element, OUT HRESULT &HResult ) { T *ListMember = CreateListMemberIfRequired(Index, HResult); if ( NULL == ListMember ) { return FALSE; }
if ( !Set(*ListMember, NumEntries, Element, HResult) ) { return FALSE; } ASSERT(ListMember->IsValid());
// if its a newly created instance, make it valid and add it to the list at the appropriate
// index
if ( Index >= (ULONG)m_TList.GetSize() ) { try { m_TList.SetAtGrow(Index, ListMember); } catch(...) { delete ListMember;
SetLastError(ERROR_OUTOFMEMORY); return FALSE; } }
return TRUE; }
template <class T, class TLIST> void SDP_SAFEARRAY_WRAP_EX<T, TLIST>::RemoveExcessElements( IN ULONG StartIndex ) { ASSERT(0 <= m_TList.GetSize());
// for each list element that is in excess of the safearray members,
// delete and remove them
for ( ULONG i = StartIndex; i < (ULONG)m_TList.GetSize(); i++ ) { delete m_TList[i]; m_TList.RemoveAt(i); i++; } }
#endif // __SDP_SAFEARRAY__
|