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.

1363 lines
50 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: stlsoft/memory/auto_buffer.hpp (originally MTLocBfr.h, ::SynesisStl)
  3. *
  4. * Purpose: Contains the auto_buffer template class.
  5. *
  6. * Created: 19th January 2002
  7. * Updated: 21st June 2010
  8. *
  9. * Thanks: To Thorsten Ottosen for pointing out that allocators were
  10. * not swapped.
  11. *
  12. * Home: http://stlsoft.org/
  13. *
  14. * Copyright (c) 2002-2010, Matthew Wilson and Synesis Software
  15. * All rights reserved.
  16. *
  17. * Redistribution and use in source and binary forms, with or without
  18. * modification, are permitted provided that the following conditions are
  19. * met:
  20. *
  21. * - Redistributions of source code must retain the above copyright notice,
  22. * this list of conditions and the following disclaimer.
  23. * - Redistributions in binary form must reproduce the above copyright
  24. * notice, this list of conditions and the following disclaimer in the
  25. * documentation and/or other materials provided with the distribution.
  26. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the
  27. * names of any contributors may be used to endorse or promote products
  28. * derived from this software without specific prior written permission.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  31. * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  32. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  33. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  35. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  36. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  37. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  38. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  39. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  40. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  41. *
  42. * ////////////////////////////////////////////////////////////////////// */
  43. /** \file stlsoft/memory/auto_buffer.hpp
  44. *
  45. * \brief [C++ only] Definition of the stlsoft::auto_buffer class template
  46. * (\ref group__library__memory "Memory" Library).
  47. */
  48. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  49. #define STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER
  50. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  51. # define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_BUFFER_MAJOR 5
  52. # define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_BUFFER_MINOR 2
  53. # define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_BUFFER_REVISION 4
  54. # define STLSOFT_VER_STLSOFT_MEMORY_HPP_AUTO_BUFFER_EDIT 163
  55. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  56. /* /////////////////////////////////////////////////////////////////////////
  57. * Compatibility
  58. */
  59. /*
  60. [Incompatibilies-start]
  61. STLSOFT_COMPILER_IS_GCC: __GNUC__ < 3
  62. [Incompatibilies-end]
  63. [DocumentationStatus:Ready]
  64. */
  65. /* /////////////////////////////////////////////////////////////////////////
  66. * Includes
  67. */
  68. #ifndef STLSOFT_INCL_STLSOFT_H_STLSOFT
  69. # include <stlsoft/stlsoft.h>
  70. #endif /* !STLSOFT_INCL_STLSOFT_H_STLSOFT */
  71. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_FEATURES
  72. # include <stlsoft/memory/allocator_features.hpp> // for STLSOFT_LF_ALLOCATOR_ALLOCATE_HAS_HINT
  73. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_FEATURES */
  74. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR
  75. # include <stlsoft/memory/allocator_selector.hpp>
  76. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_SELECTOR */
  77. #ifndef STLSOFT_INCL_STLSOFT_ALGORITHMS_HPP_POD
  78. # include <stlsoft/algorithms/pod.hpp>
  79. #endif /* !STLSOFT_INCL_STLSOFT_HPP_ALGORITHMS_POD */
  80. #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP
  81. # include <stlsoft/util/std_swap.hpp>
  82. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_STD_SWAP */
  83. #ifdef _STLSOFT_AUTO_BUFFER_ALLOW_UDT
  84. # define _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
  85. # ifdef STLSOFT_CF_PRAGMA_MESSAGE_SUPPORT
  86. # pragma message("_STLSOFT_AUTO_BUFFER_ALLOW_UDT is deprecated. Use _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD instead")
  87. # endif /* STLSOFT_CF_PRAGMA_MESSAGE_SUPPORT */
  88. #endif /* _STLSOFT_AUTO_BUFFER_ALLOW_UDT */
  89. #ifndef STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER
  90. # include <stlsoft/util/std/iterator_helper.hpp>
  91. #endif /* !STLSOFT_INCL_STLSOFT_UTIL_STD_HPP_ITERATOR_HELPER */
  92. #ifndef _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
  93. # ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS
  94. # include <stlsoft/util/constraints.hpp>
  95. # endif /* !STLSOFT_INCL_STLSOFT_UTIL_HPP_CONSTRAINTS */
  96. #endif /* _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD */
  97. #ifndef STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS
  98. # include <stlsoft/collections/util/collections.hpp>
  99. #endif /* !STLSOFT_INCL_STLSOFT_COLLECTIONS_UTIL_HPP_COLLECTIONS */
  100. #ifdef STLSOFT_UNITTEST
  101. # include <algorithm>
  102. # if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  103. # include <numeric>
  104. # endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  105. # include <stdio.h>
  106. #endif /* STLSOFT_UNITTEST */
  107. /* /////////////////////////////////////////////////////////////////////////
  108. * Namespace
  109. */
  110. #ifndef _STLSOFT_NO_NAMESPACE
  111. namespace stlsoft
  112. {
  113. #endif /* _STLSOFT_NO_NAMESPACE */
  114. /* /////////////////////////////////////////////////////////////////////////
  115. * Classes
  116. */
  117. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  118. # if !defined(STLSOFT_COMPILER_IS_BORLAND) && \
  119. !defined(STLSOFT_COMPILER_IS_DMC)
  120. struct auto_buffer_internal_default
  121. {
  122. enum { min_value = 32 };
  123. enum { max_value = 256 };
  124. enum { division_factor = 2 };
  125. };
  126. template <ss_typename_param_k T>
  127. struct auto_buffer_internal_size_calculator
  128. : private auto_buffer_internal_default
  129. {
  130. private:
  131. // Stupid, stupid, stupid GCC requires them all to share the same
  132. // enum, which totally sucks. It whinges about comparisons between
  133. // enumerals (sic.) of different types. Thankfully it's irrelevant
  134. // because they're private
  135. enum
  136. {
  137. min_value = auto_buffer_internal_default::min_value
  138. , max_value = auto_buffer_internal_default::max_value
  139. , division_factor = auto_buffer_internal_default::division_factor
  140. , divided_value_ = static_cast<int>((division_factor * max_value) / sizeof(T))
  141. , divided_value = (max_value < divided_value_)
  142. ? max_value
  143. : divided_value_
  144. };
  145. public:
  146. enum { value = 1 == sizeof(T)
  147. ? max_value
  148. : divided_value < min_value
  149. ? min_value
  150. : divided_value };
  151. };
  152. STLSOFT_TEMPLATE_SPECIALISATION
  153. struct auto_buffer_internal_size_calculator<ss_char_a_t>
  154. {
  155. enum { value = auto_buffer_internal_default::max_value };
  156. };
  157. # if defined(STLSOFT_CF_NATIVE_WCHAR_T_SUPPORT) || \
  158. defined(STLSOFT_CF_TYPEDEF_WCHAR_T_SUPPORT)
  159. STLSOFT_TEMPLATE_SPECIALISATION
  160. struct auto_buffer_internal_size_calculator<ss_char_w_t>
  161. {
  162. enum { value = auto_buffer_internal_default::max_value };
  163. };
  164. # endif /* STLSOFT_CF_NATIVE_WCHAR_T_SUPPORT */
  165. # endif /* compiler */
  166. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  167. // class auto_buffer
  168. //
  169. /** \brief This class provides an efficient variable automatic buffer
  170. *
  171. * \ingroup group__library__memory
  172. *
  173. * \param T The type of the elements in the array
  174. * \param SPACE The number of elements in the array. For translators that
  175. * support default template arguments, this is defaulted to <b>256</b>
  176. * \param A The allocator type. Defaults to
  177. * \link stlsoft::allocator_selector allocator_selector<T>::allocator_type\endlink
  178. * for translators that support default template arguments.
  179. *
  180. * This class provides an efficient replacement for dynamic memory block
  181. * allocation when the block size generally falls under a predictable limit. In
  182. * such cases, significant performance benefits can be achieved by using an
  183. * instance of a parameterisation of auto_buffer, whose size parameter SPACE
  184. * is set to a level to cater for most of the requested sizes. Only where
  185. * the size of the buffer needs to be larger than this limit does an
  186. * allocation occur from the heap/free-store via the given allocator.
  187. *
  188. * Using <code>auto_buffer</code> means one can avoid use of heap memory in
  189. * circumstances where stack memory is unsuitable, i.e. where there is no
  190. * maximum size to a memory requirement, or the maximum size is potentially
  191. * very large (and considerably larger than the median size). Consider the
  192. * following code extract from the core of the
  193. * <a href = "http://pantheios.org/">Pantheios</a> logging library:
  194. \code
  195. int pantheios_log_n( pan_sev_t severity
  196. , size_t numSlices
  197. , pan_slice_t const* slices)
  198. {
  199. typedef stlsoft::auto_buffer<char, 2048> buffer_t;
  200. // Calculate the total size of the log statement, by summation of the slice array
  201. const size_t n = std::accumulate(stlsoft::member_selector(slices, &pan_slice_t::len)
  202. , stlsoft::member_selector(slices + numSlices, &pan_slice_t::len)
  203. , size_t(0));
  204. buffer_t buffer(1 + n);
  205. . . .
  206. \endcode
  207. *
  208. * This use of auto_buffer illustrates two important features:
  209. * - there is no (compile-time) limit on the maximum size of a log statement
  210. * - memory is only allocated from the heap in the case where the total statement length >= 2047 bytes.
  211. *
  212. * Without auto_buffer, we would have three choices, all bad:
  213. *
  214. * 1. We could go to the heap in all cases:
  215. \code
  216. int pantheios_log_n( pan_sev_t severity
  217. , size_t numSlices
  218. , pan_slice_t const* slices)
  219. {
  220. typedef stlsoft::vector<char> buffer_t;
  221. // Calculate the total size of the log statement, by summation of the slice array
  222. const size_t n = std::accumulate(stlsoft::member_selector(slices, &pan_slice_t::len)
  223. , stlsoft::member_selector(slices + numSlices, &pan_slice_t::len)
  224. , size_t(0));
  225. buffer_t buffer(1 + n);
  226. . . .
  227. \endcode
  228. * But this would have an unacceptable performance hit (since the vast
  229. * majority of log statements are less than 2K in extent).
  230. *
  231. * 2. We could use a stack buffer, and truncate any log statement exceeding
  232. * the limit:
  233. \code
  234. int pantheios_log_n( pan_sev_t severity
  235. , size_t numSlices
  236. , pan_slice_t const* slices)
  237. {
  238. // Calculate the total size of the log statement, by summation of the slice array
  239. const size_t n = std::accumulate(stlsoft::member_selector(slices, &pan_slice_t::len)
  240. , stlsoft::member_selector(slices + numSlices, &pan_slice_t::len)
  241. , size_t(0));
  242. char buffer[2048];
  243. . . . // make sure to truncate the statement to a max 2047 characters
  244. \endcode
  245. * But this would unnecessarily constrain users of the Pantheios logging
  246. * functionality.
  247. *
  248. * 3. Finally, we could synthesise the functionality of auto_buffer
  249. * manually, as in:
  250. \code
  251. int pantheios_log_n( pan_sev_t severity
  252. , size_t numSlices
  253. , pan_slice_t const* slices)
  254. {
  255. // Calculate the total size of the log statement, by summation of the slice array
  256. const size_t n = std::accumulate(stlsoft::member_selector(slices, &pan_slice_t::len)
  257. , stlsoft::member_selector(slices + numSlices, &pan_slice_t::len)
  258. , size_t(0));
  259. char buff[2048];
  260. char *buffer = (n < 2048) ? &buff[0] : new char[1 + n];
  261. . . .
  262. if(buffer != &buff[0])
  263. {
  264. delete [] buffer;
  265. }
  266. \endcode
  267. * But this is onerous manual fiddling, and exception-unsafe. What would be
  268. * the point, when auto_buffer already does this (safely) for us?
  269. *
  270. * As a consequence of its blending of the best features of stack and heap
  271. * memory, auto_buffer is an invaluable component in the implementation of
  272. * many components within the STLSoft libraries, and in several other
  273. * open-source projects, including:
  274. * <a href = "http://synesis.com.au/software/b64.html">b64</a>,
  275. * <a href = "http://openrj.org/">Open-RJ</a>,
  276. * <a href = "http://pantheios.org/">Pantheios</a>,
  277. * <a href = "http://recls.org/">recls</a>,
  278. * and
  279. * <a href = "http://shwild.org/">shwild</a>.
  280. *
  281. * \remarks auto_buffer works correctly whether the given allocator throws an
  282. * exception on allocation failure, or returns <code>NULL</code>. In the
  283. * latter case, construction failure to allocate is reflected by the size()
  284. * method returning 0.
  285. *
  286. * \remarks The design of auto_buffer is described in Chapter 32 of
  287. * <a href = "http://imperfectcplusplus.com">Imperfect C++</a>, and its
  288. * interface is discussed in detail in Section 16.2 of
  289. * <a href = "http://extendedstl.com">Extended STL, volume 1</a>.
  290. *
  291. * \note With version 1.9 of STLSoft, the order of the space and allocator
  292. * arguments were reversed. Further, the allocator default changed from
  293. * stlsoft::new_allocator to <code>std::allocator</code> for translators that support
  294. * the standard library. If you need the old characteristics, you can
  295. * <code>\#define</code> the symbol <b>STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS</b>.
  296. */
  297. #if defined(STLSOFT_COMPILER_IS_MSVC) && \
  298. _MSC_VER < 1200
  299. # define STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS
  300. #endif /* compiler */
  301. #if defined(STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS)
  302. # ifdef STLSOFT_AUTO_BUFFER_NEW_FORM
  303. # undef STLSOFT_AUTO_BUFFER_NEW_FORM
  304. # endif /* STLSOFT_AUTO_BUFFER_NEW_FORM */
  305. // //////////////////////////////////////////////
  306. // This is the pre-1.9 template parameter list
  307. template< ss_typename_param_k T
  308. # ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  309. , ss_typename_param_k A = ss_typename_type_def_k allocator_selector<T>::allocator_type
  310. # else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  311. , ss_typename_param_k A
  312. # endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  313. # ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT
  314. # if defined(STLSOFT_COMPILER_IS_BORLAND)
  315. , ss_size_t space = 256
  316. # elif defined(STLSOFT_COMPILER_IS_DMC)
  317. , ss_size_t SPACE = 256
  318. # else /* ? compiler */
  319. , ss_size_t SPACE = auto_buffer_internal_size_calculator<T>::value
  320. # endif /* compiler */
  321. # else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  322. # if !defined(STLSOFT_COMPILER_IS_BORLAND)
  323. , ss_size_t SPACE /* = auto_buffer_internal_size_calculator<T>::value */
  324. # else /* ? compiler */
  325. , ss_size_t space /* = 256 */
  326. # endif /* compiler */
  327. # endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT */
  328. >
  329. // End of pre-1.9 template parameter list
  330. // //////////////////////////////////////////////
  331. #else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  332. // //////////////////////////////////////////////
  333. // This is the 1.9+ template parameter list
  334. # ifndef STLSOFT_AUTO_BUFFER_NEW_FORM
  335. # define STLSOFT_AUTO_BUFFER_NEW_FORM
  336. # endif /* !STLSOFT_AUTO_BUFFER_NEW_FORM */
  337. template< ss_typename_param_k T
  338. # ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT
  339. # if defined(STLSOFT_COMPILER_IS_BORLAND)
  340. , ss_size_t space = 256
  341. # elif defined(STLSOFT_COMPILER_IS_DMC)
  342. , ss_size_t SPACE = 256
  343. # else /* ? compiler */
  344. , ss_size_t SPACE = auto_buffer_internal_size_calculator<T>::value
  345. # endif /* compiler */
  346. # else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT */
  347. # if !defined(STLSOFT_COMPILER_IS_BORLAND)
  348. , ss_size_t SPACE /* = auto_buffer_internal_size_calculator<T>::value */
  349. # else /* ? compiler */
  350. , ss_size_t space /* = 256 */
  351. # endif /* compiler */
  352. # endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT */
  353. # ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  354. , ss_typename_param_k A = ss_typename_type_def_k allocator_selector<T>::allocator_type
  355. # else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  356. , ss_typename_param_k A
  357. # endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  358. >
  359. // End of 1.9+ template parameter list
  360. // //////////////////////////////////////////////
  361. #endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  362. class auto_buffer
  363. #if !defined(STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE)
  364. : protected A
  365. , public stl_collection_tag
  366. #else /* ? STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
  367. : public stl_collection_tag
  368. #endif /* !STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
  369. {
  370. /// \name Member Types
  371. /// @{
  372. public:
  373. /// The value type
  374. typedef T value_type;
  375. /// The allocator type
  376. typedef A allocator_type;
  377. #if !defined(STLSOFT_COMPILER_IS_BORLAND)
  378. enum
  379. {
  380. /// The number of items in the internal buffer
  381. space = int(SPACE) // int() required for 64-bit compatibility
  382. };
  383. #endif /* compiler */
  384. /// The type of the current parameterisation
  385. #ifdef STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS
  386. typedef auto_buffer<T, A, space> class_type;
  387. #else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  388. typedef auto_buffer<T, space, A> class_type;
  389. #endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  390. /// The reference type
  391. typedef ss_typename_type_k allocator_type::reference reference;
  392. /// The non-mutable (const) reference type
  393. typedef ss_typename_type_k allocator_type::const_reference const_reference;
  394. /// The pointer type
  395. typedef ss_typename_type_k allocator_type::pointer pointer;
  396. /// The non-mutable (const) pointer type
  397. typedef ss_typename_type_k allocator_type::const_pointer const_pointer;
  398. /// The size type
  399. typedef ss_size_t size_type;
  400. /// The difference type
  401. typedef ss_ptrdiff_t difference_type;
  402. #if !defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  403. /// The iterator type
  404. typedef value_type* iterator;
  405. /// The non-mutable (const) iterator type
  406. typedef value_type const* const_iterator;
  407. #else /* ? !STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  408. /// The iterator type
  409. typedef
  410. # if !defined(STLSOFT_COMPILER_IS_BORLAND)
  411. ss_typename_type_k
  412. # endif /* compiler */
  413. pointer_iterator < value_type
  414. , pointer
  415. , reference
  416. >::type iterator;
  417. /// The non-mutating (const) iterator type
  418. typedef
  419. # if !defined(STLSOFT_COMPILER_IS_BORLAND)
  420. ss_typename_type_k
  421. # endif /* compiler */
  422. pointer_iterator < value_type const
  423. , const_pointer
  424. , const_reference
  425. >::type const_iterator;
  426. /// The mutating (non-const) reverse iterator type
  427. typedef reverse_iterator_base < iterator
  428. , value_type
  429. , reference
  430. , pointer
  431. , difference_type
  432. > reverse_iterator;
  433. /// The non-mutating (const) reverse iterator type
  434. typedef const_reverse_iterator_base < const_iterator
  435. , value_type const
  436. , const_reference
  437. , const_pointer
  438. , difference_type
  439. > const_reverse_iterator;
  440. #endif /* !STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  441. /// @}
  442. /// \name Implementation
  443. /// @{
  444. private:
  445. pointer allocate_(size_type cItems, void const* hint)
  446. {
  447. #ifdef STLSOFT_LF_ALLOCATOR_ALLOCATE_HAS_HINT
  448. # ifdef STLSOFT_CF_STD_LIBRARY_IS_SUNPRO_RW
  449. return static_cast<pointer>(get_allocator().allocate(cItems, const_cast<void*>(hint)));
  450. # else /* ? STLSOFT_CF_STD_LIBRARY_IS_SUNPRO_RW */
  451. return get_allocator().allocate(cItems, hint);
  452. # endif /* STLSOFT_CF_STD_LIBRARY_IS_SUNPRO_RW */
  453. #else /* ? STLSOFT_LF_ALLOCATOR_ALLOCATE_HAS_HINT */
  454. STLSOFT_SUPPRESS_UNUSED(hint);
  455. return get_allocator().allocate(cItems);
  456. #endif /* STLSOFT_LF_ALLOCATOR_ALLOCATE_HAS_HINT */
  457. }
  458. pointer allocate_(size_type cItems)
  459. {
  460. return allocate_(cItems, NULL);
  461. }
  462. void deallocate_(pointer p, size_type cItems)
  463. {
  464. STLSOFT_ASSERT(NULL != p);
  465. #ifdef STLSOFT_LF_ALLOCATOR_DEALLOCATE_HAS_COUNT
  466. get_allocator().deallocate(p, cItems);
  467. #else /* ? STLSOFT_LF_ALLOCATOR_DEALLOCATE_HAS_COUNT */
  468. STLSOFT_SUPPRESS_UNUSED(cItems);
  469. get_allocator().deallocate(p);
  470. #endif /* STLSOFT_LF_ALLOCATOR_DEALLOCATE_HAS_COUNT */
  471. }
  472. pointer reallocate_(pointer p, size_type cItems, size_type cNewItems)
  473. {
  474. pointer new_p = allocate_(cNewItems, p);
  475. // This test is needed, since some allocators may not throw
  476. // bad_alloc
  477. if(NULL != new_p)
  478. {
  479. block_copy(new_p, p, cItems);
  480. deallocate_(p, cItems);
  481. }
  482. return new_p;
  483. }
  484. protected:
  485. static void block_copy(pointer dest, const_pointer src, size_type cItems)
  486. {
  487. pod_copy_n(dest, src, cItems);
  488. }
  489. static void block_set(pointer dest, size_type cItems, const_reference value)
  490. {
  491. pod_fill_n(dest, cItems, value);
  492. }
  493. /// @}
  494. /// \name Construction
  495. /// @{
  496. public:
  497. /// \brief Constructs an auto_buffer with the given number of elements
  498. ///
  499. /// Constructs an auto_buffer with the given number of elements. If the
  500. /// allocation fails by throwing an exception, that exception is passed
  501. /// through to the caller. If allocation fails by returning a null
  502. /// pointer the auto_buffer instance is correctly constructed, and the
  503. /// \link #size size() \endlink method returns 0.
  504. ///
  505. /// \see \link #size size() \endlink
  506. /// \param cItems The number of items in the constructed instance
  507. ss_explicit_k auto_buffer(size_type cItems)
  508. : m_buffer((space < cItems) ? allocate_(cItems) : const_cast<pointer>(&m_internal[0]))
  509. , m_cItems((NULL != m_buffer) ? cItems : 0)
  510. , m_bExternal(space < cItems)
  511. {
  512. // Can't create one with an empty buffer. Though such is not legal
  513. // it is supported by some compilers, so we must ensure it cannot be
  514. // so
  515. STLSOFT_STATIC_ASSERT(0 != space);
  516. // These assertions ensure that the member ordering is not
  517. // changed, invalidating the initialisation logic of m_buffer and
  518. // m_cItems. The runtime assert is included for those compilers that
  519. // do not implement compile-time asserts.
  520. #ifdef STLSOFT_CF_USE_RAW_OFFSETOF_IN_STATIC_ASSERT
  521. STLSOFT_STATIC_ASSERT(STLSOFT_RAW_OFFSETOF(class_type, m_buffer) < STLSOFT_RAW_OFFSETOF(class_type, m_cItems));
  522. #endif /* STLSOFT_CF_USE_RAW_OFFSETOF_IN_STATIC_ASSERT */
  523. STLSOFT_MESSAGE_ASSERT("m_buffer must be before m_cItems in the auto_buffer definition", stlsoft_reinterpret_cast(ss_byte_t*, &m_buffer) < stlsoft_reinterpret_cast(ss_byte_t*, &m_cItems));
  524. #ifndef _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
  525. // Use the must_be_pod constraint to ensure that
  526. // no type is managed in auto_buffer which would result in
  527. // dangerous mismanagement of the lifetime of its instances.
  528. //
  529. // Preprocessor specification of _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD
  530. // prevents this, but the natural rules of the language will
  531. // still prevent non POD types being placed in m_internal[].
  532. stlsoft_constraint_must_be_pod(value_type);
  533. #endif /* _STLSOFT_AUTO_BUFFER_ALLOW_NON_POD */
  534. STLSOFT_ASSERT(is_valid());
  535. }
  536. /// \brief Releases the allocated element array
  537. ///
  538. /// Releases any allocated memory. If the internal memory buffer was
  539. /// used, then nothing is done, otherwise the allocated memory is
  540. /// returned to the allocator.
  541. #if defined(STLSOFT_CF_EXCEPTION_SIGNATURE_SUPPORT)
  542. ~auto_buffer()
  543. #else /* ? STLSOFT_CF_EXCEPTION_SIGNATURE_SUPPORT */
  544. ~auto_buffer() stlsoft_throw_0()
  545. #endif /* STLSOFT_CF_EXCEPTION_SIGNATURE_SUPPORT */
  546. {
  547. STLSOFT_ASSERT(is_valid());
  548. if(is_in_external_array_())
  549. {
  550. STLSOFT_ASSERT(NULL != m_buffer);
  551. STLSOFT_ASSERT(m_bExternal);
  552. STLSOFT_ASSERT(&m_internal[0] != m_buffer);
  553. deallocate_(m_buffer, m_cItems);
  554. }
  555. }
  556. /// @}
  557. /// \name Operations
  558. /// @{
  559. private:
  560. // Policy functions
  561. ss_bool_t is_in_external_array_() const
  562. {
  563. #if defined(STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK)
  564. // Old implementation always uses internal array if size() <= internal_size()
  565. STLSOFT_ASSERT((space < m_cItems) == (m_buffer != &m_internal[0]));
  566. return space < m_cItems;
  567. #else /* ? STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK */
  568. // Old implementation always uses internal array if size() <= internal_size()
  569. // STLSOFT_ASSERT((m_buffer != &m_internal[0]) || !(space < m_cItems));
  570. STLSOFT_ASSERT((m_buffer != &m_internal[0]) == m_bExternal);
  571. STLSOFT_ASSERT(m_bExternal || !(space < m_cItems));
  572. // return m_buffer != &m_internal[0];
  573. return m_bExternal;
  574. #endif /* STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK */
  575. }
  576. public:
  577. /// \brief Expands or contracts the number of items in the buffer
  578. ///
  579. /// \param cItems The number of items to change in the buffer. If 0, the
  580. /// external array (if allocated) will be deallocated.
  581. /// \return Returns \c true if successful. Function failure occurs when
  582. /// sufficient storage for the requested items cannot be allocated. In
  583. /// that case, std::bad_alloc will be throw for allocators that
  584. /// support it, otherwise the function will return \c false. In either
  585. /// case, the original storage and contents of the buffer will remain
  586. /// unchanged.
  587. ///
  588. /// \note When reducing the number of elements, the implementation
  589. /// favours speed above memory consumption. If the new item size is
  590. /// still larger than the internal storage size (\c internal_size())
  591. /// then the heap allocated block will not be changed (i.e. it will
  592. /// not be exchanged for a smaller block).
  593. ///
  594. /// \note As from STLSoft version 1.9, the external array is not
  595. /// discarded in favour of the internal array when
  596. /// <code>0 < cItems < internal_size()</code>.
  597. /// Only <code>resize(0)</code> will deallocate the external array.
  598. ss_bool_t resize(size_type cItems)
  599. {
  600. STLSOFT_ASSERT(is_valid());
  601. // There are four changes possible:
  602. //
  603. // 1. Expansion within the internal buffer
  604. // 2. Contraction within the internal buffer
  605. // 3. Expansion from the internal buffer to an allocated buffer
  606. // 4. Contraction from an allocated buffer to the internal buffer
  607. // 4.a Where n is 0, or when STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK is defined
  608. // 4.b Where 0 < n <= internal_size() - this is new behaviour - we do not go to the internal array
  609. // 5. Expansion from the allocated buffer to another allocated buffer
  610. // 6. Contraction from the allocated buffer to another allocated buffer
  611. if(m_cItems < cItems)
  612. {
  613. // Expansion; cases 1, 3 & 5
  614. if(is_in_external_array_())
  615. {
  616. // Current buffer is allocated: case 5
  617. pointer new_buffer = reallocate_(m_buffer, m_cItems, cItems);
  618. // Still test for NULL here, since some allocators will
  619. // not throw bad_alloc.
  620. if(NULL == new_buffer)
  621. {
  622. return false;
  623. }
  624. // Now repoint to the new buffer
  625. m_buffer = new_buffer;
  626. }
  627. else
  628. {
  629. // Expanding from internal buffer; cases 1 & 3
  630. if(space < cItems)
  631. {
  632. // Expanding to allocated buffer; case 3
  633. pointer new_buffer = allocate_(cItems);
  634. // Still test for NULL here, since some allocators will
  635. // not throw bad_alloc.
  636. if(NULL == new_buffer)
  637. {
  638. return false;
  639. }
  640. block_copy(new_buffer, m_buffer, m_cItems);
  641. m_buffer = new_buffer;
  642. m_bExternal = true;
  643. }
  644. else
  645. {
  646. // Expanding to internal buffer; case 1
  647. // Nothing to do
  648. STLSOFT_ASSERT(!(space < cItems));
  649. }
  650. }
  651. }
  652. else
  653. {
  654. // Contraction; cases 2, 4 & 6
  655. if(is_in_external_array_())
  656. {
  657. // Current buffer is allocated: cases 4 & 6
  658. if(space < cItems)
  659. {
  660. // Contracting within allocated buffer; case 6
  661. // Nothing to do
  662. STLSOFT_ASSERT(space < cItems);
  663. }
  664. #if defined(STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK)
  665. else
  666. #else /* ? STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK */
  667. else if(0 == cItems)
  668. #endif /* STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK */
  669. {
  670. // Contracting back to internal; case 4
  671. block_copy(const_cast<pointer>(&m_internal[0]), m_buffer, cItems);
  672. deallocate_(m_buffer, m_cItems);
  673. m_buffer = const_cast<pointer>(&m_internal[0]);
  674. m_bExternal = false;
  675. }
  676. }
  677. else
  678. {
  679. // Current buffer is internal; case 2
  680. // Nothing to do
  681. STLSOFT_ASSERT(!(space < cItems));
  682. }
  683. }
  684. m_cItems = cItems;
  685. STLSOFT_ASSERT(is_valid());
  686. return true;
  687. }
  688. /// \brief Swaps contents with the given buffer
  689. ///
  690. /// \note This method is only constant time when the memory for two buffers
  691. /// has been acquired via the allocator. Otherwise, it will depend on the
  692. /// costs of exchanging the memory
  693. ///
  694. /// \note Exception-safety: Provides the no-throw guarantee
  695. void swap(class_type& rhs) stlsoft_throw_0()
  696. {
  697. STLSOFT_ASSERT(is_valid());
  698. // Swap:
  699. //
  700. // 1. Allocator
  701. // 2. Member variables
  702. // 1. Allocator
  703. #if !defined(STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE)
  704. std_swap(static_cast<allocator_type&>(*this), static_cast<allocator_type&>(rhs));
  705. #endif /* !STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
  706. // 2. Member variables
  707. if( is_in_external_array_() &&
  708. rhs.is_in_external_array_())
  709. {
  710. // Both are allocated, so just swap them
  711. std_swap(m_buffer, rhs.m_buffer);
  712. }
  713. else if(is_in_external_array_())
  714. {
  715. // *this is allocated on the heap, rhs is using m_internal
  716. // 1. Copy the contents of rhs.m_internal to this->m_internal
  717. block_copy(&m_internal[0], &rhs.m_internal[0], rhs.m_cItems);
  718. // 2. Move m_buffer from *this to rhs
  719. rhs.m_buffer = m_buffer;
  720. // 3. Tell *this to use its internal buffer
  721. m_buffer = &m_internal[0];
  722. }
  723. else if(rhs.is_in_external_array_())
  724. {
  725. // This is a lazy cheat, but eminently effective.
  726. rhs.swap(*this);
  727. return;
  728. }
  729. else
  730. {
  731. // Both are using internal buffers, so we exchange the contents
  732. value_type t[space];
  733. block_copy(&t[0], &rhs.m_internal[0], rhs.m_cItems);
  734. block_copy(&rhs.m_internal[0], &m_internal[0], m_cItems);
  735. block_copy(&m_internal[0], &t[0], rhs.m_cItems);
  736. }
  737. std_swap(m_cItems, rhs.m_cItems);
  738. std_swap(m_bExternal, rhs.m_bExternal);
  739. STLSOFT_ASSERT(is_valid());
  740. }
  741. /// @}
  742. /// \name Operators
  743. /// @{
  744. public:
  745. // Note: The following two const and non-const implicit conversion
  746. // operators are correctly implemented. However, GCC will pedantically
  747. // give a verbose warning describing its having selected one over the
  748. // other, and this is, in current versions of the compiler, not
  749. // suppressable. The warnings must, alas, simply be ignored.
  750. #ifdef _STLSOFT_AUTO_BUFFER_ALLOW_NON_CONST_CONVERSION_OPERATOR
  751. /// \brief An implicit conversion to a pointer to the start of the element array
  752. ///
  753. /// \deprecate This is deprecated
  754. operator pointer ()
  755. {
  756. STLSOFT_ASSERT(is_valid());
  757. return m_buffer;
  758. }
  759. #else /* ? _STLSOFT_AUTO_BUFFER_ALLOW_NON_CONST_CONVERSION_OPERATOR */
  760. /// \brief Subscript operator
  761. reference operator [](size_type index)
  762. {
  763. STLSOFT_MESSAGE_ASSERT("Index is out of bounds", index <= m_cItems);
  764. STLSOFT_ASSERT(is_valid());
  765. return m_buffer[index];
  766. }
  767. /// \brief Subscript operator
  768. const_reference operator [](size_type index) const
  769. {
  770. STLSOFT_MESSAGE_ASSERT("Index is out of bounds", index <= m_cItems);
  771. STLSOFT_ASSERT(is_valid());
  772. return m_buffer[index];
  773. }
  774. #endif /* _STLSOFT_AUTO_BUFFER_ALLOW_NON_CONST_CONVERSION_OPERATOR */
  775. #ifdef _STLSOFT_AUTO_BUFFER_ALLOW_CONST_CONVERSION_OPERATOR
  776. /// \brief An implicit conversion to a pointer-to-const to the start of the element array
  777. operator const_pointer () const
  778. {
  779. STLSOFT_ASSERT(is_valid());
  780. return m_buffer;
  781. }
  782. #endif /* _STLSOFT_AUTO_BUFFER_ALLOW_CONST_CONVERSION_OPERATOR */
  783. /// @}
  784. /// \name Accessors
  785. /// @{
  786. public:
  787. /// \brief Returns a pointer to the element array
  788. pointer data()
  789. {
  790. STLSOFT_ASSERT(is_valid());
  791. return m_buffer;
  792. }
  793. /// \brief Returns a pointer-to-const to the element array
  794. const_pointer data() const
  795. {
  796. STLSOFT_ASSERT(is_valid());
  797. return m_buffer;
  798. }
  799. /// \brief Returns a reference to the last element in the buffer
  800. ///
  801. /// \pre The buffer instance must not be empty
  802. reference front()
  803. {
  804. STLSOFT_ASSERT(is_valid());
  805. STLSOFT_MESSAGE_ASSERT("Cannot call front() on an empty buffer!", !empty());
  806. return m_buffer[0];
  807. }
  808. /// \brief Returns a reference to the last element in the buffer
  809. ///
  810. /// \pre The buffer instance must not be empty
  811. reference back()
  812. {
  813. STLSOFT_ASSERT(is_valid());
  814. STLSOFT_MESSAGE_ASSERT("Cannot call back() on an empty buffer!", !empty());
  815. return m_buffer[size() - 1];
  816. }
  817. /// \brief Returns a non-mutating (const) reference to the last element
  818. /// in the buffer
  819. ///
  820. /// \pre The buffer instance must not be empty
  821. const_reference front() const
  822. {
  823. STLSOFT_ASSERT(is_valid());
  824. STLSOFT_MESSAGE_ASSERT("Cannot call front() on an empty buffer!", !empty());
  825. return m_buffer[0];
  826. }
  827. /// \brief Returns a non-mutating (const) reference to the last element
  828. /// in the buffer
  829. ///
  830. /// \pre The buffer instance must not be empty
  831. const_reference back() const
  832. {
  833. STLSOFT_ASSERT(is_valid());
  834. STLSOFT_MESSAGE_ASSERT("Cannot call back() on an empty buffer!", !empty());
  835. return m_buffer[size() - 1];
  836. }
  837. /// @}
  838. /// \name Iteration
  839. /// @{
  840. public:
  841. /// \brief Returns a non-mutating iterator representing the start of the sequence
  842. const_iterator begin() const
  843. {
  844. STLSOFT_ASSERT(is_valid());
  845. return m_buffer;
  846. }
  847. /// \brief Returns a non-mutating iterator representing the end of the sequence
  848. ///
  849. /// \note In the case where memory allocation has failed in the context
  850. /// where exceptions are not thrown for allocation failure, this method will
  851. /// return the same value as begin(). Hence, operations on the <i>empty</i>
  852. /// auto_buffer<> instance will be safe if made in respect of the range
  853. /// defined by [begin(), end()).
  854. const_iterator end() const
  855. {
  856. STLSOFT_ASSERT(is_valid());
  857. return m_buffer + m_cItems;
  858. }
  859. /// \brief Returns a mutable iterator representing the start of the sequence
  860. iterator begin()
  861. {
  862. STLSOFT_ASSERT(is_valid());
  863. return m_buffer;
  864. }
  865. /// \brief Returns a mutable iterator representing the end of the sequence
  866. ///
  867. /// \note In the case where memory allocation has failed in the context
  868. /// where exceptions are not thrown for allocation failure, this method will
  869. /// return the same value as begin(). Hence, operations on the <i>empty</i>
  870. /// auto_buffer<> instance will be safe if made in respect of the range
  871. /// defined by [begin(), end()).
  872. iterator end()
  873. {
  874. STLSOFT_ASSERT(is_valid());
  875. return m_buffer + m_cItems;
  876. }
  877. #if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  878. /// Begins the reverse iteration
  879. ///
  880. /// \return An iterator representing the start of the reverse sequence
  881. const_reverse_iterator rbegin() const
  882. {
  883. STLSOFT_ASSERT(is_valid());
  884. return const_reverse_iterator(end());
  885. }
  886. /// Ends the reverse iteration
  887. ///
  888. /// \return An iterator representing the end of the reverse sequence
  889. const_reverse_iterator rend() const
  890. {
  891. STLSOFT_ASSERT(is_valid());
  892. return const_reverse_iterator(begin());
  893. }
  894. /// Begins the reverse iteration
  895. ///
  896. /// \return An iterator representing the start of the reverse sequence
  897. reverse_iterator rbegin()
  898. {
  899. STLSOFT_ASSERT(is_valid());
  900. return reverse_iterator(end());
  901. }
  902. /// Ends the reverse iteration
  903. ///
  904. /// \return An iterator representing the end of the reverse sequence
  905. reverse_iterator rend()
  906. {
  907. STLSOFT_ASSERT(is_valid());
  908. return reverse_iterator(begin());
  909. }
  910. #endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  911. /// @}
  912. /// \name Attributes
  913. /// @{
  914. public:
  915. /// \brief Returns the number of elements in the auto_buffer
  916. ///
  917. /// \note In the case where memory allocation has failed in the context
  918. /// where exceptions are not thrown for allocation failure in the
  919. /// constructor, this method will return 0. Hence, operations on the
  920. /// <i>empty</i> auto_buffer<> instance will be safe if made in respect of
  921. /// the value returned by this method.
  922. size_type size() const
  923. {
  924. STLSOFT_ASSERT(is_valid());
  925. return m_cItems;
  926. }
  927. /// \brief Returns the number of elements in the auto_buffer's internal buffer
  928. static size_type internal_size()
  929. {
  930. return space;
  931. }
  932. /// \brief Indicates whether the buffer has any contents
  933. ///
  934. /// \note This will only ever be true when an allocation above the number
  935. /// of elements in the internal array has been requested, and failed.
  936. ss_bool_t empty() const
  937. {
  938. STLSOFT_ASSERT(is_valid());
  939. return 0 == m_cItems;
  940. }
  941. #if defined(STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVEx)
  942. /// \brief Returns an instance of the allocator used to specialise the
  943. /// instance.
  944. static allocator_type &get_allocator()
  945. {
  946. # if !defined(STLSOFT_STRICT) && \
  947. defined(STLSOFT_COMPILER_IS_MSVC) && \
  948. _MSC_VER >= 1310
  949. # pragma warning(push)
  950. # pragma warning(disable : 4640) /* "construction of local static object is not thread-safe" - since it is here! (As long as one uses a 'conformant' allocator) - maybe use a spin_mutex in future */
  951. # endif /* compiler */
  952. static allocator_type s_allocator;
  953. return s_allocator;
  954. # if !defined(STLSOFT_STRICT) && \
  955. defined(STLSOFT_COMPILER_IS_MSVC) && \
  956. _MSC_VER >= 1310
  957. # pragma warning(pop)
  958. # endif /* compiler */
  959. }
  960. #else /* ? STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
  961. /// \brief Returns an instance of the allocator used to specialise the
  962. /// instance.
  963. allocator_type get_allocator() const
  964. {
  965. # if defined(STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE)
  966. return allocator_type();
  967. # else /* ? STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
  968. return *this;
  969. # endif /* STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
  970. }
  971. #endif /* STLSOFT_CF_ALLOCATOR_BASE_EXPENSIVE */
  972. /// @}
  973. /// \name Implementation
  974. /// @{
  975. private:
  976. ss_bool_t is_valid() const
  977. {
  978. ss_bool_t bRet = true;
  979. #if defined(STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK)
  980. if( space < m_cItems &&
  981. !m_bExternal)
  982. {
  983. # ifdef STLSOFT_UNITTEST
  984. printf("auto_buffer is in external domain, but think's it isn't\n");
  985. # endif /* STLSOFT_UNITTEST */
  986. bRet = false;
  987. }
  988. if( !(space < m_cItems) &&
  989. m_bExternal)
  990. {
  991. # ifdef STLSOFT_UNITTEST
  992. printf("auto_buffer is in internal domain, but think's it isn't\n");
  993. # endif /* STLSOFT_UNITTEST */
  994. bRet = false;
  995. }
  996. #else /* ? STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK */
  997. if( space < m_cItems &&
  998. !m_bExternal)
  999. {
  1000. # ifdef STLSOFT_UNITTEST
  1001. printf("auto_buffer is in external domain, but think's it isn't\n");
  1002. # endif /* STLSOFT_UNITTEST */
  1003. bRet = false;
  1004. }
  1005. #endif /* STLSOFT_AUTO_BUFFER_AGGRESSIVE_SHRINK */
  1006. if(m_bExternal)
  1007. {
  1008. if(m_buffer == &m_internal[0])
  1009. {
  1010. #ifdef STLSOFT_UNITTEST
  1011. printf("auto_buffer is in external domain, but buffer refers to internal array\n");
  1012. #endif /* STLSOFT_UNITTEST */
  1013. bRet = false;
  1014. }
  1015. }
  1016. else
  1017. {
  1018. if(m_buffer != &m_internal[0])
  1019. {
  1020. #ifdef STLSOFT_UNITTEST
  1021. printf("auto_buffer is in internal domain, but buffer does not refer to internal array\n");
  1022. #endif /* STLSOFT_UNITTEST */
  1023. bRet = false;
  1024. }
  1025. }
  1026. return bRet;
  1027. }
  1028. /// @}
  1029. /// \name Members
  1030. /// @{
  1031. private:
  1032. pointer m_buffer; // Pointer to used buffer
  1033. size_type m_cItems; // Number of items in buffer
  1034. ss_bool_t m_bExternal; // This is required, since not allowed to compare m_buffer with &m_internal[0] - can't remember why; // NOTE: Check std
  1035. value_type m_internal[space]; // Internal storage
  1036. /// @}
  1037. // Not to be implemented
  1038. private:
  1039. auto_buffer(class_type const& rhs);
  1040. auto_buffer const& operator =(class_type const& rhs);
  1041. };
  1042. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  1043. template< ss_typename_param_k T
  1044. # ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT
  1045. , ss_typename_param_k A = ss_typename_type_def_k allocator_selector<T>::allocator_type
  1046. # else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  1047. , ss_typename_param_k A
  1048. # endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_CLASS_ARGUMENT_SUPPORT */
  1049. # ifdef STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT
  1050. # if !defined(STLSOFT_COMPILER_IS_BORLAND) && \
  1051. !defined(STLSOFT_COMPILER_IS_DMC)
  1052. , ss_size_t SPACE = auto_buffer_internal_size_calculator<T>::value
  1053. # else /* ? compiler */
  1054. , ss_size_t SPACE = 256
  1055. # endif /* compiler */
  1056. # else /* ? STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT */
  1057. , ss_size_t SPACE /* = auto_buffer_internal_size_calculator<T>::value */
  1058. # endif /* STLSOFT_CF_TEMPLATE_CLASS_DEFAULT_FUNDAMENTAL_ARGUMENT_SUPPORT */
  1059. >
  1060. class auto_buffer_old
  1061. # if defined(STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS)
  1062. : public auto_buffer<T, A, SPACE>
  1063. # else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1064. : public auto_buffer<T, SPACE, A>
  1065. # endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1066. {
  1067. /// \name Member Types
  1068. /// @{
  1069. private:
  1070. # if defined(STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS)
  1071. typedef auto_buffer<T, A, SPACE> parent_class_type;
  1072. # else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1073. typedef auto_buffer<T, SPACE, A> parent_class_type;
  1074. # endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1075. typedef auto_buffer_old<T, A, SPACE> class_type;
  1076. public:
  1077. typedef ss_typename_type_k parent_class_type::value_type value_type;
  1078. typedef ss_typename_type_k parent_class_type::allocator_type allocator_type;
  1079. typedef ss_typename_type_k parent_class_type::reference reference;
  1080. typedef ss_typename_type_k parent_class_type::const_reference const_reference;
  1081. typedef ss_typename_type_k parent_class_type::pointer pointer;
  1082. typedef ss_typename_type_k parent_class_type::const_pointer const_pointer;
  1083. typedef ss_typename_type_k parent_class_type::size_type size_type;
  1084. typedef ss_typename_type_k parent_class_type::difference_type difference_type;
  1085. typedef ss_typename_type_k parent_class_type::iterator iterator;
  1086. typedef ss_typename_type_k parent_class_type::const_iterator const_iterator;
  1087. # if defined(STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT)
  1088. typedef ss_typename_type_k parent_class_type::reverse_iterator reverse_iterator;
  1089. typedef ss_typename_type_k parent_class_type::const_reverse_iterator const_reverse_iterator;
  1090. # endif /* STLSOFT_LF_BIDIRECTIONAL_ITERATOR_SUPPORT */
  1091. /// @}
  1092. /// \name Construction
  1093. /// @{
  1094. public:
  1095. ss_explicit_k auto_buffer_old(size_type cItems)
  1096. : parent_class_type(cItems)
  1097. {}
  1098. /// @}
  1099. // Not to be implemented
  1100. private:
  1101. auto_buffer_old(class_type const& rhs);
  1102. class_type& operator =(class_type const& rhs);
  1103. };
  1104. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  1105. /* /////////////////////////////////////////////////////////////////////////
  1106. * swapping
  1107. */
  1108. #if !defined(STLSOFT_COMPILER_IS_WATCOM)
  1109. template< ss_typename_param_k T
  1110. # ifdef STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS
  1111. , ss_typename_param_k A
  1112. , ss_size_t SPACE
  1113. # else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1114. , ss_size_t SPACE
  1115. , ss_typename_param_k A
  1116. # endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1117. >
  1118. # ifdef STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS
  1119. inline void swap(auto_buffer<T, A, SPACE>& lhs, auto_buffer<T, A, SPACE>& rhs)
  1120. # else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1121. inline void swap(auto_buffer<T, SPACE, A>& lhs, auto_buffer<T, SPACE, A>& rhs)
  1122. # endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1123. {
  1124. lhs.swap(rhs);
  1125. }
  1126. #endif /* compiler */
  1127. /* /////////////////////////////////////////////////////////////////////////
  1128. * Shims
  1129. */
  1130. #ifndef STLSOFT_CF_TEMPLATE_SHIMS_NOT_SUPPORTED
  1131. template< ss_typename_param_k T
  1132. # ifdef STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS
  1133. , ss_typename_param_k A
  1134. , ss_size_t SPACE
  1135. # else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1136. , ss_size_t SPACE
  1137. , ss_typename_param_k A
  1138. # endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1139. >
  1140. # ifdef STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS
  1141. inline ss_bool_t is_empty(auto_buffer<T, A, SPACE> const& b)
  1142. # else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1143. inline ss_bool_t is_empty(auto_buffer<T, SPACE, A> const& b)
  1144. # endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1145. {
  1146. return b.empty();
  1147. }
  1148. #endif /* !STLSOFT_CF_TEMPLATE_SHIMS_NOT_SUPPORTED */
  1149. ////////////////////////////////////////////////////////////////////////////
  1150. // Unit-testing
  1151. #ifdef STLSOFT_UNITTEST
  1152. # include "./unittest/auto_buffer_unittest_.h"
  1153. #endif /* STLSOFT_UNITTEST */
  1154. /* ////////////////////////////////////////////////////////////////////// */
  1155. #ifndef _STLSOFT_NO_NAMESPACE
  1156. } // namespace stlsoft
  1157. #endif /* _STLSOFT_NO_NAMESPACE */
  1158. /* In the special case of Intel behaving as VC++ 7.0 or earlier on Win32, we
  1159. * illegally insert into the std namespace.
  1160. */
  1161. #if defined(STLSOFT_CF_std_NAMESPACE)
  1162. # if ( ( defined(STLSOFT_COMPILER_IS_INTEL) && \
  1163. defined(_MSC_VER))) && \
  1164. _MSC_VER < 1310
  1165. namespace std
  1166. {
  1167. template< ss_typename_param_k T
  1168. # ifdef STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS
  1169. , ss_typename_param_k A
  1170. , stlsoft_ns_qual(ss_size_t) SPACE
  1171. # else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1172. , stlsoft_ns_qual(ss_size_t) SPACE
  1173. , ss_typename_param_k A
  1174. # endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1175. >
  1176. # ifdef STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS
  1177. inline void swap(stlsoft_ns_qual(auto_buffer)<T, A, SPACE>& lhs, stlsoft_ns_qual(auto_buffer)<T, A, SPACE>& rhs)
  1178. # else /* ? STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1179. inline void swap(stlsoft_ns_qual(auto_buffer)<T, SPACE, A>& lhs, stlsoft_ns_qual(auto_buffer)<T, SPACE, A>& rhs)
  1180. # endif /* STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS */
  1181. {
  1182. lhs.swap(rhs);
  1183. }
  1184. } // namespace std
  1185. # endif /* INTEL && _MSC_VER < 1310 */
  1186. #endif /* STLSOFT_CF_std_NAMESPACE */
  1187. /* ////////////////////////////////////////////////////////////////////// */
  1188. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_AUTO_BUFFER */
  1189. /* ///////////////////////////// end of file //////////////////////////// */