//==========================================================================; // // fwdseq.h : forward sequence infrastructure to extend the dshow stuff so that it // works nicely from c++ // Copyright (c) Microsoft Corporation 1995-1999. // ///////////////////////////////////////////////////////////////////////////// #pragma once #ifndef FWDSEQ_H #define FWDSEQ_H #include template class Forward_Sequence; // NOTE: all of this stuff with the indirected static templated functions for fetch, reset, next // is to get around an assortment of compiler bugs. // a) you can't have a pointer to a member function as a template parm if it references earlier template parms // b) in the initializations of these fetch,reset,next functions if we globally initialize the // constructor isn't getting called and the vtable isn't set up. hence we create them off the // heap at runtime. // enumerator_iterator // this is an stl based forward iterator for dealing with legacy com enumerators with no prev method template< class Enumerator_Type, class Value_Type, class Enumerator_Type_Inner = Enumerator_Type, class Value_Type_Inner = Value_Type, class difference_type = ptrdiff_t > class enumerator_iterator : public std::iterator { public: // these are for com enumerators so use __stdcall version of binders static std_arity0pmf *Reset; static std_arity1pmf *Next; inline enumerator_iterator(const Enumerator_Type e = Enumerator_Type(), const Value_Type c = Value_Type()) : enumerator_state(e), current_value(c) { if (enumerator_state != NULL) { if (!current_value) { #ifdef FORWARD_TRACE TRACELM(TRACE_PAINT, "enumerator_iterator constructor, attempting reset"); #endif Enumerator_Type_Inner *peti = enumerator_state; HRESULT hr = (*Reset)(*peti); if (SUCCEEDED(hr)) { Value_Type temp_val; #ifdef FORWARD_TRACE TRACELM(TRACE_PAINT, "enumerator_iterator constructor, attempting next()"); #endif hr = (*Next)(*peti, &temp_val); if (SUCCEEDED(hr) && hr != S_FALSE) { current_value = temp_val; #ifdef FORWARD_TRACE TRACELSM(TRACE_PAINT, (dbgDump << "enumerator_iterator constructor, set to first value = " << current_value), ""); #endif } #ifdef FORWARD_TRACE TRACELSM(TRACE_PAINT, (dbgDump << "enumerator_iterator constructor, next() hr = " << hr), ""); #endif } } } else { current_value = Value_Type(); } #ifdef FORWARD_TRACE TRACELM(TRACE_PAINT, "enumerator_iterator constructor complete"); #endif } inline enumerator_iterator(const enumerator_iterator &e) : enumerator_state(e.enumerator_state), current_value(e.current_value) {} inline Value_Type operator*() const { return current_value; } inline enumerator_iterator& operator++() { if (enumerator_state) { Value_Type temp_val; Enumerator_Type_Inner *peti = enumerator_state; HRESULT hr = (*Next)(*peti, &temp_val); if (SUCCEEDED(hr) && (hr != S_FALSE)) { current_value = temp_val; } else { current_value = Value_Type(); } } else { current_value = Value_Type(); } return (*this); } inline enumerator_iterator operator++(int) { enumerator_iterator Tmp = *this; ++*this; return (Tmp); } inline enumerator_iterator& operator=(const enumerator_iterator &e) { if (&e != this) { enumerator_state = e.enumerator_state; current_value = e.current_value; } return *this; } inline bool operator==(const enumerator_iterator& e) const { #ifdef FORWARD_TRACE TRACELSM(TRACE_PAINT, (dbgDump << "enumerator_iterator operator==() current_value = " << current_value << " e.current_value = " << e.current_value), ""); #endif return (current_value == e.current_value); } inline bool operator!=(const enumerator_iterator& e) const {return (!(*this == e)); } inline Value_Type CurrentValue() const {return current_value; } protected: Enumerator_Type enumerator_state; Value_Type current_value; }; // const_enumerator_iterator template class const_enumerator_iterator : public enumerator_iterator { public: inline const_enumerator_iterator(const Enumerator_Type e = Enumerator_Type(), const Value_Type c = Value_Type()) : enumerator_iterator(e, c) {} inline const_enumerator_iterator(const enumerator_iterator &e) : enumerator_iterator(e) {} inline const_enumerator_iterator(const const_enumerator_iterator &e) : enumerator_iterator(e) {} inline const Value_Type operator*() const { return enumerator_iterator::operator*(); } inline const_enumerator_iterator& operator=(const const_enumerator_iterator &e) { if (&e != this) { enumerator_iterator::operator=(e); } return *this; } }; // this is a stl based template for containing legacy com collections // this is *almost* a standard stl sequence container class. the reason its // not a complete sequence container is because for many of the com enumerators we have no prev method // and therefore, no efficient way of reverse iterating through the collection. // so we can't provide a bidirectional iterator only a forward one. // call this a forward sequence container if you will // Base is smart pointer wrapper class being contained in this container // Base_Inner is actual wrapped class that the smart pointer class contains(usually com IXXX). // if you're making a forward_sequence out of some ordinary class instead of a smart pointer class // then use the default and make both Base_Inner == Base template< class Base, class Enumerator_Type, class Value_Type, class Base_Inner = Base, class Enumerator_Type_Inner = Enumerator_Type, class Value_Type_Inner = Value_Type, class Allocator = Value_Type::stl_allocator > class Forward_Sequence : public Base { public: Forward_Sequence(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) : Base(rclsid, pUnkOuter, dwClsContext) {} virtual ~Forward_Sequence() {} typedef Allocator::value_type value_type; typedef Allocator::value_type& reference; typedef const Allocator::value_type& const_reference; typedef Allocator::size_type size_type; typedef Allocator::difference_type difference_type; // the compiler doesn't recognize this typedef in this template. but, derived classes // can refer to it. typedef std_arity1pmf FetchType; static FetchType* Fetch; virtual FetchType* GetFetch() const { return Fetch; } typedef enumerator_iterator iterator; friend iterator; typedef const_enumerator_iterator const_iterator; friend const_iterator; Forward_Sequence() {} Forward_Sequence(const Forward_Sequence &a) : Base(a) { } Forward_Sequence(const Base &a) : Base(a) {} Forward_Sequence(Base_Inner *p) : Base(p) {} Forward_Sequence(IUnknown *p) : Base(p) {} iterator begin() { Enumerator_Type temp_enum; if (!(*this)) { return iterator(); } #ifdef FORWARD_TRACE TRACELM(TRACE_DETAIL, "iterator ForwardSequence::begin() attempting fetch"); #endif Base_Inner *peti = *this; HRESULT hr = (*(GetFetch()))(*peti, &temp_enum); if (SUCCEEDED(hr)) { #ifdef FORWARD_TRACE TRACELM(TRACE_DETAIL, "iterator ForwardSequence::begin() fetch succeeded"); #endif return iterator(temp_enum); } else { #ifdef FORWARD_TRACE TRACELM(TRACE_DETAIL, "iterator ForwardSequence::begin() fetch failed"); #endif return iterator(); } } const_iterator begin() const { Enumerator_Type temp_enum; #ifdef FORWARD_TRACE TRACELM(TRACE_DETAIL, "const_iterator ForwardSequence::begin() attempting fetch"); #endif Base_Inner *peti = *this; HRESULT hr = (*(GetFetch()))(*peti, &temp_enum); if (SUCCEEDED(hr)) { #ifdef FORWARD_TRACE TRACELM(TRACE_DETAIL, "const_iterator ForwardSequence::begin() fetch succeeded"); #endif return iterator(temp_enum); } else { #ifdef FORWARD_TRACE TRACELM(TRACE_DETAIL, "const_iterator ForwardSequence::begin() fetch failed"); #endif return iterator(); } } iterator end() { #ifdef FORWARD_TRACE TRACELM(TRACE_DETAIL, "iterator ForwardSequence::end()"); #endif return iterator(); } const_iterator end() const { return const_iterator(); } }; #endif // end of file fwdseq.h