]> git.sesse.net Git - vlc/commitdiff
- ActiveX: optimized implementation of all IEnumXXX classes (more template obfuscatio...
authorDamien Fouilleul <damienf@videolan.org>
Thu, 21 Sep 2006 17:01:45 +0000 (17:01 +0000)
committerDamien Fouilleul <damienf@videolan.org>
Thu, 21 Sep 2006 17:01:45 +0000 (17:01 +0000)
activex/connectioncontainer.cpp
activex/connectioncontainer.h
activex/dataobject.cpp
activex/utils.h

index cfc52672453e2544857a22a5285c5fef7e7d133b..36e8eba8053319b9211c222888dcb1d864dfe874 100644 (file)
@@ -29,46 +29,62 @@ using namespace std;
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
-class VLCEnumConnections : public IEnumConnections
+/* this function object is used to return the value from a map pair */
+struct VLCEnumConnectionsDereference
 {
-public:
-    VLCEnumConnections(vector<CONNECTDATA> &v) :
-        e(VLCEnum<CONNECTDATA>(IID_IEnumConnections, v))
-    { e.setRetainOperation((VLCEnum<CONNECTDATA>::retainer)&retain); };
-
-    VLCEnumConnections(const VLCEnumConnections &vlcEnum) : IEnumConnections(), e(vlcEnum.e) {};
-
-    virtual ~VLCEnumConnections() {};
-
-    // IUnknown methods
-    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
-        { return e.QueryInterface(riid, ppv); };
-    STDMETHODIMP_(ULONG) AddRef(void)
-        { return e.AddRef(); };
-    STDMETHODIMP_(ULONG) Release(void)
-        {return e.Release(); };
-
-    //IEnumConnectionPoints
-    STDMETHODIMP Next(ULONG celt, LPCONNECTDATA rgelt, ULONG *pceltFetched)
-        { return e.Next(celt, rgelt, pceltFetched); };
-    STDMETHODIMP Skip(ULONG celt)
-        { return e.Skip(celt);};
-    STDMETHODIMP Reset(void)
-        { return e.Reset();};
-    STDMETHODIMP Clone(LPENUMCONNECTIONS *ppenum)
-        { if( NULL == ppenum ) return E_POINTER;
-          *ppenum = dynamic_cast<LPENUMCONNECTIONS>(new VLCEnumConnections(*this));
-          return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
-        };
-
-private:
-
-    static void retain(CONNECTDATA cd)
+    CONNECTDATA operator()(const map<DWORD,LPUNKNOWN>::iterator& i)
     {
-        cd.pUnk->AddRef();
+        CONNECTDATA cd;
+        
+        cd.dwCookie = i->first;
+        cd.pUnk     = i->second;
+        return cd;
     };
+};
+
+class VLCEnumConnections : public VLCEnumIterator<IID_IEnumConnections,
+    IEnumConnections,
+    CONNECTDATA,
+    map<DWORD,LPUNKNOWN>::iterator,
+    VLCEnumConnectionsDereference>
+{
+public:
+    VLCEnumConnections(map<DWORD,LPUNKNOWN> &m) :
+        VLCEnumIterator<IID_IEnumConnections,
+            IEnumConnections,
+            CONNECTDATA,
+            map<DWORD,LPUNKNOWN>::iterator,
+            VLCEnumConnectionsDereference> (m.begin(), m.end())
+    {};
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
 
-    VLCEnum<CONNECTDATA> e;
+/* this function object is used to retain the dereferenced iterator value */
+struct VLCEnumConnectionPointsDereference
+{
+    LPCONNECTIONPOINT operator()(const vector<LPCONNECTIONPOINT>::iterator& i)
+    {
+        LPCONNECTIONPOINT cp = *i;
+        cp->AddRef();
+        return cp;
+    }
+};
+
+class VLCEnumConnectionPoints: public VLCEnumIterator<IID_IEnumConnectionPoints,
+    IEnumConnectionPoints,
+    LPCONNECTIONPOINT,
+    vector<LPCONNECTIONPOINT>::iterator,
+    VLCEnumConnectionPointsDereference>
+{
+public:
+    VLCEnumConnectionPoints(vector<LPCONNECTIONPOINT>& v) :
+        VLCEnumIterator<IID_IEnumConnectionPoints,
+            IEnumConnectionPoints,
+            LPCONNECTIONPOINT,
+            vector<LPCONNECTIONPOINT>::iterator,
+            VLCEnumConnectionPointsDereference> (v.begin(), v.end())
+    {};
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
@@ -94,31 +110,28 @@ STDMETHODIMP VLCConnectionPoint::GetConnectionPointContainer(LPCONNECTIONPOINTCO
 
 STDMETHODIMP VLCConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)
 {
+    static DWORD dwCookieCounter = 0;
+
     if( (NULL == pUnk) || (NULL == pdwCookie) )
         return E_POINTER;
 
-    CONNECTDATA cd;
-
     pUnk->AddRef();
-    cd.pUnk = pUnk;
-    *pdwCookie = cd.dwCookie = _connections.size()+1;
 
-    _connections.push_back(cd);
+    *pdwCookie = ++dwCookieCounter;
+    _connections[*pdwCookie] = pUnk;
 
     return S_OK;
 };
 
 STDMETHODIMP VLCConnectionPoint::Unadvise(DWORD pdwCookie)
 {
-    if( (0 < pdwCookie) && (pdwCookie <= _connections.size()) )
+    map<DWORD,LPUNKNOWN>::iterator pcd = _connections.find((DWORD)pdwCookie);
+    if( pcd != _connections.end() )
     {
-        CONNECTDATA cd = _connections[pdwCookie-1];
-        if( NULL != cd.pUnk )
-        {
-            cd.pUnk->Release();
-            cd.pUnk = NULL;
-            return S_OK;
-        }
+        pcd->second->Release();
+
+        _connections.erase(pdwCookie);
+        return S_OK;
     }
     return CONNECT_E_NOCONNECTION;
 };
@@ -135,16 +148,16 @@ STDMETHODIMP VLCConnectionPoint::EnumConnections(IEnumConnections **ppEnum)
 
 void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams)
 {
-    vector<CONNECTDATA>::iterator end = _connections.end();
-    vector<CONNECTDATA>::iterator iter = _connections.begin();
+    map<DWORD,LPUNKNOWN>::iterator end = _connections.end();
+    map<DWORD,LPUNKNOWN>::iterator iter = _connections.begin();
 
     while( iter != end )
     {
-        CONNECTDATA cd = *iter;
-        if( NULL != cd.pUnk )
+        LPUNKNOWN pUnk = iter->second;
+        if( NULL != pUnk )
         {
             IDispatch *pDisp;
-            if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp)) )
+            if( SUCCEEDED(pUnk->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp)) )
             {
                 pDisp->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, pDispParams, NULL, NULL, NULL);
                 pDisp->Release();
@@ -156,16 +169,16 @@ void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams)
 
 void VLCConnectionPoint::firePropChangedEvent(DISPID dispId)
 {
-    vector<CONNECTDATA>::iterator end = _connections.end();
-    vector<CONNECTDATA>::iterator iter = _connections.begin();
+    map<DWORD,LPUNKNOWN>::iterator end = _connections.end();
+    map<DWORD,LPUNKNOWN>::iterator iter = _connections.begin();
 
     while( iter != end )
     {
-        CONNECTDATA cd = *iter;
-        if( NULL != cd.pUnk )
+        LPUNKNOWN pUnk = iter->second;
+        if( NULL != pUnk )
         {
             IPropertyNotifySink *pPropSink;
-            if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) )
+            if( SUCCEEDED(pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) )
             {
                 pPropSink->OnChanged(dispId);
                 pPropSink->Release();
@@ -177,50 +190,6 @@ void VLCConnectionPoint::firePropChangedEvent(DISPID dispId)
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
-class VLCEnumConnectionPoints : public IEnumConnectionPoints
-{
-public:
-    VLCEnumConnectionPoints(vector<LPCONNECTIONPOINT> &v) :
-        e(VLCEnum<LPCONNECTIONPOINT>(IID_IEnumConnectionPoints, v))
-    { e.setRetainOperation((VLCEnum<LPCONNECTIONPOINT>::retainer)&retain); };
-
-    VLCEnumConnectionPoints(const VLCEnumConnectionPoints &vlcEnum) : IEnumConnectionPoints(), e(vlcEnum.e) {};
-
-    virtual ~VLCEnumConnectionPoints() {};
-
-    // IUnknown methods
-    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
-        { return e.QueryInterface(riid, ppv); };
-    STDMETHODIMP_(ULONG) AddRef(void)
-        { return e.AddRef(); };
-    STDMETHODIMP_(ULONG) Release(void)
-        {return e.Release(); };
-
-    //IEnumConnectionPoints
-    STDMETHODIMP Next(ULONG celt, LPCONNECTIONPOINT *rgelt, ULONG *pceltFetched)
-        { return e.Next(celt, rgelt, pceltFetched); };
-    STDMETHODIMP Skip(ULONG celt)
-        { return e.Skip(celt);};
-    STDMETHODIMP Reset(void)
-        { return e.Reset();};
-    STDMETHODIMP Clone(LPENUMCONNECTIONPOINTS *ppenum)
-        { if( NULL == ppenum ) return E_POINTER;
-          *ppenum = dynamic_cast<LPENUMCONNECTIONPOINTS>(new VLCEnumConnectionPoints(*this));
-          return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
-        };
-
-private:
-
-    static void retain(LPCONNECTIONPOINT cp)
-    {
-        cp->AddRef();
-    };
-
-    VLCEnum<LPCONNECTIONPOINT> e;
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
 VLCDispatchEvent::~VLCDispatchEvent()
 {
     //clear event arguments
index 71f1f5b1312e24f79e815a6609cb0d3ea7e741b9..0e3b65bf8843b89716bc494e0e33b22ff2a7f187 100644 (file)
@@ -26,6 +26,7 @@
 #include <ocidl.h>
 #include <vector>
 #include <queue>
+#include <map>
 
 class VLCConnectionPoint : public IConnectionPoint
 {
@@ -69,7 +70,7 @@ private:
 
     REFIID _iid;
     IConnectionPointContainer *_p_cpc;
-    std::vector<CONNECTDATA> _connections;
+    std::map<DWORD, LPUNKNOWN> _connections;
 };
 
 //////////////////////////////////////////////////////////////////////////
index 931f45d1505b81ea70f59606e8e3f33bc4da21a3..d77614620e1a89f7331f2dfa42296796c5f7c070 100644 (file)
@@ -29,44 +29,6 @@ using namespace std;
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
-class VLCEnumFORMATETC : public IEnumFORMATETC
-{
-public:
-
-    VLCEnumFORMATETC(vector<FORMATETC> &v) :
-        e(VLCEnum<FORMATETC>(IID_IEnumFORMATETC, v)) {};
-
-    VLCEnumFORMATETC(const VLCEnumFORMATETC &vlcEnum) : IEnumFORMATETC(), e(vlcEnum.e) {};
-    virtual ~VLCEnumFORMATETC() {};
-
-    // IUnknown methods
-    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
-        { return e.QueryInterface(riid, ppv); };
-    STDMETHODIMP_(ULONG) AddRef(void)
-        { return e.AddRef(); };
-    STDMETHODIMP_(ULONG) Release(void)
-        {return e.Release(); };
-
-    //IEnumConnectionPoints
-    STDMETHODIMP Next(ULONG celt, LPFORMATETC rgelt, ULONG *pceltFetched)
-        { return e.Next(celt, rgelt, pceltFetched); };
-    STDMETHODIMP Skip(ULONG celt)
-        { return e.Skip(celt);};
-    STDMETHODIMP Reset(void)
-        { return e.Reset();};
-    STDMETHODIMP Clone(LPENUMFORMATETC *ppenum)
-        { if( NULL == ppenum ) return E_POINTER;
-          *ppenum = dynamic_cast<LPENUMFORMATETC>(new VLCEnumFORMATETC(*this));
-          return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
-        };
-
-private:
-
-    VLCEnum<FORMATETC> e;
-};
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-
 static const FORMATETC _metaFileFormatEtc =
     {
         CF_METAFILEPICT,
@@ -84,6 +46,22 @@ static const FORMATETC _enhMetaFileFormatEtc =
         TYMED_ENHMF,
     };
 
+class VLCEnumFORMATETC : public VLCEnumIterator<IID_IEnumFORMATETC,
+    IEnumFORMATETC,
+    FORMATETC,
+    vector<FORMATETC>::iterator>
+{
+public:
+    VLCEnumFORMATETC(vector<FORMATETC> v) :
+        VLCEnumIterator<IID_IEnumFORMATETC,
+        IEnumFORMATETC,
+        FORMATETC,
+        vector<FORMATETC>::iterator>(v.begin(), v.end())
+    {};
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
 VLCDataObject::VLCDataObject(VLCPlugin *p_instance) : _p_instance(p_instance)
 {
     _v_formatEtc.push_back(_enhMetaFileFormatEtc);
@@ -114,13 +92,14 @@ STDMETHODIMP VLCDataObject::EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
     return _p_adviseHolder->EnumAdvise(ppenumAdvise);
 };
 
-STDMETHODIMP VLCDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumformatetc)
+STDMETHODIMP VLCDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnum)
 {
-    if( NULL == ppenumformatetc )
+    if( NULL == ppEnum )
         return E_POINTER;
 
-    *ppenumformatetc = new VLCEnumFORMATETC(_v_formatEtc);
-    return NOERROR;
+    *ppEnum = dynamic_cast<IEnumFORMATETC *>(new VLCEnumFORMATETC(_v_formatEtc));
+
+    return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
 };
 
 STDMETHODIMP VLCDataObject::GetCanonicalFormatEtc(LPFORMATETC pFormatEtcIn, LPFORMATETC pFormatEtcOut)
index 4514880ae7293d3d2719b382f3bedc286dae04dc..f4a9c4f55020fab2c650875034886ab75a6c0c27 100644 (file)
@@ -43,151 +43,130 @@ extern void HimetricFromDP(HDC hdc, LPPOINT pt, int count);
 
 /**************************************************************************************************/
 
-// enumeration
-template<class T> class VLCEnum : IUnknown
+/* this function object is used to dereference the iterator into a value */
+template <class T, class Iterator>
+struct VLCDereference
+{
+    T operator()(const Iterator& i) const
+    {
+        return *i;
+    };
+};
+
+template<REFIID EnumeratorIID, class Enumerator, class T, class Iterator, typename Dereference = VLCDereference<T, Iterator> >
+class VLCEnumIterator : public Enumerator
 {
 
 public:
 
-    VLCEnum(REFIID riid, std::vector<T> &);
-    VLCEnum(const VLCEnum<T> &);
-    virtual ~VLCEnum() {};
+    VLCEnumIterator(const Iterator& from, const Iterator& to) :
+        _refcount(1),
+        _begin(from),
+        _curr(from),
+        _end(to)
+    {};
+
+    VLCEnumIterator(const VLCEnumIterator& e) :
+        Enumerator(),
+        _refcount(e._refcount),
+        _begin(e._begin),
+        _curr(e._curr),
+        _end(e._end)
+    {};
 
-    VLCEnum<T>& operator=(const VLCEnum<T> &t);
+    virtual ~VLCEnumIterator()
+    {};
 
     // IUnknown methods
-    STDMETHODIMP QueryInterface(REFIID riid, void **);
-    STDMETHODIMP_(ULONG) AddRef(void);
-    STDMETHODIMP_(ULONG) Release(void);
+    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
+    {
+        if( NULL == ppv )
+            return E_POINTER;
+        if( (IID_IUnknown == riid) 
+         || (EnumeratorIID == riid) )
+        {
+            AddRef();
+            *ppv = reinterpret_cast<LPVOID>(this);
+            return NOERROR;
+        }
+        // standalone object
+        return E_NOINTERFACE;
+    };
+
+    STDMETHODIMP_(ULONG) AddRef(void)
+    {
+        return InterlockedIncrement(&_refcount);
+    };
 
-    // IEnumXXXX methods
-    STDMETHODIMP Next(ULONG, T *, ULONG *);
-    STDMETHODIMP Skip(ULONG);
-    STDMETHODIMP Reset(void);
-    // cloning is implemented by subclasses and must use copy constructor
-    //STDMETHODIMP Clone(VLCEnum<T> **);
+    STDMETHODIMP_(ULONG) Release(void)
+    {
+        ULONG refcount = InterlockedDecrement(&_refcount);
+        if( 0 == refcount )
+        {
+            delete this;
+            return 0;
+        }
+        return refcount;
+    };
 
-    typedef void (*retainer)(T);
 
-    void setRetainOperation(retainer retain) { _retain = retain; };
+    // IEnumXXXX methods
+    STDMETHODIMP Next(ULONG celt, T *rgelt, ULONG *pceltFetched)
+    {
+        if( NULL == rgelt )
+            return E_POINTER;
 
-private:
+        if( (celt > 1) && (NULL == pceltFetched) )
+            return E_INVALIDARG;
 
-    LONG                                _refcount;
-    std::vector<T>                      _v;
-    typename std::vector<T>::iterator   _i;
-    REFIID                              _riid;
-    retainer                            _retain;
-};
+        ULONG c = 0;
 
-template<class T>
-VLCEnum<T>::VLCEnum(REFIID riid, std::vector<T> &v) :
-    _refcount(1),
-    _v(v),
-    _riid(riid),
-    _retain(NULL)
-{
-    _i= v.begin();
-};
+        while( (c < celt) && (_curr != _end) )
+        {
+            rgelt[c] = dereference(_curr);
+            ++_curr;
+            ++c;
+        }
 
-template<class T>
-VLCEnum<T>::VLCEnum(const VLCEnum<T> &e) :
-    IUnknown(),
-    _refcount(1),
-    _v(e._v),
-    _riid(e._riid)
-{
-};
+        if( NULL != pceltFetched )
+            *pceltFetched = c;
 
-template<class T>
-VLCEnum<T>& VLCEnum<T>::operator=(const VLCEnum<T> &e)
-{
-    this->_refcount = 1;
-    this->_riid = e._riid;
-    this->_v    = e._v;
-    this->_i    = e._i;
-    return this;
-};
+        return (c == celt) ? S_OK : S_FALSE;
+    };
 
-template<class T>
-STDMETHODIMP VLCEnum<T>::QueryInterface(REFIID riid, void **ppv)
-{
-    if( NULL == ppv )
-        return E_POINTER;
-    if( (IID_IUnknown == riid) 
-     || (_riid == riid) )
+    STDMETHODIMP Skip(ULONG celt)
     {
-        AddRef();
-        *ppv = reinterpret_cast<LPVOID>(this);
-        return NOERROR;
-    }
-    // standalone object
-    return E_NOINTERFACE;
-};
+        ULONG c = 0;
 
-template<class T>
-STDMETHODIMP_(ULONG) VLCEnum<T>::AddRef(void)
-{
-    return InterlockedIncrement(&_refcount);
-};
+        while( (c < celt) && (_curr != _end) )
+        {
+            ++_curr;
+            ++c;
+        }
+        return (c == celt) ? S_OK : S_FALSE;
+    };
 
-template<class T>
-STDMETHODIMP_(ULONG) VLCEnum<T>::Release(void)
-{
-    ULONG refcount = InterlockedDecrement(&_refcount);
-    if( 0 == refcount )
+    STDMETHODIMP Reset(void)
     {
-        delete this;
-        return 0;
-    }
-    return refcount;
-};
-
-template<class T>
-STDMETHODIMP VLCEnum<T>::Next(ULONG celt, T *rgelt, ULONG *pceltFetched)
-{
-    if( NULL == rgelt )
-        return E_POINTER;
+        _curr = _begin;
+        return S_OK;
+    };
 
-    if( (celt > 1) && (NULL == pceltFetched) )
-        return E_INVALIDARG;
-
-    ULONG c = 0;
-    typename std::vector<T>::iterator end = _v.end();
-
-    while( (c < celt) && (_i != end) )
+    STDMETHODIMP Clone(Enumerator **ppEnum)
     {
-        rgelt[c] = *_i;
-        if( NULL != _retain ) _retain(rgelt[c]);
-        ++_i;
-        ++c;
-    }
+        if( NULL == ppEnum )
+            return E_POINTER;
+        *ppEnum = dynamic_cast<Enumerator *>(new VLCEnumIterator(*this));
+        return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
+    };
 
-    if( NULL != pceltFetched )
-        *pceltFetched = c;
+private:
 
-    return (c == celt) ? S_OK : S_FALSE;
-};
+    LONG     _refcount;
+    Iterator _begin, _curr, _end;
 
-template<class T>
-STDMETHODIMP VLCEnum<T>::Skip(ULONG celt)
-{
-    ULONG c = 0;
-    typename std::vector<T>::iterator end = _v.end();
+    Dereference dereference;
 
-    while( (c < celt) && (_i != end) )
-    {
-        ++_i;
-        ++c;
-    }
-    return (c == celt) ? S_OK : S_FALSE;
-};
-
-template<class T>
-STDMETHODIMP VLCEnum<T>::Reset(void)
-{
-    _i= _v.begin();
-    return S_OK;
 };
 
 #endif