| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- ///////////////////////////////////////////////////////////////////////////////
- // Name: msw/ole/safearray.h
- // Purpose: Helpers for working with OLE SAFEARRAYs.
- // Author: PB
- // Created: 2012-09-23
- // Copyright: (c) 2012 wxWidgets development team
- // Licence: wxWindows licence
- ///////////////////////////////////////////////////////////////////////////////
- #ifndef _MSW_OLE_SAFEARRAY_H_
- #define _MSW_OLE_SAFEARRAY_H_
- #include "wx/msw/ole/oleutils.h"
- #if wxUSE_OLE && wxUSE_VARIANT
- /*
- wxSafeArray is wxWidgets wrapper for working with MS Windows SAFEARRAYs.
- It also has convenience functions for converting between SAFEARRAY
- and wxVariant with list type or wxArrayString.
- */
- // The base class with type-independent methods. It exists solely in order to
- // reduce the template bloat.
- class WXDLLIMPEXP_CORE wxSafeArrayBase
- {
- public:
- // If owns a SAFEARRAY, it's unlocked and destroyed.
- virtual ~wxSafeArrayBase() { Destroy(); }
- // Unlocks and destroys the owned SAFEARRAY.
- void Destroy();
- // Unlocks the owned SAFEARRAY, returns it and gives up its ownership.
- SAFEARRAY* Detach();
- // Returns true if has a valid SAFEARRAY.
- bool HasArray() const { return m_array != NULL; }
- // Returns the number of dimensions.
- size_t GetDim() const;
- // Returns lower bound for dimension dim in bound. Dimensions start at 1.
- bool GetLBound(size_t dim, long& bound) const;
- // Returns upper bound for dimension dim in bound. Dimensions start at 1.
- bool GetUBound(size_t dim, long& bound) const;
- // Returns element count for dimension dim. Dimensions start at 1.
- size_t GetCount(size_t dim) const;
- protected:
- // Default constructor, protected so the class can't be used on its own,
- // it's only used as a base class of wxSafeArray<>.
- wxSafeArrayBase()
- {
- m_array = NULL;
- }
- bool Lock();
- bool Unlock();
- SAFEARRAY* m_array;
- };
- // wxSafeArrayConvertor<> must be specialized for the type in order to allow
- // using it with wxSafeArray<>.
- //
- // We specialize it below for the standard types.
- template <VARTYPE varType>
- struct wxSafeArrayConvertor {};
- /**
- Macro for specializing wxSafeArrayConvertor for simple types.
- The template parameters are:
- - externType: basic C data type, e.g. wxFloat64 or wxInt32
- - varType: corresponding VARIANT type constant, e.g. VT_R8 or VT_I4.
- */
- #define wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(externType, varType) \
- template <> \
- struct wxSafeArrayConvertor<varType> \
- { \
- typedef externType externT; \
- typedef externT internT; \
- static bool ToArray(const externT& from, internT& to) \
- { \
- to = from; \
- return true; \
- } \
- static bool FromArray(const internT& from, externT& to) \
- { \
- to = from; \
- return true; \
- } \
- }
- wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxInt16, VT_I2);
- wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxInt32, VT_I4);
- wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxFloat32, VT_R4);
- wxSPECIALIZE_WXSAFEARRAY_CONVERTOR_SIMPLE(wxFloat64, VT_R8);
- // Specialization for VT_BSTR using wxString.
- template <>
- struct wxSafeArrayConvertor<VT_BSTR>
- {
- typedef wxString externT;
- typedef BSTR internT;
- static bool ToArray(const wxString& from, BSTR& to)
- {
- BSTR bstr = wxConvertStringToOle(from);
- if ( !bstr && !from.empty() )
- {
- // BSTR can be NULL for empty strings but if the string was
- // not empty, it means we failed to allocate memory for it.
- return false;
- }
- to = bstr;
- return true;
- }
- static bool FromArray(const BSTR from, wxString& to)
- {
- to = wxConvertStringFromOle(from);
- return true;
- }
- };
- // Specialization for VT_VARIANT using wxVariant.
- template <>
- struct wxSafeArrayConvertor<VT_VARIANT>
- {
- typedef wxVariant externT;
- typedef VARIANT internT;
- static bool ToArray(const wxVariant& from, VARIANT& to)
- {
- return wxConvertVariantToOle(from, to);
- }
- static bool FromArray(const VARIANT& from, wxVariant& to)
- {
- return wxConvertOleToVariant(from, to);
- }
- };
- template <VARTYPE varType>
- class wxSafeArray : public wxSafeArrayBase
- {
- public:
- typedef wxSafeArrayConvertor<varType> Convertor;
- typedef typename Convertor::internT internT;
- typedef typename Convertor::externT externT;
- // Default constructor.
- wxSafeArray()
- {
- m_array = NULL;
- }
- // Creates and locks a zero-based one-dimensional SAFEARRAY with the given
- // number of elements.
- bool Create(size_t count)
- {
- SAFEARRAYBOUND bound;
- bound.lLbound = 0;
- bound.cElements = count;
- return Create(&bound, 1);
- }
- // Creates and locks a SAFEARRAY. See SafeArrayCreate() in MSDN
- // documentation for more information.
- bool Create(SAFEARRAYBOUND* bound, size_t dimensions)
- {
- wxCHECK_MSG( !m_array, false, wxS("Can't be created twice") );
- m_array = SafeArrayCreate(varType, dimensions, bound);
- if ( !m_array )
- return false;
- return Lock();
- }
- /**
- Creates a 0-based one-dimensional SAFEARRAY from wxVariant with the
- list type.
- Can be called only for wxSafeArray<VT_VARIANT>.
- */
- bool CreateFromListVariant(const wxVariant& variant)
- {
- wxCHECK(varType == VT_VARIANT, false);
- wxCHECK(variant.GetType() == wxS("list"), false);
- if ( !Create(variant.GetCount()) )
- return false;
- VARIANT* data = static_cast<VARIANT*>(m_array->pvData);
- for ( size_t i = 0; i < variant.GetCount(); i++)
- {
- if ( !Convertor::ToArray(variant[i], data[i]) )
- return false;
- }
- return true;
- }
- /**
- Creates a 0-based one-dimensional SAFEARRAY from wxArrayString.
- Can be called only for wxSafeArray<VT_BSTR>.
- */
- bool CreateFromArrayString(const wxArrayString& strings)
- {
- wxCHECK(varType == VT_BSTR, false);
- if ( !Create(strings.size()) )
- return false;
- BSTR* data = static_cast<BSTR*>(m_array->pvData);
- for ( size_t i = 0; i < strings.size(); i++ )
- {
- if ( !Convertor::ToArray(strings[i], data[i]) )
- return false;
- }
- return true;
- }
- /**
- Attaches and locks an existing SAFEARRAY.
- The array must have the same VARTYPE as this wxSafeArray was
- instantiated with.
- */
- bool Attach(SAFEARRAY* array)
- {
- wxCHECK_MSG(!m_array && array, false,
- wxS("Can only attach a valid array to an uninitialized one") );
- VARTYPE vt;
- HRESULT hr = SafeArrayGetVartype(array, &vt);
- if ( FAILED(hr) )
- {
- wxLogApiError(wxS("SafeArrayGetVarType()"), hr);
- return false;
- }
- wxCHECK_MSG(vt == varType, false,
- wxS("Attaching array of invalid type"));
- m_array = array;
- return Lock();
- }
- /**
- Indices have the same row-column order as rgIndices in
- SafeArrayPutElement(), i.e. they follow BASIC rules, NOT C ones.
- */
- bool SetElement(long* indices, const externT& element)
- {
- wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
- wxCHECK_MSG( indices, false, wxS("Invalid index") );
- internT* data;
- if ( FAILED( SafeArrayPtrOfIndex(m_array, (LONG *)indices, (void**)&data) ) )
- return false;
- return Convertor::ToArray(element, *data);
- }
- /**
- Indices have the same row-column order as rgIndices in
- SafeArrayPutElement(), i.e. they follow BASIC rules, NOT C ones.
- */
- bool GetElement(long* indices, externT& element) const
- {
- wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
- wxCHECK_MSG( indices, false, wxS("Invalid index") );
- internT* data;
- if ( FAILED( SafeArrayPtrOfIndex(m_array, (LONG *)indices, (void**)&data) ) )
- return false;
- return Convertor::FromArray(*data, element);
- }
- /**
- Converts the array to a wxVariant with the list type, regardless of the
- underlying SAFEARRAY type.
- If the array is multidimensional, it is flattened using the alghoritm
- originally employed in wxConvertOleToVariant().
- */
- bool ConvertToVariant(wxVariant& variant) const
- {
- wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
- size_t dims = m_array->cDims;
- size_t count = 1;
- for ( size_t i = 0; i < dims; i++ )
- count *= m_array->rgsabound[i].cElements;
- const internT* data = static_cast<const internT*>(m_array->pvData);
- externT element;
- variant.ClearList();
- for ( size_t i1 = 0; i1 < count; i1++ )
- {
- if ( !Convertor::FromArray(data[i1], element) )
- {
- variant.ClearList();
- return false;
- }
- variant.Append(element);
- }
- return true;
- }
- /**
- Converts an array to an ArrayString.
- Can be called only for wxSafeArray<VT_BSTR>. If the array is
- multidimensional, it is flattened using the alghoritm originally
- employed in wxConvertOleToVariant().
- */
- bool ConvertToArrayString(wxArrayString& strings) const
- {
- wxCHECK_MSG( m_array, false, wxS("Uninitialized array") );
- wxCHECK(varType == VT_BSTR, false);
- size_t dims = m_array->cDims;
- size_t count = 1;
- for ( size_t i = 0; i < dims; i++ )
- count *= m_array->rgsabound[i].cElements;
- const BSTR* data = static_cast<const BSTR*>(m_array->pvData);
- wxString element;
- strings.clear();
- strings.reserve(count);
- for ( size_t i1 = 0; i1 < count; i1++ )
- {
- if ( !Convertor::FromArray(data[i1], element) )
- {
- strings.clear();
- return false;
- }
- strings.push_back(element);
- }
- return true;
- }
- static bool ConvertToVariant(SAFEARRAY* psa, wxVariant& variant)
- {
- wxSafeArray<varType> sa;
- bool result = false;
- if ( sa.Attach(psa) )
- result = sa.ConvertToVariant(variant);
- if ( sa.HasArray() )
- sa.Detach();
- return result;
- }
- static bool ConvertToArrayString(SAFEARRAY* psa, wxArrayString& strings)
- {
- wxSafeArray<varType> sa;
- bool result = false;
- if ( sa.Attach(psa) )
- result = sa.ConvertToArrayString(strings);
- if ( sa.HasArray() )
- sa.Detach();
- return result;
- }
- wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxSafeArray, varType);
- };
- #endif // wxUSE_OLE && wxUSE_VARIANT
- #endif // _MSW_OLE_SAFEARRAY_H_
|