GME  13
CommonCollection.h
Go to the documentation of this file.
00001 
00002 #ifndef MGA_COMMONCOLLECTION_H
00003 #define MGA_COMMONCOLLECTION_H
00004 
00005 #include <vector>
00006 #include <list>//slist
00007 
00008 template<class ITFTYPE, class OBJTYPE>
00009 struct CopyItfFromObj
00010 {
00011         static HRESULT copy(ITFTYPE **p, OBJTYPE *const*q)
00012         {
00013                 ASSERT( p != NULL && q != NULL);
00014                 if( *p != NULL )
00015                         COMRETURN(E_POINTER);
00016 
00017                 if( *q == NULL )
00018                 {
00019                         *p = NULL; 
00020                         return S_OK;
00021                 }
00022 
00023                 return (*q)->QueryInterface(__uuidof(ITFTYPE), (void**)p);
00024         }
00025 
00026         static void init(ITFTYPE **p) 
00027         {
00028                 ASSERT( p != NULL );
00029 
00030                 *p = NULL;
00031         }
00032 
00033         static void destroy(ITFTYPE **p) 
00034         {
00035                 ASSERT( p != NULL );
00036 
00037                 if( *p )
00038                 {
00039                         (*p)->Release();
00040                         *p = NULL;
00041                 }
00042         }
00043 };
00044 
00045 template<class ITFTYPE>
00046 struct CopyItfFromItf
00047 {
00048         static HRESULT copy(ITFTYPE **p, ITFTYPE *const*q)
00049         {
00050                 ASSERT( p != NULL && q != NULL);
00051 
00052                 if( *p != NULL )
00053                         COMRETURN(E_POINTER);
00054 
00055                 *p = *q;
00056                 if(*p) 
00057                         (*p)->AddRef();
00058 
00059                 return S_OK;
00060         }
00061 
00062         static void init(ITFTYPE **p)
00063         {
00064                 ASSERT( p != NULL );
00065 
00066                 *p = NULL;
00067         }
00068 
00069         static void destroy(ITFTYPE **p)
00070         {
00071                 ASSERT( p != NULL );
00072 
00073                 if( *p )
00074                 {
00075                         (*p)->Release();
00076                         *p = NULL;
00077                 }
00078         }
00079 };
00080 
00081 template<class OBJTYPE>
00082 struct CopyDispVariantFromObj
00083 {
00084         static HRESULT copy(VARIANT *p, OBJTYPE *const*q)
00085         {
00086                 ASSERT( p != NULL && q != NULL);
00087 
00088                 if( p->vt != VT_EMPTY )
00089                         COMRETURN(E_POINTER);
00090 
00091                 if( *q == NULL )
00092                         return S_OK;            // leave as VT_EMPTY !!
00093 
00094                 HRESULT hr = (*q)->QueryInterface(IID_IDispatch, (void**)&p->pdispVal);
00095                 if( SUCCEEDED(hr) )
00096                         p->vt = VT_DISPATCH;
00097 
00098                 return hr;
00099         }
00100 
00101         static void init(VARIANT *p) { VariantInit(p); }
00102         static void destroy(VARIANT *p) { VariantClear(p); }
00103 };
00104 
00105 template<class ITFTYPE>
00106 struct CopyDispVariantFromItf
00107 {
00108         static HRESULT copy(VARIANT *p, ITFTYPE *const * q)
00109         {
00110                 ASSERT( p != NULL && q != NULL);
00111 
00112                 if( p->vt != VT_EMPTY )
00113                         COMRETURN(E_POINTER);
00114 
00115                 if(*q == NULL)
00116                         return S_OK;            // leave as VT_EMPTY !!
00117 
00118                 HRESULT hr = (*q)->QueryInterface(IID_IDispatch, (void**)&p->pdispVal);
00119                 if( SUCCEEDED(hr) )
00120                         p->vt = VT_DISPATCH;
00121 
00122                 return hr;
00123         }
00124 
00125         static void init(VARIANT *p) { VariantInit(p); }
00126         static void destroy(VARIANT *p) { VariantClear(p); }
00127 };
00128 
00129 template<class COLLTYPE, class OBJTYPE>
00130 class ATL_NO_VTABLE CComEnumDispVariantOnObjColl :
00131         public CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT,
00132         VARIANT, CopyDispVariantFromObj<OBJTYPE>,
00133         COLLTYPE>
00134 {
00135 };
00136 
00137 template<class COLLTYPE, class ITFTYPE>
00138 class ATL_NO_VTABLE CComEnumDispVariantOnItfColl :
00139         public CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT,
00140         VARIANT, CopyDispVariantFromItf<ITFTYPE>, COLLTYPE>
00141 {
00142 };
00143 
00144 
00145 template<class ITFTYPE> 
00146 void push_best(std::list<ITFTYPE*> &into, ITFTYPE *o) { into.push_front(o); }//slist
00147 template<class ITFTYPE> 
00148 void push_best(std::vector<ITFTYPE*> &into, ITFTYPE *o) { into.push_back(o); }
00149 
00150 template<class COLLITF, class COLLTYPE, class ITFTYPE, class OBJTYPE>
00151 class ATL_NO_VTABLE CCoreCollection;
00152 
00153 class __declspec(uuid("9FE3BB80-B596-41BA-910F-0FF9C3B4F38A")) CoreCollectionHandlerCLSID;
00154 
00155 template<class COLLITF, class COLLTYPE, class ITFTYPE, class OBJTYPE>
00156 class CCoreCollectionMarshalTearOff : 
00157         public CComTearOffObjectBase<CCoreCollection<COLLITF, COLLTYPE, ITFTYPE, OBJTYPE>>,
00158         IStdMarshalInfo
00159 {
00160 BEGIN_COM_MAP(CCoreCollectionMarshalTearOff)
00161         COM_INTERFACE_ENTRY(IStdMarshalInfo)
00162 END_COM_MAP()
00163 
00164     public:
00165         virtual HRESULT STDMETHODCALLTYPE GetClassForHandler( 
00166             __in  DWORD dwDestContext,
00167             __reserved  void *pvDestContext,
00168             __out  CLSID *pClsid)
00169         {
00170                 *pClsid = __uuidof(CoreCollectionHandlerCLSID);
00171                 return S_OK;
00172         }
00173 };
00174 
00175 
00176 template<class COLLITF, class COLLTYPE, class ITFTYPE, class OBJTYPE>
00177 class ATL_NO_VTABLE CCoreCollection :
00178         public CComObjectRootEx<CComSingleThreadModel>,
00179         public ICollectionOnSTLImpl<
00180         IDispatchImpl<COLLITF, &__uuidof(COLLITF)>,
00181         COLLTYPE, ITFTYPE*, CopyItfFromItf<ITFTYPE>,
00182         CComEnumDispVariantOnItfColl<COLLTYPE, ITFTYPE> >,
00183         public ISupportErrorInfoImpl<&__uuidof(COLLITF)>
00184 {
00185 public:
00186         typedef CCoreCollection<COLLITF, COLLTYPE, ITFTYPE, OBJTYPE> CLASS;
00187         typedef typename COLLTYPE::iterator ITERTYPE;
00188         typedef CopyItfFromObj<ITFTYPE, OBJTYPE> FILL_COPYTYPE;
00189         typedef CopyItfFromItf<ITFTYPE> GETALL_COPYTYPE;
00190         typedef typename CCoreCollectionMarshalTearOff<COLLITF, COLLTYPE, ITFTYPE, OBJTYPE> ColTearOff;
00191 
00192 BEGIN_COM_MAP(CLASS)
00193         COM_INTERFACE_ENTRY(COLLITF)
00194         COM_INTERFACE_ENTRY(IDispatch)
00195         COM_INTERFACE_ENTRY(ISupportErrorInfo)
00196         COM_INTERFACE_ENTRY_TEAR_OFF(IID_IStdMarshalInfo, ColTearOff)
00197 END_COM_MAP()
00198 
00199 public:
00200         ~CCoreCollection()
00201         {
00202                 ITERTYPE i = m_coll.begin();
00203                 ITERTYPE e = m_coll.end();
00204 
00205                 while( i != e) 
00206                         FILL_COPYTYPE::destroy(&*i++);
00207         }
00208 
00209         COLLTYPE &GetCollection() { return m_coll; }
00210 
00211         STDMETHODIMP GetAll(long count, ITFTYPE **p)
00212         {
00213                 ITERTYPE i = m_coll.begin();
00214                 ITERTYPE e = m_coll.end();
00215                 long copied = 0;
00216                 HRESULT hr = S_OK;
00217 
00218                 while( i != e && copied < count )
00219                 {
00220                         ASSERT( *(p+copied) == NULL );
00221                         hr = GETALL_COPYTYPE::copy(p+copied, &*i);
00222                         if( FAILED(hr) )
00223                                 break;
00224 
00225                         ++copied;
00226                         ++i;
00227                 }
00228 
00229                 if( FAILED(hr) || i != e || copied != count )
00230                 {
00231                         while( copied > 0 )
00232                         {
00233                                 GETALL_COPYTYPE::destroy(p+copied);
00234                                 --copied;
00235                         }
00236 
00237                         if( SUCCEEDED(hr) )
00238                                 hr = E_GETALL;
00239                 }
00240 
00241                 if( FAILED(hr) )
00242                         SetErrorInfo(hr);
00243 
00244                 return hr;
00245         }
00246 
00247         template<class ITERTYPE2>
00248         void Fill(ITERTYPE2 i, ITERTYPE2 e)
00249         {
00250                 while( i != e )
00251                 {
00252                         ITFTYPE *o = NULL;
00253                         COMTHROW( FILL_COPYTYPE::copy(&o, &*i) );
00254                         push_best<ITFTYPE>(m_coll, o);
00255                         ++i;
00256                 }
00257         }
00258 
00259         template<class COLLTYPE_>
00260         void Reserve(COLLTYPE_& col, size_t num_additional) { }
00261         template<>
00262         void Reserve(std::vector<ITFTYPE*>& col, size_t num_additional)
00263         {
00264                 col.reserve(col.size() + num_additional);
00265         }
00266 
00267         template<class COLLTYPE2>
00268         void FillAll(COLLTYPE2& col)
00269         {
00270                 Reserve(m_coll, col.size());
00271                 Fill(col.begin(), col.end());
00272         }
00273 
00274         template<class COLLTYPE2>
00275         void FillAllNoReserve(COLLTYPE2& col)
00276         {
00277                 Fill(col.begin(), col.end());
00278         }
00279 
00280         void Add(OBJTYPE *i)
00281         {
00282                 ASSERT( i != NULL );
00283 
00284                 ITFTYPE *o = NULL;
00285                 COMTHROW( FILL_COPYTYPE::copy(&o, &i) );
00286                 push_best<ITFTYPE>(m_coll, o);
00287         }
00288 
00289 //start and index are 1-based, index is 0 if not found
00290         STDMETHOD(Find)(ITFTYPE* pvar, long start, long *index) {
00291 
00292                 if(start == 0) start = m_coll.size();
00293                 else start--;
00294                 if((unsigned long)start > m_coll.size()) return E_FAIL;
00295                 if (pvar == NULL)
00296                         return E_POINTER;
00297                 CComPtr<ITFTYPE> pp = pvar;
00298                 COLLTYPE::iterator iter = m_coll.begin()+start;
00299                 while (iter != m_coll.end()) {
00300                         if(pvar == *iter) {
00301                                 *index = m_coll.begin() - iter + 1;
00302                                 return S_OK;
00303                         }
00304                         ++iter;
00305                 }
00306                 *index = 0;
00307                 return E_NOTFOUND;
00308         }
00309 
00310 //pos is 1-based  0 means 'to the end'
00311         STDMETHOD(Insert)(ITFTYPE* pvar, long pos) {
00312                 // this fuction must be supplied by the user for CollectionEx to compile
00313                 // extern HRESULT check_location_compatibility(ITFTYPE *newobj, ITFTYPE *oldobj);
00314                 if(pos == 0) pos = m_coll.size();
00315                 else pos--;
00316                 if((unsigned long)pos > m_coll.size()) return E_FAIL;
00317                 if (pvar == NULL)
00318                         return E_POINTER;
00319 
00320                 // HRESULT hr = E_FAIL;
00321                 HRESULT hr = check_location_compatibility(pvar, m_coll.size() ? m_coll.front() : NULL);
00322                 if(hr != S_OK) return hr;
00323 
00324                 COLLTYPE::iterator iter = m_coll.insert(m_coll.begin()+ pos, static_cast<ITFTYPE*>(NULL));
00325                 hr = GETALL_COPYTYPE::copy(&*iter, &pvar);
00326                 return hr;
00327         }
00328 
00329         STDMETHOD(Append)(ITFTYPE* pvar) {
00330                 return Insert(pvar,0);
00331         }
00332 
00333         STDMETHOD(Remove)(long pos) {
00334                 if(pos == 0) pos = m_coll.size();
00335                 else pos--;
00336                 if((unsigned long)pos > m_coll.size()) return E_FAIL;
00337                 GETALL_COPYTYPE::destroy(&(m_coll[0])+pos);
00338                 m_coll.erase(m_coll.begin()+pos);
00339                 return S_OK;
00340         }
00341 
00342 };
00343 
00344 
00345 template<class COLLITF, class COLLTYPE, class ITFTYPE, class OBJTYPE, const CLSID *CLSIDP, const int IDR>
00346 class ATL_NO_VTABLE CCoreCollectionEx : public CCoreCollection<COLLITF, COLLTYPE, ITFTYPE, OBJTYPE>,
00347         public CComCoClass<CCoreCollectionEx<COLLITF, COLLTYPE, ITFTYPE, OBJTYPE, CLSIDP, IDR>, CLSIDP> {
00348 public:
00349         typedef CCoreCollectionEx<COLLITF, COLLTYPE, ITFTYPE, OBJTYPE, CLSIDP, IDR> EXCLASS;
00350 
00351 DECLARE_REGISTRY_RESOURCEID(IDR)
00352 
00353 };
00354 
00355 template<class COLLITF, class ITFTYPE>
00356 void GetAll(COLLITF *coll, std::vector< CComObjPtr<ITFTYPE> > &ret)
00357 {
00358         ASSERT( coll != NULL );
00359         ASSERT( ret.empty() );
00360 
00361         long count = 0;
00362         COMTHROW( coll->get_Count(&count) );
00363         ASSERT( count >= 0 );
00364 
00365         ret.clear();
00366         ret.insert(ret.begin(), count, NULL);
00367 
00368         COMTHROW( coll->GetAll(count, (ITFTYPE**)&ret[0]) );
00369 }
00370 
00371 inline HRESULT check_location_compatibility(IUnknown *, IUnknown *) { return S_OK; }
00372 
00373 
00374 #endif//MGA_COMMONCOLLECTION_H