Commits

Anonymous committed 4bddb02

Split enum.h into pieces.

enum.h contained several, unrelated pieces of code.
This change splits them into separate files making
it easier to extend in future.

Comments (0)

Files changed (7)

include/comet/enum.h

 /** \file 
-  * Implement _NewEnum style classes and iterators.
+  * Legacy header for enum-related implementations and iterators.
+  *
+  * This exists for backward compatibility only.  Include specific headers
+  * instead.
   */
 /*
  * Copyright Š 2000 Sofus Mortensen
 #ifndef COMET_ENUM_H
 #define COMET_ENUM_H
 
-#include <comet/config.h>
+#include <comet/enum_common.h>
+#include <comet/stl_enum.h>
+#include <comet/variant_iterator.h>
 
-#include <comet/variant.h>
-#include <comet/server.h>
-#include <comet/util.h>
-
-#include <comet/stl.h>
-
-namespace comet {
-
-	namespace impl {
-		template<typename T> struct type_policy;
-
-		template<> struct type_policy<VARIANT>
-		{
-			template<typename S>
-			static void init(VARIANT& t, const S& s) 
-			{ ::VariantInit(&t); t = variant_t::detach( variant_t(s) ); }
-
-			static void clear(VARIANT& t) { ::VariantClear(&t); }	
-		};
-
-		template<> struct type_policy<CONNECTDATA>
-		{
-			template<typename S>
-			static void init(CONNECTDATA& t, const S& s) {
-				t.dwCookie = s.first;
-				t.pUnk = com_ptr<IUnknown>::detach( com_ptr<IUnknown>(s.second) );
-			}
-
-			static void clear(CONNECTDATA& t) { t.pUnk->Release(); }
-		};
-	}
-
-	/** \class stl_enumeration_t  enum.h comet/enum.h
-	  * Implements _NewEnum style COM object.
-	  * \param Itf Enumeration Interface.
-	  * \param C STL Style container. 
-	  * \param T Iteration Element type (VARIANT)
-	  * \param CONVERTER Converts container element to \p T type. (std::identity<C::value_type>)
-	  * \sa stl_enumeration create_enum
-	  */
-    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 > {
-		typedef impl::type_policy<T> policy;
-	public:
-		/// \name Interface \p Itf
-		//@{
-		STDMETHOD(Next)(ULONG celt, T *rgelt, ULONG* pceltFetched)
-		{
-			UINT i = 0;
-			typename C::const_iterator backup_it_ = it_;
-			try {
-				for (;i<celt && it_ != container_.end(); ++i, ++it_) {
-					policy::init(rgelt[i], converter_(*it_));
-				}
-				if (pceltFetched) *pceltFetched = i;
-			}
-			catch (...) {
-				it_ = backup_it_;
-				for (size_t j=0; j<=i; ++j) policy::clear(rgelt[j]);
-				return E_FAIL;
-			}
-			return i == celt ? S_OK : S_FALSE;
-		}
-		
-		STDMETHOD(Reset)()
-		{
-			try {
-				it_ = container_.begin();
-			}
-			catch (...) {
-				return E_FAIL;
-			}
-			return S_OK;
-		}
-		
-		STDMETHOD(Skip)(ULONG celt)
-		{
-			try {
-				while (celt--) it_++;
-			} catch (...) {
-				return E_FAIL;
-			}
-			return S_OK;
-		}
-		
-		STDMETHOD(Clone)(Itf** ppenum)
-		{
-			try {
-				stl_enumeration_t* new_enum = new stl_enumeration_t(container_, pOuter_.in(), converter_);
-				new_enum->AddRef();
-				*ppenum = new_enum;
-			} catch (...) {
-				return E_FAIL;
-			}
-			return S_OK;
-		}
-		//@}
-		
-		stl_enumeration_t(const C& c, TH* pOuter = 0, const CONVERTER &converter = CONVERTER() )
-			: container_(c), pOuter_(pOuter) , converter_(converter)
-		{
-			it_ = container_.begin();
-		}
-		
-		~stl_enumeration_t() 
-		{
-		}
-		
-		const C& container_;
-		typename C::const_iterator it_;
-		com_ptr<TH> pOuter_;
-		CONVERTER converter_;
-
-	private:
-		stl_enumeration_t(const stl_enumeration_t&);
-		stl_enumeration_t& operator=(const stl_enumeration_t&);
-	};
-	
-	/** \struct enumerated_type_of enum.h comet/enum.h
-	  * Traits wrapper mapping COM Enumeration interface to element.
-	  */
-	template<typename EnumItf> struct enumerated_type_of;
-	template<> struct enumerated_type_of<IEnumVARIANT> { typedef VARIANT is; };
-	template<> struct enumerated_type_of<IEnumConnectionPoints> { typedef IConnectionPoint* is; };
-	template<> struct enumerated_type_of<IEnumConnections> { typedef CONNECTDATA is; };
-	
-	/** \struct stl_enumeration  enum.h comet/enum.h
-	  * STL Enumeration creation helper.
-	  * \param ET Enumeration Type (COM Interface).
-	  */
-	template<typename ET> struct stl_enumeration {
-
-		/** Auto-Create a _NewEnum enumerator from an STL container.
-		  * No contained object.
-		  * \param container STL Container.
-		  */
-		template<typename C>
-		static com_ptr<ET> create(const C& container)
-		{
-			typedef typename enumerated_type_of<ET>::is T;
-			typedef std::identity<COMET_STRICT_TYPENAME C::value_type> CONVERTER;
-			return new stl_enumeration_t<ET, C, T, CONVERTER,::IUnknown>(container, 0);
-		}
-
-		/** Auto-Create a _NewEnum enumerator from an STL container.
-		  * \param container STL Container.
-		  * \param th Outer or \e this pointer.
-		  */
-		template<typename C, typename TH>
-		static com_ptr<ET> create(const C& container, TH* th )
-		{
-			typedef typename enumerated_type_of<ET>::is T;
-			typedef std::identity<COMET_STRICT_TYPENAME C::value_type> CONVERTER;
-			return new stl_enumeration_t<ET, C, T, CONVERTER,TH>(container, th);
-		}
-
-		/** Auto-Create a _NewEnum enumerator from an STL container, specifying
-		  * a converter.
-		  * \param container STL Container.
-		  * \param th Outer or \e this pointer.
-		  * \param converter Converter type (convert Container element to
-		  * iterator interface element types).
-		  */
-		template<typename C, typename TH, typename CONVERTER>
-		static com_ptr<ET> create(const C& container, TH* th, const CONVERTER &converter)
-		{
-			typedef typename enumerated_type_of<ET>::is T;
-			return new stl_enumeration_t<ET, C, T, CONVERTER, TH>(container, th, converter);
-		}
-	};
-	
-	/*! Creates IEnumVARIANT enumeration of a STL container.
-	 * \param container STL Container.
-	 * \param th Outer or \e this pointer.
-		\code
-			com_ptr<IEnumVARIANT> get__NewEnum() {
-				return create_enum( collection_, this );
-			}
-		\endcode
-	  * \relates stl_enumeration
-	*/
-	template<typename C, typename TH> com_ptr<IEnumVARIANT> create_enum(const C& container, TH* th = 0)
-	{
-		return stl_enumeration<IEnumVARIANT>::create(container, th); 
-	}
-	
-	//! Creates IEnumVARIANT enumeration of a STL container with a converter.
-	/*! \param container STL Container.
-	  * \param th Outer or \e this pointer.
-	  * \param converter Converter type (convert Container element to VARIANT)
-	  * \sa ptr_converter ptr_converter_select1st ptr_converter_select2nd
-	  * \relates stl_enumeration
-	  */
-	template<typename C, typename TH, typename CONVERTER> com_ptr<IEnumVARIANT> create_enum(const C& container, TH* th, CONVERTER converter )
-	{
-		return stl_enumeration<IEnumVARIANT>::create(container, th, converter); 
-	}
-	
-	/** \struct ptr_converter  enum.h comet/enum.h
-	  * IUnknown Converter for containers containing Comet objects.
-	  * \relates stl_enumeration
-	  */
-	template<typename T> struct ptr_converter : std::unary_function< com_ptr<IUnknown>, T>
-	{
-		com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x); }
-	};
-	
-	/** \struct ptr_converter_select1st  enum.h comet/enum.h
-	  * IUnknown Converter for containers containing Comet objects as the first
-	  * elment of a pair.
-	  * \relates stl_enumeration
-	  */
-	template<typename T> struct ptr_converter_select1st : std::unary_function< com_ptr<IUnknown>, T>
-	{
-		com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x.first); }
-	};
-	
-	/** \struct ptr_converter_select2nd  enum.h comet/enum.h
-	  * IUnknown Converter for containers containing Comet objects as the second
-	  * elment of a pair.
-	  * \relates stl_enumeration
-	  */
-	template<typename T> struct ptr_converter_select2nd : std::unary_function< com_ptr<IUnknown>, T>
-	{
-		com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x.second); }
-	};
-	
-	/** \class variant_iterator enum.h comet/enum.h
-	  * STL style iterator for IEnumVariant interface.
-	  */
-	class variant_iterator
-	{
-		com_ptr<IEnumVARIANT> enum_;
-		variant_t ce_;
-	public:
-		/** Constructor.
-		  */
-		variant_iterator( const com_ptr<IEnumVARIANT>& e ) : enum_(e) {
-			next();
-		}
-		
-		variant_iterator() {}
-		
-		/** Move to next element.
-		  */
-		variant_iterator& operator++() {
-			next();
-			return *this;
-		}
-		
-		bool operator!=(const variant_iterator& v) {
-			if (!v.enum_.is_null()) throw std::logic_error("variant_iterator comparison does not work");
-			
-			return !enum_.is_null();
-		}
-		
-		/** Move to next element (post increment).
-		  */
-		variant_iterator operator++(int) {
-			variant_iterator t(*this);
-			operator++();
-			return t;
-		}
-		
-		/** Current element.
-		  */
-		variant_t& operator*() {
-			return ce_;
-		}
-	private:
-		void next() {
-			if (enum_) {
-				unsigned long x = 0;
-				enum_->Next(1, ce_.out(), &x) | raise_exception;
-				if (x == 0) enum_ = 0;
-			}
-		}
-	};
-	
-	/** \class itf_iterator enum.h comet/enum.h
-	  * STL style Iterator for IEnumVARIANT interface returning a contained
-	  * interface pointer.
-	  */
-	template<typename Itf> class itf_iterator
-	{
-		com_ptr<IEnumVARIANT> enum_;
-		com_ptr<Itf> p_;
-	public:
-		/** Constructor.
-		  */
-		itf_iterator( const com_ptr<IEnumVARIANT>& e ) : enum_(e) {
-			next();
-		}
-		
-		itf_iterator() {}
-		
-		/** Move to next element.
-		  */
-		itf_iterator& operator++() {
-			next();
-			return *this;
-		}
-		
-		bool operator!=(const itf_iterator& v) {
-			if (v.enum_) throw std::logic_error("itf_iterator comparison does not work");
-			
-			return enum_ != 0;
-		}
-		
-		/** Move to next element.
-		  */
-		itf_iterator operator++(int) {
-			itf_iterator t(*this);
-			operator++();
-			return t;
-		}
-		
-		/** Acess element.
-		  */
-		com_ptr<Itf>& operator*() {
-			return p_;
-		}
-	private:
-		void next() {
-			if (enum_) {
-				unsigned long x = 0;
-				variant_t v;
-				enum_->Next(1, v.out(), &x) | raise_exception;
-				if (x == 0) {
-					enum_ = 0;
-					p_ = 0;
-				}
-				else {
-					p_ = try_cast(v);
-				}
-			}
-		}
-	};
-	
-}	
-	
 #endif

include/comet/enum_common.h

+/** \file 
+  * Code common to enumerator implementations.
+  */
+/*
+ * Copyright Š 2000 Sofus Mortensen
+ *
+ * This material is provided "as is", with absolutely no warranty 
+ * expressed or implied. Any use is at your own risk. Permission to 
+ * use or copy this software for any purpose is hereby granted without 
+ * fee, provided the above notices are retained on all copies. 
+ * Permission to modify the code and to distribute modified code is 
+ * granted, provided the above notices are retained, and a notice that 
+ * the code was modified is included with the above copyright notice. 
+ *
+ * This header is part of comet.
+ * http://www.lambdasoft.dk/comet
+ */
+
+#ifndef COMET_ENUM_IMPL_H
+#define COMET_ENUM_IMPL_H
+
+#include <comet/config.h>
+
+#include <comet/variant.h>
+#include <comet/stl.h>
+
+namespace comet {
+
+	namespace impl {
+
+		template<typename T> struct type_policy;
+
+		template<> struct type_policy<VARIANT>
+		{
+			template<typename S>
+			static void init(VARIANT& t, const S& s) 
+			{ ::VariantInit(&t); t = variant_t::detach( variant_t(s) ); }
+
+			static void clear(VARIANT& t) { ::VariantClear(&t); }	
+		};
+
+		template<> struct type_policy<CONNECTDATA>
+		{
+			template<typename S>
+			static void init(CONNECTDATA& t, const S& s)
+			{
+				t.dwCookie = s.first;
+				t.pUnk =
+					com_ptr<IUnknown>::detach(com_ptr<IUnknown>(s.second));
+			}
+
+			static void clear(CONNECTDATA& t) { t.pUnk->Release(); }
+		};
+	}
+	
+	/** \struct enumerated_type_of enum.h comet/enum.h
+	  * Traits wrapper mapping COM Enumeration interface to element.
+	  */
+	template<typename EnumItf> struct enumerated_type_of;
+
+	template<> struct enumerated_type_of<IEnumVARIANT>
+	{ typedef VARIANT is; };
+
+	template<> struct enumerated_type_of<IEnumConnectionPoints>
+	{ typedef IConnectionPoint* is; };
+
+	template<> struct enumerated_type_of<IEnumConnections>
+	{ typedef CONNECTDATA is; };
+	
+	/** \struct ptr_converter  enum.h comet/enum.h
+	  * IUnknown Converter for containers containing Comet objects.
+	  * \relates stl_enumeration
+	  */
+	template<typename T> struct ptr_converter : std::unary_function< com_ptr<IUnknown>, T>
+	{
+		com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x); }
+	};
+	
+	/** \struct ptr_converter_select1st  enum.h comet/enum.h
+	  * IUnknown Converter for containers containing Comet objects as the first
+	  * elment of a pair.
+	  * \relates stl_enumeration
+	  */
+	template<typename T> struct ptr_converter_select1st : std::unary_function< com_ptr<IUnknown>, T>
+	{
+		com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x.first); }
+	};
+	
+	/** \struct ptr_converter_select2nd  enum.h comet/enum.h
+	  * IUnknown Converter for containers containing Comet objects as the second
+	  * elment of a pair.
+	  * \relates stl_enumeration
+	  */
+	template<typename T> struct ptr_converter_select2nd : std::unary_function< com_ptr<IUnknown>, T>
+	{
+		com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x.second); }
+	};
+}	
+	
+#endif

include/comet/stl_enum.h

+/** \file 
+  * Implement _NewEnum style classes and iterators.
+  */
+/*
+ * Copyright Š 2000 Sofus Mortensen
+ *
+ * This material is provided "as is", with absolutely no warranty 
+ * expressed or implied. Any use is at your own risk. Permission to 
+ * use or copy this software for any purpose is hereby granted without 
+ * fee, provided the above notices are retained on all copies. 
+ * Permission to modify the code and to distribute modified code is 
+ * granted, provided the above notices are retained, and a notice that 
+ * the code was modified is included with the above copyright notice. 
+ *
+ * This header is part of comet.
+ * http://www.lambdasoft.dk/comet
+ */
+
+#ifndef COMET_STL_ENUM_H
+#define COMET_STL_ENUM_H
+
+#include <comet/config.h>
+
+#include <comet/enum_common.h>
+#include <comet/server.h>
+#include <comet/stl.h>
+#include <comet/variant.h>
+
+namespace comet {
+
+	/** \class stl_enumeration_t  enum.h comet/enum.h
+	  * Implements _NewEnum style COM object.
+	  * \param Itf Enumeration Interface.
+	  * \param C STL Style container. 
+	  * \param T Iteration Element type (VARIANT)
+	  * \param CONVERTER Converts container element to \p T type. (std::identity<C::value_type>)
+	  * \sa stl_enumeration create_enum
+	  */
+    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>
+	{
+		typedef impl::type_policy<T> policy;
+	public:
+		/// \name Interface \p Itf
+		//@{
+		STDMETHOD(Next)(ULONG celt, T *rgelt, ULONG* pceltFetched)
+		{
+			if (pceltFetched)
+				*pceltFetched = 0;
+			if (!rgelt)
+				return E_POINTER;
+
+			UINT i = 0;
+			typename C::const_iterator backup_it_ = it_;
+			try {
+				for (;i<celt && it_ != container_.end(); ++i, ++it_) {
+					policy::init(rgelt[i], converter_(*it_));
+				}
+				if (pceltFetched) *pceltFetched = i;
+			}
+			catch (...) {
+				it_ = backup_it_;
+				for (size_t j=0; j<=i; ++j) policy::clear(rgelt[j]);
+				return E_FAIL;
+			}
+			return i == celt ? S_OK : S_FALSE;
+		}
+		
+		STDMETHOD(Reset)()
+		{
+			try {
+				it_ = container_.begin();
+			}
+			catch (...) {
+				return E_FAIL;
+			}
+			return S_OK;
+		}
+		
+		STDMETHOD(Skip)(ULONG celt)
+		{
+			try {
+				while (celt--) it_++;
+			} catch (...) {
+				return E_FAIL;
+			}
+			return S_OK;
+		}
+		
+		STDMETHOD(Clone)(Itf** ppenum)
+		{
+			try {
+				stl_enumeration_t* new_enum =
+					new stl_enumeration_t(container_, pOuter_.in(), converter_);
+				new_enum->AddRef();
+				*ppenum = new_enum;
+			} catch (...) {
+				return E_FAIL;
+			}
+			return S_OK;
+		}
+		//@}
+		
+		stl_enumeration_t(
+			const C& c, TH* pOuter = 0, const CONVERTER& converter=CONVERTER())
+			: container_(c), pOuter_(pOuter), converter_(converter)
+		{
+			it_ = container_.begin();
+		}
+		
+		~stl_enumeration_t() 
+		{
+		}
+		
+		const C& container_;
+		typename C::const_iterator it_;
+		com_ptr<TH> pOuter_;
+		CONVERTER converter_;
+
+	private:
+		stl_enumeration_t(const stl_enumeration_t&);
+		stl_enumeration_t& operator=(const stl_enumeration_t&);
+	};
+	
+	/**
+	 * STL Enumeration creation helper.
+	 *
+	 * Creates the enumeration with the element type specified by the
+	 * enumerated_type_of policy.  To specify the element type directly, use
+	 * stl_enumeration_t.
+	 *
+	 * \param ET Enumeration Type e.g. IEnumUnknown.
+	 */
+	template<typename ET>
+	struct stl_enumeration
+	{
+
+		/** Auto-Create a _NewEnum enumerator from an STL container.
+		  * No contained object.
+		  * \param container STL Container.
+		  */
+		template<typename C>
+		static com_ptr<ET> create(const C& container)
+		{
+			typedef typename enumerated_type_of<ET>::is T;
+			typedef std::identity<COMET_STRICT_TYPENAME C::value_type>
+				CONVERTER;
+			return new stl_enumeration_t<ET, C, T, CONVERTER, IUnknown>(
+				container, 0);
+		}
+
+		/** Auto-Create a _NewEnum enumerator from an STL container.
+		  * \param container STL Container.
+		  * \param th Outer or \e this pointer.
+		  */
+		template<typename C, typename TH>
+		static com_ptr<ET> create(const C& container, TH* th)
+		{
+			typedef typename enumerated_type_of<ET>::is T;
+			typedef std::identity<COMET_STRICT_TYPENAME C::value_type>
+				CONVERTER;
+			return new stl_enumeration_t<ET, C, T, CONVERTER, TH>(
+				container, th);
+		}
+
+		/** Auto-Create a _NewEnum enumerator from an STL container, specifying
+		  * a converter.
+		  * \param container STL Container.
+		  * \param th Outer or \e this pointer.
+		  * \param converter Converter type (convert Container element to
+		  * iterator interface element types).
+		  */
+		template<typename C, typename TH, typename CONVERTER>
+		static com_ptr<ET> create(
+			const C& container, TH* th, const CONVERTER& converter)
+		{
+			typedef typename enumerated_type_of<ET>::is T;
+			return new stl_enumeration_t<ET, C, T, CONVERTER, TH>(
+				container, th, converter);
+		}
+	};
+	
+	/*! Creates IEnumVARIANT enumeration of a STL container.
+	 * \param container STL Container.
+	 * \param th Outer or \e this pointer.
+		\code
+			com_ptr<IEnumVARIANT> get__NewEnum() {
+				return create_enum( collection_, this );
+			}
+		\endcode
+	  * \relates stl_enumeration
+	*/
+	template<typename C, typename TH>
+	com_ptr<IEnumVARIANT> create_enum(const C& container, TH* th = 0)
+	{
+		return stl_enumeration<IEnumVARIANT>::create(container, th); 
+	}
+	
+	//! Creates IEnumVARIANT enumeration of a STL container with a converter.
+	/*! \param container STL Container.
+	  * \param th Outer or \e this pointer.
+	  * \param converter Converter type (convert Container element to VARIANT)
+	  * \sa ptr_converter ptr_converter_select1st ptr_converter_select2nd
+	  * \relates stl_enumeration
+	  */
+	template<typename C, typename TH, typename CONVERTER>
+	com_ptr<IEnumVARIANT> create_enum(const C& container, TH* th, CONVERTER converter)
+	{
+		return stl_enumeration<IEnumVARIANT>::create(container, th, converter); 
+	}
+
+}	
+	
+#endif

include/comet/variant_iterator.h

+/** \file 
+  * Standard C++ iterators wrapping IEnumVARIANT objects.
+  */
+/*
+ * Copyright Š 2000 Sofus Mortensen
+ *
+ * This material is provided "as is", with absolutely no warranty 
+ * expressed or implied. Any use is at your own risk. Permission to 
+ * use or copy this software for any purpose is hereby granted without 
+ * fee, provided the above notices are retained on all copies. 
+ * Permission to modify the code and to distribute modified code is 
+ * granted, provided the above notices are retained, and a notice that 
+ * the code was modified is included with the above copyright notice. 
+ *
+ * This header is part of comet.
+ * http://www.lambdasoft.dk/comet
+ */
+
+#ifndef COMET_VARIANT_ITERATOR_H
+#define COMET_VARIANT_ITERATOR_H
+
+#include <comet/config.h>
+
+#include <comet/ptr.h>
+#include <comet/variant.h>
+
+#include <stdexcept>
+
+namespace comet {
+
+	/** \class variant_iterator enum.h comet/enum.h
+	  * STL style iterator for IEnumVariant interface.
+	  */
+	class variant_iterator
+	{
+		com_ptr<IEnumVARIANT> enum_;
+		variant_t ce_;
+	public:
+		/** Constructor.
+		  */
+		variant_iterator( const com_ptr<IEnumVARIANT>& e ) : enum_(e) {
+			next();
+		}
+		
+		variant_iterator() {}
+		
+		/** Move to next element.
+		  */
+		variant_iterator& operator++() {
+			next();
+			return *this;
+		}
+		
+		bool operator!=(const variant_iterator& v) {
+			if (!v.enum_.is_null())
+				throw std::logic_error(
+					"variant_iterator comparison does not work");
+			
+			return !enum_.is_null();
+		}
+		
+		/** Move to next element (post increment).
+		  */
+		variant_iterator operator++(int) {
+			variant_iterator t(*this);
+			operator++();
+			return t;
+		}
+		
+		/** Current element.
+		  */
+		variant_t& operator*() {
+			return ce_;
+		}
+	private:
+		void next() {
+			if (enum_) {
+				unsigned long x = 0;
+				enum_->Next(1, ce_.out(), &x) | raise_exception;
+				if (x == 0) enum_ = 0;
+			}
+		}
+	};
+	
+	/** \class itf_iterator enum.h comet/enum.h
+	  * STL style Iterator for IEnumVARIANT interface returning a contained
+	  * interface pointer.
+	  */
+	template<typename Itf> class itf_iterator
+	{
+		com_ptr<IEnumVARIANT> enum_;
+		com_ptr<Itf> p_;
+	public:
+		/** Constructor.
+		  */
+		itf_iterator( const com_ptr<IEnumVARIANT>& e ) : enum_(e) {
+			next();
+		}
+		
+		itf_iterator() {}
+		
+		/** Move to next element.
+		  */
+		itf_iterator& operator++() {
+			next();
+			return *this;
+		}
+		
+		bool operator!=(const itf_iterator& v) {
+			if (v.enum_)
+				throw std::logic_error(
+					"itf_iterator comparison does not work");
+			
+			return enum_ != 0;
+		}
+		
+		/** Move to next element.
+		  */
+		itf_iterator operator++(int) {
+			itf_iterator t(*this);
+			operator++();
+			return t;
+		}
+		
+		/** Access element.
+		  */
+		com_ptr<Itf>& operator*() {
+			return p_;
+		}
+	private:
+		void next() {
+			if (enum_) {
+				unsigned long x = 0;
+				variant_t v;
+				enum_->Next(1, v.out(), &x) | raise_exception;
+				if (x == 0) {
+					enum_ = 0;
+					p_ = 0;
+				}
+				else {
+					p_ = try_cast(v);
+				}
+			}
+		}
+	};
+	
+}	
+	
+#endif

src/test/Test.vcproj

 				>
 			</File>
 			<File
+				RelativePath=".\test17.cpp"
+				>
+			</File>
+			<File
 				RelativePath="test2.cpp"
 				>
 			</File>

src/test/test1.cpp

 #define COMET_ASSERT_THROWS_ALWAYS
 
 #include <comet/comet.h>
+#include <comet/enum.h>
 #include <comet/server.h>
 #include <comet/datetime.h>
 #include <comet/safearray.h>
 	}
 };
 
+template<> struct comet::comtype<IEnumUnknown>
+{
+	static const IID& uuid() throw() { return IID_IEnumUnknown; }
+	typedef IUnknown base;
+};
+
+template<> struct comet::impl::type_policy<IUnknown*>
+{
+	template<typename S>
+	static void init(IUnknown*& p, const S& s) 
+	{  p = s.get(); p->AddRef(); }
+
+	static void clear(IUnknown*& p) { p->Release(); }	
+};
+
+void empty_enum_test(com_ptr<IEnumUnknown> e)
+{
+	IUnknown* punk;
+	ULONG count = 12;
+	HRESULT hr = e->Next(1, &punk, &count);
+	if (hr != S_FALSE)
+		throw runtime_error("HRESULT is not S_FALSE");
+	if (count != 0)
+		throw runtime_error("Incorrect return count");
+}
+
+/**
+ * Empty stl_enumeration_t.
+ */
+template<>
+struct comet::test<37>
+{
+	void run()
+	{
+		typedef std::vector< com_ptr<IUnknown> > collection_type;
+		collection_type coll;
+		com_ptr<IEnumUnknown> e = new stl_enumeration_t<
+			IEnumUnknown, collection_type, IUnknown*>(coll);
+		empty_enum_test(e);
+	}
+};
+
+class test_obj : public simple_object<nil> {};
+
+vector< com_ptr<IUnknown> > test_collection()
+{
+	vector< com_ptr<IUnknown> > collection;
+	collection.push_back(new test_obj());
+	collection.push_back(new test_obj());
+	collection.push_back(new test_obj());
+	return collection;
+}
+
+void enum_test(com_ptr<IEnumUnknown> e)
+{
+	IUnknown* punks[3];
+
+	// Test validity
+	for (int i = 0; i < 3; ++i)
+	{
+		IUnknown* punk;
+		ULONG count = 12;
+		HRESULT hr = e->Next(1, &punk, &count);
+		if (hr != S_OK)
+			throw runtime_error("HRESULT is not S_OK");
+
+		if (count != 1)
+			throw runtime_error("Incorrect return count");
+
+		if (punk == NULL)
+			throw runtime_error("NULL returned instead of object");
+		punk->AddRef();
+		punk->Release();
+
+		punks[i] = punk; // store for uniqueness test later
+	}
+
+	empty_enum_test(e);
+
+	// Test uniqueness
+	if (punks[0] == punks[1])
+	   throw runtime_error("Same object returned twice");
+	if (punks[0] == punks[2])
+	   throw runtime_error("Same object returned twice");
+	if (punks[2] == punks[1])
+	   throw runtime_error("Same object returned twice");
+}
+
+void enum_chunk_test(com_ptr<IEnumUnknown> e)
+{
+	IUnknown* punk[4];
+	ULONG count = 12;
+	HRESULT hr = e->Next(4, punk, &count); // request more than expected
+	if (hr != S_FALSE)
+		throw runtime_error("HRESULT is not S_FALSE");
+
+	if (count != 3)
+		throw runtime_error("Incorrect return count");
+
+	// Test validity
+	for (int i = 0; i < 3; ++i)
+	{
+		if (punk[i] == NULL)
+			throw runtime_error("NULL returned instead of object");
+		punk[i]->AddRef();
+		punk[i]->Release();
+	}
+
+	empty_enum_test(e);
+
+	// Test uniqueness
+	if (punk[0] == punk[1])
+	   throw runtime_error("Same object returned twice");
+	if (punk[0] == punk[2])
+	   throw runtime_error("Same object returned twice");
+	if (punk[2] == punk[1])
+	   throw runtime_error("Same object returned twice");
+}
+
+/**
+ * Populated stl_enumeration_t.
+ */
+template<>
+struct comet::test<38>
+{
+	void run()
+	{
+		typedef std::vector< com_ptr<IUnknown> > collection_type;
+		collection_type coll = test_collection();
+		com_ptr<IEnumUnknown> e = new stl_enumeration_t<
+			IEnumUnknown, collection_type, IUnknown*>(coll);
+		enum_test(e);
+		e->Reset();
+		enum_chunk_test(e);
+	}
+};
+
 COMET_TEST_MAIN

src/test/test17.cpp

+#include <comet/enum.h>
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.