OSDN Git Service

2005-08-17 Kelley Cook <kcook@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / vector.tcc
1 // Vector implementation (out of line) -*- C++ -*-
2
3 // Copyright (C) 2001, 2002, 2003, 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
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 _VECTOR_TCC
62 #define _VECTOR_TCC 1
63
64 namespace _GLIBCXX_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(__N("vector::reserve"));
73       if (this->capacity() < __n)
74         {
75           const size_type __old_size = size();
76           pointer __tmp = _M_allocate_and_copy(__n,
77                                                this->_M_impl._M_start,
78                                                this->_M_impl._M_finish);
79           std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
80                         _M_get_Tp_allocator());
81           _M_deallocate(this->_M_impl._M_start,
82                         this->_M_impl._M_end_of_storage
83                         - this->_M_impl._M_start);
84           this->_M_impl._M_start = __tmp;
85           this->_M_impl._M_finish = __tmp + __old_size;
86           this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
87         }
88     }
89
90   template<typename _Tp, typename _Alloc>
91     typename vector<_Tp, _Alloc>::iterator
92     vector<_Tp, _Alloc>::
93     insert(iterator __position, const value_type& __x)
94     {
95       const size_type __n = __position - begin();
96       if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage
97           && __position == end())
98         {
99           this->_M_impl.construct(this->_M_impl._M_finish, __x);
100           ++this->_M_impl._M_finish;
101         }
102       else
103         _M_insert_aux(__position, __x);
104       return begin() + __n;
105     }
106
107   template<typename _Tp, typename _Alloc>
108     typename vector<_Tp, _Alloc>::iterator
109     vector<_Tp, _Alloc>::
110     erase(iterator __position)
111     {
112       if (__position + 1 != end())
113         std::copy(__position + 1, end(), __position);
114       --this->_M_impl._M_finish;
115       this->_M_impl.destroy(this->_M_impl._M_finish);
116       return __position;
117     }
118
119   template<typename _Tp, typename _Alloc>
120     typename vector<_Tp, _Alloc>::iterator
121     vector<_Tp, _Alloc>::
122     erase(iterator __first, iterator __last)
123     {
124       iterator __i(std::copy(__last, end(), __first));
125       std::_Destroy(__i, end(), _M_get_Tp_allocator());
126       this->_M_impl._M_finish = this->_M_impl._M_finish - (__last - __first);
127       return __first;
128     }
129
130   template<typename _Tp, typename _Alloc>
131     vector<_Tp, _Alloc>&
132     vector<_Tp, _Alloc>::
133     operator=(const vector<_Tp, _Alloc>& __x)
134     {
135       if (&__x != this)
136         {
137           const size_type __xlen = __x.size();
138           if (__xlen > capacity())
139             {
140               pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(),
141                                                    __x.end());
142               std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
143                             _M_get_Tp_allocator());
144               _M_deallocate(this->_M_impl._M_start,
145                             this->_M_impl._M_end_of_storage
146                             - this->_M_impl._M_start);
147               this->_M_impl._M_start = __tmp;
148               this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __xlen;
149             }
150           else if (size() >= __xlen)
151             {
152               iterator __i(std::copy(__x.begin(), __x.end(), begin()));
153               std::_Destroy(__i, end(), _M_get_Tp_allocator());
154             }
155           else
156             {
157               std::copy(__x.begin(), __x.begin() + size(),
158                         this->_M_impl._M_start);
159               std::__uninitialized_copy_a(__x.begin() + size(),
160                                           __x.end(), this->_M_impl._M_finish,
161                                           _M_get_Tp_allocator());
162             }
163           this->_M_impl._M_finish = this->_M_impl._M_start + __xlen;
164         }
165       return *this;
166     }
167
168   template<typename _Tp, typename _Alloc>
169     void
170     vector<_Tp, _Alloc>::
171     _M_fill_assign(size_t __n, const value_type& __val)
172     {
173       if (__n > capacity())
174         {
175           vector __tmp(__n, __val, _M_get_Tp_allocator());
176           __tmp.swap(*this);
177         }
178       else if (__n > size())
179         {
180           std::fill(begin(), end(), __val);
181           std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
182                                         __n - size(), __val,
183                                         _M_get_Tp_allocator());
184           this->_M_impl._M_finish += __n - size();
185         }
186       else
187         erase(fill_n(begin(), __n, __val), end());
188     }
189
190   template<typename _Tp, typename _Alloc>
191     template<typename _InputIterator>
192       void
193       vector<_Tp, _Alloc>::
194       _M_assign_aux(_InputIterator __first, _InputIterator __last,
195                     std::input_iterator_tag)
196       {
197         iterator __cur(begin());
198         for (; __first != __last && __cur != end(); ++__cur, ++__first)
199           *__cur = *__first;
200         if (__first == __last)
201           erase(__cur, end());
202         else
203           insert(end(), __first, __last);
204       }
205
206   template<typename _Tp, typename _Alloc>
207     template<typename _ForwardIterator>
208       void
209       vector<_Tp, _Alloc>::
210       _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last,
211                     std::forward_iterator_tag)
212       {
213         const size_type __len = std::distance(__first, __last);
214
215         if (__len > capacity())
216           {
217             pointer __tmp(_M_allocate_and_copy(__len, __first, __last));
218             std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
219                           _M_get_Tp_allocator());
220             _M_deallocate(this->_M_impl._M_start,
221                           this->_M_impl._M_end_of_storage
222                           - this->_M_impl._M_start);
223             this->_M_impl._M_start = __tmp;
224             this->_M_impl._M_finish = this->_M_impl._M_start + __len;
225             this->_M_impl._M_end_of_storage = this->_M_impl._M_finish;
226           }
227         else if (size() >= __len)
228           {
229             iterator __new_finish(std::copy(__first, __last,
230                                        this->_M_impl._M_start));
231             std::_Destroy(__new_finish, end(), _M_get_Tp_allocator());
232             this->_M_impl._M_finish = __new_finish.base();
233           }
234         else
235           {
236             _ForwardIterator __mid = __first;
237             std::advance(__mid, size());
238             std::copy(__first, __mid, this->_M_impl._M_start);
239             this->_M_impl._M_finish =
240               std::__uninitialized_copy_a(__mid, __last,
241                                           this->_M_impl._M_finish,
242                                           _M_get_Tp_allocator());
243           }
244       }
245
246   template<typename _Tp, typename _Alloc>
247     void
248     vector<_Tp, _Alloc>::
249     _M_insert_aux(iterator __position, const _Tp& __x)
250     {
251       if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
252         {
253           this->_M_impl.construct(this->_M_impl._M_finish,
254                                   *(this->_M_impl._M_finish - 1));
255           ++this->_M_impl._M_finish;
256           _Tp __x_copy = __x;
257           std::copy_backward(__position,
258                              iterator(this->_M_impl._M_finish-2),
259                              iterator(this->_M_impl._M_finish-1));
260           *__position = __x_copy;
261         }
262       else
263         {
264           const size_type __old_size = size();
265           if (__old_size == this->max_size())
266             __throw_length_error(__N("vector::_M_insert_aux"));
267
268           // When sizeof(value_type) == 1 and __old_size > size_type(-1)/2
269           // __len overflows: if we don't notice and _M_allocate doesn't
270           // throw we crash badly later.
271           size_type __len = __old_size != 0 ? 2 * __old_size : 1;         
272           if (__len < __old_size)
273             __len = this->max_size();
274
275           iterator __new_start(this->_M_allocate(__len));
276           iterator __new_finish(__new_start);
277           try
278             {
279               __new_finish =
280                 std::__uninitialized_copy_a(iterator(this->_M_impl._M_start),
281                                             __position,
282                                             __new_start,
283                                             _M_get_Tp_allocator());
284               this->_M_impl.construct(__new_finish.base(), __x);
285               ++__new_finish;
286               __new_finish =
287                 std::__uninitialized_copy_a(__position,
288                                             iterator(this->_M_impl._M_finish),
289                                             __new_finish,
290                                             _M_get_Tp_allocator());
291             }
292           catch(...)
293             {
294               std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
295               _M_deallocate(__new_start.base(),__len);
296               __throw_exception_again;
297             }
298           std::_Destroy(begin(), end(), _M_get_Tp_allocator());
299           _M_deallocate(this->_M_impl._M_start,
300                         this->_M_impl._M_end_of_storage
301                         - this->_M_impl._M_start);
302           this->_M_impl._M_start = __new_start.base();
303           this->_M_impl._M_finish = __new_finish.base();
304           this->_M_impl._M_end_of_storage = __new_start.base() + __len;
305         }
306     }
307
308   template<typename _Tp, typename _Alloc>
309     void
310     vector<_Tp, _Alloc>::
311     _M_fill_insert(iterator __position, size_type __n, const value_type& __x)
312     {
313       if (__n != 0)
314         {
315           if (size_type(this->_M_impl._M_end_of_storage
316                         - this->_M_impl._M_finish) >= __n)
317             {
318               value_type __x_copy = __x;
319               const size_type __elems_after = end() - __position;
320               iterator __old_finish(this->_M_impl._M_finish);
321               if (__elems_after > __n)
322                 {
323                   std::__uninitialized_copy_a(this->_M_impl._M_finish - __n,
324                                               this->_M_impl._M_finish,
325                                               this->_M_impl._M_finish,
326                                               _M_get_Tp_allocator());
327                   this->_M_impl._M_finish += __n;
328                   std::copy_backward(__position, __old_finish - __n,
329                                      __old_finish);
330                   std::fill(__position, __position + __n, __x_copy);
331                 }
332               else
333                 {
334                   std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
335                                                 __n - __elems_after,
336                                                 __x_copy,
337                                                 _M_get_Tp_allocator());
338                   this->_M_impl._M_finish += __n - __elems_after;
339                   std::__uninitialized_copy_a(__position, __old_finish,
340                                               this->_M_impl._M_finish,
341                                               _M_get_Tp_allocator());
342                   this->_M_impl._M_finish += __elems_after;
343                   std::fill(__position, __old_finish, __x_copy);
344                 }
345             }
346           else
347             {
348               const size_type __old_size = size();
349               if (this->max_size() - __old_size < __n)
350                 __throw_length_error(__N("vector::_M_fill_insert"));
351               
352               // See _M_insert_aux above.
353               size_type __len = __old_size + std::max(__old_size, __n);
354               if (__len < __old_size)
355                 __len = this->max_size();
356
357               iterator __new_start(this->_M_allocate(__len));
358               iterator __new_finish(__new_start);
359               try
360                 {
361                   __new_finish =
362                     std::__uninitialized_copy_a(begin(), __position,
363                                                 __new_start,
364                                                 _M_get_Tp_allocator());
365                   std::__uninitialized_fill_n_a(__new_finish, __n, __x,
366                                                 _M_get_Tp_allocator());
367                   __new_finish += __n;
368                   __new_finish =
369                     std::__uninitialized_copy_a(__position, end(), __new_finish,
370                                                 _M_get_Tp_allocator());
371                 }
372               catch(...)
373                 {
374                   std::_Destroy(__new_start, __new_finish,
375                                 _M_get_Tp_allocator());
376                   _M_deallocate(__new_start.base(), __len);
377                   __throw_exception_again;
378                 }
379               std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
380                             _M_get_Tp_allocator());
381               _M_deallocate(this->_M_impl._M_start,
382                             this->_M_impl._M_end_of_storage
383                             - this->_M_impl._M_start);
384               this->_M_impl._M_start = __new_start.base();
385               this->_M_impl._M_finish = __new_finish.base();
386               this->_M_impl._M_end_of_storage = __new_start.base() + __len;
387             }
388         }
389     }
390
391   template<typename _Tp, typename _Alloc> template<typename _InputIterator>
392     void
393     vector<_Tp, _Alloc>::
394     _M_range_insert(iterator __pos, _InputIterator __first,
395                     _InputIterator __last, std::input_iterator_tag)
396     {
397       for (; __first != __last; ++__first)
398         {
399           __pos = insert(__pos, *__first);
400           ++__pos;
401         }
402     }
403
404   template<typename _Tp, typename _Alloc>
405     template<typename _ForwardIterator>
406       void
407       vector<_Tp, _Alloc>::
408       _M_range_insert(iterator __position, _ForwardIterator __first,
409                       _ForwardIterator __last, std::forward_iterator_tag)
410       {
411         if (__first != __last)
412           {
413             const size_type __n = std::distance(__first, __last);
414             if (size_type(this->_M_impl._M_end_of_storage
415                           - this->_M_impl._M_finish) >= __n)
416               {
417                 const size_type __elems_after = end() - __position;
418                 iterator __old_finish(this->_M_impl._M_finish);
419                 if (__elems_after > __n)
420                   {
421                     std::__uninitialized_copy_a(this->_M_impl._M_finish - __n,
422                                                 this->_M_impl._M_finish,
423                                                 this->_M_impl._M_finish,
424                                                 _M_get_Tp_allocator());
425                     this->_M_impl._M_finish += __n;
426                     std::copy_backward(__position, __old_finish - __n,
427                                        __old_finish);
428                     std::copy(__first, __last, __position);
429                   }
430                 else
431                   {
432                     _ForwardIterator __mid = __first;
433                     std::advance(__mid, __elems_after);
434                     std::__uninitialized_copy_a(__mid, __last,
435                                                 this->_M_impl._M_finish,
436                                                 _M_get_Tp_allocator());
437                     this->_M_impl._M_finish += __n - __elems_after;
438                     std::__uninitialized_copy_a(__position, __old_finish,
439                                                 this->_M_impl._M_finish,
440                                                 _M_get_Tp_allocator());
441                     this->_M_impl._M_finish += __elems_after;
442                     std::copy(__first, __mid, __position);
443                   }
444               }
445             else
446               {
447                 const size_type __old_size = size();
448                 if (this->max_size() - __old_size < __n)
449                   __throw_length_error(__N("vector::_M_range_insert")); 
450
451                 // See _M_insert_aux above.
452                 size_type __len = __old_size + std::max(__old_size, __n);
453                 if (__len < __old_size)
454                   __len = this->max_size();
455
456                 iterator __new_start(this->_M_allocate(__len));
457                 iterator __new_finish(__new_start);
458                 try
459                   {
460                     __new_finish =
461                       std::__uninitialized_copy_a(iterator(this->_M_impl._M_start),
462                                                   __position,
463                                                   __new_start,
464                                                   _M_get_Tp_allocator());
465                     __new_finish =
466                       std::__uninitialized_copy_a(__first, __last, __new_finish,
467                                                   _M_get_Tp_allocator());
468                     __new_finish =
469                       std::__uninitialized_copy_a(__position,
470                                                   iterator(this->_M_impl._M_finish),
471                                                   __new_finish,
472                                                   _M_get_Tp_allocator());
473                   }
474                 catch(...)
475                   {
476                     std::_Destroy(__new_start,__new_finish,
477                                   _M_get_Tp_allocator());
478                     _M_deallocate(__new_start.base(), __len);
479                     __throw_exception_again;
480                   }
481                 std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
482                               _M_get_Tp_allocator());
483                 _M_deallocate(this->_M_impl._M_start,
484                               this->_M_impl._M_end_of_storage
485                               - this->_M_impl._M_start);
486                 this->_M_impl._M_start = __new_start.base();
487                 this->_M_impl._M_finish = __new_finish.base();
488                 this->_M_impl._M_end_of_storage = __new_start.base() + __len;
489               }
490           }
491       }
492 } // namespace std
493
494 #endif /* _VECTOR_TCC */