197403Sobrien// Raw memory manipulators -*- C++ -*-
297403Sobrien
3169691Skan// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
4169691Skan// Free Software Foundation, Inc.
597403Sobrien//
697403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
797403Sobrien// software; you can redistribute it and/or modify it under the
897403Sobrien// terms of the GNU General Public License as published by the
997403Sobrien// Free Software Foundation; either version 2, or (at your option)
1097403Sobrien// any later version.
1197403Sobrien
1297403Sobrien// This library is distributed in the hope that it will be useful,
1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1597403Sobrien// GNU General Public License for more details.
1697403Sobrien
1797403Sobrien// You should have received a copy of the GNU General Public License along
1897403Sobrien// with this library; see the file COPYING.  If not, write to the Free
19169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
2097403Sobrien// USA.
2197403Sobrien
2297403Sobrien// As a special exception, you may use this file as part of a free software
2397403Sobrien// library without restriction.  Specifically, if other files instantiate
2497403Sobrien// templates or use macros or inline functions from this file, or you compile
2597403Sobrien// this file and link it with other files to produce an executable, this
2697403Sobrien// file does not by itself cause the resulting executable to be covered by
2797403Sobrien// the GNU General Public License.  This exception does not however
2897403Sobrien// invalidate any other reasons why the executable file might be covered by
2997403Sobrien// the GNU General Public License.
3097403Sobrien
3197403Sobrien/*
3297403Sobrien *
3397403Sobrien * Copyright (c) 1994
3497403Sobrien * Hewlett-Packard Company
3597403Sobrien *
3697403Sobrien * Permission to use, copy, modify, distribute and sell this software
3797403Sobrien * and its documentation for any purpose is hereby granted without fee,
3897403Sobrien * provided that the above copyright notice appear in all copies and
3997403Sobrien * that both that copyright notice and this permission notice appear
4097403Sobrien * in supporting documentation.  Hewlett-Packard Company makes no
4197403Sobrien * representations about the suitability of this software for any
4297403Sobrien * purpose.  It is provided "as is" without express or implied warranty.
4397403Sobrien *
4497403Sobrien *
4597403Sobrien * Copyright (c) 1996,1997
4697403Sobrien * Silicon Graphics Computer Systems, Inc.
4797403Sobrien *
4897403Sobrien * Permission to use, copy, modify, distribute and sell this software
4997403Sobrien * and its documentation for any purpose is hereby granted without fee,
5097403Sobrien * provided that the above copyright notice appear in all copies and
5197403Sobrien * that both that copyright notice and this permission notice appear
5297403Sobrien * in supporting documentation.  Silicon Graphics makes no
5397403Sobrien * representations about the suitability of this software for any
5497403Sobrien * purpose.  It is provided "as is" without express or implied warranty.
5597403Sobrien */
5697403Sobrien
5797403Sobrien/** @file stl_uninitialized.h
5897403Sobrien *  This is an internal header file, included by other library headers.
5997403Sobrien *  You should not attempt to use it directly.
6097403Sobrien */
6197403Sobrien
62132720Skan#ifndef _STL_UNINITIALIZED_H
63132720Skan#define _STL_UNINITIALIZED_H 1
6497403Sobrien
6597403Sobrien#include <cstring>
6697403Sobrien
67169691Skan_GLIBCXX_BEGIN_NAMESPACE(std)
68169691Skan
6997403Sobrien  // uninitialized_copy
70132720Skan  template<typename _InputIterator, typename _ForwardIterator>
71132720Skan    inline _ForwardIterator
72132720Skan    __uninitialized_copy_aux(_InputIterator __first, _InputIterator __last,
73132720Skan			     _ForwardIterator __result,
7497403Sobrien			     __true_type)
75132720Skan    { return std::copy(__first, __last, __result); }
7697403Sobrien
77132720Skan  template<typename _InputIterator, typename _ForwardIterator>
78132720Skan    inline _ForwardIterator
79132720Skan    __uninitialized_copy_aux(_InputIterator __first, _InputIterator __last,
80132720Skan			     _ForwardIterator __result,
8197403Sobrien			     __false_type)
8297403Sobrien    {
83132720Skan      _ForwardIterator __cur = __result;
84132720Skan      try
85132720Skan	{
86169691Skan	  for (; __first != __last; ++__first, ++__cur)
87132720Skan	    std::_Construct(&*__cur, *__first);
88132720Skan	  return __cur;
89132720Skan	}
9097403Sobrien      catch(...)
9197403Sobrien	{
92132720Skan	  std::_Destroy(__result, __cur);
93132720Skan	  __throw_exception_again;
9497403Sobrien	}
9597403Sobrien    }
9697403Sobrien
9797403Sobrien  /**
9897403Sobrien   *  @brief Copies the range [first,last) into result.
9997403Sobrien   *  @param  first  An input iterator.
10097403Sobrien   *  @param  last   An input iterator.
10197403Sobrien   *  @param  result An output iterator.
10297403Sobrien   *  @return   result + (first - last)
10397403Sobrien   *
10497403Sobrien   *  Like copy(), but does not require an initialized output range.
10597403Sobrien  */
106132720Skan  template<typename _InputIterator, typename _ForwardIterator>
107132720Skan    inline _ForwardIterator
108132720Skan    uninitialized_copy(_InputIterator __first, _InputIterator __last,
109132720Skan		       _ForwardIterator __result)
11097403Sobrien    {
111132720Skan      typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
112169691Skan      typedef typename std::__is_scalar<_ValueType>::__type _Is_POD;
113132720Skan      return std::__uninitialized_copy_aux(__first, __last, __result,
114132720Skan					   _Is_POD());
11597403Sobrien    }
11697403Sobrien
11797403Sobrien  inline char*
11897403Sobrien  uninitialized_copy(const char* __first, const char* __last, char* __result)
11997403Sobrien  {
120132720Skan    std::memmove(__result, __first, __last - __first);
12197403Sobrien    return __result + (__last - __first);
12297403Sobrien  }
12397403Sobrien
124132720Skan  inline wchar_t*
12597403Sobrien  uninitialized_copy(const wchar_t* __first, const wchar_t* __last,
12697403Sobrien		     wchar_t* __result)
12797403Sobrien  {
128132720Skan    std::memmove(__result, __first, sizeof(wchar_t) * (__last - __first));
12997403Sobrien    return __result + (__last - __first);
13097403Sobrien  }
13197403Sobrien
13297403Sobrien  // Valid if copy construction is equivalent to assignment, and if the
13397403Sobrien  // destructor is trivial.
134132720Skan  template<typename _ForwardIterator, typename _Tp>
13597403Sobrien    inline void
136132720Skan    __uninitialized_fill_aux(_ForwardIterator __first,
137132720Skan			     _ForwardIterator __last,
13897403Sobrien			     const _Tp& __x, __true_type)
139132720Skan    { std::fill(__first, __last, __x); }
14097403Sobrien
141132720Skan  template<typename _ForwardIterator, typename _Tp>
14297403Sobrien    void
143132720Skan    __uninitialized_fill_aux(_ForwardIterator __first, _ForwardIterator __last,
14497403Sobrien			     const _Tp& __x, __false_type)
14597403Sobrien    {
146132720Skan      _ForwardIterator __cur = __first;
147132720Skan      try
148132720Skan	{
149169691Skan	  for (; __cur != __last; ++__cur)
150132720Skan	    std::_Construct(&*__cur, __x);
151132720Skan	}
15297403Sobrien      catch(...)
15397403Sobrien	{
154132720Skan	  std::_Destroy(__first, __cur);
155132720Skan	  __throw_exception_again;
15697403Sobrien	}
15797403Sobrien    }
15897403Sobrien
15997403Sobrien  /**
16097403Sobrien   *  @brief Copies the value x into the range [first,last).
16197403Sobrien   *  @param  first  An input iterator.
16297403Sobrien   *  @param  last   An input iterator.
16397403Sobrien   *  @param  x      The source value.
16497403Sobrien   *  @return   Nothing.
16597403Sobrien   *
16697403Sobrien   *  Like fill(), but does not require an initialized output range.
16797403Sobrien  */
168132720Skan  template<typename _ForwardIterator, typename _Tp>
16997403Sobrien    inline void
170132720Skan    uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last,
171132720Skan		       const _Tp& __x)
17297403Sobrien    {
173132720Skan      typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
174169691Skan      typedef typename std::__is_scalar<_ValueType>::__type _Is_POD;
175132720Skan      std::__uninitialized_fill_aux(__first, __last, __x, _Is_POD());
17697403Sobrien    }
17797403Sobrien
17897403Sobrien  // Valid if copy construction is equivalent to assignment, and if the
17997403Sobrien  //  destructor is trivial.
180132720Skan  template<typename _ForwardIterator, typename _Size, typename _Tp>
181169691Skan    inline void
182132720Skan    __uninitialized_fill_n_aux(_ForwardIterator __first, _Size __n,
18397403Sobrien			       const _Tp& __x, __true_type)
184169691Skan    { std::fill_n(__first, __n, __x); }
18597403Sobrien
186132720Skan  template<typename _ForwardIterator, typename _Size, typename _Tp>
187169691Skan    void
188132720Skan    __uninitialized_fill_n_aux(_ForwardIterator __first, _Size __n,
18997403Sobrien			       const _Tp& __x, __false_type)
19097403Sobrien    {
191132720Skan      _ForwardIterator __cur = __first;
192132720Skan      try
193132720Skan	{
194169691Skan	  for (; __n > 0; --__n, ++__cur)
195132720Skan	    std::_Construct(&*__cur, __x);
196132720Skan	}
19797403Sobrien      catch(...)
198132720Skan	{
199132720Skan	  std::_Destroy(__first, __cur);
200132720Skan	  __throw_exception_again;
20197403Sobrien	}
20297403Sobrien    }
20397403Sobrien
20497403Sobrien  /**
20597403Sobrien   *  @brief Copies the value x into the range [first,first+n).
20697403Sobrien   *  @param  first  An input iterator.
20797403Sobrien   *  @param  n      The number of copies to make.
20897403Sobrien   *  @param  x      The source value.
209169691Skan   *  @return   Nothing.
21097403Sobrien   *
21197403Sobrien   *  Like fill_n(), but does not require an initialized output range.
21297403Sobrien  */
213132720Skan  template<typename _ForwardIterator, typename _Size, typename _Tp>
214169691Skan    inline void
215132720Skan    uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
21697403Sobrien    {
217132720Skan      typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
218169691Skan      typedef typename std::__is_scalar<_ValueType>::__type _Is_POD;
219169691Skan      std::__uninitialized_fill_n_aux(__first, __n, __x, _Is_POD());
22097403Sobrien    }
22197403Sobrien
222169691Skan  // Extensions: versions of uninitialized_copy, uninitialized_fill,
223169691Skan  //  and uninitialized_fill_n that take an allocator parameter.
224169691Skan  //  We dispatch back to the standard versions when we're given the
225169691Skan  //  default allocator.  For nondefault allocators we do not use
226169691Skan  //  any of the POD optimizations.
227169691Skan
228169691Skan  template<typename _InputIterator, typename _ForwardIterator,
229169691Skan	   typename _Allocator>
230169691Skan    _ForwardIterator
231169691Skan    __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
232169691Skan			   _ForwardIterator __result,
233169691Skan			   _Allocator __alloc)
234169691Skan    {
235169691Skan      _ForwardIterator __cur = __result;
236169691Skan      try
237169691Skan	{
238169691Skan	  for (; __first != __last; ++__first, ++__cur)
239169691Skan	    __alloc.construct(&*__cur, *__first);
240169691Skan	  return __cur;
241169691Skan	}
242169691Skan      catch(...)
243169691Skan	{
244169691Skan	  std::_Destroy(__result, __cur, __alloc);
245169691Skan	  __throw_exception_again;
246169691Skan	}
247169691Skan    }
248169691Skan
249169691Skan  template<typename _InputIterator, typename _ForwardIterator, typename _Tp>
250169691Skan    inline _ForwardIterator
251169691Skan    __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
252169691Skan			   _ForwardIterator __result,
253169691Skan			   allocator<_Tp>)
254169691Skan    { return std::uninitialized_copy(__first, __last, __result); }
255169691Skan
256169691Skan  template<typename _ForwardIterator, typename _Tp, typename _Allocator>
257169691Skan    void
258169691Skan    __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
259169691Skan			   const _Tp& __x, _Allocator __alloc)
260169691Skan    {
261169691Skan      _ForwardIterator __cur = __first;
262169691Skan      try
263169691Skan	{
264169691Skan	  for (; __cur != __last; ++__cur)
265169691Skan	    __alloc.construct(&*__cur, __x);
266169691Skan	}
267169691Skan      catch(...)
268169691Skan	{
269169691Skan	  std::_Destroy(__first, __cur, __alloc);
270169691Skan	  __throw_exception_again;
271169691Skan	}
272169691Skan    }
273169691Skan
274169691Skan  template<typename _ForwardIterator, typename _Tp, typename _Tp2>
275169691Skan    inline void
276169691Skan    __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
277169691Skan			   const _Tp& __x, allocator<_Tp2>)
278169691Skan    { std::uninitialized_fill(__first, __last, __x); }
279169691Skan
280169691Skan  template<typename _ForwardIterator, typename _Size, typename _Tp,
281169691Skan	   typename _Allocator>
282169691Skan    void
283169691Skan    __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
284169691Skan			     const _Tp& __x,
285169691Skan			     _Allocator __alloc)
286169691Skan    {
287169691Skan      _ForwardIterator __cur = __first;
288169691Skan      try
289169691Skan	{
290169691Skan	  for (; __n > 0; --__n, ++__cur)
291169691Skan	    __alloc.construct(&*__cur, __x);
292169691Skan	}
293169691Skan      catch(...)
294169691Skan	{
295169691Skan	  std::_Destroy(__first, __cur, __alloc);
296169691Skan	  __throw_exception_again;
297169691Skan	}
298169691Skan    }
299169691Skan
300169691Skan  template<typename _ForwardIterator, typename _Size, typename _Tp,
301169691Skan	   typename _Tp2>
302169691Skan    inline void
303169691Skan    __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
304169691Skan			     const _Tp& __x,
305169691Skan			     allocator<_Tp2>)
306169691Skan    { std::uninitialized_fill_n(__first, __n, __x); }
307169691Skan
308169691Skan
309132720Skan  // Extensions: __uninitialized_copy_copy, __uninitialized_copy_fill,
310169691Skan  // __uninitialized_fill_copy.  All of these algorithms take a user-
311169691Skan  // supplied allocator, which is used for construction and destruction.
31297403Sobrien
31397403Sobrien  // __uninitialized_copy_copy
31497403Sobrien  // Copies [first1, last1) into [result, result + (last1 - first1)), and
31597403Sobrien  //  copies [first2, last2) into
31697403Sobrien  //  [result, result + (last1 - first1) + (last2 - first2)).
31797403Sobrien
318132720Skan  template<typename _InputIterator1, typename _InputIterator2,
319169691Skan	   typename _ForwardIterator, typename _Allocator>
320132720Skan    inline _ForwardIterator
321132720Skan    __uninitialized_copy_copy(_InputIterator1 __first1,
322132720Skan			      _InputIterator1 __last1,
323132720Skan			      _InputIterator2 __first2,
324132720Skan			      _InputIterator2 __last2,
325169691Skan			      _ForwardIterator __result,
326169691Skan			      _Allocator __alloc)
32797403Sobrien    {
328169691Skan      _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1,
329169691Skan							   __result,
330169691Skan							   __alloc);
331132720Skan      try
332132720Skan	{
333169691Skan	  return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc);
334132720Skan	}
33597403Sobrien      catch(...)
336132720Skan	{
337169691Skan	  std::_Destroy(__result, __mid, __alloc);
338132720Skan	  __throw_exception_again;
33997403Sobrien	}
34097403Sobrien    }
34197403Sobrien
34297403Sobrien  // __uninitialized_fill_copy
34397403Sobrien  // Fills [result, mid) with x, and copies [first, last) into
34497403Sobrien  //  [mid, mid + (last - first)).
345169691Skan  template<typename _ForwardIterator, typename _Tp, typename _InputIterator,
346169691Skan	   typename _Allocator>
347132720Skan    inline _ForwardIterator
348132720Skan    __uninitialized_fill_copy(_ForwardIterator __result, _ForwardIterator __mid,
349132720Skan			      const _Tp& __x, _InputIterator __first,
350169691Skan			      _InputIterator __last,
351169691Skan			      _Allocator __alloc)
35297403Sobrien    {
353169691Skan      std::__uninitialized_fill_a(__result, __mid, __x, __alloc);
354132720Skan      try
355132720Skan	{
356169691Skan	  return std::__uninitialized_copy_a(__first, __last, __mid, __alloc);
357132720Skan	}
35897403Sobrien      catch(...)
35997403Sobrien	{
360169691Skan	  std::_Destroy(__result, __mid, __alloc);
361132720Skan	  __throw_exception_again;
36297403Sobrien	}
36397403Sobrien    }
36497403Sobrien
36597403Sobrien  // __uninitialized_copy_fill
36697403Sobrien  // Copies [first1, last1) into [first2, first2 + (last1 - first1)), and
36797403Sobrien  //  fills [first2 + (last1 - first1), last2) with x.
368169691Skan  template<typename _InputIterator, typename _ForwardIterator, typename _Tp,
369169691Skan	   typename _Allocator>
37097403Sobrien    inline void
371132720Skan    __uninitialized_copy_fill(_InputIterator __first1, _InputIterator __last1,
372132720Skan			      _ForwardIterator __first2,
373169691Skan			      _ForwardIterator __last2, const _Tp& __x,
374169691Skan			      _Allocator __alloc)
37597403Sobrien    {
376169691Skan      _ForwardIterator __mid2 = std::__uninitialized_copy_a(__first1, __last1,
377169691Skan							    __first2,
378169691Skan							    __alloc);
379132720Skan      try
380132720Skan	{
381169691Skan	  std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc);
382132720Skan	}
38397403Sobrien      catch(...)
38497403Sobrien	{
385169691Skan	  std::_Destroy(__first2, __mid2, __alloc);
386132720Skan	  __throw_exception_again;
38797403Sobrien	}
38897403Sobrien    }
38997403Sobrien
390169691Skan_GLIBCXX_END_NAMESPACE
39197403Sobrien
392132720Skan#endif /* _STL_UNINITIALIZED_H */
393