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.

436 lines
13 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/memory/heapwalk_sequence.hpp (originally MWHeapWk.h; ::SynesisWin)
  3. *
  4. * Purpose: Contains the heapwalk_sequence template class, and ANSI
  5. * and Unicode specialisations thereof.
  6. *
  7. * Notes: The original implementation of the class had the const_iterator
  8. * and value_type as nested classes. Unfortunately, Visual C++ 5 &
  9. * 6 both had either compilation or linking problems so these are
  10. * regretably now implemented as independent classes.
  11. *
  12. * Created: 15th January 2002
  13. * Updated: 10th August 2009
  14. *
  15. * Home: http://stlsoft.org/
  16. *
  17. * Copyright (c) 2002-2009, Matthew Wilson and Synesis Software
  18. * All rights reserved.
  19. *
  20. * Redistribution and use in source and binary forms, with or without
  21. * modification, are permitted provided that the following conditions are met:
  22. *
  23. * - Redistributions of source code must retain the above copyright notice, this
  24. * list of conditions and the following disclaimer.
  25. * - Redistributions in binary form must reproduce the above copyright notice,
  26. * this list of conditions and the following disclaimer in the documentation
  27. * and/or other materials provided with the distribution.
  28. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  29. * any contributors may be used to endorse or promote products derived from
  30. * this software without specific prior written permission.
  31. *
  32. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  33. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  34. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  36. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  37. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  38. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  39. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  40. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42. * POSSIBILITY OF SUCH DAMAGE.
  43. *
  44. * ////////////////////////////////////////////////////////////////////// */
  45. /** \file winstl/memory/heapwalk_sequence.hpp
  46. *
  47. * \brief [C++ only] Definition of the winstl::heapwalk_sequence class
  48. * (\ref group__library__memory "Memory" Library).
  49. */
  50. #ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_HEAPWALK_SEQUENCE
  51. #define WINSTL_INCL_WINSTL_MEMORY_HPP_HEAPWALK_SEQUENCE
  52. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  53. # define WINSTL_VER_WINSTL_MEMORY_HPP_HEAPWALK_SEQUENCE_MAJOR 4
  54. # define WINSTL_VER_WINSTL_MEMORY_HPP_HEAPWALK_SEQUENCE_MINOR 0
  55. # define WINSTL_VER_WINSTL_MEMORY_HPP_HEAPWALK_SEQUENCE_REVISION 3
  56. # define WINSTL_VER_WINSTL_MEMORY_HPP_HEAPWALK_SEQUENCE_EDIT 62
  57. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  58. /* /////////////////////////////////////////////////////////////////////////
  59. * Compatibility
  60. */
  61. /*
  62. [DocumentationStatus:Ready]
  63. */
  64. /* /////////////////////////////////////////////////////////////////////////
  65. * Includes
  66. */
  67. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  68. # include <winstl/winstl.h>
  69. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  70. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  71. # include <stlsoft/util/std/iterator_helper.hpp>
  72. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  73. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  74. # include <stlsoft/collections/util/collections.hpp>
  75. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  76. #ifdef STLSOFT_UNITTEST
  77. # include <algorithm>
  78. #endif /* STLSOFT_UNITTEST */
  79. /* /////////////////////////////////////////////////////////////////////////
  80. * Namespace
  81. */
  82. #ifndef _WINSTL_NO_NAMESPACE
  83. # if defined(_STLSOFT_NO_NAMESPACE) || \
  84. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  85. /* There is no stlsoft namespace, so must define ::winstl */
  86. namespace winstl
  87. {
  88. # else
  89. /* Define stlsoft::winstl_project */
  90. namespace stlsoft
  91. {
  92. namespace winstl_project
  93. {
  94. # endif /* _STLSOFT_NO_NAMESPACE */
  95. #endif /* !_WINSTL_NO_NAMESPACE */
  96. /* /////////////////////////////////////////////////////////////////////////
  97. * Forward declarations
  98. */
  99. class heapwalk_sequence_const_iterator;
  100. /* /////////////////////////////////////////////////////////////////////////
  101. * Classes
  102. */
  103. // class heapwalk_sequence
  104. /** \brief An STL-like sequence for walking heap allocated blocks
  105. *
  106. * \ingroup group__library__memory
  107. *
  108. * The following code illustrates the use of the class to enumerate all
  109. * currently allocated blocks in the given heap:
  110. \code
  111. HANDLE hHeap = . . . // Handle to an existing heap
  112. winstl::heapwalk_sequence blocks(hHeap);
  113. winstl::heapwalk_sequence::const_iterator b = blocks.begin();
  114. winstl::heapwalk_sequence::const_iterator e = blocks.end();
  115. for(; b != e; ++b)
  116. {
  117. printf(" Block of size %lu at %p\n", (*b).cbData, (*b).lpData);
  118. }
  119. \endcode
  120. *
  121. * If you do not specify a heap handle, the sequence uses the
  122. * process heap, as shown in the following code:
  123. \code
  124. winstl::heapwalk_sequence blocks; // Uses process heap
  125. winstl::heapwalk_sequence::const_iterator b = blocks.begin();
  126. winstl::heapwalk_sequence::const_iterator e = blocks.end();
  127. for(; b != e; ++b)
  128. {
  129. printf(" Block of size %lu at %p\n", (*b).cbData, (*b).lpData);
  130. }
  131. \endcode
  132. */
  133. class heapwalk_sequence
  134. : public stlsoft_ns_qual(stl_collection_tag)
  135. {
  136. /// \name Member Types
  137. /// @{
  138. private:
  139. typedef PROCESS_HEAP_ENTRY entry_type;
  140. public:
  141. /// \brief The class
  142. typedef heapwalk_sequence class_type;
  143. /// \brief The value type
  144. typedef entry_type const& value_type;
  145. /// \brief The non-mutating (const) iterator type
  146. typedef heapwalk_sequence_const_iterator const_iterator;
  147. /// \brief The non-mutating (const) reference type
  148. typedef entry_type const& const_reference;
  149. /// @}
  150. /// \name Construction
  151. /// @{
  152. public:
  153. /// \brief Creates an instance that walks the default process heap
  154. heapwalk_sequence();
  155. /// \brief Creates an instance that walks the given heap
  156. ///
  157. /// \note The heapwalk_sequence does <i>not</i> take ownership of the given heap handle
  158. ss_explicit_k heapwalk_sequence(HANDLE hHeap);
  159. /// Destructor
  160. ~heapwalk_sequence() stlsoft_throw_0();
  161. /// @}
  162. /// \name Iteration
  163. /// @{
  164. public:
  165. /// \brief Begins the iteration
  166. ///
  167. /// \return An iterator representing the start of the sequence
  168. const_iterator begin() const;
  169. /// \brief Ends the iteration
  170. ///
  171. /// \return An iterator representing the end of the sequence
  172. const_iterator end() const;
  173. /// @}
  174. /// \name Implementation
  175. /// @{
  176. private:
  177. friend class heapwalk_sequence_const_iterator;
  178. /// @}
  179. /// \name Members
  180. /// @{
  181. private:
  182. HANDLE m_hHeap;
  183. /// @}
  184. /// \name Not to be implemented
  185. /// @{
  186. private:
  187. heapwalk_sequence(class_type const&);
  188. heapwalk_sequence const& operator =(class_type const&);
  189. /// @}
  190. };
  191. // class heapwalk_sequence_const_iterator
  192. /** \brief Iterator for the heapwalk_sequence class
  193. *
  194. * \ingroup group__library__memory
  195. *
  196. */
  197. class heapwalk_sequence_const_iterator
  198. : public stlsoft_ns_qual(iterator_base) < winstl_ns_qual_std(forward_iterator_tag)
  199. , PROCESS_HEAP_ENTRY const
  200. , ws_ptrdiff_t
  201. , PROCESS_HEAP_ENTRY const*
  202. , PROCESS_HEAP_ENTRY const&>
  203. {
  204. /// \name Member Types
  205. /// @{
  206. private:
  207. typedef PROCESS_HEAP_ENTRY entry_type;
  208. public:
  209. /// \brief The value type
  210. typedef entry_type const value_type;
  211. /// \brief The class
  212. typedef heapwalk_sequence_const_iterator class_type;
  213. /// @}
  214. /// \name Construction
  215. /// @{
  216. private:
  217. heapwalk_sequence_const_iterator(heapwalk_sequence const& l, entry_type const& value)
  218. : m_list(&l)
  219. , m_value(value)
  220. {}
  221. heapwalk_sequence_const_iterator(heapwalk_sequence const& l);
  222. public:
  223. /// \brief Default constructor
  224. heapwalk_sequence_const_iterator();
  225. /// \brief Copy constructor
  226. heapwalk_sequence_const_iterator(class_type const& rhs);
  227. /// \brief Destructor
  228. ~heapwalk_sequence_const_iterator() stlsoft_throw_0();
  229. /// \brief Copy asignment operator
  230. heapwalk_sequence_const_iterator& operator =(class_type const& rhs);
  231. /// @}
  232. /// \name Forward Iterator methods
  233. /// @{
  234. public:
  235. /// \brief Pre-increment operator
  236. class_type& operator ++();
  237. /// \brief Post-increment operator
  238. class_type const operator ++(int);
  239. /// \brief Dereferences and returns a reference to the \c PROCESS_HEAP_ENTRY structure for the current position
  240. value_type& operator *() const;
  241. /// \brief Evaluates whether \c this and \c rhs are equivalent
  242. ws_bool_t operator ==(class_type const& rhs) const;
  243. /// \brief Evaluates whether \c this and \c rhs are not equivalent
  244. ws_bool_t operator !=(class_type const& rhs) const;
  245. /// @}
  246. /// \name Implementation
  247. /// @{
  248. private:
  249. friend class heapwalk_sequence;
  250. /// @}
  251. /// \name Members
  252. /// @{
  253. private:
  254. heapwalk_sequence const* const m_list;
  255. entry_type m_value;
  256. /// @}
  257. };
  258. ////////////////////////////////////////////////////////////////////////////
  259. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  260. // heapwalk_sequence
  261. inline heapwalk_sequence::heapwalk_sequence()
  262. : m_hHeap(::GetProcessHeap())
  263. {}
  264. inline heapwalk_sequence::heapwalk_sequence(HANDLE hHeap)
  265. : m_hHeap(hHeap)
  266. {}
  267. inline heapwalk_sequence::~heapwalk_sequence() stlsoft_throw_0()
  268. {}
  269. inline heapwalk_sequence::const_iterator heapwalk_sequence::begin() const
  270. {
  271. entry_type value;
  272. value.lpData = NULL; // Want start of iteration
  273. if(::HeapWalk(m_hHeap, &value))
  274. {
  275. return const_iterator(*this, value);
  276. }
  277. else
  278. {
  279. return const_iterator(*this);
  280. }
  281. }
  282. inline heapwalk_sequence::const_iterator heapwalk_sequence::end() const
  283. {
  284. return const_iterator(*this);
  285. }
  286. // heapwalk_sequence_const_iterator
  287. inline heapwalk_sequence_const_iterator::heapwalk_sequence_const_iterator()
  288. : m_list(NULL)
  289. {
  290. m_value.lpData = reinterpret_cast<LPVOID>(-1);
  291. }
  292. inline heapwalk_sequence_const_iterator::heapwalk_sequence_const_iterator(heapwalk_sequence const& l)
  293. : m_list(&l)
  294. {
  295. m_value.lpData = reinterpret_cast<LPVOID>(-1);
  296. }
  297. inline heapwalk_sequence_const_iterator::heapwalk_sequence_const_iterator(class_type const& rhs)
  298. : m_list(rhs.m_list)
  299. , m_value(rhs.m_value)
  300. {}
  301. inline heapwalk_sequence_const_iterator::class_type& heapwalk_sequence_const_iterator::operator =(const heapwalk_sequence_const_iterator::class_type& rhs)
  302. {
  303. WINSTL_ASSERT(m_list == rhs.m_list);
  304. m_value = rhs.m_value;
  305. return *this;
  306. }
  307. inline heapwalk_sequence_const_iterator::~heapwalk_sequence_const_iterator() stlsoft_throw_0()
  308. {}
  309. inline heapwalk_sequence_const_iterator::class_type& heapwalk_sequence_const_iterator::operator ++()
  310. {
  311. if( NULL != m_list &&
  312. !::HeapWalk(m_list->m_hHeap, &m_value))
  313. {
  314. m_value.lpData = reinterpret_cast<LPVOID>(-1);
  315. }
  316. return *this;
  317. }
  318. inline heapwalk_sequence_const_iterator::class_type const heapwalk_sequence_const_iterator::operator ++(int)
  319. {
  320. class_type it(*this);
  321. operator ++();
  322. return it;
  323. }
  324. inline heapwalk_sequence_const_iterator::value_type &heapwalk_sequence_const_iterator::operator *() const
  325. {
  326. return m_value;
  327. }
  328. inline ws_bool_t heapwalk_sequence_const_iterator::operator ==(class_type const& rhs) const
  329. {
  330. ws_bool_t eq;
  331. WINSTL_ASSERT(m_list == rhs.m_list); // Should only be comparing iterators from same container
  332. // Not equal if one but not both handles are not equal.
  333. if(m_value.lpData != rhs.m_value.lpData)
  334. {
  335. eq = ws_false_v;
  336. }
  337. else
  338. {
  339. eq = ws_true_v;
  340. }
  341. return eq;
  342. }
  343. inline ws_bool_t heapwalk_sequence_const_iterator::operator !=(class_type const& rhs) const
  344. {
  345. return ! operator ==(rhs);
  346. }
  347. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  348. ////////////////////////////////////////////////////////////////////////////
  349. // Unit-testing
  350. #ifdef STLSOFT_UNITTEST
  351. # include "./unittest/heapwalk_sequence_unittest_.h"
  352. #endif /* STLSOFT_UNITTEST */
  353. /* ////////////////////////////////////////////////////////////////////// */
  354. #ifndef _WINSTL_NO_NAMESPACE
  355. # if defined(_STLSOFT_NO_NAMESPACE) || \
  356. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  357. } // namespace winstl
  358. # else
  359. } // namespace winstl_project
  360. } // namespace stlsoft
  361. # endif /* _STLSOFT_NO_NAMESPACE */
  362. #endif /* !_WINSTL_NO_NAMESPACE */
  363. /* ////////////////////////////////////////////////////////////////////// */
  364. #endif /* WINSTL_INCL_WINSTL_MEMORY_HPP_HEAPWALK_SEQUENCE */
  365. /* ///////////////////////////// end of file //////////////////////////// */