xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/bits/stl_tempbuf.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
14fee23f9Smrg // Temporary buffer implementation -*- C++ -*-
24fee23f9Smrg 
3b1e83836Smrg // Copyright (C) 2001-2022 Free Software Foundation, Inc.
44fee23f9Smrg //
54fee23f9Smrg // This file is part of the GNU ISO C++ Library.  This library is free
64fee23f9Smrg // software; you can redistribute it and/or modify it under the
74fee23f9Smrg // terms of the GNU General Public License as published by the
84fee23f9Smrg // Free Software Foundation; either version 3, or (at your option)
94fee23f9Smrg // any later version.
104fee23f9Smrg 
114fee23f9Smrg // This library is distributed in the hope that it will be useful,
124fee23f9Smrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
134fee23f9Smrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144fee23f9Smrg // GNU General Public License for more details.
154fee23f9Smrg 
164fee23f9Smrg // Under Section 7 of GPL version 3, you are granted additional
174fee23f9Smrg // permissions described in the GCC Runtime Library Exception, version
184fee23f9Smrg // 3.1, as published by the Free Software Foundation.
194fee23f9Smrg 
204fee23f9Smrg // You should have received a copy of the GNU General Public License and
214fee23f9Smrg // a copy of the GCC Runtime Library Exception along with this program;
224fee23f9Smrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
234fee23f9Smrg // <http://www.gnu.org/licenses/>.
244fee23f9Smrg 
254fee23f9Smrg /*
264fee23f9Smrg  *
274fee23f9Smrg  * Copyright (c) 1994
284fee23f9Smrg  * Hewlett-Packard Company
294fee23f9Smrg  *
304fee23f9Smrg  * Permission to use, copy, modify, distribute and sell this software
314fee23f9Smrg  * and its documentation for any purpose is hereby granted without fee,
324fee23f9Smrg  * provided that the above copyright notice appear in all copies and
334fee23f9Smrg  * that both that copyright notice and this permission notice appear
344fee23f9Smrg  * in supporting documentation.  Hewlett-Packard Company makes no
354fee23f9Smrg  * representations about the suitability of this software for any
364fee23f9Smrg  * purpose.  It is provided "as is" without express or implied warranty.
374fee23f9Smrg  *
384fee23f9Smrg  *
394fee23f9Smrg  * Copyright (c) 1996,1997
404fee23f9Smrg  * Silicon Graphics Computer Systems, Inc.
414fee23f9Smrg  *
424fee23f9Smrg  * Permission to use, copy, modify, distribute and sell this software
434fee23f9Smrg  * and its documentation for any purpose is hereby granted without fee,
444fee23f9Smrg  * provided that the above copyright notice appear in all copies and
454fee23f9Smrg  * that both that copyright notice and this permission notice appear
464fee23f9Smrg  * in supporting documentation.  Silicon Graphics makes no
474fee23f9Smrg  * representations about the suitability of this software for any
484fee23f9Smrg  * purpose.  It is provided "as is" without express or implied warranty.
494fee23f9Smrg  */
504fee23f9Smrg 
5148fb7bfaSmrg /** @file bits/stl_tempbuf.h
524fee23f9Smrg  *  This is an internal header file, included by other library headers.
5348fb7bfaSmrg  *  Do not attempt to use it directly. @headername{memory}
544fee23f9Smrg  */
554fee23f9Smrg 
564fee23f9Smrg #ifndef _STL_TEMPBUF_H
574fee23f9Smrg #define _STL_TEMPBUF_H 1
584fee23f9Smrg 
594fee23f9Smrg #include <bits/stl_algobase.h>
604fee23f9Smrg #include <bits/stl_construct.h>
614fee23f9Smrg 
_GLIBCXX_VISIBILITY(default)6248fb7bfaSmrg namespace std _GLIBCXX_VISIBILITY(default)
6348fb7bfaSmrg {
6448fb7bfaSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
654fee23f9Smrg 
66fb8a8121Smrg   namespace __detail
67fb8a8121Smrg   {
68fb8a8121Smrg     template<typename _Tp>
69fb8a8121Smrg       inline void
70fb8a8121Smrg       __return_temporary_buffer(_Tp* __p,
71fb8a8121Smrg 				size_t __len __attribute__((__unused__)))
72fb8a8121Smrg       {
73fb8a8121Smrg #if __cpp_sized_deallocation
74fb8a8121Smrg 	::operator delete(__p, __len * sizeof(_Tp));
75fb8a8121Smrg #else
76fb8a8121Smrg 	::operator delete(__p);
77fb8a8121Smrg #endif
78fb8a8121Smrg       }
79fb8a8121Smrg   }
80fb8a8121Smrg 
814fee23f9Smrg   /**
824fee23f9Smrg    *  @brief Allocates a temporary buffer.
8348fb7bfaSmrg    *  @param  __len  The number of objects of type Tp.
844fee23f9Smrg    *  @return See full description.
854fee23f9Smrg    *
864fee23f9Smrg    *  Reinventing the wheel, but this time with prettier spokes!
874fee23f9Smrg    *
8848fb7bfaSmrg    *  This function tries to obtain storage for @c __len adjacent Tp
894fee23f9Smrg    *  objects.  The objects themselves are not constructed, of course.
904fee23f9Smrg    *  A pair<> is returned containing <em>the buffer s address and
9148fb7bfaSmrg    *  capacity (in the units of sizeof(_Tp)), or a pair of 0 values if
924fee23f9Smrg    *  no storage can be obtained.</em>  Note that the capacity obtained
934fee23f9Smrg    *  may be less than that requested if the memory is unavailable;
944fee23f9Smrg    *  you should compare len with the .second return value.
954fee23f9Smrg    *
964fee23f9Smrg    * Provides the nothrow exception guarantee.
974fee23f9Smrg    */
984fee23f9Smrg   template<typename _Tp>
99b1e83836Smrg     _GLIBCXX17_DEPRECATED
1004fee23f9Smrg     pair<_Tp*, ptrdiff_t>
10148fb7bfaSmrg     get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT
1024fee23f9Smrg     {
1034fee23f9Smrg       const ptrdiff_t __max =
1044fee23f9Smrg 	__gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp);
1054fee23f9Smrg       if (__len > __max)
1064fee23f9Smrg 	__len = __max;
1074fee23f9Smrg 
1084fee23f9Smrg       while (__len > 0)
1094fee23f9Smrg 	{
1104fee23f9Smrg 	  _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp),
1114fee23f9Smrg 							std::nothrow));
1124fee23f9Smrg 	  if (__tmp != 0)
1134fee23f9Smrg 	    return std::pair<_Tp*, ptrdiff_t>(__tmp, __len);
114b1e83836Smrg 	  __len = __len == 1 ? 0 : ((__len + 1) / 2);
1154fee23f9Smrg 	}
1164fee23f9Smrg       return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0);
1174fee23f9Smrg     }
1184fee23f9Smrg 
1194fee23f9Smrg   /**
1204fee23f9Smrg    *  @brief The companion to get_temporary_buffer().
12148fb7bfaSmrg    *  @param  __p  A buffer previously allocated by get_temporary_buffer.
1224fee23f9Smrg    *  @return   None.
1234fee23f9Smrg    *
12448fb7bfaSmrg    *  Frees the memory pointed to by __p.
1254fee23f9Smrg    */
1264fee23f9Smrg   template<typename _Tp>
1274fee23f9Smrg     inline void
1284fee23f9Smrg     return_temporary_buffer(_Tp* __p)
129181254a7Smrg     { ::operator delete(__p); }
1304fee23f9Smrg 
1314fee23f9Smrg   /**
1324fee23f9Smrg    *  This class is used in two places: stl_algo.h and ext/memory,
1334fee23f9Smrg    *  where it is wrapped as the temporary_buffer class.  See
1344fee23f9Smrg    *  temporary_buffer docs for more notes.
1354fee23f9Smrg    */
1364fee23f9Smrg   template<typename _ForwardIterator, typename _Tp>
1374fee23f9Smrg     class _Temporary_buffer
1384fee23f9Smrg     {
1394fee23f9Smrg       // concept requirements
1404fee23f9Smrg       __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept)
1414fee23f9Smrg 
1424fee23f9Smrg     public:
1434fee23f9Smrg       typedef _Tp         value_type;
1444fee23f9Smrg       typedef value_type* pointer;
1454fee23f9Smrg       typedef pointer     iterator;
1464fee23f9Smrg       typedef ptrdiff_t   size_type;
1474fee23f9Smrg 
1484fee23f9Smrg     protected:
1494fee23f9Smrg       size_type  _M_original_len;
1504fee23f9Smrg       size_type  _M_len;
1514fee23f9Smrg       pointer    _M_buffer;
1524fee23f9Smrg 
1534fee23f9Smrg     public:
1544fee23f9Smrg       /// As per Table mumble.
1554fee23f9Smrg       size_type
1564fee23f9Smrg       size() const
1574fee23f9Smrg       { return _M_len; }
1584fee23f9Smrg 
1594fee23f9Smrg       /// Returns the size requested by the constructor; may be >size().
1604fee23f9Smrg       size_type
1614fee23f9Smrg       requested_size() const
1624fee23f9Smrg       { return _M_original_len; }
1634fee23f9Smrg 
1644fee23f9Smrg       /// As per Table mumble.
1654fee23f9Smrg       iterator
1664fee23f9Smrg       begin()
1674fee23f9Smrg       { return _M_buffer; }
1684fee23f9Smrg 
1694fee23f9Smrg       /// As per Table mumble.
1704fee23f9Smrg       iterator
1714fee23f9Smrg       end()
1724fee23f9Smrg       { return _M_buffer + _M_len; }
1734fee23f9Smrg 
1744fee23f9Smrg       /**
1754fee23f9Smrg        * Constructs a temporary buffer of a size somewhere between
176181254a7Smrg        * zero and the given length.
1774fee23f9Smrg        */
178181254a7Smrg       _Temporary_buffer(_ForwardIterator __seed, size_type __original_len);
1794fee23f9Smrg 
1804fee23f9Smrg       ~_Temporary_buffer()
1814fee23f9Smrg       {
1824fee23f9Smrg 	std::_Destroy(_M_buffer, _M_buffer + _M_len);
183fb8a8121Smrg 	std::__detail::__return_temporary_buffer(_M_buffer, _M_len);
1844fee23f9Smrg       }
1854fee23f9Smrg 
1864fee23f9Smrg     private:
1874fee23f9Smrg       // Disable copy constructor and assignment operator.
1884fee23f9Smrg       _Temporary_buffer(const _Temporary_buffer&);
1894fee23f9Smrg 
1904fee23f9Smrg       void
1914fee23f9Smrg       operator=(const _Temporary_buffer&);
1924fee23f9Smrg     };
1934fee23f9Smrg 
19448fb7bfaSmrg 
19548fb7bfaSmrg   template<bool>
19648fb7bfaSmrg     struct __uninitialized_construct_buf_dispatch
19748fb7bfaSmrg     {
19848fb7bfaSmrg       template<typename _Pointer, typename _ForwardIterator>
19948fb7bfaSmrg         static void
20048fb7bfaSmrg         __ucr(_Pointer __first, _Pointer __last,
20148fb7bfaSmrg 	      _ForwardIterator __seed)
20248fb7bfaSmrg         {
20348fb7bfaSmrg 	  if (__first == __last)
20448fb7bfaSmrg 	    return;
20548fb7bfaSmrg 
20648fb7bfaSmrg 	  _Pointer __cur = __first;
20748fb7bfaSmrg 	  __try
20848fb7bfaSmrg 	    {
20948fb7bfaSmrg 	      std::_Construct(std::__addressof(*__first),
21048fb7bfaSmrg 			      _GLIBCXX_MOVE(*__seed));
21148fb7bfaSmrg 	      _Pointer __prev = __cur;
21248fb7bfaSmrg 	      ++__cur;
21348fb7bfaSmrg 	      for(; __cur != __last; ++__cur, ++__prev)
21448fb7bfaSmrg 		std::_Construct(std::__addressof(*__cur),
21548fb7bfaSmrg 				_GLIBCXX_MOVE(*__prev));
21648fb7bfaSmrg 	      *__seed = _GLIBCXX_MOVE(*__prev);
21748fb7bfaSmrg 	    }
21848fb7bfaSmrg 	  __catch(...)
21948fb7bfaSmrg 	    {
22048fb7bfaSmrg 	      std::_Destroy(__first, __cur);
22148fb7bfaSmrg 	      __throw_exception_again;
22248fb7bfaSmrg 	    }
22348fb7bfaSmrg 	}
22448fb7bfaSmrg     };
22548fb7bfaSmrg 
22648fb7bfaSmrg   template<>
22748fb7bfaSmrg     struct __uninitialized_construct_buf_dispatch<true>
22848fb7bfaSmrg     {
22948fb7bfaSmrg       template<typename _Pointer, typename _ForwardIterator>
23048fb7bfaSmrg         static void
23148fb7bfaSmrg         __ucr(_Pointer, _Pointer, _ForwardIterator) { }
23248fb7bfaSmrg     };
23348fb7bfaSmrg 
23448fb7bfaSmrg   // Constructs objects in the range [first, last).
23548fb7bfaSmrg   // Note that while these new objects will take valid values,
23648fb7bfaSmrg   // their exact value is not defined. In particular they may
23748fb7bfaSmrg   // be 'moved from'.
23848fb7bfaSmrg   //
23948fb7bfaSmrg   // While *__seed may be altered during this algorithm, it will have
24048fb7bfaSmrg   // the same value when the algorithm finishes, unless one of the
24148fb7bfaSmrg   // constructions throws.
24248fb7bfaSmrg   //
24348fb7bfaSmrg   // Requirements: _Pointer::value_type(_Tp&&) is valid.
24448fb7bfaSmrg   template<typename _Pointer, typename _ForwardIterator>
24548fb7bfaSmrg     inline void
24648fb7bfaSmrg     __uninitialized_construct_buf(_Pointer __first, _Pointer __last,
24748fb7bfaSmrg 				  _ForwardIterator __seed)
24848fb7bfaSmrg     {
24948fb7bfaSmrg       typedef typename std::iterator_traits<_Pointer>::value_type
25048fb7bfaSmrg 	_ValueType;
25148fb7bfaSmrg 
25248fb7bfaSmrg       std::__uninitialized_construct_buf_dispatch<
25348fb7bfaSmrg         __has_trivial_constructor(_ValueType)>::
25448fb7bfaSmrg 	  __ucr(__first, __last, __seed);
25548fb7bfaSmrg     }
25648fb7bfaSmrg 
257*0a307195Smrg #pragma GCC diagnostic push
258*0a307195Smrg #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
2594fee23f9Smrg   template<typename _ForwardIterator, typename _Tp>
2604fee23f9Smrg     _Temporary_buffer<_ForwardIterator, _Tp>::
261181254a7Smrg     _Temporary_buffer(_ForwardIterator __seed, size_type __original_len)
262181254a7Smrg     : _M_original_len(__original_len), _M_len(0), _M_buffer(0)
2634fee23f9Smrg     {
264fb8a8121Smrg       std::pair<pointer, size_type> __p(
265fb8a8121Smrg 		std::get_temporary_buffer<value_type>(_M_original_len));
266fb8a8121Smrg 
267fb8a8121Smrg       if (__p.first)
268fb8a8121Smrg 	{
2694fee23f9Smrg 	  __try
2704fee23f9Smrg 	    {
271fb8a8121Smrg 	      std::__uninitialized_construct_buf(__p.first, __p.first + __p.second,
272fb8a8121Smrg 						 __seed);
2734fee23f9Smrg 	      _M_buffer = __p.first;
2744fee23f9Smrg 	      _M_len = __p.second;
2754fee23f9Smrg 	    }
2764fee23f9Smrg 	  __catch(...)
2774fee23f9Smrg 	    {
278fb8a8121Smrg 	      std::__detail::__return_temporary_buffer(__p.first, __p.second);
2794fee23f9Smrg 	      __throw_exception_again;
2804fee23f9Smrg 	    }
2814fee23f9Smrg 	}
282fb8a8121Smrg     }
283*0a307195Smrg #pragma GCC diagnostic pop
2844fee23f9Smrg 
28548fb7bfaSmrg _GLIBCXX_END_NAMESPACE_VERSION
28648fb7bfaSmrg } // namespace
2874fee23f9Smrg 
2884fee23f9Smrg #endif /* _STL_TEMPBUF_H */
289