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.

396 lines
13 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: comstl/collections/safearray_sequence.hpp
  3. *
  4. * Purpose: STL sequence for COM collection interfaces.
  5. *
  6. * Created: 17th April 2004
  7. * Updated: 10th August 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2004-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 comstl/collections/safearray_sequence.hpp
  40. *
  41. * \brief [C++ only] Definition of the comstl::safearray_sequence
  42. * collection class template
  43. * (\ref group__library__collections "Collections" Library).
  44. */
  45. #ifndef COMSTL_INCL_COMSTL_COLLECTIONS_HPP_SAFEARRAY_SEQUENCE
  46. #define COMSTL_INCL_COMSTL_COLLECTIONS_HPP_SAFEARRAY_SEQUENCE
  47. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  48. # define COMSTL_VER_COMSTL_COLLECTIONS_HPP_SAFEARRAY_SEQUENCE_MAJOR 4
  49. # define COMSTL_VER_COMSTL_COLLECTIONS_HPP_SAFEARRAY_SEQUENCE_MINOR 2
  50. # define COMSTL_VER_COMSTL_COLLECTIONS_HPP_SAFEARRAY_SEQUENCE_REVISION 1
  51. # define COMSTL_VER_COMSTL_COLLECTIONS_HPP_SAFEARRAY_SEQUENCE_EDIT 61
  52. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  53. /* /////////////////////////////////////////////////////////////////////////
  54. * Compatibility
  55. */
  56. /*
  57. [Incompatibilies-start]
  58. STLSOFT_COMPILER_IS_MSVC: _MSC_VER<1200
  59. [Incompatibilies-end]
  60. */
  61. /* /////////////////////////////////////////////////////////////////////////
  62. * Includes
  63. */
  64. #ifndef COMSTL_INCL_COMSTL_H_COMSTL
  65. # include <comstl/comstl.h>
  66. #endif /* !COMSTL_INCL_COMSTL_H_COMSTL */
  67. #if defined(STLSOFT_COMPILER_IS_MSVC) && \
  68. _MSC_VER < 1200
  69. # error comstl/collections/safearray_sequence.hpp is not compatible with Visual C++ 5.0 or earlier
  70. #endif /* compiler */
  71. #ifndef COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS
  72. # include <comstl/error/exceptions.hpp>
  73. #endif /* !COMSTL_INCL_COMSTL_ERROR_HPP_EXCEPTIONS */
  74. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  75. # include <stlsoft/util/std/iterator_helper.hpp>
  76. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  77. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  78. # include <stlsoft/collections/util/collections.hpp>
  79. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  80. #ifdef STLSOFT_UNITTEST
  81. # include <algorithm>
  82. #endif /* STLSOFT_UNITTEST */
  83. /* /////////////////////////////////////////////////////////////////////////
  84. * Namespace
  85. */
  86. #ifndef _COMSTL_NO_NAMESPACE
  87. # if defined(_STLSOFT_NO_NAMESPACE) || \
  88. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  89. /* There is no stlsoft namespace, so must define ::comstl */
  90. namespace comstl
  91. {
  92. # else
  93. /* Define stlsoft::comstl_project */
  94. namespace stlsoft
  95. {
  96. namespace comstl_project
  97. {
  98. # endif /* _STLSOFT_NO_NAMESPACE */
  99. #endif /* !_COMSTL_NO_NAMESPACE */
  100. /* /////////////////////////////////////////////////////////////////////////
  101. * Classes
  102. */
  103. /** \brief Provides an STL-iterable view over a COM SAFEARRAY
  104. *
  105. * \ingroup group__library__collections
  106. */
  107. template <ss_typename_param_k T>
  108. class safearray_sequence
  109. : public stlsoft_ns_qual(stl_collection_tag)
  110. {
  111. /// \name Member Types
  112. /// @{
  113. private:
  114. typedef SAFEARRAY const* LPCSAFEARRAY;
  115. public:
  116. /// \brief The value type
  117. typedef T value_type;
  118. /// \brief The current parameterisation of the type
  119. typedef safearray_sequence<T> class_type;
  120. /// \brief The size type
  121. typedef cs_size_t size_type;
  122. /// \brief The difference type
  123. typedef cs_ptrdiff_t difference_type;
  124. /// \brief The reference type
  125. typedef value_type& reference;
  126. /// \brief The non-mutable (const) reference type
  127. typedef value_type const& const_reference;
  128. /// \brief The pointer type
  129. typedef value_type* pointer;
  130. /// \brief The non-mutable (const) pointer type
  131. typedef value_type const* const_pointer;
  132. /// \brief The iterator type
  133. typedef
  134. #if !defined(STLSOFT_COMPILER_IS_BORLAND)
  135. ss_typename_type_k
  136. #endif /* compiler */
  137. pointer_iterator<value_type
  138. , pointer
  139. , reference
  140. >::type iterator;
  141. /// \brief The non-mutating (const) iterator type
  142. typedef
  143. #if !defined(STLSOFT_COMPILER_IS_BORLAND)
  144. ss_typename_type_k
  145. #endif /* compiler */
  146. pointer_iterator<value_type const
  147. , const_pointer
  148. , const_reference
  149. >::type const_iterator;
  150. /// \brief The non-mutating (const) reverse iterator type
  151. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  152. typedef stlsoft_ns_qual(reverse_iterator_base)< iterator
  153. , value_type
  154. , reference
  155. , pointer
  156. , difference_type
  157. > reverse_iterator;
  158. typedef stlsoft_ns_qual(const_reverse_iterator_base)< const_iterator
  159. , value_type const
  160. , const_reference
  161. , const_pointer
  162. , difference_type
  163. > const_reverse_iterator;
  164. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  165. /// @}
  166. /// \name Construction
  167. /// @{
  168. public:
  169. ss_explicit_k safearray_sequence(LPCSAFEARRAY array); // throw variant_type_exception
  170. /// @}
  171. /// \name Iteration
  172. /// @{
  173. public:
  174. /// \brief Begins the iteration
  175. ///
  176. /// \return An iterator representing the start of the sequence
  177. const_iterator begin() const;
  178. /// \brief Ends the iteration
  179. ///
  180. /// \return An iterator representing the end of the sequence
  181. const_iterator end() const;
  182. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  183. /// \brief Begins the reverse iteration
  184. ///
  185. /// \return An iterator representing the start of the reverse sequence
  186. const_reverse_iterator rbegin() const;
  187. /// \brief Ends the reverse iteration
  188. ///
  189. /// \return An iterator representing the end of the reverse sequence
  190. const_reverse_iterator rend() const;
  191. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  192. /// \brief Begins the iteration
  193. ///
  194. /// \return An iterator representing the start of the sequence
  195. iterator begin();
  196. /// \brief Ends the iteration
  197. ///
  198. /// \return An iterator representing the end of the sequence
  199. iterator end();
  200. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  201. /// \brief Begins the reverse iteration
  202. ///
  203. /// \return An iterator representing the start of the reverse sequence
  204. reverse_iterator rbegin();
  205. /// \brief Ends the reverse iteration
  206. ///
  207. /// \return An iterator representing the end of the reverse sequence
  208. reverse_iterator rend();
  209. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  210. /// @}
  211. /// \name Attributes
  212. /// @{
  213. public:
  214. /// \brief The number of elements in the array
  215. size_type size() const;
  216. /// \brief Indicates whether the array is empty
  217. bool empty() const;
  218. /// @}
  219. /// \name Direct memory access
  220. /// @{
  221. public:
  222. // void **access_data(); // Should RAII this
  223. // void unaccess_data();
  224. /// @}
  225. /// \name Implementation
  226. /// @{
  227. private:
  228. static bool type_is_compatible_(LPCSAFEARRAY array);
  229. static DWORD calc_size_(LPCSAFEARRAY array);
  230. /// @}
  231. /// \name Members
  232. /// @{
  233. private:
  234. LPCSAFEARRAY m_sa;
  235. DWORD const m_cItems;
  236. /// @}
  237. /// \name Not to be implemented
  238. /// @{
  239. private:
  240. class_type& operator =(class_type const&);
  241. /// @}
  242. };
  243. ////////////////////////////////////////////////////////////////////////////
  244. // Unit-testing
  245. #ifdef STLSOFT_UNITTEST
  246. # include "./unittest/safearray_sequence_unittest_.h"
  247. #endif /* STLSOFT_UNITTEST */
  248. ////////////////////////////////////////////////////////////////////////////
  249. // Implementation
  250. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  251. template <ss_typename_param_k T>
  252. inline /* static */ bool safearray_sequence<T>::type_is_compatible_(LPCSAFEARRAY array)
  253. {
  254. return sizeof(value_type) == array->cbElements;
  255. }
  256. template <ss_typename_param_k T>
  257. inline /* static */ DWORD safearray_sequence<T>::calc_size_(LPCSAFEARRAY array)
  258. {
  259. DWORD cItems = 1;
  260. for(USHORT dim = 0; dim < array->cDims; ++dim)
  261. {
  262. cItems *= array->rgsabound[dim].cElements;
  263. }
  264. return cItems;
  265. }
  266. template <ss_typename_param_k T>
  267. inline safearray_sequence<T>::safearray_sequence(LPCSAFEARRAY array) // throw variant_type_exception
  268. : m_sa(array)
  269. , m_cItems(calc_size_(array))
  270. {
  271. if(!type_is_compatible_(array))
  272. {
  273. STLSOFT_THROW_X(variant_type_exception("initialising safearray_sequence from safe array to incompatible type", DISP_E_BADVARTYPE));
  274. }
  275. }
  276. template <ss_typename_param_k T>
  277. inline ss_typename_type_ret_k safearray_sequence<T>::const_iterator safearray_sequence<T>::begin() const
  278. {
  279. return static_cast<pointer>(m_sa->pvData);
  280. }
  281. template <ss_typename_param_k T>
  282. inline ss_typename_type_ret_k safearray_sequence<T>::const_iterator safearray_sequence<T>::end() const
  283. {
  284. return static_cast<pointer>(m_sa->pvData) + size();
  285. }
  286. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  287. template <ss_typename_param_k T>
  288. inline ss_typename_type_ret_k safearray_sequence<T>::const_reverse_iterator safearray_sequence<T>::rbegin() const
  289. {
  290. return const_reverse_iterator(end());
  291. }
  292. template <ss_typename_param_k T>
  293. inline ss_typename_type_ret_k safearray_sequence<T>::const_reverse_iterator safearray_sequence<T>::rend() const
  294. {
  295. return const_reverse_iterator(begin());
  296. }
  297. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  298. template <ss_typename_param_k T>
  299. inline ss_typename_type_ret_k safearray_sequence<T>::iterator safearray_sequence<T>::begin()
  300. {
  301. return static_cast<pointer>(m_sa->pvData);
  302. }
  303. template <ss_typename_param_k T>
  304. inline ss_typename_type_ret_k safearray_sequence<T>::iterator safearray_sequence<T>::end()
  305. {
  306. return static_cast<pointer>(m_sa->pvData) + size();
  307. }
  308. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  309. template <ss_typename_param_k T>
  310. inline ss_typename_type_ret_k safearray_sequence<T>::reverse_iterator safearray_sequence<T>::rbegin()
  311. {
  312. return reverse_iterator(end());
  313. }
  314. template <ss_typename_param_k T>
  315. inline ss_typename_type_ret_k safearray_sequence<T>::reverse_iterator safearray_sequence<T>::rend()
  316. {
  317. return reverse_iterator(begin());
  318. }
  319. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  320. template <ss_typename_param_k T>
  321. inline ss_typename_type_ret_k safearray_sequence<T>::size_type safearray_sequence<T>::size() const
  322. {
  323. return m_cItems;
  324. }
  325. template <ss_typename_param_k T>
  326. inline bool safearray_sequence<T>::empty() const
  327. {
  328. return 0 != size();
  329. }
  330. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  331. /* ////////////////////////////////////////////////////////////////////// */
  332. #ifndef _COMSTL_NO_NAMESPACE
  333. # if defined(_STLSOFT_NO_NAMESPACE) || \
  334. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  335. } // namespace comstl
  336. # else
  337. } // namespace stlsoft::comstl_project
  338. } // namespace stlsoft
  339. # endif /* _STLSOFT_NO_NAMESPACE */
  340. #endif /* !_COMSTL_NO_NAMESPACE */
  341. /* ////////////////////////////////////////////////////////////////////// */
  342. #endif /* !COMSTL_INCL_COMSTL_COLLECTIONS_HPP_SAFEARRAY_SEQUENCE */
  343. /* ///////////////////////////// end of file //////////////////////////// */