|
|
//==========================================================================;
//
// 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 <arity.h>
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 = typename Value_Type::stl_allocator> 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<std::forward_iterator_tag, Value_Type, difference_type> { public: // these are for com enumerators so use __stdcall version of binders
static std_arity0pmf<Enumerator_Type_Inner, HRESULT> *Reset; static std_arity1pmf<Enumerator_Type_Inner, Value_Type_Inner *, HRESULT> *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 Enumerator_Type, class Value_Type, class Enumerator_Type_Inner = Enumerator_Type, class Value_Type_Inner = Value_Type, class difference_type = ptrdiff_t> class const_enumerator_iterator : public enumerator_iterator<Enumerator_Type, Value_Type, Enumerator_Type_Inner, Value_Type_Inner, difference_type> { public: inline const_enumerator_iterator(const Enumerator_Type e = Enumerator_Type(), const Value_Type c = Value_Type()) : enumerator_iterator<Enumerator_Type, Value_Type, Enumerator_Type_Inner, Value_Type_Inner, difference_type>(e, c) {} inline const_enumerator_iterator(const enumerator_iterator<Enumerator_Type, Value_Type, Enumerator_Type_Inner, Value_Type_Inner, difference_type> &e) : enumerator_iterator<Enumerator_Type, Value_Type, Enumerator_Type_Inner, Value_Type_Inner, difference_type>(e) {} inline const_enumerator_iterator(const const_enumerator_iterator &e) : enumerator_iterator<Enumerator_Type, Value_Type, Enumerator_Type_Inner, Value_Type_Inner, difference_type>(e) {} inline const Value_Type operator*() const { return enumerator_iterator<Enumerator_Type, Value_Type, Enumerator_Type_Inner, Value_Type_Inner, difference_type>::operator*(); } inline const_enumerator_iterator& operator=(const const_enumerator_iterator &e) { if (&e != this) { enumerator_iterator<Enumerator_Type, Value_Type, Enumerator_Type_Inner, Value_Type_Inner, difference_type>::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 typename Allocator::value_type value_type; typedef typename Allocator::value_type& reference; typedef const typename Allocator::value_type& const_reference; typedef typename Allocator::size_type size_type; typedef typename 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<Base_Inner, Enumerator_Type_Inner **, HRESULT> FetchType;
static FetchType* Fetch;
virtual FetchType* GetFetch() const { return Fetch; }
typedef enumerator_iterator<Enumerator_Type, Value_Type, Enumerator_Type_Inner, Value_Type_Inner, difference_type> iterator; friend iterator;
typedef const_enumerator_iterator<Enumerator_Type, Value_Type, Enumerator_Type_Inner, Value_Type_Inner, difference_type> 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
|