stl_tempbuf.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // Temporary buffer implementation -*- C++ -*-
  2. // Copyright (C) 2001-2022 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /*
  21. *
  22. * Copyright (c) 1994
  23. * Hewlett-Packard Company
  24. *
  25. * Permission to use, copy, modify, distribute and sell this software
  26. * and its documentation for any purpose is hereby granted without fee,
  27. * provided that the above copyright notice appear in all copies and
  28. * that both that copyright notice and this permission notice appear
  29. * in supporting documentation. Hewlett-Packard Company makes no
  30. * representations about the suitability of this software for any
  31. * purpose. It is provided "as is" without express or implied warranty.
  32. *
  33. *
  34. * Copyright (c) 1996,1997
  35. * Silicon Graphics Computer Systems, Inc.
  36. *
  37. * Permission to use, copy, modify, distribute and sell this software
  38. * and its documentation for any purpose is hereby granted without fee,
  39. * provided that the above copyright notice appear in all copies and
  40. * that both that copyright notice and this permission notice appear
  41. * in supporting documentation. Silicon Graphics makes no
  42. * representations about the suitability of this software for any
  43. * purpose. It is provided "as is" without express or implied warranty.
  44. */
  45. /** @file bits/stl_tempbuf.h
  46. * This is an internal header file, included by other library headers.
  47. * Do not attempt to use it directly. @headername{memory}
  48. */
  49. #ifndef _STL_TEMPBUF_H
  50. #define _STL_TEMPBUF_H 1
  51. #include <bits/stl_algobase.h>
  52. #include <bits/stl_construct.h>
  53. namespace std _GLIBCXX_VISIBILITY(default)
  54. {
  55. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  56. namespace __detail
  57. {
  58. template<typename _Tp>
  59. inline void
  60. __return_temporary_buffer(_Tp* __p,
  61. size_t __len __attribute__((__unused__)))
  62. {
  63. #if __cpp_sized_deallocation
  64. ::operator delete(__p, __len * sizeof(_Tp));
  65. #else
  66. ::operator delete(__p);
  67. #endif
  68. }
  69. }
  70. /**
  71. * @brief Allocates a temporary buffer.
  72. * @param __len The number of objects of type Tp.
  73. * @return See full description.
  74. *
  75. * Reinventing the wheel, but this time with prettier spokes!
  76. *
  77. * This function tries to obtain storage for @c __len adjacent Tp
  78. * objects. The objects themselves are not constructed, of course.
  79. * A pair<> is returned containing <em>the buffer s address and
  80. * capacity (in the units of sizeof(_Tp)), or a pair of 0 values if
  81. * no storage can be obtained.</em> Note that the capacity obtained
  82. * may be less than that requested if the memory is unavailable;
  83. * you should compare len with the .second return value.
  84. *
  85. * Provides the nothrow exception guarantee.
  86. */
  87. template<typename _Tp>
  88. _GLIBCXX17_DEPRECATED
  89. pair<_Tp*, ptrdiff_t>
  90. get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT
  91. {
  92. const ptrdiff_t __max =
  93. __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp);
  94. if (__len > __max)
  95. __len = __max;
  96. while (__len > 0)
  97. {
  98. _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp),
  99. std::nothrow));
  100. if (__tmp != 0)
  101. return std::pair<_Tp*, ptrdiff_t>(__tmp, __len);
  102. __len = __len == 1 ? 0 : ((__len + 1) / 2);
  103. }
  104. return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0);
  105. }
  106. /**
  107. * @brief The companion to get_temporary_buffer().
  108. * @param __p A buffer previously allocated by get_temporary_buffer.
  109. * @return None.
  110. *
  111. * Frees the memory pointed to by __p.
  112. */
  113. template<typename _Tp>
  114. inline void
  115. return_temporary_buffer(_Tp* __p)
  116. { ::operator delete(__p); }
  117. /**
  118. * This class is used in two places: stl_algo.h and ext/memory,
  119. * where it is wrapped as the temporary_buffer class. See
  120. * temporary_buffer docs for more notes.
  121. */
  122. template<typename _ForwardIterator, typename _Tp>
  123. class _Temporary_buffer
  124. {
  125. // concept requirements
  126. __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept)
  127. public:
  128. typedef _Tp value_type;
  129. typedef value_type* pointer;
  130. typedef pointer iterator;
  131. typedef ptrdiff_t size_type;
  132. protected:
  133. size_type _M_original_len;
  134. size_type _M_len;
  135. pointer _M_buffer;
  136. public:
  137. /// As per Table mumble.
  138. size_type
  139. size() const
  140. { return _M_len; }
  141. /// Returns the size requested by the constructor; may be >size().
  142. size_type
  143. requested_size() const
  144. { return _M_original_len; }
  145. /// As per Table mumble.
  146. iterator
  147. begin()
  148. { return _M_buffer; }
  149. /// As per Table mumble.
  150. iterator
  151. end()
  152. { return _M_buffer + _M_len; }
  153. /**
  154. * Constructs a temporary buffer of a size somewhere between
  155. * zero and the given length.
  156. */
  157. _Temporary_buffer(_ForwardIterator __seed, size_type __original_len);
  158. ~_Temporary_buffer()
  159. {
  160. std::_Destroy(_M_buffer, _M_buffer + _M_len);
  161. std::__detail::__return_temporary_buffer(_M_buffer, _M_len);
  162. }
  163. private:
  164. // Disable copy constructor and assignment operator.
  165. _Temporary_buffer(const _Temporary_buffer&);
  166. void
  167. operator=(const _Temporary_buffer&);
  168. };
  169. template<bool>
  170. struct __uninitialized_construct_buf_dispatch
  171. {
  172. template<typename _Pointer, typename _ForwardIterator>
  173. static void
  174. __ucr(_Pointer __first, _Pointer __last,
  175. _ForwardIterator __seed)
  176. {
  177. if (__first == __last)
  178. return;
  179. _Pointer __cur = __first;
  180. __try
  181. {
  182. std::_Construct(std::__addressof(*__first),
  183. _GLIBCXX_MOVE(*__seed));
  184. _Pointer __prev = __cur;
  185. ++__cur;
  186. for(; __cur != __last; ++__cur, ++__prev)
  187. std::_Construct(std::__addressof(*__cur),
  188. _GLIBCXX_MOVE(*__prev));
  189. *__seed = _GLIBCXX_MOVE(*__prev);
  190. }
  191. __catch(...)
  192. {
  193. std::_Destroy(__first, __cur);
  194. __throw_exception_again;
  195. }
  196. }
  197. };
  198. template<>
  199. struct __uninitialized_construct_buf_dispatch<true>
  200. {
  201. template<typename _Pointer, typename _ForwardIterator>
  202. static void
  203. __ucr(_Pointer, _Pointer, _ForwardIterator) { }
  204. };
  205. // Constructs objects in the range [first, last).
  206. // Note that while these new objects will take valid values,
  207. // their exact value is not defined. In particular they may
  208. // be 'moved from'.
  209. //
  210. // While *__seed may be altered during this algorithm, it will have
  211. // the same value when the algorithm finishes, unless one of the
  212. // constructions throws.
  213. //
  214. // Requirements: _Pointer::value_type(_Tp&&) is valid.
  215. template<typename _Pointer, typename _ForwardIterator>
  216. inline void
  217. __uninitialized_construct_buf(_Pointer __first, _Pointer __last,
  218. _ForwardIterator __seed)
  219. {
  220. typedef typename std::iterator_traits<_Pointer>::value_type
  221. _ValueType;
  222. std::__uninitialized_construct_buf_dispatch<
  223. __has_trivial_constructor(_ValueType)>::
  224. __ucr(__first, __last, __seed);
  225. }
  226. template<typename _ForwardIterator, typename _Tp>
  227. _Temporary_buffer<_ForwardIterator, _Tp>::
  228. _Temporary_buffer(_ForwardIterator __seed, size_type __original_len)
  229. : _M_original_len(__original_len), _M_len(0), _M_buffer(0)
  230. {
  231. std::pair<pointer, size_type> __p(
  232. std::get_temporary_buffer<value_type>(_M_original_len));
  233. if (__p.first)
  234. {
  235. __try
  236. {
  237. std::__uninitialized_construct_buf(__p.first, __p.first + __p.second,
  238. __seed);
  239. _M_buffer = __p.first;
  240. _M_len = __p.second;
  241. }
  242. __catch(...)
  243. {
  244. std::__detail::__return_temporary_buffer(__p.first, __p.second);
  245. __throw_exception_again;
  246. }
  247. }
  248. }
  249. _GLIBCXX_END_NAMESPACE_VERSION
  250. } // namespace
  251. #endif /* _STL_TEMPBUF_H */