Import libstdc++ from GCC 3.3.3-pre 20031106.
[dragonfly.git] / contrib / libstdc++3 / include / bits / vector.tcc
1 // Vector implementation (out of line) -*- C++ -*-
2
3 // Copyright (C) 2001, 2002 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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
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 vector.tcc
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 __GLIBCPP_INTERNAL_VECTOR_TCC
62 #define __GLIBCPP_INTERNAL_VECTOR_TCC
63
64 namespace std
65 {
66   template<typename _Tp, typename _Alloc>
67     void
68     vector<_Tp,_Alloc>::
69     reserve(size_type __n)
70     {
71       if (__n > this->max_size())
72         __throw_length_error("vector::reserve");
73       if (this->capacity() < __n)
74         {
75           const size_type __old_size = size();
76           pointer __tmp = _M_allocate_and_copy(__n, _M_start, _M_finish);
77           _Destroy(_M_start, _M_finish);
78           _M_deallocate(_M_start, _M_end_of_storage - _M_start);
79           _M_start = __tmp;
80           _M_finish = __tmp + __old_size;
81           _M_end_of_storage = _M_start + __n;
82         }
83     }
84   
85   template<typename _Tp, typename _Alloc>
86     typename vector<_Tp,_Alloc>::iterator
87     vector<_Tp,_Alloc>::
88     insert(iterator __position, const value_type& __x)
89     {
90       size_type __n = __position - begin();
91       if (_M_finish != _M_end_of_storage && __position == end())
92       {
93         _Construct(_M_finish, __x);
94         ++_M_finish;
95       }
96       else
97         _M_insert_aux(__position, __x);
98       return begin() + __n;
99     }
100   
101   template<typename _Tp, typename _Alloc>
102     typename vector<_Tp,_Alloc>::iterator
103     vector<_Tp,_Alloc>::
104     erase(iterator __position)
105     {
106       if (__position + 1 != end())
107         copy(__position + 1, end(), __position);
108       --_M_finish;
109       _Destroy(_M_finish);
110       return __position;
111     }
112   
113   template<typename _Tp, typename _Alloc>
114     typename vector<_Tp,_Alloc>::iterator
115     vector<_Tp,_Alloc>::
116     erase(iterator __first, iterator __last)
117     {
118       iterator __i(copy(__last, end(), __first));
119       _Destroy(__i, end());
120       _M_finish = _M_finish - (__last - __first);
121       return __first;
122     }
123   
124   template<typename _Tp, typename _Alloc>
125     vector<_Tp,_Alloc>&
126     vector<_Tp,_Alloc>::
127     operator=(const vector<_Tp,_Alloc>& __x)
128     {
129       if (&__x != this)
130       {
131         const size_type __xlen = __x.size();
132         if (__xlen > capacity())
133         {
134           pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), __x.end());
135           _Destroy(_M_start, _M_finish);
136           _M_deallocate(_M_start, _M_end_of_storage - _M_start);
137           _M_start = __tmp;
138           _M_end_of_storage = _M_start + __xlen;
139         }
140         else if (size() >= __xlen)
141         {
142           iterator __i(copy(__x.begin(), __x.end(), begin()));
143           _Destroy(__i, end());
144         }
145         else
146         {
147           copy(__x.begin(), __x.begin() + size(), _M_start);
148           uninitialized_copy(__x.begin() + size(), __x.end(), _M_finish);
149         }
150         _M_finish = _M_start + __xlen;
151       }
152       return *this;
153     }
154   
155   template<typename _Tp, typename _Alloc>
156     void
157     vector<_Tp,_Alloc>::
158     _M_fill_assign(size_t __n, const value_type& __val)
159     {
160       if (__n > capacity())
161       {
162         vector __tmp(__n, __val, get_allocator());
163         __tmp.swap(*this);
164       }
165       else if (__n > size())
166       {
167         fill(begin(), end(), __val);
168         _M_finish = uninitialized_fill_n(_M_finish, __n - size(), __val);
169       }
170       else
171         erase(fill_n(begin(), __n, __val), end());
172     }
173   
174   template<typename _Tp, typename _Alloc> template<typename _InputIter>
175     void
176     vector<_Tp,_Alloc>::
177     _M_assign_aux(_InputIter __first, _InputIter __last, input_iterator_tag)
178     {
179       iterator __cur(begin());
180       for ( ; __first != __last && __cur != end(); ++__cur, ++__first)
181         *__cur = *__first;
182       if (__first == __last)
183         erase(__cur, end());
184       else
185         insert(end(), __first, __last);
186     }
187   
188   template<typename _Tp, typename _Alloc> template<typename _ForwardIter>
189     void
190     vector<_Tp,_Alloc>::
191     _M_assign_aux(_ForwardIter __first, _ForwardIter __last,
192                   forward_iterator_tag)
193     {
194       size_type __len = distance(__first, __last);
195   
196       if (__len > capacity())
197       {
198         pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
199         _Destroy(_M_start, _M_finish);
200         _M_deallocate(_M_start, _M_end_of_storage - _M_start);
201         _M_start = __tmp;
202         _M_end_of_storage = _M_finish = _M_start + __len;
203       }
204       else if (size() >= __len)
205       {
206         iterator __new_finish(copy(__first, __last, _M_start));
207         _Destroy(__new_finish, end());
208         _M_finish = __new_finish.base();
209       }
210       else
211       {
212         _ForwardIter __mid = __first;
213         advance(__mid, size());
214         copy(__first, __mid, _M_start);
215         _M_finish = uninitialized_copy(__mid, __last, _M_finish);
216       }
217     }
218   
219   template<typename _Tp, typename _Alloc>
220     void
221     vector<_Tp,_Alloc>::
222     _M_insert_aux(iterator __position, const _Tp& __x)
223     {
224       if (_M_finish != _M_end_of_storage)
225       {
226         _Construct(_M_finish, *(_M_finish - 1));
227         ++_M_finish;
228         _Tp __x_copy = __x;
229         copy_backward(__position, iterator(_M_finish-2), iterator(_M_finish-1));
230         *__position = __x_copy;
231       }
232       else
233       {
234         const size_type __old_size = size();
235         const size_type __len = __old_size != 0 ? 2 * __old_size : 1;
236         iterator __new_start(_M_allocate(__len));
237         iterator __new_finish(__new_start);
238         try
239           {
240             __new_finish = uninitialized_copy(iterator(_M_start), __position,
241                                               __new_start);
242             _Construct(__new_finish.base(), __x);
243             ++__new_finish;
244             __new_finish = uninitialized_copy(__position, iterator(_M_finish),
245                                               __new_finish);
246           }
247         catch(...)
248           {
249             _Destroy(__new_start,__new_finish);
250             _M_deallocate(__new_start.base(),__len);
251             __throw_exception_again;
252           }
253         _Destroy(begin(), end());
254         _M_deallocate(_M_start, _M_end_of_storage - _M_start);
255         _M_start = __new_start.base();
256         _M_finish = __new_finish.base();
257         _M_end_of_storage = __new_start.base() + __len;
258       }
259     }
260   
261   #ifdef _GLIBCPP_DEPRECATED
262   template<typename _Tp, typename _Alloc>
263     void
264     vector<_Tp,_Alloc>::
265     _M_insert_aux(iterator __position)
266     {
267       if (_M_finish != _M_end_of_storage)
268       {
269         _Construct(_M_finish, *(_M_finish - 1));
270         ++_M_finish;
271         copy_backward(__position, iterator(_M_finish - 2),
272                       iterator(_M_finish - 1));
273         *__position = value_type();
274       }
275       else
276       {
277         const size_type __old_size = size();
278         const size_type __len = __old_size != 0 ? 2 * __old_size : 1;
279         pointer __new_start = _M_allocate(__len);
280         pointer __new_finish = __new_start;
281         try
282           {
283             __new_finish = uninitialized_copy(iterator(_M_start), __position,
284                                               __new_start);
285             _Construct(__new_finish);
286             ++__new_finish;
287             __new_finish = uninitialized_copy(__position, iterator(_M_finish),
288                                               __new_finish);
289           }
290         catch(...)
291           {
292             _Destroy(__new_start,__new_finish);
293             _M_deallocate(__new_start,__len);
294             __throw_exception_again;
295           }
296         _Destroy(begin(), end());
297         _M_deallocate(_M_start, _M_end_of_storage - _M_start);
298         _M_start = __new_start;
299         _M_finish = __new_finish;
300         _M_end_of_storage = __new_start + __len;
301       }
302     }
303   #endif
304   
305   template<typename _Tp, typename _Alloc>
306     void
307     vector<_Tp,_Alloc>::
308     _M_fill_insert(iterator __position, size_type __n, const value_type& __x)
309     {
310       if (__n != 0)
311       {
312         if (size_type(_M_end_of_storage - _M_finish) >= __n) 
313           {
314            value_type __x_copy = __x;
315            const size_type __elems_after = end() - __position;
316            iterator __old_finish(_M_finish);
317            if (__elems_after > __n)
318              {
319                uninitialized_copy(_M_finish - __n, _M_finish, _M_finish);
320                _M_finish += __n;
321                copy_backward(__position, __old_finish - __n, __old_finish);
322                fill(__position, __position + __n, __x_copy);
323              }
324            else
325              {
326                uninitialized_fill_n(_M_finish, __n - __elems_after, __x_copy);
327                _M_finish += __n - __elems_after;
328                uninitialized_copy(__position, __old_finish, _M_finish);
329                _M_finish += __elems_after;
330                fill(__position, __old_finish, __x_copy);
331              }
332           }
333         else
334           {
335             const size_type __old_size = size();
336             const size_type __len = __old_size + max(__old_size, __n);
337             iterator __new_start(_M_allocate(__len));
338             iterator __new_finish(__new_start);
339             try
340               {
341                 __new_finish = uninitialized_copy(begin(), __position,
342                                                   __new_start);
343                 __new_finish = uninitialized_fill_n(__new_finish, __n, __x);
344                 __new_finish = uninitialized_copy(__position, end(), 
345                                                   __new_finish);
346               }
347             catch(...)
348               {
349                 _Destroy(__new_start,__new_finish);
350                 _M_deallocate(__new_start.base(),__len);
351                 __throw_exception_again;
352               }
353             _Destroy(_M_start, _M_finish);
354             _M_deallocate(_M_start, _M_end_of_storage - _M_start);
355             _M_start = __new_start.base();
356             _M_finish = __new_finish.base();
357             _M_end_of_storage = __new_start.base() + __len;
358           }
359       }
360     }
361   
362   template<typename _Tp, typename _Alloc> template<typename _InputIterator>
363     void
364     vector<_Tp,_Alloc>::
365     _M_range_insert(iterator __pos,
366                     _InputIterator __first, _InputIterator __last,
367                     input_iterator_tag)
368     {
369       for ( ; __first != __last; ++__first)
370       {
371         __pos = insert(__pos, *__first);
372         ++__pos;
373       }
374     }
375   
376   template<typename _Tp, typename _Alloc> template<typename _ForwardIterator>
377     void
378     vector<_Tp,_Alloc>::
379     _M_range_insert(iterator __position,_ForwardIterator __first, 
380                     _ForwardIterator __last, forward_iterator_tag)
381     {
382       if (__first != __last)
383       {
384         size_type __n = distance(__first, __last);
385         if (size_type(_M_end_of_storage - _M_finish) >= __n)
386         {
387           const size_type __elems_after = end() - __position;
388           iterator __old_finish(_M_finish);
389           if (__elems_after > __n)
390           {
391             uninitialized_copy(_M_finish - __n, _M_finish, _M_finish);
392             _M_finish += __n;
393             copy_backward(__position, __old_finish - __n, __old_finish);
394             copy(__first, __last, __position);
395           }
396           else
397           {
398             _ForwardIterator __mid = __first;
399             advance(__mid, __elems_after);
400             uninitialized_copy(__mid, __last, _M_finish);
401             _M_finish += __n - __elems_after;
402             uninitialized_copy(__position, __old_finish, _M_finish);
403             _M_finish += __elems_after;
404             copy(__first, __mid, __position);
405           }
406         }
407         else
408         {
409           const size_type __old_size = size();
410           const size_type __len = __old_size + max(__old_size, __n);
411           iterator __new_start(_M_allocate(__len));
412           iterator __new_finish(__new_start);
413           try
414             {
415               __new_finish = uninitialized_copy(iterator(_M_start),
416                                                 __position, __new_start);
417               __new_finish = uninitialized_copy(__first, __last, __new_finish);
418               __new_finish = uninitialized_copy(__position, iterator(_M_finish),
419                                                 __new_finish);
420             }
421           catch(...)
422             {
423               _Destroy(__new_start,__new_finish);
424               _M_deallocate(__new_start.base(), __len);
425               __throw_exception_again;
426             }
427           _Destroy(_M_start, _M_finish);
428           _M_deallocate(_M_start, _M_end_of_storage - _M_start);
429           _M_start = __new_start.base();
430           _M_finish = __new_finish.base();
431           _M_end_of_storage = __new_start.base() + __len;
432         }
433       }
434     }
435 } // namespace std
436
437 #endif /* __GLIBCPP_INTERNAL_VECTOR_TCC */