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