Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

220 lines
8.4 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000
  5. //
  6. // File: enumerator.h
  7. //
  8. // Contents: Supports enumeration for collections of com objects
  9. //
  10. // History: 14-Oct-99 VivekJ Created (as comerror.h)
  11. // 08-Mar-2000 AudriusZ separated some code into enumerator.h file
  12. //
  13. //--------------------------------------------------------------------------
  14. #ifndef ENUMERATOR_H_INCLUDED
  15. #define ENUMERATOR_H_INCLUDED
  16. #pragma once
  17. /***************************************************************************\
  18. *
  19. * CLASS: CMMCNewEnumImpl<BaseClass, _Position, EnumImplementor>
  20. *
  21. * PURPOSE: Implements enumeration for collection class
  22. * EnumImplementor class is responsible for implementing these methods:
  23. * SC ScEnumNext(_Position &pos, PDISPATCH & pDispatch);
  24. * SC ScEnumSkip(unsigned long celt, unsigned long& celtSkipped, _Position &pos);
  25. * SC ScEnumReset(_Position &pos);
  26. *
  27. \***************************************************************************/
  28. /****** usage tips *******************************************************
  29. * Generally you will provide just 2 params to template - this means
  30. * the tied object of your base class needs to implement following methods:
  31. * ScEnumNext, ScEnumSkip, ScEnumReset;
  32. *
  33. * If you pass same class as the first and the third template parameter, your base class is
  34. * required to implement mentioned methods (not the tied object).
  35. * It's usefull when you want to have collection and enueration in one class.
  36. *
  37. * You also may specify any other class implementing the methods as the 3rd parameter,
  38. * but then the BaseClass needs to implement method 'ScGetEnumImplementor' returning
  39. * the instance of that class
  40. *
  41. * NOTE1: since it's template class, the BaseClass is not required to define/implement
  42. * ScGetTiedObject, when it implements enum methods itself.
  43. * NOTE2: But it always IS REQUIRED to define CMyTiedObject type to compile.
  44. * (this template class needs it to be anything different than the BaseClass)
  45. * It is suggested to typedef it as void : "typedef void CMyTiedObject;"
  46. * NOTE3: Make sure CMyTiedObject type is public or protected
  47. ************************************************************************/
  48. template <class BaseClass, class _Position, class EnumImplementor = BaseClass::CMyTiedObject>
  49. class CMMCNewEnumImpl : public BaseClass
  50. {
  51. // Methods to get proper implementor for Enum methods
  52. // simple one when implemented by the base class
  53. SC ScGetEnumImplementor(BaseClass * &pObj) { pObj = this; return SC(S_OK); }
  54. // when implemented by the tied object (default) - also simple
  55. SC ScGetEnumImplementor(BaseClass::CMyTiedObject * &pObj) { return ScGetTiedObject(pObj); }
  56. public:
  57. STDMETHOD(get__NewEnum)(IUnknown** ppUnk);
  58. };
  59. /*+-------------------------------------------------------------------------*
  60. * class CMMCEnumerator
  61. *
  62. *
  63. * PURPOSE: General purpose enumerator class. Keyed to a position object,
  64. * which is templated.
  65. *
  66. * The following three methods need to be implemented by the tied object:
  67. *
  68. * SC ScEnumNext(_Position &pos, PDISPATCH & pDispatch); // should return the next element.
  69. * SC ScEnumSkip(unsigned long celt, unsigned long& celtSkipped,
  70. * _Position &pos);
  71. * SC ScEnumReset(_Position &pos);
  72. *
  73. * Cloning the enumerator is taken care of automatically.
  74. *
  75. * NOTE: The Position object must have a copy constructor and assignment
  76. * operator.
  77. *+-------------------------------------------------------------------------*/
  78. typedef IEnumVARIANT ** PPENUMVARIANT;
  79. typedef VARIANT * PVARIANT;
  80. template<class TiedObj, class _Position>
  81. class CMMCEnumerator :
  82. public IEnumVARIANT,
  83. public IMMCSupportErrorInfoImpl<&IID_IEnumVARIANT, &GUID_NULL>, // rich error handling
  84. public CComObjectRoot,
  85. public CTiedComObject<TiedObj>
  86. {
  87. typedef CMMCEnumerator<TiedObj, _Position> ThisClass;
  88. typedef TiedObj CMyTiedObject;
  89. friend TiedObj;
  90. public:
  91. BEGIN_COM_MAP(ThisClass)
  92. COM_INTERFACE_ENTRY(IEnumVARIANT)
  93. END_COM_MAP()
  94. DECLARE_NOT_AGGREGATABLE(ThisClass)
  95. // Returns the next celt items starting from the current position
  96. // in the array rgvar
  97. STDMETHODIMP Next(unsigned long celt, PVARIANT rgvar, unsigned long * pceltFetched);
  98. // Skips over the next celt elements in the enumeration sequence.
  99. STDMETHODIMP Skip(unsigned long celt);
  100. // Resets the enumeration sequence to the beginning
  101. STDMETHODIMP Reset();
  102. // Creates a copy of the current state of enumeration
  103. STDMETHODIMP Clone(PPENUMVARIANT ppenum);
  104. public:
  105. // the position object that keeps track of the present location.
  106. _Position m_position;
  107. };
  108. /*+-------------------------------------------------------------------------*
  109. * class CMMCArrayEnumBase
  110. *
  111. * PURPOSE: General purpose array enumeration base class.
  112. * Particularly useful when array of items to be enumerated is initially
  113. * available, or when com object creation is not a big penalty and there
  114. * is no need to postpone item creation to when they are requested.
  115. *
  116. * USAGE: typedef your enumerator as CMMCNewEnumImpl parameterized by this class
  117. * - or even better - create the instance of CMMCArrayEnum class.
  118. * Use Init method passing an array of pointers to items [first, last)
  119. *+-------------------------------------------------------------------------*/
  120. template <class _CollectionInterface, class _ItemInterface>
  121. class CMMCArrayEnumBase :
  122. public CMMCIDispatchImpl<_CollectionInterface>,
  123. public CTiedObject // enumerators are tied to it
  124. {
  125. protected:
  126. typedef void CMyTiedObject; // not tied
  127. public:
  128. BEGIN_MMC_COM_MAP(CMMCArrayEnumBase)
  129. END_MMC_COM_MAP()
  130. public:
  131. // Returns count of items in the collection
  132. STDMETHODIMP get_Count( PLONG pCount );
  133. // Returns specified item from collection
  134. STDMETHODIMP Item( long Index, _ItemInterface ** ppItem );
  135. // Resets position to the first item in the collection
  136. ::SC ScEnumReset (unsigned &pos);
  137. // Returns item from the collection, advances position
  138. ::SC ScEnumNext (unsigned &pos, PDISPATCH & pDispatch);
  139. // Skips the amount of items in enumeration
  140. ::SC ScEnumSkip (unsigned long celt, unsigned long& celtSkipped, unsigned &pos);
  141. // Initializes the array with given iterators
  142. template<typename InIt>
  143. void Init(InIt first, InIt last)
  144. {
  145. m_array.clear();
  146. m_array.reserve(last - first);
  147. while(first != last)
  148. m_array.push_back(*first), ++first;
  149. }
  150. private:
  151. // data members
  152. std::vector< CComPtr<_ItemInterface> > m_array;
  153. };
  154. /*+-------------------------------------------------------------------------*
  155. * class CMMCArrayEnumBase
  156. *
  157. * PURPOSE: General purpose array enumeration class.
  158. * Particularly useful when array of items to be enumerated is initially
  159. * available, or when com object creation is not a big penalty and there
  160. * is no need to postpone item creation to when they are requested.
  161. *
  162. * USAGE: create the instance of CMMCArrayEnum class whenever you need an
  163. * enumerator for the array of objects you have.
  164. * Parameterized by collection type and element type;
  165. * For instance CMMCArrayEnum< Nodes, Node >
  166. * Use Init method passing an array of pointers to items [first, last)
  167. *
  168. * EXAMPLE: << skipping error checking for clarity >>
  169. * void GetNodes(std::vector<PNODE>& InNodes, PPNODES ppOutNodes)
  170. * {
  171. * typedef CComObject< CMMCArrayEnum<Nodes, Node> > EnumNodes;
  172. * EnumNodes *pNodes = NULL;
  173. * EnumNodes::CreateInstance(&pNodes); // create
  174. * pNodes->Init(InNodes.begin(), InNodes.end()); // initialize with array
  175. * pNodes->AddRef(); // addref for caller
  176. * *ppOutNodes = pNodes; // return
  177. * }
  178. *
  179. *+-------------------------------------------------------------------------*/
  180. template <class _CollT, class _ItemT>
  181. class CMMCArrayEnum :
  182. public CMMCNewEnumImpl<CMMCArrayEnumBase<_CollT, _ItemT>, unsigned, CMMCArrayEnumBase<_CollT, _ItemT> >
  183. {
  184. };
  185. // include inline definitions
  186. #include "enumerator.inl"
  187. #endif // ENUMERATOR_H_INCLUDED