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