GME
13
|
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