1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
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 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
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 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | template<typename _Tp> |
111 | inline void |
112 | return_temporary_buffer(_Tp* __p) |
113 | { ::operator delete(__p, std::nothrow); } |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | template<typename _ForwardIterator, typename _Tp> |
122 | class _Temporary_buffer |
123 | { |
124 | |
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 | |
140 | size_type |
141 | size() const |
142 | { return _M_len; } |
143 | |
144 | |
145 | size_type |
146 | requested_size() const |
147 | { return _M_original_len; } |
148 | |
149 | |
150 | iterator |
151 | begin() |
152 | { return _M_buffer; } |
153 | |
154 | |
155 | iterator |
156 | end() |
157 | { return _M_buffer + _M_len; } |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | _Temporary_buffer(_ForwardIterator __first, _ForwardIterator __last); |
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 | |
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 | |
220 | |
221 | |
222 | |
223 | |
224 | |
225 | |
226 | |
227 | |
228 | |
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 __first, _ForwardIterator __last) |
245 | : _M_original_len(std::distance(__first, __last)), |
246 | _M_len(0), _M_buffer(0) |
247 | { |
248 | __try |
249 | { |
250 | std::pair<pointer, size_type> __p(std::get_temporary_buffer< |
251 | value_type>(_M_original_len)); |
252 | _M_buffer = __p.first; |
253 | _M_len = __p.second; |
254 | if (_M_buffer) |
255 | std::__uninitialized_construct_buf(_M_buffer, _M_buffer + _M_len, |
256 | __first); |
257 | } |
258 | __catch(...) |
259 | { |
260 | std::return_temporary_buffer(_M_buffer); |
261 | _M_buffer = 0; |
262 | _M_len = 0; |
263 | __throw_exception_again; |
264 | } |
265 | } |
266 | |
267 | _GLIBCXX_END_NAMESPACE_VERSION |
268 | } |
269 | |
270 | #endif |
271 | |
272 | |