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.

285 lines
8.4KB

  1. // Temporary buffer implementation -*- C++ -*-
  2. // Copyright (C) 2001-2020 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. pair<_Tp*, ptrdiff_t>
  89. get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT
  90. {
  91. const ptrdiff_t __max =
  92. __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp);
  93. if (__len > __max)
  94. __len = __max;
  95. while (__len > 0)
  96. {
  97. _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp),
  98. std::nothrow));
  99. if (__tmp != 0)
  100. return std::pair<_Tp*, ptrdiff_t>(__tmp, __len);
  101. __len /= 2;
  102. }
  103. return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0);
  104. }
  105. /**
  106. * @brief The companion to get_temporary_buffer().
  107. * @param __p A buffer previously allocated by get_temporary_buffer.
  108. * @return None.
  109. *
  110. * Frees the memory pointed to by __p.
  111. */
  112. template<typename _Tp>
  113. inline void
  114. return_temporary_buffer(_Tp* __p)
  115. { ::operator delete(__p); }
  116. /**
  117. * This class is used in two places: stl_algo.h and ext/memory,
  118. * where it is wrapped as the temporary_buffer class. See
  119. * temporary_buffer docs for more notes.
  120. */
  121. template<typename _ForwardIterator, typename _Tp>
  122. class _Temporary_buffer
  123. {
  124. // concept requirements
  125. __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept)
  126. public:
  127. typedef _Tp value_type;
  128. typedef value_type* pointer;
  129. typedef pointer iterator;
  130. typedef ptrdiff_t size_type;
  131. protected:
  132. size_type _M_original_len;
  133. size_type _M_len;
  134. pointer _M_buffer;
  135. public:
  136. /// As per Table mumble.
  137. size_type
  138. size() const
  139. { return _M_len; }
  140. /// Returns the size requested by the constructor; may be >size().
  141. size_type
  142. requested_size() const
  143. { return _M_original_len; }
  144. /// As per Table mumble.
  145. iterator
  146. begin()
  147. { return _M_buffer; }
  148. /// As per Table mumble.
  149. iterator
  150. end()
  151. { return _M_buffer + _M_len; }
  152. /**
  153. * Constructs a temporary buffer of a size somewhere between
  154. * zero and the given length.
  155. */
  156. _Temporary_buffer(_ForwardIterator __seed, size_type __original_len);
  157. ~_Temporary_buffer()
  158. {
  159. std::_Destroy(_M_buffer, _M_buffer + _M_len);
  160. std::__detail::__return_temporary_buffer(_M_buffer, _M_len);
  161. }
  162. private:
  163. // Disable copy constructor and assignment operator.
  164. _Temporary_buffer(const _Temporary_buffer&);
  165. void
  166. operator=(const _Temporary_buffer&);
  167. };
  168. template<bool>
  169. struct __uninitialized_construct_buf_dispatch
  170. {
  171. template<typename _Pointer, typename _ForwardIterator>
  172. static void
  173. __ucr(_Pointer __first, _Pointer __last,
  174. _ForwardIterator __seed)
  175. {
  176. if (__first == __last)
  177. return;
  178. _Pointer __cur = __first;
  179. __try
  180. {
  181. std::_Construct(std::__addressof(*__first),
  182. _GLIBCXX_MOVE(*__seed));
  183. _Pointer __prev = __cur;
  184. ++__cur;
  185. for(; __cur != __last; ++__cur, ++__prev)
  186. std::_Construct(std::__addressof(*__cur),
  187. _GLIBCXX_MOVE(*__prev));
  188. *__seed = _GLIBCXX_MOVE(*__prev);
  189. }
  190. __catch(...)
  191. {
  192. std::_Destroy(__first, __cur);
  193. __throw_exception_again;
  194. }
  195. }
  196. };
  197. template<>
  198. struct __uninitialized_construct_buf_dispatch<true>
  199. {
  200. template<typename _Pointer, typename _ForwardIterator>
  201. static void
  202. __ucr(_Pointer, _Pointer, _ForwardIterator) { }
  203. };
  204. // Constructs objects in the range [first, last).
  205. // Note that while these new objects will take valid values,
  206. // their exact value is not defined. In particular they may
  207. // be 'moved from'.
  208. //
  209. // While *__seed may be altered during this algorithm, it will have
  210. // the same value when the algorithm finishes, unless one of the
  211. // constructions throws.
  212. //
  213. // Requirements: _Pointer::value_type(_Tp&&) is valid.
  214. template<typename _Pointer, typename _ForwardIterator>
  215. inline void
  216. __uninitialized_construct_buf(_Pointer __first, _Pointer __last,
  217. _ForwardIterator __seed)
  218. {
  219. typedef typename std::iterator_traits<_Pointer>::value_type
  220. _ValueType;
  221. std::__uninitialized_construct_buf_dispatch<
  222. __has_trivial_constructor(_ValueType)>::
  223. __ucr(__first, __last, __seed);
  224. }
  225. template<typename _ForwardIterator, typename _Tp>
  226. _Temporary_buffer<_ForwardIterator, _Tp>::
  227. _Temporary_buffer(_ForwardIterator __seed, size_type __original_len)
  228. : _M_original_len(__original_len), _M_len(0), _M_buffer(0)
  229. {
  230. std::pair<pointer, size_type> __p(
  231. std::get_temporary_buffer<value_type>(_M_original_len));
  232. if (__p.first)
  233. {
  234. __try
  235. {
  236. std::__uninitialized_construct_buf(__p.first, __p.first + __p.second,
  237. __seed);
  238. _M_buffer = __p.first;
  239. _M_len = __p.second;
  240. }
  241. __catch(...)
  242. {
  243. std::__detail::__return_temporary_buffer(__p.first, __p.second);
  244. __throw_exception_again;
  245. }
  246. }
  247. }
  248. _GLIBCXX_END_NAMESPACE_VERSION
  249. } // namespace
  250. #endif /* _STL_TEMPBUF_H */