windows-nt/Source/XPSP1/NT/admin/activec/inc/enumerator.h
2020-09-26 16:20:57 +08:00

221 lines
8.4 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 2000
//
// File: enumerator.h
//
// Contents: Supports enumeration for collections of com objects
//
// History: 14-Oct-99 VivekJ Created (as comerror.h)
// 08-Mar-2000 AudriusZ separated some code into enumerator.h file
//
//--------------------------------------------------------------------------
#ifndef ENUMERATOR_H_INCLUDED
#define ENUMERATOR_H_INCLUDED
#pragma once
/***************************************************************************\
*
* CLASS: CMMCNewEnumImpl<BaseClass, _Position, EnumImplementor>
*
* PURPOSE: Implements enumeration for collection class
* EnumImplementor class is responsible for implementing these methods:
* SC ScEnumNext(_Position &pos, PDISPATCH & pDispatch);
* SC ScEnumSkip(unsigned long celt, unsigned long& celtSkipped, _Position &pos);
* SC ScEnumReset(_Position &pos);
*
\***************************************************************************/
/****** usage tips *******************************************************
* Generally you will provide just 2 params to template - this means
* the tied object of your base class needs to implement following methods:
* ScEnumNext, ScEnumSkip, ScEnumReset;
*
* If you pass same class as the first and the third template parameter, your base class is
* required to implement mentioned methods (not the tied object).
* It's usefull when you want to have collection and enueration in one class.
*
* You also may specify any other class implementing the methods as the 3rd parameter,
* but then the BaseClass needs to implement method 'ScGetEnumImplementor' returning
* the instance of that class
*
* NOTE1: since it's template class, the BaseClass is not required to define/implement
* ScGetTiedObject, when it implements enum methods itself.
* NOTE2: But it always IS REQUIRED to define CMyTiedObject type to compile.
* (this template class needs it to be anything different than the BaseClass)
* It is suggested to typedef it as void : "typedef void CMyTiedObject;"
* NOTE3: Make sure CMyTiedObject type is public or protected
************************************************************************/
template <class BaseClass, class _Position, class EnumImplementor = BaseClass::CMyTiedObject>
class CMMCNewEnumImpl : public BaseClass
{
// Methods to get proper implementor for Enum methods
// simple one when implemented by the base class
SC ScGetEnumImplementor(BaseClass * &pObj) { pObj = this; return SC(S_OK); }
// when implemented by the tied object (default) - also simple
SC ScGetEnumImplementor(BaseClass::CMyTiedObject * &pObj) { return ScGetTiedObject(pObj); }
public:
STDMETHOD(get__NewEnum)(IUnknown** ppUnk);
};
/*+-------------------------------------------------------------------------*
* class CMMCEnumerator
*
*
* PURPOSE: General purpose enumerator class. Keyed to a position object,
* which is templated.
*
* The following three methods need to be implemented by the tied object:
*
* SC ScEnumNext(_Position &pos, PDISPATCH & pDispatch); // should return the next element.
* SC ScEnumSkip(unsigned long celt, unsigned long& celtSkipped,
* _Position &pos);
* SC ScEnumReset(_Position &pos);
*
* Cloning the enumerator is taken care of automatically.
*
* NOTE: The Position object must have a copy constructor and assignment
* operator.
*+-------------------------------------------------------------------------*/
typedef IEnumVARIANT ** PPENUMVARIANT;
typedef VARIANT * PVARIANT;
template<class TiedObj, class _Position>
class CMMCEnumerator :
public IEnumVARIANT,
public IMMCSupportErrorInfoImpl<&IID_IEnumVARIANT, &GUID_NULL>, // rich error handling
public CComObjectRoot,
public CTiedComObject<TiedObj>
{
typedef CMMCEnumerator<TiedObj, _Position> ThisClass;
typedef TiedObj CMyTiedObject;
friend TiedObj;
public:
BEGIN_COM_MAP(ThisClass)
COM_INTERFACE_ENTRY(IEnumVARIANT)
END_COM_MAP()
DECLARE_NOT_AGGREGATABLE(ThisClass)
// Returns the next celt items starting from the current position
// in the array rgvar
STDMETHODIMP Next(unsigned long celt, PVARIANT rgvar, unsigned long * pceltFetched);
// Skips over the next celt elements in the enumeration sequence.
STDMETHODIMP Skip(unsigned long celt);
// Resets the enumeration sequence to the beginning
STDMETHODIMP Reset();
// Creates a copy of the current state of enumeration
STDMETHODIMP Clone(PPENUMVARIANT ppenum);
public:
// the position object that keeps track of the present location.
_Position m_position;
};
/*+-------------------------------------------------------------------------*
* class CMMCArrayEnumBase
*
* PURPOSE: General purpose array enumeration base class.
* Particularly useful when array of items to be enumerated is initially
* available, or when com object creation is not a big penalty and there
* is no need to postpone item creation to when they are requested.
*
* USAGE: typedef your enumerator as CMMCNewEnumImpl parameterized by this class
* - or even better - create the instance of CMMCArrayEnum class.
* Use Init method passing an array of pointers to items [first, last)
*+-------------------------------------------------------------------------*/
template <class _CollectionInterface, class _ItemInterface>
class CMMCArrayEnumBase :
public CMMCIDispatchImpl<_CollectionInterface>,
public CTiedObject // enumerators are tied to it
{
protected:
typedef void CMyTiedObject; // not tied
public:
BEGIN_MMC_COM_MAP(CMMCArrayEnumBase)
END_MMC_COM_MAP()
public:
// Returns count of items in the collection
STDMETHODIMP get_Count( PLONG pCount );
// Returns specified item from collection
STDMETHODIMP Item( long Index, _ItemInterface ** ppItem );
// Resets position to the first item in the collection
::SC ScEnumReset (unsigned &pos);
// Returns item from the collection, advances position
::SC ScEnumNext (unsigned &pos, PDISPATCH & pDispatch);
// Skips the amount of items in enumeration
::SC ScEnumSkip (unsigned long celt, unsigned long& celtSkipped, unsigned &pos);
// Initializes the array with given iterators
template<typename InIt>
void Init(InIt first, InIt last)
{
m_array.clear();
m_array.reserve(last - first);
while(first != last)
m_array.push_back(*first), ++first;
}
private:
// data members
std::vector< CComPtr<_ItemInterface> > m_array;
};
/*+-------------------------------------------------------------------------*
* class CMMCArrayEnumBase
*
* PURPOSE: General purpose array enumeration class.
* Particularly useful when array of items to be enumerated is initially
* available, or when com object creation is not a big penalty and there
* is no need to postpone item creation to when they are requested.
*
* USAGE: create the instance of CMMCArrayEnum class whenever you need an
* enumerator for the array of objects you have.
* Parameterized by collection type and element type;
* For instance CMMCArrayEnum< Nodes, Node >
* Use Init method passing an array of pointers to items [first, last)
*
* EXAMPLE: << skipping error checking for clarity >>
* void GetNodes(std::vector<PNODE>& InNodes, PPNODES ppOutNodes)
* {
* typedef CComObject< CMMCArrayEnum<Nodes, Node> > EnumNodes;
* EnumNodes *pNodes = NULL;
* EnumNodes::CreateInstance(&pNodes); // create
* pNodes->Init(InNodes.begin(), InNodes.end()); // initialize with array
* pNodes->AddRef(); // addref for caller
* *ppOutNodes = pNodes; // return
* }
*
*+-------------------------------------------------------------------------*/
template <class _CollT, class _ItemT>
class CMMCArrayEnum :
public CMMCNewEnumImpl<CMMCArrayEnumBase<_CollT, _ItemT>, unsigned, CMMCArrayEnumBase<_CollT, _ItemT> >
{
};
// include inline definitions
#include "enumerator.inl"
#endif // ENUMERATOR_H_INCLUDED