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.

637 lines
19 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: atlstl/automation/enumerators.hpp (originally MAEnum.h)
  3. *
  4. * Purpose: Enumerator classes.
  5. *
  6. * Created: 11th November 1998
  7. * Updated: 26th December 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 1998-2009, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file atlstl/automation/enumerators.hpp
  40. * \brief [C++ only; requires ATL library] Definition of the
  41. * atlstl::copy_enumerator class template (and its supporting components),
  42. * which provides a copying alternative to the stock <code>CComEnum</code>
  43. * ATL component that may be initialised from any range and whose contents
  44. * may be modified subsequent to initialisation
  45. * (\ref group__library__com_automation "COM Automation" Library).
  46. */
  47. #ifndef ATLSTL_INCL_ATLSTL_AUTOMATION_HPP_ENUMERATORS
  48. #define ATLSTL_INCL_ATLSTL_AUTOMATION_HPP_ENUMERATORS
  49. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  50. # define ATLSTL_VER_ATLSTL_AUTOMATION_HPP_ENUMERATORS_MAJOR 4
  51. # define ATLSTL_VER_ATLSTL_AUTOMATION_HPP_ENUMERATORS_MINOR 0
  52. # define ATLSTL_VER_ATLSTL_AUTOMATION_HPP_ENUMERATORS_REVISION 5
  53. # define ATLSTL_VER_ATLSTL_AUTOMATION_HPP_ENUMERATORS_EDIT 67
  54. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  55. ////////////////////////////////////////////////////////////////////////////
  56. // Includes
  57. #ifndef ATLSTL_INCL_ATLSTL_HPP_ATLSTL
  58. # include <atlstl/atlstl.hpp>
  59. #endif /* !ATLSTL_INCL_ATLSTL_HPP_ATLSTL */
  60. #ifndef STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_REF_PTR
  61. # include <stlsoft/smartptr/ref_ptr.hpp>
  62. #endif /* !STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_REF_PTR */
  63. #ifndef STLSOFT_INCL_STLSOFT_FUNCTIONAL_HPP_INDIRECT_FUNCTION_POINTER_ADAPTORS
  64. # include <stlsoft/functional/indirect_function_pointer_adaptors.hpp>
  65. #endif /* !STLSOFT_INCL_STLSOFT_FUNCTIONAL_HPP_INDIRECT_FUNCTION_POINTER_ADAPTORS */
  66. #ifndef STLSOFT_INCL_SYS_H_ATLCOM
  67. # define STLSOFT_INCL_SYS_H_ATLCOM
  68. # include <atlcom.h>
  69. #endif /* !STLSOFT_INCL_SYS_H_ATLCOM */
  70. #ifndef STLSOFT_INCL_ALGORITHM
  71. # define STLSOFT_INCL_ALGORITHM
  72. # include <algorithm>
  73. #endif /* !STLSOFT_INCL_ALGORITHM */
  74. #ifndef STLSOFT_INCL_LIST
  75. # define STLSOFT_INCL_LIST
  76. # include <list>
  77. #endif /* !STLSOFT_INCL_LIST */
  78. /* /////////////////////////////////////////////////////////////////////////
  79. * Namespace
  80. */
  81. #ifndef _ATLSTL_NO_NAMESPACE
  82. # if defined(_STLSOFT_NO_NAMESPACE) || \
  83. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  84. /* There is no stlsoft namespace, so must define ::atlstl */
  85. namespace atlstl
  86. {
  87. # else
  88. /* Define stlsoft::atlstl_project */
  89. namespace stlsoft
  90. {
  91. namespace atlstl_project
  92. {
  93. # endif /* _STLSOFT_NO_NAMESPACE */
  94. #endif /* !_ATLSTL_NO_NAMESPACE */
  95. /* /////////////////////////////////////////////////////////////////////////
  96. * Classes
  97. */
  98. /** A policy that indicates that values should be copied between internal
  99. * and external representations in the enumerator
  100. */
  101. template< ss_typename_param_k XV // Enumerator interface value type (External value type)
  102. , ss_typename_param_k IV // Internal value type
  103. >
  104. struct copy_policy
  105. {
  106. public:
  107. typedef XV external_value_type;
  108. typedef IV internal_value_type;
  109. public:
  110. static void init(external_value_type *xv);
  111. #if 0
  112. {
  113. *xv = external_value_type();
  114. }
  115. #endif /* 0 */
  116. static HRESULT copy(external_value_type *xv, internal_value_type const& iv);
  117. #if 0
  118. {
  119. *xv = iv;
  120. return S_OK;
  121. }
  122. #endif /* 0 */
  123. /// This is only called when copy() has failed, and a number of copies must be undone
  124. static void clear(external_value_type *xv);
  125. #if 0
  126. {
  127. STLSOFT_SUPPRESS_UNUSED(xv);
  128. }
  129. #endif /* 0 */
  130. };
  131. ////////////////////////////////////////////////////////////////////////////
  132. // Classes
  133. /** \brief Modifiable, copying enumerator class template
  134. *
  135. * \ingroup group__library__com_automation
  136. *
  137. * copy_enumerator_impl is the analogue to CComEnumImpl, but the advantages
  138. * over the ATL class is that it can be added to/removed from after
  139. * initialisation, and it can be initialised/appended from a sequence (as
  140. * defined by the start and end iterators), rather than assuming an array as
  141. * source.
  142. *
  143. * copy_enumerator is the analogue to CComEnum, but uses the
  144. * atlstl::copy_enumerator_impl as its 'implementation' class template.
  145. *
  146. * \param I The interface, e.g. IEnumString
  147. * \param piid The address of the interface, e.g. &IID_IEnumString
  148. * \param V The value type of the enumeration, e.g. LPOLESTR
  149. * \param It The iterator class, e.g. LPOLESTR*
  150. * \param Copy A class that implements copy behaviour (see CComEnumImpl)
  151. * \param ThreadModel The threading model of the instances (see CComObjectRoot)
  152. *
  153. * \note The copy_enumerator_impl class only supports copy semantics on the
  154. * Init and Add methods, i.e. it always creates its enumeration contents by
  155. * taking a copy of the contents of its source.
  156. */
  157. template< ss_typename_param_k I //!< Enumerator interface
  158. , IID const* piid //!< Enumerator interface Id
  159. , ss_typename_param_k V //!< Enumerator interface value type
  160. , ss_typename_param_k IV = V //!< Internal type. Must have value semantics
  161. , ss_typename_param_k I2ETx = copy_policy<IV, V> //!< Internal to external transformation policy
  162. , ss_typename_param_k TM = CComObjectThreadModel //!< Thread model
  163. >
  164. class ATL_NO_VTABLE copy_enumerator
  165. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  166. ;
  167. // class copy_enumerator_impl
  168. // [[synesis:class: atlstl::copy_enumerator_impl<T<I>, IID const*, T<V>, T<IV>, T<I2ETx>>]]
  169. template< ss_typename_param_k I
  170. , IID const* piid
  171. , ss_typename_param_k V
  172. , ss_typename_param_k IV
  173. , ss_typename_param_k I2ETx
  174. >
  175. class ATL_NO_VTABLE copy_enumerator_impl
  176. : public I
  177. {
  178. /// \name Member Types
  179. /// @{
  180. public:
  181. typedef I interface_type;
  182. typedef V value_type;
  183. typedef IV internal_value_type;
  184. typedef I2ETx internal_to_external_transformer_type;
  185. // typedef V const* const_pointer;
  186. typedef copy_enumerator_impl<I, piid, V, IV, I2ETx> class_type;
  187. typedef ss_size_t size_type;
  188. typedef ss_ptrdiff_t difference_type;
  189. private:
  190. typedef stlsoft_ns_qual_std(list)<internal_value_type> values_type;
  191. public:
  192. typedef ss_typename_type_k values_type::iterator iterator;
  193. typedef ss_typename_type_k values_type::const_iterator const_iterator;
  194. /// @}
  195. /// \name Construction
  196. /// @{
  197. public:
  198. copy_enumerator_impl();
  199. ~copy_enumerator_impl() stlsoft_throw_0();
  200. /// @}
  201. /// \name Enumeration
  202. /// @{
  203. public:
  204. STDMETHOD(Next)(ULONG celt, V *rgelt, ULONG *pceltFetched);
  205. STDMETHOD(Skip)(ULONG celt);
  206. STDMETHOD(Reset)(void);
  207. STDMETHOD(Clone)(I **ppEnum);
  208. /// @}
  209. /// \name Operations
  210. /// @{
  211. public:
  212. template<ss_typename_param_k I, ss_typename_param_k F>
  213. HRESULT Init(I begin, I end, F fn)
  214. {
  215. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  216. try
  217. {
  218. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  219. m_values.clear();
  220. for(; begin != end; ++begin)
  221. {
  222. m_values.push_back(fn(*begin));
  223. }
  224. m_current = m_values.begin();
  225. return S_OK;
  226. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  227. }
  228. catch(std::bad_alloc &)
  229. {
  230. return E_OUTOFMEMORY;
  231. }
  232. catch(std::exception &)
  233. {
  234. return E_UNEXPECTED;
  235. }
  236. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  237. }
  238. template<ss_typename_param_k I>
  239. HRESULT Init(I begin, I end)
  240. {
  241. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  242. try
  243. {
  244. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  245. m_values.clear();
  246. for(; begin != end; ++begin)
  247. {
  248. m_values.push_back(*begin);
  249. }
  250. m_current = m_values.begin();
  251. return S_OK;
  252. # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  253. }
  254. catch(std::bad_alloc &)
  255. {
  256. return E_OUTOFMEMORY;
  257. }
  258. catch(std::exception &)
  259. {
  260. return E_UNEXPECTED;
  261. }
  262. # endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  263. }
  264. size_type size() const;
  265. const_iterator begin() const;
  266. iterator begin();
  267. const_iterator end() const;
  268. iterator end();
  269. /// @}
  270. /// \name Implementation
  271. /// @{
  272. private:
  273. virtual class_type *CreateEmptyClone() const = 0;
  274. template <typename T>
  275. static difference_type count_all(T const& b, T const& e)
  276. {
  277. difference_type d = 0;
  278. T begin = b;
  279. T end = e;
  280. for(; begin != end; ++begin)
  281. {
  282. ++d;
  283. }
  284. return d;
  285. }
  286. template <typename T>
  287. static T increment_by(T it, difference_type by)
  288. {
  289. for(; by-- > 0; )
  290. {
  291. ++it;
  292. }
  293. return it;
  294. }
  295. /// @}
  296. /// \name Members
  297. /// @{
  298. private:
  299. values_type m_values;
  300. const_iterator m_current;
  301. /// @}
  302. /// \name Not to be implemented
  303. /// @{
  304. private:
  305. copy_enumerator_impl(class_type const&);
  306. class_type& operator =(class_type const&);
  307. /// @}
  308. };
  309. # if defined(STLSOFT_COMPILER_IS_INTEL) || \
  310. defined(STLSOFT_COMPILER_IS_MSVC)
  311. # if _MSC_VER >= 1200
  312. # pragma warning(push)
  313. # endif /* compiler */
  314. # pragma warning(disable : 4348)
  315. # endif /* compiler */
  316. // class copy_enumerator
  317. // [[synesis:class: atlstl::copy_enumerator<T<I>, IID const*, T<V>, T<IV>, T<I2ETx>, T<TM>>]]
  318. template< ss_typename_param_k I // Enumerator interface
  319. , IID const* piid // Enumerator interface Id
  320. , ss_typename_param_k V // Enumerator interface value type
  321. , ss_typename_param_k IV = V // Internal type
  322. , ss_typename_param_k I2ETx = copy_policy<IV, V> // Internal to external transformation policy
  323. , ss_typename_param_k TM = CComObjectThreadModel // Thread model
  324. >
  325. class ATL_NO_VTABLE copy_enumerator
  326. : public copy_enumerator_impl<I, piid, V, IV, I2ETx>
  327. , public CComObjectRootEx<TM>
  328. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  329. {
  330. public:
  331. typedef copy_enumerator<I, piid, V, IV, I2ETx, TM> class_type;
  332. private:
  333. typedef copy_enumerator_impl<I, piid, V, IV, I2ETx> impl_type_;
  334. public:
  335. BEGIN_COM_MAP(class_type)
  336. COM_INTERFACE_ENTRY_IID(*piid, impl_type_)
  337. END_COM_MAP()
  338. protected:
  339. virtual impl_type_ *CreateEmptyClone() const
  340. {
  341. return new CComObject<class_type>;
  342. }
  343. };
  344. #if defined(STLSOFT_COMPILER_IS_INTEL) || \
  345. defined(STLSOFT_COMPILER_IS_MSVC)
  346. # if _MSC_VER >= 1200
  347. # pragma warning(pop)
  348. # else /* ? compiler */
  349. # pragma warning(default: 4348)
  350. # endif /* _MSC_VER */
  351. #endif /* compiler */
  352. ////////////////////////////////////////////////////////////////////////////
  353. // Implementation
  354. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  355. template< ss_typename_param_k I
  356. , IID const* piid
  357. , ss_typename_param_k V
  358. , ss_typename_param_k IV
  359. , ss_typename_param_k I2ETx
  360. >
  361. inline copy_enumerator_impl<I, piid, V, IV, I2ETx>::copy_enumerator_impl()
  362. : m_values()
  363. , m_current(m_values.begin())
  364. {}
  365. template< ss_typename_param_k I
  366. , IID const* piid
  367. , ss_typename_param_k V
  368. , ss_typename_param_k IV
  369. , ss_typename_param_k I2ETx
  370. >
  371. inline copy_enumerator_impl<I, piid, V, IV, I2ETx>::~copy_enumerator_impl() stlsoft_throw_0()
  372. {}
  373. template< ss_typename_param_k I
  374. , IID const* piid
  375. , ss_typename_param_k V
  376. , ss_typename_param_k IV
  377. , ss_typename_param_k I2ETx
  378. >
  379. inline STDMETHODIMP copy_enumerator_impl<I, piid, V, IV, I2ETx>::Next(ULONG celt, V *rgelt, ULONG *pceltFetched)
  380. {
  381. HRESULT hr;
  382. if( rgelt == NULL ||
  383. ( celt != 1 &&
  384. pceltFetched == NULL))
  385. {
  386. hr = E_POINTER;
  387. }
  388. else
  389. {
  390. ULONG celtFetched_;
  391. if(NULL == pceltFetched)
  392. {
  393. pceltFetched = &celtFetched_;
  394. }
  395. { for(*pceltFetched = 0, hr = S_OK; /* SUCCEEDED(hr) && */ celt > 0 && m_current != m_values.end(); --celt, ++m_current, ++rgelt, ++*pceltFetched)
  396. {
  397. internal_to_external_transformer_type::init(rgelt);
  398. hr = internal_to_external_transformer_type::copy(rgelt, *m_current);
  399. if(FAILED(hr))
  400. {
  401. break;
  402. }
  403. }}
  404. if(FAILED(hr))
  405. {
  406. for(; 0 != *pceltFetched; --*pceltFetched)
  407. {
  408. internal_to_external_transformer_type::clear(--rgelt);
  409. }
  410. }
  411. if(SUCCEEDED(hr))
  412. {
  413. hr = (0 == celt) ? S_OK : S_FALSE;
  414. }
  415. }
  416. return hr;
  417. }
  418. template< ss_typename_param_k I
  419. , IID const* piid
  420. , ss_typename_param_k V
  421. , ss_typename_param_k IV
  422. , ss_typename_param_k I2ETx
  423. >
  424. inline STDMETHODIMP copy_enumerator_impl<I, piid, V, IV, I2ETx>::Skip(ULONG celt)
  425. {
  426. { for(; celt > 0 && m_current == m_values.end(); --celt, ++m_current)
  427. {
  428. }}
  429. return (0 == celt) ? S_OK : S_FALSE;
  430. }
  431. template< ss_typename_param_k I
  432. , IID const* piid
  433. , ss_typename_param_k V
  434. , ss_typename_param_k IV
  435. , ss_typename_param_k I2ETx
  436. >
  437. inline STDMETHODIMP copy_enumerator_impl<I, piid, V, IV, I2ETx>::Reset(void)
  438. {
  439. m_current = m_values.begin();
  440. return S_OK;
  441. }
  442. template< ss_typename_param_k I
  443. , IID const* piid
  444. , ss_typename_param_k V
  445. , ss_typename_param_k IV
  446. , ss_typename_param_k I2ETx
  447. >
  448. inline STDMETHODIMP copy_enumerator_impl<I, piid, V, IV, I2ETx>::Clone(I** ppEnum)
  449. {
  450. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  451. try
  452. {
  453. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  454. if(NULL == ppEnum)
  455. {
  456. return E_POINTER;
  457. }
  458. else
  459. {
  460. *ppEnum = NULL;
  461. HRESULT hr;
  462. class_type *pThis = this;
  463. class_type *p = pThis->CreateEmptyClone();
  464. if(p == NULL)
  465. {
  466. hr = E_OUTOFMEMORY;
  467. }
  468. else
  469. {
  470. stlsoft::ref_ptr<class_type, I> en(p, true); // Sink the instance, with a bumped (to 1) ref-count
  471. hr = p->Init(this->begin(), this->end());
  472. if(SUCCEEDED(hr))
  473. {
  474. const_iterator begin = this->m_values.begin();
  475. const_iterator current = this->m_current;
  476. std::advance(p->m_current, std::distance(begin, current));
  477. hr = en->QueryInterface(*piid, reinterpret_cast<void**>(ppEnum));
  478. }
  479. }
  480. return hr;
  481. }
  482. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  483. }
  484. catch(std::bad_alloc &)
  485. {
  486. return E_OUTOFMEMORY;
  487. }
  488. catch(std::exception &)
  489. {
  490. return E_UNEXPECTED;
  491. }
  492. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  493. }
  494. template< ss_typename_param_k I
  495. , IID const* piid
  496. , ss_typename_param_k V
  497. , ss_typename_param_k IV
  498. , ss_typename_param_k I2ETx
  499. >
  500. inline ss_size_t copy_enumerator_impl<I, piid, V, IV, I2ETx>::size() const
  501. {
  502. return m_values.size();
  503. }
  504. template< ss_typename_param_k I
  505. , IID const* piid
  506. , ss_typename_param_k V
  507. , ss_typename_param_k IV
  508. , ss_typename_param_k I2ETx
  509. >
  510. inline ss_typename_type_ret_k copy_enumerator_impl<I, piid, V, IV, I2ETx>::const_iterator copy_enumerator_impl<I, piid, V, IV, I2ETx>::begin() const
  511. {
  512. return m_values.begin();
  513. }
  514. template< ss_typename_param_k I
  515. , IID const* piid
  516. , ss_typename_param_k V
  517. , ss_typename_param_k IV
  518. , ss_typename_param_k I2ETx
  519. >
  520. inline ss_typename_type_ret_k copy_enumerator_impl<I, piid, V, IV, I2ETx>::iterator copy_enumerator_impl<I, piid, V, IV, I2ETx>::begin()
  521. {
  522. return m_values.begin();
  523. }
  524. template< ss_typename_param_k I
  525. , IID const* piid
  526. , ss_typename_param_k V
  527. , ss_typename_param_k IV
  528. , ss_typename_param_k I2ETx
  529. >
  530. inline ss_typename_type_ret_k copy_enumerator_impl<I, piid, V, IV, I2ETx>::const_iterator copy_enumerator_impl<I, piid, V, IV, I2ETx>::end() const
  531. {
  532. return m_values.end();
  533. }
  534. template< ss_typename_param_k I
  535. , IID const* piid
  536. , ss_typename_param_k V
  537. , ss_typename_param_k IV
  538. , ss_typename_param_k I2ETx
  539. >
  540. inline ss_typename_type_ret_k copy_enumerator_impl<I, piid, V, IV, I2ETx>::iterator copy_enumerator_impl<I, piid, V, IV, I2ETx>::end()
  541. {
  542. return m_values.end();
  543. }
  544. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  545. /* ////////////////////////////////////////////////////////////////////// */
  546. #ifndef _ATLSTL_NO_NAMESPACE
  547. # if defined(_STLSOFT_NO_NAMESPACE) || \
  548. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  549. } // namespace atlstl
  550. # else
  551. } // namespace atlstl_project
  552. } // namespace stlsoft
  553. # endif /* _STLSOFT_NO_NAMESPACE */
  554. #endif /* !_ATLSTL_NO_NAMESPACE */
  555. /* ////////////////////////////////////////////////////////////////////// */
  556. #endif /* ATLSTL_INCL_ATLSTL_AUTOMATION_HPP_ENUMERATORS */
  557. /* ///////////////////////////// end of file //////////////////////////// */