VirtualBox

Changeset 6874 in vbox for trunk/include


Ignore:
Timestamp:
Feb 10, 2008 2:34:59 PM (17 years ago)
Author:
vboxsync
Message:

Main: Arrays: 1) Added com::SafeIfaceArray to manage arrays of interface pointers. 2) Added template constructor that takes std C++ containers and creates a deep copy.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/com/array.h

    r6851 r6874  
    2828#define ___VBox_com_array_h
    2929
     30#include <VBox/com/ptr.h>
     31
    3032/** @defgroup   grp_COM_arrays    COM/XPCOM Arrays
    3133 * @{
     
    125127 * @endcode
    126128 *
    127  * Implementation declarations and function bodies of attribute getters and
    128  * setters are very similar to the examples shown above and therefore not
    129  * explained separately.
     129 * For interoperability with standard C++ containers, there is a template
     130 * constructor that takes such a container as argument and performs a deep copy
     131 * of its contents. This can be used in method implementations like this:
     132 * @code
     133
     134    STDMETHODIMP Component::COMGETTER(Values) (ComSafeArrayOut (int, aValues))
     135    {
     136        // ... assume there is a |std::list <int> mValues| data member
     137
     138        com::SafeArray <int> values (mValues);
     139        values.detachTo (ComSafeArrayOutArg (aValues));
     140
     141        return S_OK;
     142    }
     143
     144 * @endcode
    130145 *
    131146 * The current implementation of the SafeArray layer supports all types normally
    132  * allowed in XIDL as array element types (including 'wstring', 'uuid' types and
    133  * interface pointers). However 'pointer-to' types (e.g. 'long *', 'wstrig *',
    134  * 'IUnknown **') are not supported and therefore cannot be used as element
    135  * types.
     147 * allowed in XIDL as array element types (including 'wstring' and 'uuid').
     148 * However, 'pointer-to-...' types (e.g. 'long *', 'wstring *') are not
     149 * supported and therefore cannot be used as element types.
     150 *
     151 * Arrays of interface pointers are also supported but they require to use a
     152 * special SafeArray implementation, com::SafeIfacePointer, which takes the
     153 * interface class name as a template argument (e.g. com::SafeIfacePointer
     154 * <IUnknown>). This implementation functions identically to com::SafeArray.
    136155 */
    137156
     
    193212    static void Init (T &aElem) { aElem = 0; }
    194213    static void Uninit (T &aElem) { aElem = 0; }
    195 
    196     /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard.
    197      * Then initial reason for this magic is that XPIDL declares input strings
     214    static void Copy (const T &aFrom, T &aTo) { aTo = aFrom; }
     215
     216    /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard (that
     217     * in particular forbid casts of 'char **' to 'const char **'). Then initial
     218     * reason for this magic is that XPIDL declares input strings
    198219     * (char/PRUnichar pointers) as const but doesn't do so for pointers to
    199220     * arrays. */
     
    202223};
    203224
     225template <typename T>
     226struct SafeArrayTraits <T *>
     227{
     228    // Arbitrary pointers are not supported
     229};
     230
    204231template<>
    205232struct SafeArrayTraits <PRUnichar *>
     
    215242    }
    216243
     244    static void Copy (const PRUnichar * aFrom, PRUnichar * &aTo)
     245    {
     246        AssertCompile (sizeof (PRUnichar) == sizeof (OLECHAR));
     247        aTo = aFrom ? ::SysAllocString ((const OLECHAR *) aFrom) : NULL;
     248    }
     249
    217250    /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard */
    218251    static const PRUnichar **__asInParam_Arr (PRUnichar **aArr)
     
    233266struct SafeArrayTraits
    234267{
    235     static VARTYPE VarType() { AssertMsgFailedReturn ("Not supported", VT_EMPTY) }
     268    // Arbitrary types are not supported
    236269};
    237270
     
    240273{
    241274    static VARTYPE VarType() { return VT_I4; }
     275    static void Copy (LONG aFrom, LONG &aTo) { aTo = aFrom; }
    242276};
    243277
     
    246280{
    247281    static VARTYPE VarType() { return VT_UI4; }
     282    static void Copy (ULONG aFrom, ULONG &aTo) { aTo = aFrom; }
    248283};
    249284
     
    252287{
    253288    static VARTYPE VarType() { return VT_BSTR; }
     289
     290    static void Copy (BSTR aFrom, BSTR &aTo)
     291    {
     292        aTo = aFrom ? ::SysAllocString ((const OLECHAR *) aFrom) : NULL;
     293    }
    254294};
    255295
     
    284324 * @note This class is not thread-safe.
    285325 */
    286 template  <typename T>
    287 class SafeArray : public SafeArrayTraits <T>
     326template  <typename T, class Traits = SafeArrayTraits <T> >
     327class SafeArray : protected Traits
    288328{
    289329public:
     
    358398
    359399    /**
     400     * Creates a deep copy of the goven standard C++ container.
     401     *
     402     * @param aCntr Container object to copy.
     403     *
     404     * @param C     Standard C++ container template class (normally deduced from
     405     *              @c aCntr).
     406     */
     407    template <template <class> class C>
     408    SafeArray (const C <T> & aCntr)
     409    {
     410        reset (aCntr.size());
     411        AssertReturnVoid (!isNull());
     412
     413        int i = 0;
     414        for (typename C <T>::const_iterator it = aCntr.begin();
     415             it != aCntr.end(); ++ it, ++ i)
     416#if defined (VBOX_WITH_XPCOM)
     417            Copy (*it, m.arr [i]);
     418#else
     419            Copy (*it, m.raw [i]);
     420#endif
     421    }
     422
     423    /**
    360424     * Destroys this instance after calling #setNull() to release allocated
    361425     * resources. See #setNull() for more details.
    362426     */
    363     ~SafeArray() { setNull(); }
     427    virtual ~SafeArray() { setNull(); }
    364428
    365429    /**
     
    376440     *       array itself is destroyed.
    377441     */
    378     void setNull() { m.uninit(); }
     442    virtual void setNull() { m.uninit(); }
    379443
    380444    /**
     
    409473     *                  memory for resizing.
    410474     */
    411     bool resize (size_t aNewSize)
     475    virtual bool resize (size_t aNewSize)
    412476    {
    413477        /// @todo Implement me!
     
    423487     *                  memory for resizing.
    424488     */
    425     bool reset (size_t aNewSize)
     489    virtual bool reset (size_t aNewSize)
    426490    {
    427491        m.uninit();
     
    532596     * @param aArg  Output method parameter to clone to.
    533597     */
    534     const SafeArray &cloneTo (ComSafeArrayOut (T, aArg)) const
     598    virtual const SafeArray &cloneTo (ComSafeArrayOut (T, aArg)) const
    535599    {
    536600        /// @todo Implement me!
     
    553617     * @param aArg  Output method parameter to detach to.
    554618     */
    555     SafeArray &detachTo (ComSafeArrayOut (T, aArg))
     619    virtual SafeArray &detachTo (ComSafeArrayOut (T, aArg))
    556620    {
    557621        AssertReturn (m.isWeak == false, *this);
     
    611675    static const SafeArray Null;
    612676
    613 private:
     677protected:
    614678
    615679    DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP(SafeArray)
     
    699763};
    700764
     765////////////////////////////////////////////////////////////////////////////////
     766
     767#if defined (VBOX_WITH_XPCOM)
     768
     769template <class I>
     770struct SafeIfaceArrayTraits
     771{
     772    static void Init (I * &aElem) { aElem = NULL; }
     773    static void Uninit (I * &aElem)
     774    {
     775        if (aElem)
     776        {
     777            aElem->Release();
     778            aElem = NULL;
     779        }
     780    }
     781
     782    static void Copy (I * aFrom, I * &aTo)
     783    {
     784        if (aFrom != NULL)
     785        {
     786            aTo = aFrom;
     787            aTo->AddRef();
     788        }
     789        else
     790            aTo = NULL;
     791    }
     792
     793    /* Magic to workaround strict rules of par. 4.4.4 of the C++ standard. */
     794    static I **__asInParam_Arr (I **aArr) { return aArr; }
     795    static I **__asInParam_Arr (const I **aArr) { return const_cast <I **> (aArr); }
     796};
     797
     798#else /* defined (VBOX_WITH_XPCOM) */
     799
     800template <class I>
     801struct SafeIfaceArrayTraits
     802{
     803    static VARTYPE VarType() { return VT_UNKNOWN; }
     804
     805    static void Copy (I * aFrom, I * &aTo)
     806    {
     807        if (aFrom != NULL)
     808        {
     809            aTo = aFrom;
     810            aTo->AddRef();
     811        }
     812        else
     813            aTo = NULL;
     814    }
     815};
     816
     817#endif /* defined (VBOX_WITH_XPCOM) */
     818
     819////////////////////////////////////////////////////////////////////////////////
     820
     821/**
     822 * Version of com::SafeArray for arrays of interface pointers.
     823 *
     824 * Except that it manages arrays of interface pointers, the usage of this class
     825 * is identical to com::SafeArray.
     826 *
     827 * @param I     Interface class (no asterisk).
     828 */
     829template <class I>
     830class SafeIfaceArray : public SafeArray <I *, SafeIfaceArrayTraits <I> >
     831{
     832public:
     833
     834    typedef SafeArray <I *, SafeIfaceArrayTraits <I> > Base;
     835
     836    /**
     837     * Creates a null array.
     838     */
     839    SafeIfaceArray() {}
     840
     841    /**
     842     * Creates a new array of the given size. All elements of the newly created
     843     * array initialized with null values.
     844     *
     845     * @param aSize     Initial number of elements in the array. Must be greater
     846     *                  than 0.
     847     *
     848     * @note If this object remains null after construction it means that there
     849     *       was not enough memory for creating an array of the requested size.
     850     *       The constructor will also assert in this case.
     851     */
     852    SafeIfaceArray (size_t aSize) { reset (aSize); }
     853
     854    /**
     855     * Weakly attaches this instance to the existing array passed in a method
     856     * parameter declared using the ComSafeArrayIn macro. When using this call,
     857     * always wrap the parameter name in the ComSafeArrayOutArg macro call like
     858     * this:
     859     * <pre>
     860     *  SafeArray safeArray (ComSafeArrayInArg (aArg));
     861     * </pre>
     862     *
     863     * Note that this constructor doesn't take the ownership of the array. In
     864     * particular, it means that operations that operate on the ownership (e.g.
     865     * #detachTo()) are forbidden and will assert.
     866     *
     867     * @param aArg  Input method parameter to attach to.
     868     */
     869    SafeIfaceArray (ComSafeArrayIn (I *, aArg))
     870    {
     871#if defined (VBOX_WITH_XPCOM)
     872
     873        AssertReturnVoid (aArg != NULL);
     874
     875        Base::m.size = aArgSize;
     876        Base::m.arr = aArg;
     877        Base::m.isWeak = true;
     878
     879#else /* defined (VBOX_WITH_XPCOM) */
     880
     881        AssertReturnVoid (aArg != NULL);
     882        SAFEARRAY *arg = *aArg;
     883
     884        if (arg)
     885        {
     886            AssertReturnVoid (arg->cDims == 1);
     887
     888            VARTYPE vt;
     889            HRESULT rc = SafeArrayGetVartype (arg, &vt);
     890            AssertComRCReturnVoid (rc);
     891            AssertMsgReturnVoid (vt == VT_UNKNOWN,
     892                                 ("Expected vartype VT_UNKNOWN, got %d.\n",
     893                                  VarType(), vt));
     894            GUID guid;
     895            rc = SafeArrayGetIID (arg, &guid);
     896            AssertComRCReturnVoid (rc);
     897            AssertMsgReturnVoid (InlineIsEqualGUID (_ATL_IIDOF (I), guid),
     898                                 ("Expected IID {%Vuuid}, got {%Vuuid}.\n",
     899                                  &_ATL_IIDOF (I), &guid));
     900        }
     901
     902        m.arr = arg;
     903        m.isWeak = true;
     904
     905        AssertReturnVoid (accessRaw() != NULL);
     906
     907#endif /* defined (VBOX_WITH_XPCOM) */
     908    }
     909
     910    /**
     911     * Creates a deep copy of the given standard C++ container that stores
     912     * interface pointers as objects of the ComPtr <I> class.
     913     *
     914     * @param aCntr Container object to copy.
     915     *
     916     * @param C     Standard C++ container template class (normally deduced from
     917     *              @c aCntr).
     918     * @param A     Standard C++ allocator class (deduced from @c aCntr).
     919     * @param OI    Argument to the ComPtr template (deduced from @c aCntr).
     920     */
     921    template <template <typename, typename> class C, class A, class OI>
     922    SafeIfaceArray (const C <ComPtr <OI>, A> & aCntr)
     923    {
     924        typedef C <ComPtr <OI>, A> List;
     925
     926        reset (aCntr.size());
     927        AssertReturnVoid (!Base::isNull());
     928
     929        int i = 0;
     930        for (typename List::const_iterator it = aCntr.begin();
     931             it != aCntr.end(); ++ it, ++ i)
     932#if defined (VBOX_WITH_XPCOM)
     933            Copy (*it, Base::m.arr [i]);
     934#else
     935            Copy (*it, Base::m.raw [i]);
     936#endif
     937    }
     938
     939    /**
     940     * Creates a deep copy of the given standard C++ container that stores
     941     * interface pointers as objects of the ComObjPtr <I> class.
     942     *
     943     * @param aCntr Container object to copy.
     944     *
     945     * @param C     Standard C++ container template class (normally deduced from
     946     *              @c aCntr).
     947     * @param A     Standard C++ allocator class (deduced from @c aCntr).
     948     * @param OI    Argument to the ComObjPtr template (deduced from @c aCntr).
     949     */
     950    template <template <typename, typename> class C, class A, class OI>
     951    SafeIfaceArray (const C <ComObjPtr <OI>, A> & aCntr)
     952    {
     953        typedef C <ComObjPtr <OI>, A> List;
     954
     955        reset (aCntr.size());
     956        AssertReturnVoid (!Base::isNull());
     957
     958        int i = 0;
     959        for (typename List::const_iterator it = aCntr.begin();
     960             it != aCntr.end(); ++ it, ++ i)
     961#if defined (VBOX_WITH_XPCOM)
     962            Copy (*it, Base::m.arr [i]);
     963#else
     964            Copy (*it, Base::m.raw [i]);
     965#endif
     966    }
     967
     968    /**
     969     * Reinitializes this instance by preallocating space for the given number
     970     * of elements. The previous array contents is lost.
     971     *
     972     * @param aNewSize  New number of elements in the array.
     973     * @return          @c true on success and false if there is not enough
     974     *                  memory for resizing.
     975     */
     976    virtual bool reset (size_t aNewSize)
     977    {
     978        Base::m.uninit();
     979
     980#if defined (VBOX_WITH_XPCOM)
     981
     982        AssertReturn (aNewSize > 0, false);
     983
     984        Base::m.arr = (I **) nsMemory::Alloc (aNewSize * sizeof (I *));
     985        AssertReturn (Base::m.arr != NULL, false);
     986
     987        Base::m.size = aNewSize;
     988
     989        for (size_t i = 0; i < Base::m.size; ++ i)
     990            Init (Base::m.arr [i]);
     991
     992#else
     993
     994        AssertReturn (aNewSize > 0, false);
     995
     996        SAFEARRAYBOUND bound = { aNewSize, 0 };
     997        m.arr = SafeArrayCreateEx (VT_UNKNOWN, 1, &bound,
     998                                   (PVOID) &_ATL_IIDOF (I));
     999        AssertReturn (m.arr != NULL, false);
     1000
     1001        AssertReturn (accessRaw() != NULL, false);
     1002
     1003#endif
     1004        return true;
     1005    }
     1006};
     1007
    7011008} /* namespace com */
    7021009
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette