1 // Deque implementation (out of line) -*- C++ -*-
2 
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
4 // 2009, 2010, 2011, 2012
5 // Free Software Foundation, Inc.
6 //
7 // This file is part of the GNU ISO C++ Library.  This library is free
8 // software; you can redistribute it and/or modify it under the
9 // terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 3, or (at your option)
11 // any later version.
12 
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 
18 // Under Section 7 of GPL version 3, you are granted additional
19 // permissions described in the GCC Runtime Library Exception, version
20 // 3.1, as published by the Free Software Foundation.
21 
22 // You should have received a copy of the GNU General Public License and
23 // a copy of the GCC Runtime Library Exception along with this program;
24 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
25 // <http://www.gnu.org/licenses/>.
26 
27 /*
28  *
29  * Copyright (c) 1994
30  * Hewlett-Packard Company
31  *
32  * Permission to use, copy, modify, distribute and sell this software
33  * and its documentation for any purpose is hereby granted without fee,
34  * provided that the above copyright notice appear in all copies and
35  * that both that copyright notice and this permission notice appear
36  * in supporting documentation.  Hewlett-Packard Company makes no
37  * representations about the suitability of this software for any
38  * purpose.  It is provided "as is" without express or implied warranty.
39  *
40  *
41  * Copyright (c) 1997
42  * Silicon Graphics Computer Systems, Inc.
43  *
44  * Permission to use, copy, modify, distribute and sell this software
45  * and its documentation for any purpose is hereby granted without fee,
46  * provided that the above copyright notice appear in all copies and
47  * that both that copyright notice and this permission notice appear
48  * in supporting documentation.  Silicon Graphics makes no
49  * representations about the suitability of this software for any
50  * purpose.  It is provided "as is" without express or implied warranty.
51  */
52 
53 /** @file bits/deque.tcc
54  *  This is an internal header file, included by other library headers.
55  *  Do not attempt to use it directly. @headername{deque}
56  */
57 
58 #ifndef _DEQUE_TCC
59 #define _DEQUE_TCC 1
60 
61 namespace std _GLIBCXX_VISIBILITY(default)
62 {
63 _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
64 
65 #ifdef __GXX_EXPERIMENTAL_CXX0X__
66   template <typename _Tp, typename _Alloc>
67     void
68     deque<_Tp, _Alloc>::
69     _M_default_initialize()
70     {
71       _Map_pointer __cur;
72       __try
73         {
74           for (__cur = this->_M_impl._M_start._M_node;
75 	       __cur < this->_M_impl._M_finish._M_node;
76 	       ++__cur)
77             std::__uninitialized_default_a(*__cur, *__cur + _S_buffer_size(),
78 					   _M_get_Tp_allocator());
79           std::__uninitialized_default_a(this->_M_impl._M_finish._M_first,
80 					 this->_M_impl._M_finish._M_cur,
81 					 _M_get_Tp_allocator());
82         }
83       __catch(...)
84         {
85           std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur),
86 			_M_get_Tp_allocator());
87           __throw_exception_again;
88         }
89     }
90 #endif
91 
92   template <typename _Tp, typename _Alloc>
93     deque<_Tp, _Alloc>&
94     deque<_Tp, _Alloc>::
95     operator=(const deque& __x)
96     {
97       const size_type __len = size();
98       if (&__x != this)
99 	{
100 	  if (__len >= __x.size())
101 	    _M_erase_at_end(std::copy(__x.begin(), __x.end(),
102 				      this->_M_impl._M_start));
103 	  else
104 	    {
105 	      const_iterator __mid = __x.begin() + difference_type(__len);
106 	      std::copy(__x.begin(), __mid, this->_M_impl._M_start);
107 	      insert(this->_M_impl._M_finish, __mid, __x.end());
108 	    }
109 	}
110       return *this;
111     }
112 
113 #ifdef __GXX_EXPERIMENTAL_CXX0X__
114   template<typename _Tp, typename _Alloc>
115     template<typename... _Args>
116       void
117       deque<_Tp, _Alloc>::
118       emplace_front(_Args&&... __args)
119       {
120 	if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first)
121 	  {
122 	    this->_M_impl.construct(this->_M_impl._M_start._M_cur - 1,
123 				    std::forward<_Args>(__args)...);
124 	    --this->_M_impl._M_start._M_cur;
125 	  }
126 	else
127 	  _M_push_front_aux(std::forward<_Args>(__args)...);
128       }
129 
130   template<typename _Tp, typename _Alloc>
131     template<typename... _Args>
132       void
133       deque<_Tp, _Alloc>::
134       emplace_back(_Args&&... __args)
135       {
136 	if (this->_M_impl._M_finish._M_cur
137 	    != this->_M_impl._M_finish._M_last - 1)
138 	  {
139 	    this->_M_impl.construct(this->_M_impl._M_finish._M_cur,
140 				    std::forward<_Args>(__args)...);
141 	    ++this->_M_impl._M_finish._M_cur;
142 	  }
143 	else
144 	  _M_push_back_aux(std::forward<_Args>(__args)...);
145       }
146 #endif
147 
148   template <typename _Tp, typename _Alloc>
149     typename deque<_Tp, _Alloc>::iterator
150     deque<_Tp, _Alloc>::
151     insert(iterator __position, const value_type& __x)
152     {
153       if (__position._M_cur == this->_M_impl._M_start._M_cur)
154 	{
155 	  push_front(__x);
156 	  return this->_M_impl._M_start;
157 	}
158       else if (__position._M_cur == this->_M_impl._M_finish._M_cur)
159 	{
160 	  push_back(__x);
161 	  iterator __tmp = this->_M_impl._M_finish;
162 	  --__tmp;
163 	  return __tmp;
164 	}
165       else
166         return _M_insert_aux(__position, __x);
167     }
168 
169 #ifdef __GXX_EXPERIMENTAL_CXX0X__
170   template<typename _Tp, typename _Alloc>
171     template<typename... _Args>
172       typename deque<_Tp, _Alloc>::iterator
173       deque<_Tp, _Alloc>::
174       emplace(iterator __position, _Args&&... __args)
175       {
176 	if (__position._M_cur == this->_M_impl._M_start._M_cur)
177 	  {
178 	    emplace_front(std::forward<_Args>(__args)...);
179 	    return this->_M_impl._M_start;
180 	  }
181 	else if (__position._M_cur == this->_M_impl._M_finish._M_cur)
182 	  {
183 	    emplace_back(std::forward<_Args>(__args)...);
184 	    iterator __tmp = this->_M_impl._M_finish;
185 	    --__tmp;
186 	    return __tmp;
187 	  }
188 	else
189 	  return _M_insert_aux(__position, std::forward<_Args>(__args)...);
190       }
191 #endif
192 
193   template <typename _Tp, typename _Alloc>
194     typename deque<_Tp, _Alloc>::iterator
195     deque<_Tp, _Alloc>::
196     erase(iterator __position)
197     {
198       iterator __next = __position;
199       ++__next;
200       const difference_type __index = __position - begin();
201       if (static_cast<size_type>(__index) < (size() >> 1))
202 	{
203 	  if (__position != begin())
204 	    _GLIBCXX_MOVE_BACKWARD3(begin(), __position, __next);
205 	  pop_front();
206 	}
207       else
208 	{
209 	  if (__next != end())
210 	    _GLIBCXX_MOVE3(__next, end(), __position);
211 	  pop_back();
212 	}
213       return begin() + __index;
214     }
215 
216   template <typename _Tp, typename _Alloc>
217     typename deque<_Tp, _Alloc>::iterator
218     deque<_Tp, _Alloc>::
219     erase(iterator __first, iterator __last)
220     {
221       if (__first == __last)
222 	return __first;
223       else if (__first == begin() && __last == end())
224 	{
225 	  clear();
226 	  return end();
227 	}
228       else
229 	{
230 	  const difference_type __n = __last - __first;
231 	  const difference_type __elems_before = __first - begin();
232 	  if (static_cast<size_type>(__elems_before) <= (size() - __n) / 2)
233 	    {
234 	      if (__first != begin())
235 		_GLIBCXX_MOVE_BACKWARD3(begin(), __first, __last);
236 	      _M_erase_at_begin(begin() + __n);
237 	    }
238 	  else
239 	    {
240 	      if (__last != end())
241 		_GLIBCXX_MOVE3(__last, end(), __first);
242 	      _M_erase_at_end(end() - __n);
243 	    }
244 	  return begin() + __elems_before;
245 	}
246     }
247 
248   template <typename _Tp, class _Alloc>
249     template <typename _InputIterator>
250       void
251       deque<_Tp, _Alloc>::
252       _M_assign_aux(_InputIterator __first, _InputIterator __last,
253 		    std::input_iterator_tag)
254       {
255         iterator __cur = begin();
256         for (; __first != __last && __cur != end(); ++__cur, ++__first)
257           *__cur = *__first;
258         if (__first == __last)
259           _M_erase_at_end(__cur);
260         else
261           insert(end(), __first, __last);
262       }
263 
264   template <typename _Tp, typename _Alloc>
265     void
266     deque<_Tp, _Alloc>::
267     _M_fill_insert(iterator __pos, size_type __n, const value_type& __x)
268     {
269       if (__pos._M_cur == this->_M_impl._M_start._M_cur)
270 	{
271 	  iterator __new_start = _M_reserve_elements_at_front(__n);
272 	  __try
273 	    {
274 	      std::__uninitialized_fill_a(__new_start, this->_M_impl._M_start,
275 					  __x, _M_get_Tp_allocator());
276 	      this->_M_impl._M_start = __new_start;
277 	    }
278 	  __catch(...)
279 	    {
280 	      _M_destroy_nodes(__new_start._M_node,
281 			       this->_M_impl._M_start._M_node);
282 	      __throw_exception_again;
283 	    }
284 	}
285       else if (__pos._M_cur == this->_M_impl._M_finish._M_cur)
286 	{
287 	  iterator __new_finish = _M_reserve_elements_at_back(__n);
288 	  __try
289 	    {
290 	      std::__uninitialized_fill_a(this->_M_impl._M_finish,
291 					  __new_finish, __x,
292 					  _M_get_Tp_allocator());
293 	      this->_M_impl._M_finish = __new_finish;
294 	    }
295 	  __catch(...)
296 	    {
297 	      _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
298 			       __new_finish._M_node + 1);
299 	      __throw_exception_again;
300 	    }
301 	}
302       else
303         _M_insert_aux(__pos, __n, __x);
304     }
305 
306 #ifdef __GXX_EXPERIMENTAL_CXX0X__
307   template <typename _Tp, typename _Alloc>
308     void
309     deque<_Tp, _Alloc>::
310     _M_default_append(size_type __n)
311     {
312       if (__n)
313 	{
314 	  iterator __new_finish = _M_reserve_elements_at_back(__n);
315 	  __try
316 	    {
317 	      std::__uninitialized_default_a(this->_M_impl._M_finish,
318 					     __new_finish,
319 					     _M_get_Tp_allocator());
320 	      this->_M_impl._M_finish = __new_finish;
321 	    }
322 	  __catch(...)
323 	    {
324 	      _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
325 			       __new_finish._M_node + 1);
326 	      __throw_exception_again;
327 	    }
328 	}
329     }
330 
331   template <typename _Tp, typename _Alloc>
332     bool
333     deque<_Tp, _Alloc>::
334     _M_shrink_to_fit()
335     {
336       const difference_type __front_capacity
337 	= (this->_M_impl._M_start._M_cur - this->_M_impl._M_start._M_first);
338       if (__front_capacity == 0)
339 	return false;
340 
341       const difference_type __back_capacity
342 	= (this->_M_impl._M_finish._M_last - this->_M_impl._M_finish._M_cur);
343       if (__front_capacity + __back_capacity < _S_buffer_size())
344 	return false;
345 
346       return std::__shrink_to_fit_aux<deque>::_S_do_it(*this);
347     }
348 #endif
349 
350   template <typename _Tp, typename _Alloc>
351     void
352     deque<_Tp, _Alloc>::
353     _M_fill_initialize(const value_type& __value)
354     {
355       _Map_pointer __cur;
356       __try
357         {
358           for (__cur = this->_M_impl._M_start._M_node;
359 	       __cur < this->_M_impl._M_finish._M_node;
360 	       ++__cur)
361             std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(),
362 					__value, _M_get_Tp_allocator());
363           std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first,
364 				      this->_M_impl._M_finish._M_cur,
365 				      __value, _M_get_Tp_allocator());
366         }
367       __catch(...)
368         {
369           std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur),
370 			_M_get_Tp_allocator());
371           __throw_exception_again;
372         }
373     }
374 
375   template <typename _Tp, typename _Alloc>
376     template <typename _InputIterator>
377       void
378       deque<_Tp, _Alloc>::
379       _M_range_initialize(_InputIterator __first, _InputIterator __last,
380                           std::input_iterator_tag)
381       {
382         this->_M_initialize_map(0);
383         __try
384           {
385             for (; __first != __last; ++__first)
386               push_back(*__first);
387           }
388         __catch(...)
389           {
390             clear();
391             __throw_exception_again;
392           }
393       }
394 
395   template <typename _Tp, typename _Alloc>
396     template <typename _ForwardIterator>
397       void
398       deque<_Tp, _Alloc>::
399       _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
400                           std::forward_iterator_tag)
401       {
402         const size_type __n = std::distance(__first, __last);
403         this->_M_initialize_map(__n);
404 
405         _Map_pointer __cur_node;
406         __try
407           {
408             for (__cur_node = this->_M_impl._M_start._M_node;
409                  __cur_node < this->_M_impl._M_finish._M_node;
410                  ++__cur_node)
411 	      {
412 		_ForwardIterator __mid = __first;
413 		std::advance(__mid, _S_buffer_size());
414 		std::__uninitialized_copy_a(__first, __mid, *__cur_node,
415 					    _M_get_Tp_allocator());
416 		__first = __mid;
417 	      }
418             std::__uninitialized_copy_a(__first, __last,
419 					this->_M_impl._M_finish._M_first,
420 					_M_get_Tp_allocator());
421           }
422         __catch(...)
423           {
424             std::_Destroy(this->_M_impl._M_start,
425 			  iterator(*__cur_node, __cur_node),
426 			  _M_get_Tp_allocator());
427             __throw_exception_again;
428           }
429       }
430 
431   // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_last - 1.
432   template<typename _Tp, typename _Alloc>
433 #ifdef __GXX_EXPERIMENTAL_CXX0X__
434     template<typename... _Args>
435       void
436       deque<_Tp, _Alloc>::
437       _M_push_back_aux(_Args&&... __args)
438 #else
439       void
440       deque<_Tp, _Alloc>::
441       _M_push_back_aux(const value_type& __t)
442 #endif
443       {
444 	_M_reserve_map_at_back();
445 	*(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node();
446 	__try
447 	  {
448 #ifdef __GXX_EXPERIMENTAL_CXX0X__
449 	    this->_M_impl.construct(this->_M_impl._M_finish._M_cur,
450 				    std::forward<_Args>(__args)...);
451 #else
452 	    this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t);
453 #endif
454 	    this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node
455 						+ 1);
456 	    this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first;
457 	  }
458 	__catch(...)
459 	  {
460 	    _M_deallocate_node(*(this->_M_impl._M_finish._M_node + 1));
461 	    __throw_exception_again;
462 	  }
463       }
464 
465   // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_first.
466   template<typename _Tp, typename _Alloc>
467 #ifdef __GXX_EXPERIMENTAL_CXX0X__
468     template<typename... _Args>
469       void
470       deque<_Tp, _Alloc>::
471       _M_push_front_aux(_Args&&... __args)
472 #else
473       void
474       deque<_Tp, _Alloc>::
475       _M_push_front_aux(const value_type& __t)
476 #endif
477       {
478 	_M_reserve_map_at_front();
479 	*(this->_M_impl._M_start._M_node - 1) = this->_M_allocate_node();
480 	__try
481 	  {
482 	    this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node
483 					       - 1);
484 	    this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1;
485 #ifdef __GXX_EXPERIMENTAL_CXX0X__
486 	    this->_M_impl.construct(this->_M_impl._M_start._M_cur,
487 				    std::forward<_Args>(__args)...);
488 #else
489 	    this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t);
490 #endif
491 	  }
492 	__catch(...)
493 	  {
494 	    ++this->_M_impl._M_start;
495 	    _M_deallocate_node(*(this->_M_impl._M_start._M_node - 1));
496 	    __throw_exception_again;
497 	  }
498       }
499 
500   // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_first.
501   template <typename _Tp, typename _Alloc>
502     void deque<_Tp, _Alloc>::
503     _M_pop_back_aux()
504     {
505       _M_deallocate_node(this->_M_impl._M_finish._M_first);
506       this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - 1);
507       this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_last - 1;
508       this->_M_impl.destroy(this->_M_impl._M_finish._M_cur);
509     }
510 
511   // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1.
512   // Note that if the deque has at least one element (a precondition for this
513   // member function), and if
514   //   _M_impl._M_start._M_cur == _M_impl._M_start._M_last,
515   // then the deque must have at least two nodes.
516   template <typename _Tp, typename _Alloc>
517     void deque<_Tp, _Alloc>::
518     _M_pop_front_aux()
519     {
520       this->_M_impl.destroy(this->_M_impl._M_start._M_cur);
521       _M_deallocate_node(this->_M_impl._M_start._M_first);
522       this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1);
523       this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first;
524     }
525 
526   template <typename _Tp, typename _Alloc>
527     template <typename _InputIterator>
528       void
529       deque<_Tp, _Alloc>::
530       _M_range_insert_aux(iterator __pos,
531                           _InputIterator __first, _InputIterator __last,
532                           std::input_iterator_tag)
533       { std::copy(__first, __last, std::inserter(*this, __pos)); }
534 
535   template <typename _Tp, typename _Alloc>
536     template <typename _ForwardIterator>
537       void
538       deque<_Tp, _Alloc>::
539       _M_range_insert_aux(iterator __pos,
540                           _ForwardIterator __first, _ForwardIterator __last,
541                           std::forward_iterator_tag)
542       {
543         const size_type __n = std::distance(__first, __last);
544         if (__pos._M_cur == this->_M_impl._M_start._M_cur)
545 	  {
546 	    iterator __new_start = _M_reserve_elements_at_front(__n);
547 	    __try
548 	      {
549 		std::__uninitialized_copy_a(__first, __last, __new_start,
550 					    _M_get_Tp_allocator());
551 		this->_M_impl._M_start = __new_start;
552 	      }
553 	    __catch(...)
554 	      {
555 		_M_destroy_nodes(__new_start._M_node,
556 				 this->_M_impl._M_start._M_node);
557 		__throw_exception_again;
558 	      }
559 	  }
560         else if (__pos._M_cur == this->_M_impl._M_finish._M_cur)
561 	  {
562 	    iterator __new_finish = _M_reserve_elements_at_back(__n);
563 	    __try
564 	      {
565 		std::__uninitialized_copy_a(__first, __last,
566 					    this->_M_impl._M_finish,
567 					    _M_get_Tp_allocator());
568 		this->_M_impl._M_finish = __new_finish;
569 	      }
570 	    __catch(...)
571 	      {
572 		_M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
573 				 __new_finish._M_node + 1);
574 		__throw_exception_again;
575 	      }
576 	  }
577         else
578           _M_insert_aux(__pos, __first, __last, __n);
579       }
580 
581   template<typename _Tp, typename _Alloc>
582 #ifdef __GXX_EXPERIMENTAL_CXX0X__
583     template<typename... _Args>
584       typename deque<_Tp, _Alloc>::iterator
585       deque<_Tp, _Alloc>::
586       _M_insert_aux(iterator __pos, _Args&&... __args)
587       {
588 	value_type __x_copy(std::forward<_Args>(__args)...); // XXX copy
589 #else
590     typename deque<_Tp, _Alloc>::iterator
591       deque<_Tp, _Alloc>::
592       _M_insert_aux(iterator __pos, const value_type& __x)
593       {
594 	value_type __x_copy = __x; // XXX copy
595 #endif
596 	difference_type __index = __pos - this->_M_impl._M_start;
597 	if (static_cast<size_type>(__index) < size() / 2)
598 	  {
599 	    push_front(_GLIBCXX_MOVE(front()));
600 	    iterator __front1 = this->_M_impl._M_start;
601 	    ++__front1;
602 	    iterator __front2 = __front1;
603 	    ++__front2;
604 	    __pos = this->_M_impl._M_start + __index;
605 	    iterator __pos1 = __pos;
606 	    ++__pos1;
607 	    _GLIBCXX_MOVE3(__front2, __pos1, __front1);
608 	  }
609 	else
610 	  {
611 	    push_back(_GLIBCXX_MOVE(back()));
612 	    iterator __back1 = this->_M_impl._M_finish;
613 	    --__back1;
614 	    iterator __back2 = __back1;
615 	    --__back2;
616 	    __pos = this->_M_impl._M_start + __index;
617 	    _GLIBCXX_MOVE_BACKWARD3(__pos, __back2, __back1);
618 	  }
619 	*__pos = _GLIBCXX_MOVE(__x_copy);
620 	return __pos;
621       }
622 
623   template <typename _Tp, typename _Alloc>
624     void
625     deque<_Tp, _Alloc>::
626     _M_insert_aux(iterator __pos, size_type __n, const value_type& __x)
627     {
628       const difference_type __elems_before = __pos - this->_M_impl._M_start;
629       const size_type __length = this->size();
630       value_type __x_copy = __x;
631       if (__elems_before < difference_type(__length / 2))
632 	{
633 	  iterator __new_start = _M_reserve_elements_at_front(__n);
634 	  iterator __old_start = this->_M_impl._M_start;
635 	  __pos = this->_M_impl._M_start + __elems_before;
636 	  __try
637 	    {
638 	      if (__elems_before >= difference_type(__n))
639 		{
640 		  iterator __start_n = (this->_M_impl._M_start
641 					+ difference_type(__n));
642 		  std::__uninitialized_move_a(this->_M_impl._M_start,
643 					      __start_n, __new_start,
644 					      _M_get_Tp_allocator());
645 		  this->_M_impl._M_start = __new_start;
646 		  _GLIBCXX_MOVE3(__start_n, __pos, __old_start);
647 		  std::fill(__pos - difference_type(__n), __pos, __x_copy);
648 		}
649 	      else
650 		{
651 		  std::__uninitialized_move_fill(this->_M_impl._M_start,
652 						 __pos, __new_start,
653 						 this->_M_impl._M_start,
654 						 __x_copy,
655 						 _M_get_Tp_allocator());
656 		  this->_M_impl._M_start = __new_start;
657 		  std::fill(__old_start, __pos, __x_copy);
658 		}
659 	    }
660 	  __catch(...)
661 	    {
662 	      _M_destroy_nodes(__new_start._M_node,
663 			       this->_M_impl._M_start._M_node);
664 	      __throw_exception_again;
665 	    }
666 	}
667       else
668 	{
669 	  iterator __new_finish = _M_reserve_elements_at_back(__n);
670 	  iterator __old_finish = this->_M_impl._M_finish;
671 	  const difference_type __elems_after =
672 	    difference_type(__length) - __elems_before;
673 	  __pos = this->_M_impl._M_finish - __elems_after;
674 	  __try
675 	    {
676 	      if (__elems_after > difference_type(__n))
677 		{
678 		  iterator __finish_n = (this->_M_impl._M_finish
679 					 - difference_type(__n));
680 		  std::__uninitialized_move_a(__finish_n,
681 					      this->_M_impl._M_finish,
682 					      this->_M_impl._M_finish,
683 					      _M_get_Tp_allocator());
684 		  this->_M_impl._M_finish = __new_finish;
685 		  _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish);
686 		  std::fill(__pos, __pos + difference_type(__n), __x_copy);
687 		}
688 	      else
689 		{
690 		  std::__uninitialized_fill_move(this->_M_impl._M_finish,
691 						 __pos + difference_type(__n),
692 						 __x_copy, __pos,
693 						 this->_M_impl._M_finish,
694 						 _M_get_Tp_allocator());
695 		  this->_M_impl._M_finish = __new_finish;
696 		  std::fill(__pos, __old_finish, __x_copy);
697 		}
698 	    }
699 	  __catch(...)
700 	    {
701 	      _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
702 			       __new_finish._M_node + 1);
703 	      __throw_exception_again;
704 	    }
705 	}
706     }
707 
708   template <typename _Tp, typename _Alloc>
709     template <typename _ForwardIterator>
710       void
711       deque<_Tp, _Alloc>::
712       _M_insert_aux(iterator __pos,
713                     _ForwardIterator __first, _ForwardIterator __last,
714                     size_type __n)
715       {
716         const difference_type __elemsbefore = __pos - this->_M_impl._M_start;
717         const size_type __length = size();
718         if (static_cast<size_type>(__elemsbefore) < __length / 2)
719 	  {
720 	    iterator __new_start = _M_reserve_elements_at_front(__n);
721 	    iterator __old_start = this->_M_impl._M_start;
722 	    __pos = this->_M_impl._M_start + __elemsbefore;
723 	    __try
724 	      {
725 		if (__elemsbefore >= difference_type(__n))
726 		  {
727 		    iterator __start_n = (this->_M_impl._M_start
728 					  + difference_type(__n));
729 		    std::__uninitialized_move_a(this->_M_impl._M_start,
730 						__start_n, __new_start,
731 						_M_get_Tp_allocator());
732 		    this->_M_impl._M_start = __new_start;
733 		    _GLIBCXX_MOVE3(__start_n, __pos, __old_start);
734 		    std::copy(__first, __last, __pos - difference_type(__n));
735 		  }
736 		else
737 		  {
738 		    _ForwardIterator __mid = __first;
739 		    std::advance(__mid, difference_type(__n) - __elemsbefore);
740 		    std::__uninitialized_move_copy(this->_M_impl._M_start,
741 						   __pos, __first, __mid,
742 						   __new_start,
743 						   _M_get_Tp_allocator());
744 		    this->_M_impl._M_start = __new_start;
745 		    std::copy(__mid, __last, __old_start);
746 		  }
747 	      }
748 	    __catch(...)
749 	      {
750 		_M_destroy_nodes(__new_start._M_node,
751 				 this->_M_impl._M_start._M_node);
752 		__throw_exception_again;
753 	      }
754 	  }
755         else
756         {
757           iterator __new_finish = _M_reserve_elements_at_back(__n);
758           iterator __old_finish = this->_M_impl._M_finish;
759           const difference_type __elemsafter =
760             difference_type(__length) - __elemsbefore;
761           __pos = this->_M_impl._M_finish - __elemsafter;
762           __try
763             {
764               if (__elemsafter > difference_type(__n))
765 		{
766 		  iterator __finish_n = (this->_M_impl._M_finish
767 					 - difference_type(__n));
768 		  std::__uninitialized_move_a(__finish_n,
769 					      this->_M_impl._M_finish,
770 					      this->_M_impl._M_finish,
771 					      _M_get_Tp_allocator());
772 		  this->_M_impl._M_finish = __new_finish;
773 		  _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish);
774 		  std::copy(__first, __last, __pos);
775 		}
776               else
777 		{
778 		  _ForwardIterator __mid = __first;
779 		  std::advance(__mid, __elemsafter);
780 		  std::__uninitialized_copy_move(__mid, __last, __pos,
781 						 this->_M_impl._M_finish,
782 						 this->_M_impl._M_finish,
783 						 _M_get_Tp_allocator());
784 		  this->_M_impl._M_finish = __new_finish;
785 		  std::copy(__first, __mid, __pos);
786 		}
787             }
788           __catch(...)
789             {
790               _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
791 			       __new_finish._M_node + 1);
792               __throw_exception_again;
793             }
794         }
795       }
796 
797    template<typename _Tp, typename _Alloc>
798      void
799      deque<_Tp, _Alloc>::
800      _M_destroy_data_aux(iterator __first, iterator __last)
801      {
802        for (_Map_pointer __node = __first._M_node + 1;
803 	    __node < __last._M_node; ++__node)
804 	 std::_Destroy(*__node, *__node + _S_buffer_size(),
805 		       _M_get_Tp_allocator());
806 
807        if (__first._M_node != __last._M_node)
808 	 {
809 	   std::_Destroy(__first._M_cur, __first._M_last,
810 			 _M_get_Tp_allocator());
811 	   std::_Destroy(__last._M_first, __last._M_cur,
812 			 _M_get_Tp_allocator());
813 	 }
814        else
815 	 std::_Destroy(__first._M_cur, __last._M_cur,
816 		       _M_get_Tp_allocator());
817      }
818 
819   template <typename _Tp, typename _Alloc>
820     void
821     deque<_Tp, _Alloc>::
822     _M_new_elements_at_front(size_type __new_elems)
823     {
824       if (this->max_size() - this->size() < __new_elems)
825 	__throw_length_error(__N("deque::_M_new_elements_at_front"));
826 
827       const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1)
828 				     / _S_buffer_size());
829       _M_reserve_map_at_front(__new_nodes);
830       size_type __i;
831       __try
832         {
833           for (__i = 1; __i <= __new_nodes; ++__i)
834             *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node();
835         }
836       __catch(...)
837         {
838           for (size_type __j = 1; __j < __i; ++__j)
839             _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j));
840           __throw_exception_again;
841         }
842     }
843 
844   template <typename _Tp, typename _Alloc>
845     void
846     deque<_Tp, _Alloc>::
847     _M_new_elements_at_back(size_type __new_elems)
848     {
849       if (this->max_size() - this->size() < __new_elems)
850 	__throw_length_error(__N("deque::_M_new_elements_at_back"));
851 
852       const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1)
853 				     / _S_buffer_size());
854       _M_reserve_map_at_back(__new_nodes);
855       size_type __i;
856       __try
857         {
858           for (__i = 1; __i <= __new_nodes; ++__i)
859             *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node();
860         }
861       __catch(...)
862         {
863           for (size_type __j = 1; __j < __i; ++__j)
864             _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j));
865           __throw_exception_again;
866         }
867     }
868 
869   template <typename _Tp, typename _Alloc>
870     void
871     deque<_Tp, _Alloc>::
872     _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front)
873     {
874       const size_type __old_num_nodes
875 	= this->_M_impl._M_finish._M_node - this->_M_impl._M_start._M_node + 1;
876       const size_type __new_num_nodes = __old_num_nodes + __nodes_to_add;
877 
878       _Map_pointer __new_nstart;
879       if (this->_M_impl._M_map_size > 2 * __new_num_nodes)
880 	{
881 	  __new_nstart = this->_M_impl._M_map + (this->_M_impl._M_map_size
882 					 - __new_num_nodes) / 2
883 	                 + (__add_at_front ? __nodes_to_add : 0);
884 	  if (__new_nstart < this->_M_impl._M_start._M_node)
885 	    std::copy(this->_M_impl._M_start._M_node,
886 		      this->_M_impl._M_finish._M_node + 1,
887 		      __new_nstart);
888 	  else
889 	    std::copy_backward(this->_M_impl._M_start._M_node,
890 			       this->_M_impl._M_finish._M_node + 1,
891 			       __new_nstart + __old_num_nodes);
892 	}
893       else
894 	{
895 	  size_type __new_map_size = this->_M_impl._M_map_size
896 	                             + std::max(this->_M_impl._M_map_size,
897 						__nodes_to_add) + 2;
898 
899 	  _Map_pointer __new_map = this->_M_allocate_map(__new_map_size);
900 	  __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2
901 	                 + (__add_at_front ? __nodes_to_add : 0);
902 	  std::copy(this->_M_impl._M_start._M_node,
903 		    this->_M_impl._M_finish._M_node + 1,
904 		    __new_nstart);
905 	  _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
906 
907 	  this->_M_impl._M_map = __new_map;
908 	  this->_M_impl._M_map_size = __new_map_size;
909 	}
910 
911       this->_M_impl._M_start._M_set_node(__new_nstart);
912       this->_M_impl._M_finish._M_set_node(__new_nstart + __old_num_nodes - 1);
913     }
914 
915   // Overload for deque::iterators, exploiting the "segmented-iterator
916   // optimization".
917   template<typename _Tp>
918     void
919     fill(const _Deque_iterator<_Tp, _Tp&, _Tp*>& __first,
920 	 const _Deque_iterator<_Tp, _Tp&, _Tp*>& __last, const _Tp& __value)
921     {
922       typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
923 
924       for (typename _Self::_Map_pointer __node = __first._M_node + 1;
925            __node < __last._M_node; ++__node)
926 	std::fill(*__node, *__node + _Self::_S_buffer_size(), __value);
927 
928       if (__first._M_node != __last._M_node)
929 	{
930 	  std::fill(__first._M_cur, __first._M_last, __value);
931 	  std::fill(__last._M_first, __last._M_cur, __value);
932 	}
933       else
934 	std::fill(__first._M_cur, __last._M_cur, __value);
935     }
936 
937   template<typename _Tp>
938     _Deque_iterator<_Tp, _Tp&, _Tp*>
939     copy(_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
940 	 _Deque_iterator<_Tp, const _Tp&, const _Tp*> __last,
941 	 _Deque_iterator<_Tp, _Tp&, _Tp*> __result)
942     {
943       typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
944       typedef typename _Self::difference_type difference_type;
945 
946       difference_type __len = __last - __first;
947       while (__len > 0)
948 	{
949 	  const difference_type __clen
950 	    = std::min(__len, std::min(__first._M_last - __first._M_cur,
951 				       __result._M_last - __result._M_cur));
952 	  std::copy(__first._M_cur, __first._M_cur + __clen, __result._M_cur);
953 	  __first += __clen;
954 	  __result += __clen;
955 	  __len -= __clen;
956 	}
957       return __result;
958     }
959 
960   template<typename _Tp>
961     _Deque_iterator<_Tp, _Tp&, _Tp*>
962     copy_backward(_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
963 		  _Deque_iterator<_Tp, const _Tp&, const _Tp*> __last,
964 		  _Deque_iterator<_Tp, _Tp&, _Tp*> __result)
965     {
966       typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
967       typedef typename _Self::difference_type difference_type;
968 
969       difference_type __len = __last - __first;
970       while (__len > 0)
971 	{
972 	  difference_type __llen = __last._M_cur - __last._M_first;
973 	  _Tp* __lend = __last._M_cur;
974 
975 	  difference_type __rlen = __result._M_cur - __result._M_first;
976 	  _Tp* __rend = __result._M_cur;
977 
978 	  if (!__llen)
979 	    {
980 	      __llen = _Self::_S_buffer_size();
981 	      __lend = *(__last._M_node - 1) + __llen;
982 	    }
983 	  if (!__rlen)
984 	    {
985 	      __rlen = _Self::_S_buffer_size();
986 	      __rend = *(__result._M_node - 1) + __rlen;
987 	    }
988 
989 	  const difference_type __clen = std::min(__len,
990 						  std::min(__llen, __rlen));
991 	  std::copy_backward(__lend - __clen, __lend, __rend);
992 	  __last -= __clen;
993 	  __result -= __clen;
994 	  __len -= __clen;
995 	}
996       return __result;
997     }
998 
999 #ifdef __GXX_EXPERIMENTAL_CXX0X__
1000   template<typename _Tp>
1001     _Deque_iterator<_Tp, _Tp&, _Tp*>
1002     move(_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
1003 	 _Deque_iterator<_Tp, const _Tp&, const _Tp*> __last,
1004 	 _Deque_iterator<_Tp, _Tp&, _Tp*> __result)
1005     {
1006       typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
1007       typedef typename _Self::difference_type difference_type;
1008 
1009       difference_type __len = __last - __first;
1010       while (__len > 0)
1011 	{
1012 	  const difference_type __clen
1013 	    = std::min(__len, std::min(__first._M_last - __first._M_cur,
1014 				       __result._M_last - __result._M_cur));
1015 	  std::move(__first._M_cur, __first._M_cur + __clen, __result._M_cur);
1016 	  __first += __clen;
1017 	  __result += __clen;
1018 	  __len -= __clen;
1019 	}
1020       return __result;
1021     }
1022 
1023   template<typename _Tp>
1024     _Deque_iterator<_Tp, _Tp&, _Tp*>
1025     move_backward(_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
1026 		  _Deque_iterator<_Tp, const _Tp&, const _Tp*> __last,
1027 		  _Deque_iterator<_Tp, _Tp&, _Tp*> __result)
1028     {
1029       typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
1030       typedef typename _Self::difference_type difference_type;
1031 
1032       difference_type __len = __last - __first;
1033       while (__len > 0)
1034 	{
1035 	  difference_type __llen = __last._M_cur - __last._M_first;
1036 	  _Tp* __lend = __last._M_cur;
1037 
1038 	  difference_type __rlen = __result._M_cur - __result._M_first;
1039 	  _Tp* __rend = __result._M_cur;
1040 
1041 	  if (!__llen)
1042 	    {
1043 	      __llen = _Self::_S_buffer_size();
1044 	      __lend = *(__last._M_node - 1) + __llen;
1045 	    }
1046 	  if (!__rlen)
1047 	    {
1048 	      __rlen = _Self::_S_buffer_size();
1049 	      __rend = *(__result._M_node - 1) + __rlen;
1050 	    }
1051 
1052 	  const difference_type __clen = std::min(__len,
1053 						  std::min(__llen, __rlen));
1054 	  std::move_backward(__lend - __clen, __lend, __rend);
1055 	  __last -= __clen;
1056 	  __result -= __clen;
1057 	  __len -= __clen;
1058 	}
1059       return __result;
1060     }
1061 #endif
1062 
1063 _GLIBCXX_END_NAMESPACE_CONTAINER
1064 } // namespace std
1065 
1066 #endif
1067