1// Raw memory manipulators -*- C++ -*-
2
3// Copyright (C) 2001, 2004, 2005 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 2, 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// You should have received a copy of the GNU General Public License along
17// with this library; see the file COPYING.  If not, write to the Free
18// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19// USA.
20
21// As a special exception, you may use this file as part of a free software
22// library without restriction.  Specifically, if other files instantiate
23// templates or use macros or inline functions from this file, or you compile
24// this file and link it with other files to produce an executable, this
25// file does not by itself cause the resulting executable to be covered by
26// the GNU General Public License.  This exception does not however
27// invalidate any other reasons why the executable file might be covered by
28// the GNU General Public License.
29
30/*
31 *
32 * Copyright (c) 1994
33 * Hewlett-Packard Company
34 *
35 * Permission to use, copy, modify, distribute and sell this software
36 * and its documentation for any purpose is hereby granted without fee,
37 * provided that the above copyright notice appear in all copies and
38 * that both that copyright notice and this permission notice appear
39 * in supporting documentation.  Hewlett-Packard Company makes no
40 * representations about the suitability of this software for any
41 * purpose.  It is provided "as is" without express or implied warranty.
42 *
43 *
44 * Copyright (c) 1996,1997
45 * Silicon Graphics Computer Systems, Inc.
46 *
47 * Permission to use, copy, modify, distribute and sell this software
48 * and its documentation for any purpose is hereby granted without fee,
49 * provided that the above copyright notice appear in all copies and
50 * that both that copyright notice and this permission notice appear
51 * in supporting documentation.  Silicon Graphics makes no
52 * representations about the suitability of this software for any
53 * purpose.  It is provided "as is" without express or implied warranty.
54 */
55
56/** @file stl_uninitialized.h
57 *  This is an internal header file, included by other library headers.
58 *  You should not attempt to use it directly.
59 */
60
61#ifndef _STL_UNINITIALIZED_H
62#define _STL_UNINITIALIZED_H 1
63
64#include <cstring>
65
66namespace std
67{
68  // uninitialized_copy
69  template<typename _InputIterator, typename _ForwardIterator>
70    inline _ForwardIterator
71    __uninitialized_copy_aux(_InputIterator __first, _InputIterator __last,
72			     _ForwardIterator __result,
73			     __true_type)
74    { return std::copy(__first, __last, __result); }
75
76  template<typename _InputIterator, typename _ForwardIterator>
77    inline _ForwardIterator
78    __uninitialized_copy_aux(_InputIterator __first, _InputIterator __last,
79			     _ForwardIterator __result,
80			     __false_type)
81    {
82      _ForwardIterator __cur = __result;
83      try
84	{
85	  for (; __first != __last; ++__first, ++__cur)
86	    std::_Construct(&*__cur, *__first);
87	  return __cur;
88	}
89      catch(...)
90	{
91	  std::_Destroy(__result, __cur);
92	  __throw_exception_again;
93	}
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<_ForwardIterator>::value_type _ValueType;
111      typedef typename std::__is_scalar<_ValueType>::__type _Is_POD;
112      return std::__uninitialized_copy_aux(__first, __last, __result,
113					   _Is_POD());
114    }
115
116  inline char*
117  uninitialized_copy(const char* __first, const char* __last, char* __result)
118  {
119    std::memmove(__result, __first, __last - __first);
120    return __result + (__last - __first);
121  }
122
123  inline wchar_t*
124  uninitialized_copy(const wchar_t* __first, const wchar_t* __last,
125		     wchar_t* __result)
126  {
127    std::memmove(__result, __first, sizeof(wchar_t) * (__last - __first));
128    return __result + (__last - __first);
129  }
130
131  // Valid if copy construction is equivalent to assignment, and if the
132  // destructor is trivial.
133  template<typename _ForwardIterator, typename _Tp>
134    inline void
135    __uninitialized_fill_aux(_ForwardIterator __first,
136			     _ForwardIterator __last,
137			     const _Tp& __x, __true_type)
138    { std::fill(__first, __last, __x); }
139
140  template<typename _ForwardIterator, typename _Tp>
141    void
142    __uninitialized_fill_aux(_ForwardIterator __first, _ForwardIterator __last,
143			     const _Tp& __x, __false_type)
144    {
145      _ForwardIterator __cur = __first;
146      try
147	{
148	  for (; __cur != __last; ++__cur)
149	    std::_Construct(&*__cur, __x);
150	}
151      catch(...)
152	{
153	  std::_Destroy(__first, __cur);
154	  __throw_exception_again;
155	}
156    }
157
158  /**
159   *  @brief Copies the value x into the range [first,last).
160   *  @param  first  An input iterator.
161   *  @param  last   An input iterator.
162   *  @param  x      The source value.
163   *  @return   Nothing.
164   *
165   *  Like fill(), but does not require an initialized output range.
166  */
167  template<typename _ForwardIterator, typename _Tp>
168    inline void
169    uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last,
170		       const _Tp& __x)
171    {
172      typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
173      typedef typename std::__is_scalar<_ValueType>::__type _Is_POD;
174      std::__uninitialized_fill_aux(__first, __last, __x, _Is_POD());
175    }
176
177  // Valid if copy construction is equivalent to assignment, and if the
178  //  destructor is trivial.
179  template<typename _ForwardIterator, typename _Size, typename _Tp>
180    inline void
181    __uninitialized_fill_n_aux(_ForwardIterator __first, _Size __n,
182			       const _Tp& __x, __true_type)
183    { std::fill_n(__first, __n, __x); }
184
185  template<typename _ForwardIterator, typename _Size, typename _Tp>
186    void
187    __uninitialized_fill_n_aux(_ForwardIterator __first, _Size __n,
188			       const _Tp& __x, __false_type)
189    {
190      _ForwardIterator __cur = __first;
191      try
192	{
193	  for (; __n > 0; --__n, ++__cur)
194	    std::_Construct(&*__cur, __x);
195	}
196      catch(...)
197	{
198	  std::_Destroy(__first, __cur);
199	  __throw_exception_again;
200	}
201    }
202
203  /**
204   *  @brief Copies the value x into the range [first,first+n).
205   *  @param  first  An input iterator.
206   *  @param  n      The number of copies to make.
207   *  @param  x      The source value.
208   *  @return   Nothing.
209   *
210   *  Like fill_n(), but does not require an initialized output range.
211  */
212  template<typename _ForwardIterator, typename _Size, typename _Tp>
213    inline void
214    uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
215    {
216      typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
217      typedef typename std::__is_scalar<_ValueType>::__type _Is_POD;
218      std::__uninitialized_fill_n_aux(__first, __n, __x, _Is_POD());
219    }
220
221  // Extensions: versions of uninitialized_copy, uninitialized_fill,
222  //  and uninitialized_fill_n that take an allocator parameter.
223  //  We dispatch back to the standard versions when we're given the
224  //  default allocator.  For nondefault allocators we do not use
225  //  any of the POD optimizations.
226
227  template<typename _InputIterator, typename _ForwardIterator,
228	   typename _Allocator>
229    _ForwardIterator
230    __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
231			   _ForwardIterator __result,
232			   _Allocator __alloc)
233    {
234      _ForwardIterator __cur = __result;
235      try
236	{
237	  for (; __first != __last; ++__first, ++__cur)
238	    __alloc.construct(&*__cur, *__first);
239	  return __cur;
240	}
241      catch(...)
242	{
243	  std::_Destroy(__result, __cur, __alloc);
244	  __throw_exception_again;
245	}
246    }
247
248  template<typename _InputIterator, typename _ForwardIterator, typename _Tp>
249    inline _ForwardIterator
250    __uninitialized_copy_a(_InputIterator __first, _InputIterator __last,
251			   _ForwardIterator __result,
252			   allocator<_Tp>)
253    {
254      return std::uninitialized_copy(__first, __last, __result);
255    }
256
257  template<typename _ForwardIterator, typename _Tp, typename _Allocator>
258    void
259    __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
260			   const _Tp& __x, _Allocator __alloc)
261    {
262      _ForwardIterator __cur = __first;
263      try
264	{
265	  for (; __cur != __last; ++__cur)
266	    __alloc.construct(&*__cur, __x);
267	}
268      catch(...)
269	{
270	  std::_Destroy(__first, __cur, __alloc);
271	  __throw_exception_again;
272	}
273    }
274
275  template<typename _ForwardIterator, typename _Tp, typename _Tp2>
276    inline void
277    __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last,
278			   const _Tp& __x, allocator<_Tp2>)
279    {
280      std::uninitialized_fill(__first, __last, __x);
281    }
282
283  template<typename _ForwardIterator, typename _Size, typename _Tp,
284	   typename _Allocator>
285    void
286    __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
287			     const _Tp& __x,
288			     _Allocator __alloc)
289    {
290      _ForwardIterator __cur = __first;
291      try
292	{
293	  for (; __n > 0; --__n, ++__cur)
294	    __alloc.construct(&*__cur, __x);
295	}
296      catch(...)
297	{
298	  std::_Destroy(__first, __cur, __alloc);
299	  __throw_exception_again;
300	}
301    }
302
303  template<typename _ForwardIterator, typename _Size, typename _Tp,
304	   typename _Tp2>
305    void
306    __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
307			     const _Tp& __x,
308			     allocator<_Tp2>)
309    {
310      std::uninitialized_fill_n(__first, __n, __x);
311    }
312
313
314  // Extensions: __uninitialized_copy_copy, __uninitialized_copy_fill,
315  // __uninitialized_fill_copy.  All of these algorithms take a user-
316  // supplied allocator, which is used for construction and destruction.
317
318  // __uninitialized_copy_copy
319  // Copies [first1, last1) into [result, result + (last1 - first1)), and
320  //  copies [first2, last2) into
321  //  [result, result + (last1 - first1) + (last2 - first2)).
322
323  template<typename _InputIterator1, typename _InputIterator2,
324	   typename _ForwardIterator, typename _Allocator>
325    inline _ForwardIterator
326    __uninitialized_copy_copy(_InputIterator1 __first1,
327			      _InputIterator1 __last1,
328			      _InputIterator2 __first2,
329			      _InputIterator2 __last2,
330			      _ForwardIterator __result,
331			      _Allocator __alloc)
332    {
333      _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1,
334							   __result,
335							   __alloc);
336      try
337	{
338	  return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc);
339	}
340      catch(...)
341	{
342	  std::_Destroy(__result, __mid, __alloc);
343	  __throw_exception_again;
344	}
345    }
346
347  // __uninitialized_fill_copy
348  // Fills [result, mid) with x, and copies [first, last) into
349  //  [mid, mid + (last - first)).
350  template<typename _ForwardIterator, typename _Tp, typename _InputIterator,
351	   typename _Allocator>
352    inline _ForwardIterator
353    __uninitialized_fill_copy(_ForwardIterator __result, _ForwardIterator __mid,
354			      const _Tp& __x, _InputIterator __first,
355			      _InputIterator __last,
356			      _Allocator __alloc)
357    {
358      std::__uninitialized_fill_a(__result, __mid, __x, __alloc);
359      try
360	{
361	  return std::__uninitialized_copy_a(__first, __last, __mid, __alloc);
362	}
363      catch(...)
364	{
365	  std::_Destroy(__result, __mid, __alloc);
366	  __throw_exception_again;
367	}
368    }
369
370  // __uninitialized_copy_fill
371  // Copies [first1, last1) into [first2, first2 + (last1 - first1)), and
372  //  fills [first2 + (last1 - first1), last2) with x.
373  template<typename _InputIterator, typename _ForwardIterator, typename _Tp,
374	   typename _Allocator>
375    inline void
376    __uninitialized_copy_fill(_InputIterator __first1, _InputIterator __last1,
377			      _ForwardIterator __first2,
378			      _ForwardIterator __last2, const _Tp& __x,
379			      _Allocator __alloc)
380    {
381      _ForwardIterator __mid2 = std::__uninitialized_copy_a(__first1, __last1,
382							    __first2,
383							    __alloc);
384      try
385	{
386	  std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc);
387	}
388      catch(...)
389	{
390	  std::_Destroy(__first2, __mid2, __alloc);
391	  __throw_exception_again;
392	}
393    }
394
395} // namespace std
396
397#endif /* _STL_UNINITIALIZED_H */
398