1// Raw memory manipulators -*- C++ -*-
2
3// Copyright (C) 2001-2014 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_uninitialized.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_UNINITIALIZED_H
57#define _STL_UNINITIALIZED_H 1
58
59namespace std _GLIBCXX_VISIBILITY(default)
60{
61_GLIBCXX_BEGIN_NAMESPACE_VERSION
62
63  template<bool _TrivialValueTypes>
64    struct __uninitialized_copy
65    {
66      template<typename _InputIterator, typename _ForwardIterator>
67        static _ForwardIterator
68        __uninit_copy(_InputIterator __first, _InputIterator __last,
69		      _ForwardIterator __result)
70        {
71	  _ForwardIterator __cur = __result;
72	  __try
73	    {
74	      for (; __first != __last; ++__first, ++__cur)
75		std::_Construct(std::__addressof(*__cur), *__first);
76	      return __cur;
77	    }
78	  __catch(...)
79	    {
80	      std::_Destroy(__result, __cur);
81	      __throw_exception_again;
82	    }
83	}
84    };
85
86  template<>
87    struct __uninitialized_copy<true>
88    {
89      template<typename _InputIterator, typename _ForwardIterator>
90        static _ForwardIterator
91        __uninit_copy(_InputIterator __first, _InputIterator __last,
92		      _ForwardIterator __result)
93        { return std::copy(__first, __last, __result); }
94    };
95
96  /**
97   *  @brief Copies the range [first,last) into result.
98   *  @param  __first  An input iterator.
99   *  @param  __last   An input iterator.
100   *  @param  __result An output iterator.
101   *  @return   __result + (__first - __last)
102   *
103   *  Like copy(), but does not require an initialized output range.
104  */
105  template<typename _InputIterator, typename _ForwardIterator>
106    inline _ForwardIterator
107    uninitialized_copy(_InputIterator __first, _InputIterator __last,
108		       _ForwardIterator __result)
109    {
110      typedef typename iterator_traits<_InputIterator>::value_type
111	_ValueType1;
112      typedef typename iterator_traits<_ForwardIterator>::value_type
113	_ValueType2;
114#if __cplusplus < 201103L
115      const bool __assignable = true;
116#else
117      // trivial types can have deleted assignment
118      typedef typename iterator_traits<_InputIterator>::reference _RefType1;
119      typedef typename iterator_traits<_ForwardIterator>::reference _RefType2;
120      const bool __assignable = is_assignable<_RefType2, _RefType1>::value;
121#endif
122
123      return std::__uninitialized_copy<__is_trivial(_ValueType1)
124				       && __is_trivial(_ValueType2)
125				       && __assignable>::
126	__uninit_copy(__first, __last, __result);
127    }
128
129
130  template<bool _TrivialValueType>
131    struct __uninitialized_fill
132    {
133      template<typename _ForwardIterator, typename _Tp>
134        static void
135        __uninit_fill(_ForwardIterator __first, _ForwardIterator __last,
136		      const _Tp& __x)
137        {
138	  _ForwardIterator __cur = __first;
139	  __try
140	    {
141	      for (; __cur != __last; ++__cur)
142		std::_Construct(std::__addressof(*__cur), __x);
143	    }
144	  __catch(...)
145	    {
146	      std::_Destroy(__first, __cur);
147	      __throw_exception_again;
148	    }
149	}
150    };
151
152  template<>
153    struct __uninitialized_fill<true>
154    {
155      template<typename _ForwardIterator, typename _Tp>
156        static void
157        __uninit_fill(_ForwardIterator __first, _ForwardIterator __last,
158		      const _Tp& __x)
159        { std::fill(__first, __last, __x); }
160    };
161
162  /**
163   *  @brief Copies the value x into the range [first,last).
164   *  @param  __first  An input iterator.
165   *  @param  __last   An input iterator.
166   *  @param  __x      The source value.
167   *  @return   Nothing.
168   *
169   *  Like fill(), but does not require an initialized output range.
170  */
171  template<typename _ForwardIterator, typename _Tp>
172    inline void
173    uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last,
174		       const _Tp& __x)
175    {
176      typedef typename iterator_traits<_ForwardIterator>::value_type
177	_ValueType;
178#if __cplusplus < 201103L
179      const bool __assignable = true;
180#else
181      // trivial types can have deleted assignment
182      const bool __assignable = is_copy_assignable<_ValueType>::value;
183#endif
184
185      std::__uninitialized_fill<__is_trivial(_ValueType) && __assignable>::
186	__uninit_fill(__first, __last, __x);
187    }
188
189
190  template<bool _TrivialValueType>
191    struct __uninitialized_fill_n
192    {
193      template<typename _ForwardIterator, typename _Size, typename _Tp>
194        static void
195        __uninit_fill_n(_ForwardIterator __first, _Size __n,
196			const _Tp& __x)
197        {
198	  _ForwardIterator __cur = __first;
199	  __try
200	    {
201	      for (; __n > 0; --__n, ++__cur)
202		std::_Construct(std::__addressof(*__cur), __x);
203	    }
204	  __catch(...)
205	    {
206	      std::_Destroy(__first, __cur);
207	      __throw_exception_again;
208	    }
209	}
210    };
211
212  template<>
213    struct __uninitialized_fill_n<true>
214    {
215      template<typename _ForwardIterator, typename _Size, typename _Tp>
216        static void
217        __uninit_fill_n(_ForwardIterator __first, _Size __n,
218			const _Tp& __x)
219        { std::fill_n(__first, __n, __x); }
220    };
221
222  /**
223   *  @brief Copies the value x into the range [first,first+n).
224   *  @param  __first  An input iterator.
225   *  @param  __n      The number of copies to make.
226   *  @param  __x      The source value.
227   *  @return   Nothing.
228   *
229   *  Like fill_n(), but does not require an initialized output range.
230  */
231  template<typename _ForwardIterator, typename _Size, typename _Tp>
232    inline void
233    uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
234    {
235      typedef typename iterator_traits<_ForwardIterator>::value_type
236	_ValueType;
237#if __cplusplus < 201103L
238      const bool __assignable = true;
239#else
240      // trivial types can have deleted assignment
241      const bool __assignable = is_copy_assignable<_ValueType>::value;
242#endif
243
244      std::__uninitialized_fill_n<__is_trivial(_ValueType) && __assignable>::
245	__uninit_fill_n(__first, __n, __x);
246    }
247
248  // Extensions: versions of uninitialized_copy, uninitialized_fill,
249  //  and uninitialized_fill_n that take an allocator parameter.
250  //  We dispatch back to the standard versions when we're given the
251  //  default allocator.  For nondefault allocators we do not use
252  //  any of the POD optimizations.
253
254  template<typename _InputIterator, typename _ForwardIterator,
255	   typename _Allocator>
256    _ForwardIterator
257    __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
258			   _ForwardIterator __result, _Allocator& __alloc)
259    {
260      _ForwardIterator __cur = __result;
261      __try
262	{
263	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
264	  for (; __first != __last; ++__first, ++__cur)
265	    __traits::construct(__alloc, std::__addressof(*__cur), *__first);
266	  return __cur;
267	}
268      __catch(...)
269	{
270	  std::_Destroy(__result, __cur, __alloc);
271	  __throw_exception_again;
272	}
273    }
274
275  template<typename _InputIterator, typename _ForwardIterator, typename _Tp>
276    inline _ForwardIterator
277    __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
278			   _ForwardIterator __result, allocator<_Tp>&)
279    { return std::uninitialized_copy(__first, __last, __result); }
280
281  template<typename _InputIterator, typename _ForwardIterator,
282	   typename _Allocator>
283    inline _ForwardIterator
284    __uninitialized_move_a(_InputIterator __first, _InputIterator __last,
285			   _ForwardIterator __result, _Allocator& __alloc)
286    {
287      return std::__uninitialized_copy_a(_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
288					 _GLIBCXX_MAKE_MOVE_ITERATOR(__last),
289					 __result, __alloc);
290    }
291
292  template<typename _InputIterator, typename _ForwardIterator,
293	   typename _Allocator>
294    inline _ForwardIterator
295    __uninitialized_move_if_noexcept_a(_InputIterator __first,
296				       _InputIterator __last,
297				       _ForwardIterator __result,
298				       _Allocator& __alloc)
299    {
300      return std::__uninitialized_copy_a
301	(_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first),
302	 _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc);
303    }
304
305  template<typename _ForwardIterator, typename _Tp, typename _Allocator>
306    void
307    __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
308			   const _Tp& __x, _Allocator& __alloc)
309    {
310      _ForwardIterator __cur = __first;
311      __try
312	{
313	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
314	  for (; __cur != __last; ++__cur)
315	    __traits::construct(__alloc, std::__addressof(*__cur), __x);
316	}
317      __catch(...)
318	{
319	  std::_Destroy(__first, __cur, __alloc);
320	  __throw_exception_again;
321	}
322    }
323
324  template<typename _ForwardIterator, typename _Tp, typename _Tp2>
325    inline void
326    __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
327			   const _Tp& __x, allocator<_Tp2>&)
328    { std::uninitialized_fill(__first, __last, __x); }
329
330  template<typename _ForwardIterator, typename _Size, typename _Tp,
331	   typename _Allocator>
332    void
333    __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
334			     const _Tp& __x, _Allocator& __alloc)
335    {
336      _ForwardIterator __cur = __first;
337      __try
338	{
339	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
340	  for (; __n > 0; --__n, ++__cur)
341	    __traits::construct(__alloc, std::__addressof(*__cur), __x);
342	}
343      __catch(...)
344	{
345	  std::_Destroy(__first, __cur, __alloc);
346	  __throw_exception_again;
347	}
348    }
349
350  template<typename _ForwardIterator, typename _Size, typename _Tp,
351	   typename _Tp2>
352    inline void
353    __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
354			     const _Tp& __x, allocator<_Tp2>&)
355    { std::uninitialized_fill_n(__first, __n, __x); }
356
357
358  // Extensions: __uninitialized_copy_move, __uninitialized_move_copy,
359  // __uninitialized_fill_move, __uninitialized_move_fill.
360  // All of these algorithms take a user-supplied allocator, which is used
361  // for construction and destruction.
362
363  // __uninitialized_copy_move
364  // Copies [first1, last1) into [result, result + (last1 - first1)), and
365  //  move [first2, last2) into
366  //  [result, result + (last1 - first1) + (last2 - first2)).
367  template<typename _InputIterator1, typename _InputIterator2,
368	   typename _ForwardIterator, typename _Allocator>
369    inline _ForwardIterator
370    __uninitialized_copy_move(_InputIterator1 __first1,
371			      _InputIterator1 __last1,
372			      _InputIterator2 __first2,
373			      _InputIterator2 __last2,
374			      _ForwardIterator __result,
375			      _Allocator& __alloc)
376    {
377      _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1,
378							   __result,
379							   __alloc);
380      __try
381	{
382	  return std::__uninitialized_move_a(__first2, __last2, __mid, __alloc);
383	}
384      __catch(...)
385	{
386	  std::_Destroy(__result, __mid, __alloc);
387	  __throw_exception_again;
388	}
389    }
390
391  // __uninitialized_move_copy
392  // Moves [first1, last1) into [result, result + (last1 - first1)), and
393  //  copies [first2, last2) into
394  //  [result, result + (last1 - first1) + (last2 - first2)).
395  template<typename _InputIterator1, typename _InputIterator2,
396	   typename _ForwardIterator, typename _Allocator>
397    inline _ForwardIterator
398    __uninitialized_move_copy(_InputIterator1 __first1,
399			      _InputIterator1 __last1,
400			      _InputIterator2 __first2,
401			      _InputIterator2 __last2,
402			      _ForwardIterator __result,
403			      _Allocator& __alloc)
404    {
405      _ForwardIterator __mid = std::__uninitialized_move_a(__first1, __last1,
406							   __result,
407							   __alloc);
408      __try
409	{
410	  return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc);
411	}
412      __catch(...)
413	{
414	  std::_Destroy(__result, __mid, __alloc);
415	  __throw_exception_again;
416	}
417    }
418
419  // __uninitialized_fill_move
420  // Fills [result, mid) with x, and moves [first, last) into
421  //  [mid, mid + (last - first)).
422  template<typename _ForwardIterator, typename _Tp, typename _InputIterator,
423	   typename _Allocator>
424    inline _ForwardIterator
425    __uninitialized_fill_move(_ForwardIterator __result, _ForwardIterator __mid,
426			      const _Tp& __x, _InputIterator __first,
427			      _InputIterator __last, _Allocator& __alloc)
428    {
429      std::__uninitialized_fill_a(__result, __mid, __x, __alloc);
430      __try
431	{
432	  return std::__uninitialized_move_a(__first, __last, __mid, __alloc);
433	}
434      __catch(...)
435	{
436	  std::_Destroy(__result, __mid, __alloc);
437	  __throw_exception_again;
438	}
439    }
440
441  // __uninitialized_move_fill
442  // Moves [first1, last1) into [first2, first2 + (last1 - first1)), and
443  //  fills [first2 + (last1 - first1), last2) with x.
444  template<typename _InputIterator, typename _ForwardIterator, typename _Tp,
445	   typename _Allocator>
446    inline void
447    __uninitialized_move_fill(_InputIterator __first1, _InputIterator __last1,
448			      _ForwardIterator __first2,
449			      _ForwardIterator __last2, const _Tp& __x,
450			      _Allocator& __alloc)
451    {
452      _ForwardIterator __mid2 = std::__uninitialized_move_a(__first1, __last1,
453							    __first2,
454							    __alloc);
455      __try
456	{
457	  std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc);
458	}
459      __catch(...)
460	{
461	  std::_Destroy(__first2, __mid2, __alloc);
462	  __throw_exception_again;
463	}
464    }
465
466#if __cplusplus >= 201103L
467  // Extensions: __uninitialized_default, __uninitialized_default_n,
468  // __uninitialized_default_a, __uninitialized_default_n_a.
469
470  template<bool _TrivialValueType>
471    struct __uninitialized_default_1
472    {
473      template<typename _ForwardIterator>
474        static void
475        __uninit_default(_ForwardIterator __first, _ForwardIterator __last)
476        {
477	  _ForwardIterator __cur = __first;
478	  __try
479	    {
480	      for (; __cur != __last; ++__cur)
481		std::_Construct(std::__addressof(*__cur));
482	    }
483	  __catch(...)
484	    {
485	      std::_Destroy(__first, __cur);
486	      __throw_exception_again;
487	    }
488	}
489    };
490
491  template<>
492    struct __uninitialized_default_1<true>
493    {
494      template<typename _ForwardIterator>
495        static void
496        __uninit_default(_ForwardIterator __first, _ForwardIterator __last)
497        {
498	  typedef typename iterator_traits<_ForwardIterator>::value_type
499	    _ValueType;
500
501	  std::fill(__first, __last, _ValueType());
502	}
503    };
504
505  template<bool _TrivialValueType>
506    struct __uninitialized_default_n_1
507    {
508      template<typename _ForwardIterator, typename _Size>
509        static void
510        __uninit_default_n(_ForwardIterator __first, _Size __n)
511        {
512	  _ForwardIterator __cur = __first;
513	  __try
514	    {
515	      for (; __n > 0; --__n, ++__cur)
516		std::_Construct(std::__addressof(*__cur));
517	    }
518	  __catch(...)
519	    {
520	      std::_Destroy(__first, __cur);
521	      __throw_exception_again;
522	    }
523	}
524    };
525
526  template<>
527    struct __uninitialized_default_n_1<true>
528    {
529      template<typename _ForwardIterator, typename _Size>
530        static void
531        __uninit_default_n(_ForwardIterator __first, _Size __n)
532        {
533	  typedef typename iterator_traits<_ForwardIterator>::value_type
534	    _ValueType;
535
536	  std::fill_n(__first, __n, _ValueType());
537	}
538    };
539
540  // __uninitialized_default
541  // Fills [first, last) with std::distance(first, last) default
542  // constructed value_types(s).
543  template<typename _ForwardIterator>
544    inline void
545    __uninitialized_default(_ForwardIterator __first,
546			    _ForwardIterator __last)
547    {
548      typedef typename iterator_traits<_ForwardIterator>::value_type
549	_ValueType;
550      // trivial types can have deleted assignment
551      const bool __assignable = is_copy_assignable<_ValueType>::value;
552
553      std::__uninitialized_default_1<__is_trivial(_ValueType)
554				     && __assignable>::
555	__uninit_default(__first, __last);
556    }
557
558  // __uninitialized_default_n
559  // Fills [first, first + n) with n default constructed value_type(s).
560  template<typename _ForwardIterator, typename _Size>
561    inline void
562    __uninitialized_default_n(_ForwardIterator __first, _Size __n)
563    {
564      typedef typename iterator_traits<_ForwardIterator>::value_type
565	_ValueType;
566      // trivial types can have deleted assignment
567      const bool __assignable = is_copy_assignable<_ValueType>::value;
568
569      std::__uninitialized_default_n_1<__is_trivial(_ValueType)
570				       && __assignable>::
571	__uninit_default_n(__first, __n);
572    }
573
574
575  // __uninitialized_default_a
576  // Fills [first, last) with std::distance(first, last) default
577  // constructed value_types(s), constructed with the allocator alloc.
578  template<typename _ForwardIterator, typename _Allocator>
579    void
580    __uninitialized_default_a(_ForwardIterator __first,
581			      _ForwardIterator __last,
582			      _Allocator& __alloc)
583    {
584      _ForwardIterator __cur = __first;
585      __try
586	{
587	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
588	  for (; __cur != __last; ++__cur)
589	    __traits::construct(__alloc, std::__addressof(*__cur));
590	}
591      __catch(...)
592	{
593	  std::_Destroy(__first, __cur, __alloc);
594	  __throw_exception_again;
595	}
596    }
597
598  template<typename _ForwardIterator, typename _Tp>
599    inline void
600    __uninitialized_default_a(_ForwardIterator __first,
601			      _ForwardIterator __last,
602			      allocator<_Tp>&)
603    { std::__uninitialized_default(__first, __last); }
604
605
606  // __uninitialized_default_n_a
607  // Fills [first, first + n) with n default constructed value_types(s),
608  // constructed with the allocator alloc.
609  template<typename _ForwardIterator, typename _Size, typename _Allocator>
610    void
611    __uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
612				_Allocator& __alloc)
613    {
614      _ForwardIterator __cur = __first;
615      __try
616	{
617	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
618	  for (; __n > 0; --__n, ++__cur)
619	    __traits::construct(__alloc, std::__addressof(*__cur));
620	}
621      __catch(...)
622	{
623	  std::_Destroy(__first, __cur, __alloc);
624	  __throw_exception_again;
625	}
626    }
627
628  template<typename _ForwardIterator, typename _Size, typename _Tp>
629    inline void
630    __uninitialized_default_n_a(_ForwardIterator __first, _Size __n,
631				allocator<_Tp>&)
632    { std::__uninitialized_default_n(__first, __n); }
633
634
635  template<typename _InputIterator, typename _Size,
636	   typename _ForwardIterator>
637    _ForwardIterator
638    __uninitialized_copy_n(_InputIterator __first, _Size __n,
639			   _ForwardIterator __result, input_iterator_tag)
640    {
641      _ForwardIterator __cur = __result;
642      __try
643	{
644	  for (; __n > 0; --__n, ++__first, ++__cur)
645	    std::_Construct(std::__addressof(*__cur), *__first);
646	  return __cur;
647	}
648      __catch(...)
649	{
650	  std::_Destroy(__result, __cur);
651	  __throw_exception_again;
652	}
653    }
654
655  template<typename _RandomAccessIterator, typename _Size,
656	   typename _ForwardIterator>
657    inline _ForwardIterator
658    __uninitialized_copy_n(_RandomAccessIterator __first, _Size __n,
659			   _ForwardIterator __result,
660			   random_access_iterator_tag)
661    { return std::uninitialized_copy(__first, __first + __n, __result); }
662
663  /**
664   *  @brief Copies the range [first,first+n) into result.
665   *  @param  __first  An input iterator.
666   *  @param  __n      The number of elements to copy.
667   *  @param  __result An output iterator.
668   *  @return  __result + __n
669   *
670   *  Like copy_n(), but does not require an initialized output range.
671  */
672  template<typename _InputIterator, typename _Size, typename _ForwardIterator>
673    inline _ForwardIterator
674    uninitialized_copy_n(_InputIterator __first, _Size __n,
675			 _ForwardIterator __result)
676    { return std::__uninitialized_copy_n(__first, __n, __result,
677					 std::__iterator_category(__first)); }
678#endif
679
680_GLIBCXX_END_NAMESPACE_VERSION
681} // namespace
682
683#endif /* _STL_UNINITIALIZED_H */
684