Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages
enum.h
Go to the documentation of this file.00001 00004 /* 00005 * Copyright © 2000 Sofus Mortensen 00006 * 00007 * This material is provided "as is", with absolutely no warranty 00008 * expressed or implied. Any use is at your own risk. Permission to 00009 * use or copy this software for any purpose is hereby granted without 00010 * fee, provided the above notices are retained on all copies. 00011 * Permission to modify the code and to distribute modified code is 00012 * granted, provided the above notices are retained, and a notice that 00013 * the code was modified is included with the above copyright notice. 00014 * 00015 * This header is part of comet. 00016 * http://www.lambdasoft.dk/comet 00017 */ 00018 00019 #ifndef COMET_ENUM_H 00020 #define COMET_ENUM_H 00021 00022 #include <comet/config.h> 00023 00024 #include <comet/variant.h> 00025 #include <comet/server.h> 00026 #include <comet/util.h> 00027 00028 #include <comet/stl.h> 00029 00030 namespace comet { 00031 00032 namespace impl { 00033 template<typename T> struct type_policy; 00034 00035 template<> struct type_policy<VARIANT> 00036 { 00037 template<typename S> 00038 static void init(VARIANT& t, const S& s) 00039 { ::VariantInit(&t); t = variant_t::detach( variant_t(s) ); } 00040 00041 static void clear(VARIANT& t) { ::VariantClear(&t); } 00042 }; 00043 00044 template<> struct type_policy<CONNECTDATA> 00045 { 00046 template<typename S> 00047 static void init(CONNECTDATA& t, const S& s) { 00048 t.dwCookie = s.first; 00049 t.pUnk = com_ptr<IUnknown>::detach( com_ptr<IUnknown>(s.second) ); 00050 } 00051 00052 static void clear(CONNECTDATA& t) { t.pUnk->Release(); } 00053 }; 00054 } 00055 00064 template<typename Itf, typename C, typename T = VARIANT, typename CONVERTER = std::identity<COMET_STRICT_TYPENAME C::value_type>, typename TH = ::IUnknown> class stl_enumeration_t : public simple_object< Itf > { 00065 typedef impl::type_policy<T> policy; 00066 public: 00068 00069 STDMETHOD(Next)(ULONG celt, T *rgelt, ULONG* pceltFetched) 00070 { 00071 UINT i = 0; 00072 typename C::const_iterator backup_it_ = it_; 00073 try { 00074 for (;i<celt && it_ != container_.end(); ++i, ++it_) { 00075 policy::init(rgelt[i], converter_(*it_)); 00076 } 00077 if (pceltFetched) *pceltFetched = i; 00078 } 00079 catch (...) { 00080 it_ = backup_it_; 00081 for (size_t j=0; j<=i; ++j) policy::clear(rgelt[j]); 00082 return E_FAIL; 00083 } 00084 return i == celt ? S_OK : S_FALSE; 00085 } 00086 00087 STDMETHOD(Reset)() 00088 { 00089 try { 00090 it_ = container_.begin(); 00091 } 00092 catch (...) { 00093 return E_FAIL; 00094 } 00095 return S_OK; 00096 } 00097 00098 STDMETHOD(Skip)(ULONG celt) 00099 { 00100 try { 00101 while (celt--) it_++; 00102 } catch (...) { 00103 return E_FAIL; 00104 } 00105 return S_OK; 00106 } 00107 00108 STDMETHOD(Clone)(Itf** ppenum) 00109 { 00110 try { 00111 stl_enumeration_t* new_enum = new stl_enumeration_t(container_, pOuter_.in(), converter_); 00112 new_enum->AddRef(); 00113 *ppenum = new_enum; 00114 } catch (...) { 00115 return E_FAIL; 00116 } 00117 return S_OK; 00118 } 00120 00121 stl_enumeration_t(const C& c, TH* pOuter = 0, const CONVERTER &converter = CONVERTER() ) 00122 : container_(c), pOuter_(pOuter) , converter_(converter) 00123 { 00124 it_ = container_.begin(); 00125 } 00126 00127 ~stl_enumeration_t() 00128 { 00129 } 00130 00131 const C& container_; 00132 typename C::const_iterator it_; 00133 com_ptr<TH> pOuter_; 00134 CONVERTER converter_; 00135 00136 private: 00137 stl_enumeration_t(const stl_enumeration_t&); 00138 stl_enumeration_t& operator=(const stl_enumeration_t&); 00139 }; 00140 00144 template<typename EnumItf> struct enumerated_type_of; 00145 template<> struct enumerated_type_of<IEnumVARIANT> { typedef VARIANT is; }; 00146 template<> struct enumerated_type_of<IEnumConnectionPoints> { typedef IConnectionPoint* is; }; 00147 template<> struct enumerated_type_of<IEnumConnections> { typedef CONNECTDATA is; }; 00148 00153 template<typename ET> struct stl_enumeration { 00154 00159 template<typename C> 00160 static com_ptr<ET> create(const C& container) 00161 { 00162 typedef typename enumerated_type_of<ET>::is T; 00163 typedef std::identity<COMET_STRICT_TYPENAME C::value_type> CONVERTER; 00164 return new stl_enumeration_t<ET, C, T, CONVERTER,::IUnknown>(container, 0); 00165 } 00166 00171 template<typename C, typename TH> 00172 static com_ptr<ET> create(const C& container, TH* th ) 00173 { 00174 typedef typename enumerated_type_of<ET>::is T; 00175 typedef std::identity<COMET_STRICT_TYPENAME C::value_type> CONVERTER; 00176 return new stl_enumeration_t<ET, C, T, CONVERTER,TH>(container, th); 00177 } 00178 00186 template<typename C, typename TH, typename CONVERTER> 00187 static com_ptr<ET> create(const C& container, TH* th, const CONVERTER &converter) 00188 { 00189 typedef typename enumerated_type_of<ET>::is T; 00190 return new stl_enumeration_t<ET, C, T, CONVERTER, TH>(container, th, converter); 00191 } 00192 }; 00193 00204 template<typename C, typename TH> com_ptr<IEnumVARIANT> create_enum(const C& container, TH* th = 0) 00205 { 00206 return stl_enumeration<IEnumVARIANT>::create(container, th); 00207 } 00208 00210 00216 template<typename C, typename TH, typename CONVERTER> com_ptr<IEnumVARIANT> create_enum(const C& container, TH* th, CONVERTER converter ) 00217 { 00218 return stl_enumeration<IEnumVARIANT>::create(container, th, converter); 00219 } 00220 00225 template<typename T> struct ptr_converter : std::unary_function< com_ptr<IUnknown>, T> 00226 { 00227 com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x); } 00228 }; 00229 00235 template<typename T> struct ptr_converter_select1st : std::unary_function< com_ptr<IUnknown>, T> 00236 { 00237 com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x.first); } 00238 }; 00239 00245 template<typename T> struct ptr_converter_select2nd : std::unary_function< com_ptr<IUnknown>, T> 00246 { 00247 com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x.second); } 00248 }; 00249 00253 class variant_iterator 00254 { 00255 com_ptr<IEnumVARIANT> enum_; 00256 variant_t ce_; 00257 public: 00260 variant_iterator( const com_ptr<IEnumVARIANT>& e ) : enum_(e) { 00261 next(); 00262 } 00263 00264 variant_iterator() {} 00265 00268 variant_iterator& operator++() { 00269 next(); 00270 return *this; 00271 } 00272 00273 bool operator!=(const variant_iterator& v) { 00274 if (!v.enum_.is_null()) throw std::logic_error("variant_iterator comparison does not work"); 00275 00276 return !enum_.is_null(); 00277 } 00278 00281 variant_iterator operator++(int) { 00282 variant_iterator t(*this); 00283 operator++(); 00284 return t; 00285 } 00286 00289 variant_t& operator*() { 00290 return ce_; 00291 } 00292 private: 00293 void next() { 00294 if (enum_) { 00295 unsigned long x = 0; 00296 enum_->Next(1, ce_.out(), &x) | raise_exception; 00297 if (x == 0) enum_ = 0; 00298 } 00299 } 00300 }; 00301 00306 template<typename Itf> class itf_iterator 00307 { 00308 com_ptr<IEnumVARIANT> enum_; 00309 com_ptr<Itf> p_; 00310 public: 00313 itf_iterator( const com_ptr<IEnumVARIANT>& e ) : enum_(e) { 00314 next(); 00315 } 00316 00317 itf_iterator() {} 00318 00321 itf_iterator& operator++() { 00322 next(); 00323 return *this; 00324 } 00325 00326 bool operator!=(const itf_iterator& v) { 00327 if (v.enum_) throw std::logic_error("itf_iterator comparison does not work"); 00328 00329 return enum_ != 0; 00330 } 00331 00334 itf_iterator operator++(int) { 00335 itf_iterator t(*this); 00336 operator++(); 00337 return t; 00338 } 00339 00342 com_ptr<Itf>& operator*() { 00343 return p_; 00344 } 00345 private: 00346 void next() { 00347 if (enum_) { 00348 unsigned long x = 0; 00349 variant_t v; 00350 enum_->Next(1, v.out(), &x) | raise_exception; 00351 if (x == 0) { 00352 enum_ = 0; 00353 p_ = 0; 00354 } 00355 else { 00356 p_ = try_cast(v); 00357 } 00358 } 00359 } 00360 }; 00361 00362 } 00363 00364 #endif