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