1 // Raw memory manipulators -*- C++ -*-
2 
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
4 // 2009, 2010, 2011
5 // Free Software Foundation, Inc.
6 //
7 // This file is part of the GNU ISO C++ Library.  This library is free
8 // software; you can redistribute it and/or modify it under the
9 // terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 3, or (at your option)
11 // any later version.
12 
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 
18 // Under Section 7 of GPL version 3, you are granted additional
19 // permissions described in the GCC Runtime Library Exception, version
20 // 3.1, as published by the Free Software Foundation.
21 
22 // You should have received a copy of the GNU General Public License and
23 // a copy of the GCC Runtime Library Exception along with this program;
24 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 // <http://www.gnu.org/licenses/>.
26 
27 /*
28  *
29  * Copyright (c) 1994
30  * Hewlett-Packard Company
31  *
32  * Permission to use, copy, modify, distribute and sell this software
33  * and its documentation for any purpose is hereby granted without fee,
34  * provided that the above copyright notice appear in all copies and
35  * that both that copyright notice and this permission notice appear
36  * in supporting documentation.  Hewlett-Packard Company makes no
37  * representations about the suitability of this software for any
38  * purpose.  It is provided "as is" without express or implied warranty.
39  *
40  *
41  * Copyright (c) 1996,1997
42  * Silicon Graphics Computer Systems, Inc.
43  *
44  * Permission to use, copy, modify, distribute and sell this software
45  * and its documentation for any purpose is hereby granted without fee,
46  * provided that the above copyright notice appear in all copies and
47  * that both that copyright notice and this permission notice appear
48  * in supporting documentation.  Silicon Graphics makes no
49  * representations about the suitability of this software for any
50  * purpose.  It is provided "as is" without express or implied warranty.
51  */
52 
53 /** @file bits/stl_uninitialized.h
54  *  This is an internal header file, included by other library headers.
55  *  Do not attempt to use it directly. @headername{memory}
56  */
57 
58 #ifndef _STL_UNINITIALIZED_H
59 #define _STL_UNINITIALIZED_H 1
60 
61 namespace std _GLIBCXX_VISIBILITY(default)
62 {
63 _GLIBCXX_BEGIN_NAMESPACE_VERSION
64 
65   template<bool _TrivialValueTypes>
66     struct __uninitialized_copy
67     {
68       template<typename _InputIterator, typename _ForwardIterator>
69         static _ForwardIterator
70         __uninit_copy(_InputIterator __first, _InputIterator __last,
71 		      _ForwardIterator __result)
72         {
73 	  _ForwardIterator __cur = __result;
74 	  __try
75 	    {
76 	      for (; __first != __last; ++__first, ++__cur)
77 		std::_Construct(std::__addressof(*__cur), *__first);
78 	      return __cur;
79 	    }
80 	  __catch(...)
81 	    {
82 	      std::_Destroy(__result, __cur);
83 	      __throw_exception_again;
84 	    }
85 	}
86     };
87 
88   template<>
89     struct __uninitialized_copy<true>
90     {
91       template<typename _InputIterator, typename _ForwardIterator>
92         static _ForwardIterator
93         __uninit_copy(_InputIterator __first, _InputIterator __last,
94 		      _ForwardIterator __result)
95         { return std::copy(__first, __last, __result); }
96     };
97 
98   /**
99    *  @brief Copies the range [first,last) into result.
100    *  @param  __first  An input iterator.
101    *  @param  __last   An input iterator.
102    *  @param  __result An output iterator.
103    *  @return   __result + (__first - __last)
104    *
105    *  Like copy(), but does not require an initialized output range.
106   */
107   template<typename _InputIterator, typename _ForwardIterator>
108     inline _ForwardIterator
109     uninitialized_copy(_InputIterator __first, _InputIterator __last,
110 		       _ForwardIterator __result)
111     {
112       typedef typename iterator_traits<_InputIterator>::value_type
113 	_ValueType1;
114       typedef typename iterator_traits<_ForwardIterator>::value_type
115 	_ValueType2;
116 
117       return std::__uninitialized_copy<(__is_trivial(_ValueType1)
118 					&& __is_trivial(_ValueType2))>::
119 	__uninit_copy(__first, __last, __result);
120     }
121 
122 
123   template<bool _TrivialValueType>
124     struct __uninitialized_fill
125     {
126       template<typename _ForwardIterator, typename _Tp>
127         static void
128         __uninit_fill(_ForwardIterator __first, _ForwardIterator __last,
129 		      const _Tp& __x)
130         {
131 	  _ForwardIterator __cur = __first;
132 	  __try
133 	    {
134 	      for (; __cur != __last; ++__cur)
135 		std::_Construct(std::__addressof(*__cur), __x);
136 	    }
137 	  __catch(...)
138 	    {
139 	      std::_Destroy(__first, __cur);
140 	      __throw_exception_again;
141 	    }
142 	}
143     };
144 
145   template<>
146     struct __uninitialized_fill<true>
147     {
148       template<typename _ForwardIterator, typename _Tp>
149         static void
150         __uninit_fill(_ForwardIterator __first, _ForwardIterator __last,
151 		      const _Tp& __x)
152         { std::fill(__first, __last, __x); }
153     };
154 
155   /**
156    *  @brief Copies the value x into the range [first,last).
157    *  @param  __first  An input iterator.
158    *  @param  __last   An input iterator.
159    *  @param  __x      The source value.
160    *  @return   Nothing.
161    *
162    *  Like fill(), but does not require an initialized output range.
163   */
164   template<typename _ForwardIterator, typename _Tp>
165     inline void
166     uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last,
167 		       const _Tp& __x)
168     {
169       typedef typename iterator_traits<_ForwardIterator>::value_type
170 	_ValueType;
171 
172       std::__uninitialized_fill<__is_trivial(_ValueType)>::
173 	__uninit_fill(__first, __last, __x);
174     }
175 
176 
177   template<bool _TrivialValueType>
178     struct __uninitialized_fill_n
179     {
180       template<typename _ForwardIterator, typename _Size, typename _Tp>
181         static void
182         __uninit_fill_n(_ForwardIterator __first, _Size __n,
183 			const _Tp& __x)
184         {
185 	  _ForwardIterator __cur = __first;
186 	  __try
187 	    {
188 	      for (; __n > 0; --__n, ++__cur)
189 		std::_Construct(std::__addressof(*__cur), __x);
190 	    }
191 	  __catch(...)
192 	    {
193 	      std::_Destroy(__first, __cur);
194 	      __throw_exception_again;
195 	    }
196 	}
197     };
198 
199   template<>
200     struct __uninitialized_fill_n<true>
201     {
202       template<typename _ForwardIterator, typename _Size, typename _Tp>
203         static void
204         __uninit_fill_n(_ForwardIterator __first, _Size __n,
205 			const _Tp& __x)
206         { std::fill_n(__first, __n, __x); }
207     };
208 
209   /**
210    *  @brief Copies the value x into the range [first,first+n).
211    *  @param  __first  An input iterator.
212    *  @param  __n      The number of copies to make.
213    *  @param  __x      The source value.
214    *  @return   Nothing.
215    *
216    *  Like fill_n(), but does not require an initialized output range.
217   */
218   template<typename _ForwardIterator, typename _Size, typename _Tp>
219     inline void
220     uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
221     {
222       typedef typename iterator_traits<_ForwardIterator>::value_type
223 	_ValueType;
224 
225       std::__uninitialized_fill_n<__is_trivial(_ValueType)>::
226 	__uninit_fill_n(__first, __n, __x);
227     }
228 
229   // Extensions: versions of uninitialized_copy, uninitialized_fill,
230   //  and uninitialized_fill_n that take an allocator parameter.
231   //  We dispatch back to the standard versions when we're given the
232   //  default allocator.  For nondefault allocators we do not use
233   //  any of the POD optimizations.
234 
235   template<typename _InputIterator, typename _ForwardIterator,
236 	   typename _Allocator>
237     _ForwardIterator
238     __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
239 			   _ForwardIterator __result, _Allocator& __alloc)
240     {
241       _ForwardIterator __cur = __result;
242       __try
243 	{
244 	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
245 	  for (; __first != __last; ++__first, ++__cur)
246 	    __traits::construct(__alloc, std::__addressof(*__cur), *__first);
247 	  return __cur;
248 	}
249       __catch(...)
250 	{
251 	  std::_Destroy(__result, __cur, __alloc);
252 	  __throw_exception_again;
253 	}
254     }
255 
256   template<typename _InputIterator, typename _ForwardIterator, typename _Tp>
257     inline _ForwardIterator
258     __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
259 			   _ForwardIterator __result, allocator<_Tp>&)
260     { return std::uninitialized_copy(__first, __last, __result); }
261 
262   template<typename _InputIterator, typename _ForwardIterator,
263 	   typename _Allocator>
264     inline _ForwardIterator
265     __uninitialized_move_a(_InputIterator __first, _InputIterator __last,
266 			   _ForwardIterator __result, _Allocator& __alloc)
267     {
268       return std::__uninitialized_copy_a(_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
269 					 _GLIBCXX_MAKE_MOVE_ITERATOR(__last),
270 					 __result, __alloc);
271     }
272 
273   template<typename _InputIterator, typename _ForwardIterator,
274 	   typename _Allocator>
275     inline _ForwardIterator
276     __uninitialized_move_if_noexcept_a(_InputIterator __first,
277 				       _InputIterator __last,
278 				       _ForwardIterator __result,
279 				       _Allocator& __alloc)
280     {
281       return std::__uninitialized_copy_a
282 	(_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first),
283 	 _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc);
284     }
285 
286   template<typename _ForwardIterator, typename _Tp, typename _Allocator>
287     void
288     __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
289 			   const _Tp& __x, _Allocator& __alloc)
290     {
291       _ForwardIterator __cur = __first;
292       __try
293 	{
294 	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
295 	  for (; __cur != __last; ++__cur)
296 	    __traits::construct(__alloc, std::__addressof(*__cur), __x);
297 	}
298       __catch(...)
299 	{
300 	  std::_Destroy(__first, __cur, __alloc);
301 	  __throw_exception_again;
302 	}
303     }
304 
305   template<typename _ForwardIterator, typename _Tp, typename _Tp2>
306     inline void
307     __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
308 			   const _Tp& __x, allocator<_Tp2>&)
309     { std::uninitialized_fill(__first, __last, __x); }
310 
311   template<typename _ForwardIterator, typename _Size, typename _Tp,
312 	   typename _Allocator>
313     void
314     __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
315 			     const _Tp& __x, _Allocator& __alloc)
316     {
317       _ForwardIterator __cur = __first;
318       __try
319 	{
320 	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
321 	  for (; __n > 0; --__n, ++__cur)
322 	    __traits::construct(__alloc, std::__addressof(*__cur), __x);
323 	}
324       __catch(...)
325 	{
326 	  std::_Destroy(__first, __cur, __alloc);
327 	  __throw_exception_again;
328 	}
329     }
330 
331   template<typename _ForwardIterator, typename _Size, typename _Tp,
332 	   typename _Tp2>
333     inline void
334     __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
335 			     const _Tp& __x, allocator<_Tp2>&)
336     { std::uninitialized_fill_n(__first, __n, __x); }
337 
338 
339   // Extensions: __uninitialized_copy_move, __uninitialized_move_copy,
340   // __uninitialized_fill_move, __uninitialized_move_fill.
341   // All of these algorithms take a user-supplied allocator, which is used
342   // for construction and destruction.
343 
344   // __uninitialized_copy_move
345   // Copies [first1, last1) into [result, result + (last1 - first1)), and
346   //  move [first2, last2) into
347   //  [result, result + (last1 - first1) + (last2 - first2)).
348   template<typename _InputIterator1, typename _InputIterator2,
349 	   typename _ForwardIterator, typename _Allocator>
350     inline _ForwardIterator
351     __uninitialized_copy_move(_InputIterator1 __first1,
352 			      _InputIterator1 __last1,
353 			      _InputIterator2 __first2,
354 			      _InputIterator2 __last2,
355 			      _ForwardIterator __result,
356 			      _Allocator& __alloc)
357     {
358       _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1,
359 							   __result,
360 							   __alloc);
361       __try
362 	{
363 	  return std::__uninitialized_move_a(__first2, __last2, __mid, __alloc);
364 	}
365       __catch(...)
366 	{
367 	  std::_Destroy(__result, __mid, __alloc);
368 	  __throw_exception_again;
369 	}
370     }
371 
372   // __uninitialized_move_copy
373   // Moves [first1, last1) into [result, result + (last1 - first1)), and
374   //  copies [first2, last2) into
375   //  [result, result + (last1 - first1) + (last2 - first2)).
376   template<typename _InputIterator1, typename _InputIterator2,
377 	   typename _ForwardIterator, typename _Allocator>
378     inline _ForwardIterator
379     __uninitialized_move_copy(_InputIterator1 __first1,
380 			      _InputIterator1 __last1,
381 			      _InputIterator2 __first2,
382 			      _InputIterator2 __last2,
383 			      _ForwardIterator __result,
384 			      _Allocator& __alloc)
385     {
386       _ForwardIterator __mid = std::__uninitialized_move_a(__first1, __last1,
387 							   __result,
388 							   __alloc);
389       __try
390 	{
391 	  return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc);
392 	}
393       __catch(...)
394 	{
395 	  std::_Destroy(__result, __mid, __alloc);
396 	  __throw_exception_again;
397 	}
398     }
399 
400   // __uninitialized_fill_move
401   // Fills [result, mid) with x, and moves [first, last) into
402   //  [mid, mid + (last - first)).
403   template<typename _ForwardIterator, typename _Tp, typename _InputIterator,
404 	   typename _Allocator>
405     inline _ForwardIterator
406     __uninitialized_fill_move(_ForwardIterator __result, _ForwardIterator __mid,
407 			      const _Tp& __x, _InputIterator __first,
408 			      _InputIterator __last, _Allocator& __alloc)
409     {
410       std::__uninitialized_fill_a(__result, __mid, __x, __alloc);
411       __try
412 	{
413 	  return std::__uninitialized_move_a(__first, __last, __mid, __alloc);
414 	}
415       __catch(...)
416 	{
417 	  std::_Destroy(__result, __mid, __alloc);
418 	  __throw_exception_again;
419 	}
420     }
421 
422   // __uninitialized_move_fill
423   // Moves [first1, last1) into [first2, first2 + (last1 - first1)), and
424   //  fills [first2 + (last1 - first1), last2) with x.
425   template<typename _InputIterator, typename _ForwardIterator, typename _Tp,
426 	   typename _Allocator>
427     inline void
428     __uninitialized_move_fill(_InputIterator __first1, _InputIterator __last1,
429 			      _ForwardIterator __first2,
430 			      _ForwardIterator __last2, const _Tp& __x,
431 			      _Allocator& __alloc)
432     {
433       _ForwardIterator __mid2 = std::__uninitialized_move_a(__first1, __last1,
434 							    __first2,
435 							    __alloc);
436       __try
437 	{
438 	  std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc);
439 	}
440       __catch(...)
441 	{
442 	  std::_Destroy(__first2, __mid2, __alloc);
443 	  __throw_exception_again;
444 	}
445     }
446 
447 #ifdef __GXX_EXPERIMENTAL_CXX0X__
448   // Extensions: __uninitialized_default, __uninitialized_default_n,
449   // __uninitialized_default_a, __uninitialized_default_n_a.
450 
451   template<bool _TrivialValueType>
452     struct __uninitialized_default_1
453     {
454       template<typename _ForwardIterator>
455         static void
456         __uninit_default(_ForwardIterator __first, _ForwardIterator __last)
457         {
458 	  _ForwardIterator __cur = __first;
459 	  __try
460 	    {
461 	      for (; __cur != __last; ++__cur)
462 		std::_Construct(std::__addressof(*__cur));
463 	    }
464 	  __catch(...)
465 	    {
466 	      std::_Destroy(__first, __cur);
467 	      __throw_exception_again;
468 	    }
469 	}
470     };
471 
472   template<>
473     struct __uninitialized_default_1<true>
474     {
475       template<typename _ForwardIterator>
476         static void
477         __uninit_default(_ForwardIterator __first, _ForwardIterator __last)
478         {
479 	  typedef typename iterator_traits<_ForwardIterator>::value_type
480 	    _ValueType;
481 
482 	  std::fill(__first, __last, _ValueType());
483 	}
484     };
485 
486   template<bool _TrivialValueType>
487     struct __uninitialized_default_n_1
488     {
489       template<typename _ForwardIterator, typename _Size>
490         static void
491         __uninit_default_n(_ForwardIterator __first, _Size __n)
492         {
493 	  _ForwardIterator __cur = __first;
494 	  __try
495 	    {
496 	      for (; __n > 0; --__n, ++__cur)
497 		std::_Construct(std::__addressof(*__cur));
498 	    }
499 	  __catch(...)
500 	    {
501 	      std::_Destroy(__first, __cur);
502 	      __throw_exception_again;
503 	    }
504 	}
505     };
506 
507   template<>
508     struct __uninitialized_default_n_1<true>
509     {
510       template<typename _ForwardIterator, typename _Size>
511         static void
512         __uninit_default_n(_ForwardIterator __first, _Size __n)
513         {
514 	  typedef typename iterator_traits<_ForwardIterator>::value_type
515 	    _ValueType;
516 
517 	  std::fill_n(__first, __n, _ValueType());
518 	}
519     };
520 
521   // __uninitialized_default
522   // Fills [first, last) with std::distance(first, last) default
523   // constructed value_types(s).
524   template<typename _ForwardIterator>
525     inline void
526     __uninitialized_default(_ForwardIterator __first,
527 			    _ForwardIterator __last)
528     {
529       typedef typename iterator_traits<_ForwardIterator>::value_type
530 	_ValueType;
531 
532       std::__uninitialized_default_1<__is_trivial(_ValueType)>::
533 	__uninit_default(__first, __last);
534     }
535 
536   // __uninitialized_default_n
537   // Fills [first, first + n) with n default constructed value_type(s).
538   template<typename _ForwardIterator, typename _Size>
539     inline void
540     __uninitialized_default_n(_ForwardIterator __first, _Size __n)
541     {
542       typedef typename iterator_traits<_ForwardIterator>::value_type
543 	_ValueType;
544 
545       std::__uninitialized_default_n_1<__is_trivial(_ValueType)>::
546 	__uninit_default_n(__first, __n);
547     }
548 
549 
550   // __uninitialized_default_a
551   // Fills [first, last) with std::distance(first, last) default
552   // constructed value_types(s), constructed with the allocator alloc.
553   template<typename _ForwardIterator, typename _Allocator>
554     void
555     __uninitialized_default_a(_ForwardIterator __first,
556 			      _ForwardIterator __last,
557 			      _Allocator& __alloc)
558     {
559       _ForwardIterator __cur = __first;
560       __try
561 	{
562 	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
563 	  for (; __cur != __last; ++__cur)
564 	    __traits::construct(__alloc, std::__addressof(*__cur));
565 	}
566       __catch(...)
567 	{
568 	  std::_Destroy(__first, __cur, __alloc);
569 	  __throw_exception_again;
570 	}
571     }
572 
573   template<typename _ForwardIterator, typename _Tp>
574     inline void
575     __uninitialized_default_a(_ForwardIterator __first,
576 			      _ForwardIterator __last,
577 			      allocator<_Tp>&)
578     { std::__uninitialized_default(__first, __last); }
579 
580 
581   // __uninitialized_default_n_a
582   // Fills [first, first + n) with n default constructed value_types(s),
583   // constructed with the allocator alloc.
584   template<typename _ForwardIterator, typename _Size, typename _Allocator>
585     void
586     __uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
587 				_Allocator& __alloc)
588     {
589       _ForwardIterator __cur = __first;
590       __try
591 	{
592 	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
593 	  for (; __n > 0; --__n, ++__cur)
594 	    __traits::construct(__alloc, std::__addressof(*__cur));
595 	}
596       __catch(...)
597 	{
598 	  std::_Destroy(__first, __cur, __alloc);
599 	  __throw_exception_again;
600 	}
601     }
602 
603   template<typename _ForwardIterator, typename _Size, typename _Tp>
604     inline void
605     __uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
606 				allocator<_Tp>&)
607     { std::__uninitialized_default_n(__first, __n); }
608 
609 
610   template<typename _InputIterator, typename _Size,
611 	   typename _ForwardIterator>
612     _ForwardIterator
613     __uninitialized_copy_n(_InputIterator __first, _Size __n,
614 			   _ForwardIterator __result, input_iterator_tag)
615     {
616       _ForwardIterator __cur = __result;
617       __try
618 	{
619 	  for (; __n > 0; --__n, ++__first, ++__cur)
620 	    std::_Construct(std::__addressof(*__cur), *__first);
621 	  return __cur;
622 	}
623       __catch(...)
624 	{
625 	  std::_Destroy(__result, __cur);
626 	  __throw_exception_again;
627 	}
628     }
629 
630   template<typename _RandomAccessIterator, typename _Size,
631 	   typename _ForwardIterator>
632     inline _ForwardIterator
633     __uninitialized_copy_n(_RandomAccessIterator __first, _Size __n,
634 			   _ForwardIterator __result,
635 			   random_access_iterator_tag)
636     { return std::uninitialized_copy(__first, __first + __n, __result); }
637 
638   /**
639    *  @brief Copies the range [first,first+n) into result.
640    *  @param  __first  An input iterator.
641    *  @param  __n      The number of elements to copy.
642    *  @param  __result An output iterator.
643    *  @return  __result + __n
644    *
645    *  Like copy_n(), but does not require an initialized output range.
646   */
647   template<typename _InputIterator, typename _Size, typename _ForwardIterator>
648     inline _ForwardIterator
649     uninitialized_copy_n(_InputIterator __first, _Size __n,
650 			 _ForwardIterator __result)
651     { return std::__uninitialized_copy_n(__first, __n, __result,
652 					 std::__iterator_category(__first)); }
653 #endif
654 
655 _GLIBCXX_END_NAMESPACE_VERSION
656 } // namespace
657 
658 #endif /* _STL_UNINITIALIZED_H */
659