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