Leaked source code of windows server 2003
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.

288 lines
13 KiB

  1. //==========================================================================;
  2. //
  3. // fwdseq.h : forward sequence infrastructure to extend the dshow stuff so that it
  4. // works nicely from c++
  5. // Copyright (c) Microsoft Corporation 1995-1999.
  6. //
  7. /////////////////////////////////////////////////////////////////////////////
  8. #pragma once
  9. #ifndef FWDSEQ_H
  10. #define FWDSEQ_H
  11. #include <arity.h>
  12. template<class Base, class Enumerator_Type, class Value_Type,
  13. class Base_Inner = Base,
  14. class Enumerator_Type_Inner = Enumerator_Type,
  15. class Value_Type_Inner = Value_Type,
  16. class Allocator = typename Value_Type::stl_allocator> class Forward_Sequence;
  17. // NOTE: all of this stuff with the indirected static templated functions for fetch, reset, next
  18. // is to get around an assortment of compiler bugs.
  19. // a) you can't have a pointer to a member function as a template parm if it references earlier template parms
  20. // b) in the initializations of these fetch,reset,next functions if we globally initialize the
  21. // constructor isn't getting called and the vtable isn't set up. hence we create them off the
  22. // heap at runtime.
  23. // enumerator_iterator
  24. // this is an stl based forward iterator for dealing with legacy com enumerators with no prev method
  25. template<
  26. class Enumerator_Type,
  27. class Value_Type,
  28. class Enumerator_Type_Inner = Enumerator_Type,
  29. class Value_Type_Inner = Value_Type,
  30. class difference_type = ptrdiff_t
  31. > class enumerator_iterator : public std::iterator<std::forward_iterator_tag, Value_Type, difference_type> {
  32. public:
  33. // these are for com enumerators so use __stdcall version of binders
  34. static std_arity0pmf<Enumerator_Type_Inner, HRESULT> *Reset;
  35. static std_arity1pmf<Enumerator_Type_Inner, Value_Type_Inner *, HRESULT> *Next;
  36. inline enumerator_iterator(const Enumerator_Type e = Enumerator_Type(), const Value_Type c = Value_Type()) : enumerator_state(e), current_value(c) {
  37. if (enumerator_state != NULL) {
  38. if (!current_value) {
  39. #ifdef FORWARD_TRACE
  40. TRACELM(TRACE_PAINT, "enumerator_iterator constructor, attempting reset");
  41. #endif
  42. Enumerator_Type_Inner *peti = enumerator_state;
  43. HRESULT hr = (*Reset)(*peti);
  44. if (SUCCEEDED(hr)) {
  45. Value_Type temp_val;
  46. #ifdef FORWARD_TRACE
  47. TRACELM(TRACE_PAINT, "enumerator_iterator constructor, attempting next()");
  48. #endif
  49. hr = (*Next)(*peti, &temp_val);
  50. if (SUCCEEDED(hr) && hr != S_FALSE) {
  51. current_value = temp_val;
  52. #ifdef FORWARD_TRACE
  53. TRACELSM(TRACE_PAINT, (dbgDump << "enumerator_iterator constructor, set to first value = " << current_value), "");
  54. #endif
  55. }
  56. #ifdef FORWARD_TRACE
  57. TRACELSM(TRACE_PAINT, (dbgDump << "enumerator_iterator constructor, next() hr = " << hr), "");
  58. #endif
  59. }
  60. }
  61. } else {
  62. current_value = Value_Type();
  63. }
  64. #ifdef FORWARD_TRACE
  65. TRACELM(TRACE_PAINT, "enumerator_iterator constructor complete");
  66. #endif
  67. }
  68. inline enumerator_iterator(const enumerator_iterator &e) : enumerator_state(e.enumerator_state), current_value(e.current_value) {}
  69. inline Value_Type operator*() const { return current_value; }
  70. inline enumerator_iterator& operator++() {
  71. if (enumerator_state) {
  72. Value_Type temp_val;
  73. Enumerator_Type_Inner *peti = enumerator_state;
  74. HRESULT hr = (*Next)(*peti, &temp_val);
  75. if (SUCCEEDED(hr) && (hr != S_FALSE)) {
  76. current_value = temp_val;
  77. } else {
  78. current_value = Value_Type();
  79. }
  80. } else {
  81. current_value = Value_Type();
  82. }
  83. return (*this);
  84. }
  85. inline enumerator_iterator operator++(int) {
  86. enumerator_iterator Tmp = *this;
  87. ++*this;
  88. return (Tmp);
  89. }
  90. inline enumerator_iterator& operator=(const enumerator_iterator &e) {
  91. if (&e != this) {
  92. enumerator_state = e.enumerator_state;
  93. current_value = e.current_value;
  94. }
  95. return *this;
  96. }
  97. inline bool operator==(const enumerator_iterator& e) const {
  98. #ifdef FORWARD_TRACE
  99. TRACELSM(TRACE_PAINT, (dbgDump << "enumerator_iterator operator==() current_value = " << current_value << " e.current_value = " << e.current_value), "");
  100. #endif
  101. return (current_value == e.current_value);
  102. }
  103. inline bool operator!=(const enumerator_iterator& e) const
  104. {return (!(*this == e)); }
  105. inline Value_Type CurrentValue() const
  106. {return current_value; }
  107. protected:
  108. Enumerator_Type enumerator_state;
  109. Value_Type current_value;
  110. };
  111. // const_enumerator_iterator
  112. template<class Enumerator_Type, class Value_Type,
  113. class Enumerator_Type_Inner = Enumerator_Type,
  114. class Value_Type_Inner = Value_Type,
  115. class difference_type = ptrdiff_t> class const_enumerator_iterator :
  116. public enumerator_iterator<Enumerator_Type,
  117. Value_Type,
  118. Enumerator_Type_Inner,
  119. Value_Type_Inner,
  120. difference_type> {
  121. public:
  122. inline const_enumerator_iterator(const Enumerator_Type e = Enumerator_Type(), const Value_Type c = Value_Type()) :
  123. enumerator_iterator<Enumerator_Type,
  124. Value_Type,
  125. Enumerator_Type_Inner,
  126. Value_Type_Inner,
  127. difference_type>(e, c) {}
  128. inline const_enumerator_iterator(const enumerator_iterator<Enumerator_Type,
  129. Value_Type,
  130. Enumerator_Type_Inner,
  131. Value_Type_Inner,
  132. difference_type> &e) :
  133. enumerator_iterator<Enumerator_Type,
  134. Value_Type,
  135. Enumerator_Type_Inner,
  136. Value_Type_Inner,
  137. difference_type>(e) {}
  138. inline const_enumerator_iterator(const const_enumerator_iterator &e) :
  139. enumerator_iterator<Enumerator_Type,
  140. Value_Type,
  141. Enumerator_Type_Inner,
  142. Value_Type_Inner,
  143. difference_type>(e) {}
  144. inline const Value_Type operator*() const {
  145. return enumerator_iterator<Enumerator_Type,
  146. Value_Type,
  147. Enumerator_Type_Inner,
  148. Value_Type_Inner,
  149. difference_type>::operator*(); }
  150. inline const_enumerator_iterator& operator=(const const_enumerator_iterator &e) {
  151. if (&e != this) {
  152. enumerator_iterator<Enumerator_Type,
  153. Value_Type,
  154. Enumerator_Type_Inner,
  155. Value_Type_Inner,
  156. difference_type>::operator=(e);
  157. }
  158. return *this;
  159. }
  160. };
  161. // this is a stl based template for containing legacy com collections
  162. // this is *almost* a standard stl sequence container class. the reason its
  163. // not a complete sequence container is because for many of the com enumerators we have no prev method
  164. // and therefore, no efficient way of reverse iterating through the collection.
  165. // so we can't provide a bidirectional iterator only a forward one.
  166. // call this a forward sequence container if you will
  167. // Base is smart pointer wrapper class being contained in this container
  168. // Base_Inner is actual wrapped class that the smart pointer class contains(usually com IXXX).
  169. // if you're making a forward_sequence out of some ordinary class instead of a smart pointer class
  170. // then use the default and make both Base_Inner == Base
  171. template<
  172. class Base,
  173. class Enumerator_Type,
  174. class Value_Type,
  175. class Base_Inner /*= Base */,
  176. class Enumerator_Type_Inner /*= Enumerator_Type */,
  177. class Value_Type_Inner /*= Value_Type */,
  178. class Allocator /*= Value_Type::stl_allocator */
  179. > class Forward_Sequence : public Base {
  180. public:
  181. Forward_Sequence(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) : Base(rclsid, pUnkOuter, dwClsContext) {}
  182. virtual ~Forward_Sequence() {}
  183. typedef typename Allocator::value_type value_type;
  184. typedef typename Allocator::value_type& reference;
  185. typedef const typename Allocator::value_type& const_reference;
  186. typedef typename Allocator::size_type size_type;
  187. typedef typename Allocator::difference_type difference_type;
  188. // the compiler doesn't recognize this typedef in this template. but, derived classes
  189. // can refer to it.
  190. typedef std_arity1pmf<Base_Inner, Enumerator_Type_Inner **, HRESULT> FetchType;
  191. static FetchType* Fetch;
  192. virtual FetchType* GetFetch() const {
  193. return Fetch;
  194. }
  195. typedef enumerator_iterator<Enumerator_Type,
  196. Value_Type,
  197. Enumerator_Type_Inner,
  198. Value_Type_Inner,
  199. difference_type> iterator;
  200. friend iterator;
  201. typedef const_enumerator_iterator<Enumerator_Type,
  202. Value_Type,
  203. Enumerator_Type_Inner,
  204. Value_Type_Inner,
  205. difference_type> const_iterator;
  206. friend const_iterator;
  207. Forward_Sequence() {}
  208. Forward_Sequence(const Forward_Sequence &a) : Base(a) { }
  209. Forward_Sequence(const Base &a) : Base(a) {}
  210. Forward_Sequence(Base_Inner *p) : Base(p) {}
  211. Forward_Sequence(IUnknown *p) : Base(p) {}
  212. iterator begin() {
  213. Enumerator_Type temp_enum;
  214. if (!(*this)) {
  215. return iterator();
  216. }
  217. #ifdef FORWARD_TRACE
  218. TRACELM(TRACE_DETAIL, "iterator ForwardSequence::begin() attempting fetch");
  219. #endif
  220. Base_Inner *peti = *this;
  221. HRESULT hr = (*(GetFetch()))(*peti, &temp_enum);
  222. if (SUCCEEDED(hr)) {
  223. #ifdef FORWARD_TRACE
  224. TRACELM(TRACE_DETAIL, "iterator ForwardSequence::begin() fetch succeeded");
  225. #endif
  226. return iterator(temp_enum);
  227. } else {
  228. #ifdef FORWARD_TRACE
  229. TRACELM(TRACE_DETAIL, "iterator ForwardSequence::begin() fetch failed");
  230. #endif
  231. return iterator();
  232. }
  233. }
  234. const_iterator begin() const {
  235. Enumerator_Type temp_enum;
  236. #ifdef FORWARD_TRACE
  237. TRACELM(TRACE_DETAIL, "const_iterator ForwardSequence::begin() attempting fetch");
  238. #endif
  239. Base_Inner *peti = *this;
  240. HRESULT hr = (*(GetFetch()))(*peti, &temp_enum);
  241. if (SUCCEEDED(hr)) {
  242. #ifdef FORWARD_TRACE
  243. TRACELM(TRACE_DETAIL, "const_iterator ForwardSequence::begin() fetch succeeded");
  244. #endif
  245. return iterator(temp_enum);
  246. } else {
  247. #ifdef FORWARD_TRACE
  248. TRACELM(TRACE_DETAIL, "const_iterator ForwardSequence::begin() fetch failed");
  249. #endif
  250. return iterator();
  251. }
  252. }
  253. iterator end() {
  254. #ifdef FORWARD_TRACE
  255. TRACELM(TRACE_DETAIL, "iterator ForwardSequence::end()");
  256. #endif
  257. return iterator();
  258. }
  259. const_iterator end() const { return const_iterator(); }
  260. };
  261. #endif
  262. // end of file fwdseq.h