1// Deque implementation (out of line) -*- C++ -*-
2
3// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING.  If not, write to the Free
19// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20// USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction.  Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License.  This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
31/*
32 *
33 * Copyright (c) 1994
34 * Hewlett-Packard Company
35 *
36 * Permission to use, copy, modify, distribute and sell this software
37 * and its documentation for any purpose is hereby granted without fee,
38 * provided that the above copyright notice appear in all copies and
39 * that both that copyright notice and this permission notice appear
40 * in supporting documentation.  Hewlett-Packard Company makes no
41 * representations about the suitability of this software for any
42 * purpose.  It is provided "as is" without express or implied warranty.
43 *
44 *
45 * Copyright (c) 1997
46 * Silicon Graphics Computer Systems, Inc.
47 *
48 * Permission to use, copy, modify, distribute and sell this software
49 * and its documentation for any purpose is hereby granted without fee,
50 * provided that the above copyright notice appear in all copies and
51 * that both that copyright notice and this permission notice appear
52 * in supporting documentation.  Silicon Graphics makes no
53 * representations about the suitability of this software for any
54 * purpose.  It is provided "as is" without express or implied warranty.
55 */
56
57/** @file deque.tcc
58 *  This is an internal header file, included by other library headers.
59 *  You should not attempt to use it directly.
60 */
61
62#ifndef _DEQUE_TCC
63#define _DEQUE_TCC 1
64
65_GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD)
66
67  template <typename _Tp, typename _Alloc>
68    deque<_Tp, _Alloc>&
69    deque<_Tp, _Alloc>::
70    operator=(const deque& __x)
71    {
72      const size_type __len = size();
73      if (&__x != this)
74	{
75	  if (__len >= __x.size())
76	    _M_erase_at_end(std::copy(__x.begin(), __x.end(),
77				      this->_M_impl._M_start));
78	  else
79	    {
80	      const_iterator __mid = __x.begin() + difference_type(__len);
81	      std::copy(__x.begin(), __mid, this->_M_impl._M_start);
82	      insert(this->_M_impl._M_finish, __mid, __x.end());
83	    }
84	}
85      return *this;
86    }
87
88  template <typename _Tp, typename _Alloc>
89    typename deque<_Tp, _Alloc>::iterator
90    deque<_Tp, _Alloc>::
91    insert(iterator __position, const value_type& __x)
92    {
93      if (__position._M_cur == this->_M_impl._M_start._M_cur)
94	{
95	  push_front(__x);
96	  return this->_M_impl._M_start;
97	}
98      else if (__position._M_cur == this->_M_impl._M_finish._M_cur)
99	{
100	  push_back(__x);
101	  iterator __tmp = this->_M_impl._M_finish;
102	  --__tmp;
103	  return __tmp;
104	}
105      else
106        return _M_insert_aux(__position, __x);
107    }
108
109  template <typename _Tp, typename _Alloc>
110    typename deque<_Tp, _Alloc>::iterator
111    deque<_Tp, _Alloc>::
112    erase(iterator __position)
113    {
114      iterator __next = __position;
115      ++__next;
116      const difference_type __index = __position - begin();
117      if (static_cast<size_type>(__index) < (size() >> 1))
118	{
119	  if (__position != begin())
120	    std::copy_backward(begin(), __position, __next);
121	  pop_front();
122	}
123      else
124	{
125	  if (__next != end())
126	    std::copy(__next, end(), __position);
127	  pop_back();
128	}
129      return begin() + __index;
130    }
131
132  template <typename _Tp, typename _Alloc>
133    typename deque<_Tp, _Alloc>::iterator
134    deque<_Tp, _Alloc>::
135    erase(iterator __first, iterator __last)
136    {
137      if (__first == begin() && __last == end())
138	{
139	  clear();
140	  return end();
141	}
142      else
143	{
144	  const difference_type __n = __last - __first;
145	  const difference_type __elems_before = __first - begin();
146	  if (static_cast<size_type>(__elems_before) <= (size() - __n) / 2)
147	    {
148	      if (__first != begin())
149		std::copy_backward(begin(), __first, __last);
150	      _M_erase_at_begin(begin() + __n);
151	    }
152	  else
153	    {
154	      if (__last != end())
155		std::copy(__last, end(), __first);
156	      _M_erase_at_end(end() - __n);
157	    }
158	  return begin() + __elems_before;
159	}
160    }
161
162  template <typename _Tp, class _Alloc>
163    template <typename _InputIterator>
164      void
165      deque<_Tp, _Alloc>::
166      _M_assign_aux(_InputIterator __first, _InputIterator __last,
167		    std::input_iterator_tag)
168      {
169        iterator __cur = begin();
170        for (; __first != __last && __cur != end(); ++__cur, ++__first)
171          *__cur = *__first;
172        if (__first == __last)
173          _M_erase_at_end(__cur);
174        else
175          insert(end(), __first, __last);
176      }
177
178  template <typename _Tp, typename _Alloc>
179    void
180    deque<_Tp, _Alloc>::
181    _M_fill_insert(iterator __pos, size_type __n, const value_type& __x)
182    {
183      if (__pos._M_cur == this->_M_impl._M_start._M_cur)
184	{
185	  iterator __new_start = _M_reserve_elements_at_front(__n);
186	  try
187	    {
188	      std::__uninitialized_fill_a(__new_start, this->_M_impl._M_start,
189					  __x, _M_get_Tp_allocator());
190	      this->_M_impl._M_start = __new_start;
191	    }
192	  catch(...)
193	    {
194	      _M_destroy_nodes(__new_start._M_node,
195			       this->_M_impl._M_start._M_node);
196	      __throw_exception_again;
197	    }
198	}
199      else if (__pos._M_cur == this->_M_impl._M_finish._M_cur)
200	{
201	  iterator __new_finish = _M_reserve_elements_at_back(__n);
202	  try
203	    {
204	      std::__uninitialized_fill_a(this->_M_impl._M_finish,
205					  __new_finish, __x,
206					  _M_get_Tp_allocator());
207	      this->_M_impl._M_finish = __new_finish;
208	    }
209	  catch(...)
210	    {
211	      _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
212			       __new_finish._M_node + 1);
213	      __throw_exception_again;
214	    }
215	}
216      else
217        _M_insert_aux(__pos, __n, __x);
218    }
219
220  template <typename _Tp, typename _Alloc>
221    void
222    deque<_Tp, _Alloc>::
223    _M_fill_initialize(const value_type& __value)
224    {
225      _Map_pointer __cur;
226      try
227        {
228          for (__cur = this->_M_impl._M_start._M_node;
229	       __cur < this->_M_impl._M_finish._M_node;
230	       ++__cur)
231            std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(),
232					__value, _M_get_Tp_allocator());
233          std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first,
234				      this->_M_impl._M_finish._M_cur,
235				      __value, _M_get_Tp_allocator());
236        }
237      catch(...)
238        {
239          std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur),
240			_M_get_Tp_allocator());
241          __throw_exception_again;
242        }
243    }
244
245  template <typename _Tp, typename _Alloc>
246    template <typename _InputIterator>
247      void
248      deque<_Tp, _Alloc>::
249      _M_range_initialize(_InputIterator __first, _InputIterator __last,
250                          std::input_iterator_tag)
251      {
252        this->_M_initialize_map(0);
253        try
254          {
255            for (; __first != __last; ++__first)
256              push_back(*__first);
257          }
258        catch(...)
259          {
260            clear();
261            __throw_exception_again;
262          }
263      }
264
265  template <typename _Tp, typename _Alloc>
266    template <typename _ForwardIterator>
267      void
268      deque<_Tp, _Alloc>::
269      _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
270                          std::forward_iterator_tag)
271      {
272        const size_type __n = std::distance(__first, __last);
273        this->_M_initialize_map(__n);
274
275        _Map_pointer __cur_node;
276        try
277          {
278            for (__cur_node = this->_M_impl._M_start._M_node;
279                 __cur_node < this->_M_impl._M_finish._M_node;
280                 ++__cur_node)
281	      {
282		_ForwardIterator __mid = __first;
283		std::advance(__mid, _S_buffer_size());
284		std::__uninitialized_copy_a(__first, __mid, *__cur_node,
285					    _M_get_Tp_allocator());
286		__first = __mid;
287	      }
288            std::__uninitialized_copy_a(__first, __last,
289					this->_M_impl._M_finish._M_first,
290					_M_get_Tp_allocator());
291          }
292        catch(...)
293          {
294            std::_Destroy(this->_M_impl._M_start,
295			  iterator(*__cur_node, __cur_node),
296			  _M_get_Tp_allocator());
297            __throw_exception_again;
298          }
299      }
300
301  // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_last - 1.
302  template <typename _Tp, typename _Alloc>
303    void
304    deque<_Tp, _Alloc>::
305    _M_push_back_aux(const value_type& __t)
306    {
307      value_type __t_copy = __t;
308      _M_reserve_map_at_back();
309      *(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node();
310      try
311        {
312          this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t_copy);
313          this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node
314					      + 1);
315          this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first;
316        }
317      catch(...)
318        {
319          _M_deallocate_node(*(this->_M_impl._M_finish._M_node + 1));
320          __throw_exception_again;
321        }
322    }
323
324  // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_first.
325  template <typename _Tp, typename _Alloc>
326    void
327    deque<_Tp, _Alloc>::
328    _M_push_front_aux(const value_type& __t)
329    {
330      value_type __t_copy = __t;
331      _M_reserve_map_at_front();
332      *(this->_M_impl._M_start._M_node - 1) = this->_M_allocate_node();
333      try
334        {
335          this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node
336					     - 1);
337          this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1;
338          this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t_copy);
339        }
340      catch(...)
341        {
342          ++this->_M_impl._M_start;
343          _M_deallocate_node(*(this->_M_impl._M_start._M_node - 1));
344          __throw_exception_again;
345        }
346    }
347
348  // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_first.
349  template <typename _Tp, typename _Alloc>
350    void deque<_Tp, _Alloc>::
351    _M_pop_back_aux()
352    {
353      _M_deallocate_node(this->_M_impl._M_finish._M_first);
354      this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - 1);
355      this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_last - 1;
356      this->_M_impl.destroy(this->_M_impl._M_finish._M_cur);
357    }
358
359  // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1.
360  // Note that if the deque has at least one element (a precondition for this
361  // member function), and if
362  //   _M_impl._M_start._M_cur == _M_impl._M_start._M_last,
363  // then the deque must have at least two nodes.
364  template <typename _Tp, typename _Alloc>
365    void deque<_Tp, _Alloc>::
366    _M_pop_front_aux()
367    {
368      this->_M_impl.destroy(this->_M_impl._M_start._M_cur);
369      _M_deallocate_node(this->_M_impl._M_start._M_first);
370      this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1);
371      this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first;
372    }
373
374  template <typename _Tp, typename _Alloc>
375    template <typename _InputIterator>
376      void
377      deque<_Tp, _Alloc>::
378      _M_range_insert_aux(iterator __pos,
379                          _InputIterator __first, _InputIterator __last,
380                          std::input_iterator_tag)
381      { std::copy(__first, __last, std::inserter(*this, __pos)); }
382
383  template <typename _Tp, typename _Alloc>
384    template <typename _ForwardIterator>
385      void
386      deque<_Tp, _Alloc>::
387      _M_range_insert_aux(iterator __pos,
388                          _ForwardIterator __first, _ForwardIterator __last,
389                          std::forward_iterator_tag)
390      {
391        const size_type __n = std::distance(__first, __last);
392        if (__pos._M_cur == this->_M_impl._M_start._M_cur)
393	  {
394	    iterator __new_start = _M_reserve_elements_at_front(__n);
395	    try
396	      {
397		std::__uninitialized_copy_a(__first, __last, __new_start,
398					    _M_get_Tp_allocator());
399		this->_M_impl._M_start = __new_start;
400	      }
401	    catch(...)
402	      {
403		_M_destroy_nodes(__new_start._M_node,
404				 this->_M_impl._M_start._M_node);
405		__throw_exception_again;
406	      }
407	  }
408        else if (__pos._M_cur == this->_M_impl._M_finish._M_cur)
409	  {
410	    iterator __new_finish = _M_reserve_elements_at_back(__n);
411	    try
412	      {
413		std::__uninitialized_copy_a(__first, __last,
414					    this->_M_impl._M_finish,
415					    _M_get_Tp_allocator());
416		this->_M_impl._M_finish = __new_finish;
417	      }
418	    catch(...)
419	      {
420		_M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
421				 __new_finish._M_node + 1);
422		__throw_exception_again;
423	      }
424	  }
425        else
426          _M_insert_aux(__pos, __first, __last, __n);
427      }
428
429  template <typename _Tp, typename _Alloc>
430    typename deque<_Tp, _Alloc>::iterator
431    deque<_Tp, _Alloc>::
432    _M_insert_aux(iterator __pos, const value_type& __x)
433    {
434      difference_type __index = __pos - this->_M_impl._M_start;
435      value_type __x_copy = __x; // XXX copy
436      if (static_cast<size_type>(__index) < size() / 2)
437	{
438	  push_front(front());
439	  iterator __front1 = this->_M_impl._M_start;
440	  ++__front1;
441	  iterator __front2 = __front1;
442	  ++__front2;
443	  __pos = this->_M_impl._M_start + __index;
444	  iterator __pos1 = __pos;
445	  ++__pos1;
446	  std::copy(__front2, __pos1, __front1);
447	}
448      else
449	{
450	  push_back(back());
451	  iterator __back1 = this->_M_impl._M_finish;
452	  --__back1;
453	  iterator __back2 = __back1;
454	  --__back2;
455	  __pos = this->_M_impl._M_start + __index;
456	  std::copy_backward(__pos, __back2, __back1);
457	}
458      *__pos = __x_copy;
459      return __pos;
460    }
461
462  template <typename _Tp, typename _Alloc>
463    void
464    deque<_Tp, _Alloc>::
465    _M_insert_aux(iterator __pos, size_type __n, const value_type& __x)
466    {
467      const difference_type __elems_before = __pos - this->_M_impl._M_start;
468      const size_type __length = this->size();
469      value_type __x_copy = __x;
470      if (__elems_before < difference_type(__length / 2))
471	{
472	  iterator __new_start = _M_reserve_elements_at_front(__n);
473	  iterator __old_start = this->_M_impl._M_start;
474	  __pos = this->_M_impl._M_start + __elems_before;
475	  try
476	    {
477	      if (__elems_before >= difference_type(__n))
478		{
479		  iterator __start_n = (this->_M_impl._M_start
480					+ difference_type(__n));
481		  std::__uninitialized_copy_a(this->_M_impl._M_start,
482					      __start_n, __new_start,
483					      _M_get_Tp_allocator());
484		  this->_M_impl._M_start = __new_start;
485		  std::copy(__start_n, __pos, __old_start);
486		  std::fill(__pos - difference_type(__n), __pos, __x_copy);
487		}
488	      else
489		{
490		  std::__uninitialized_copy_fill(this->_M_impl._M_start,
491						 __pos, __new_start,
492						 this->_M_impl._M_start,
493						 __x_copy,
494						 _M_get_Tp_allocator());
495		  this->_M_impl._M_start = __new_start;
496		  std::fill(__old_start, __pos, __x_copy);
497		}
498	    }
499	  catch(...)
500	    {
501	      _M_destroy_nodes(__new_start._M_node,
502			       this->_M_impl._M_start._M_node);
503	      __throw_exception_again;
504	    }
505	}
506      else
507	{
508	  iterator __new_finish = _M_reserve_elements_at_back(__n);
509	  iterator __old_finish = this->_M_impl._M_finish;
510	  const difference_type __elems_after =
511	    difference_type(__length) - __elems_before;
512	  __pos = this->_M_impl._M_finish - __elems_after;
513	  try
514	    {
515	      if (__elems_after > difference_type(__n))
516		{
517		  iterator __finish_n = (this->_M_impl._M_finish
518					 - difference_type(__n));
519		  std::__uninitialized_copy_a(__finish_n,
520					      this->_M_impl._M_finish,
521					      this->_M_impl._M_finish,
522					      _M_get_Tp_allocator());
523		  this->_M_impl._M_finish = __new_finish;
524		  std::copy_backward(__pos, __finish_n, __old_finish);
525		  std::fill(__pos, __pos + difference_type(__n), __x_copy);
526		}
527	      else
528		{
529		  std::__uninitialized_fill_copy(this->_M_impl._M_finish,
530						 __pos + difference_type(__n),
531						 __x_copy, __pos,
532						 this->_M_impl._M_finish,
533						 _M_get_Tp_allocator());
534		  this->_M_impl._M_finish = __new_finish;
535		  std::fill(__pos, __old_finish, __x_copy);
536		}
537	    }
538	  catch(...)
539	    {
540	      _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
541			       __new_finish._M_node + 1);
542	      __throw_exception_again;
543	    }
544	}
545    }
546
547  template <typename _Tp, typename _Alloc>
548    template <typename _ForwardIterator>
549      void
550      deque<_Tp, _Alloc>::
551      _M_insert_aux(iterator __pos,
552                    _ForwardIterator __first, _ForwardIterator __last,
553                    size_type __n)
554      {
555        const difference_type __elemsbefore = __pos - this->_M_impl._M_start;
556        const size_type __length = size();
557        if (static_cast<size_type>(__elemsbefore) < __length / 2)
558	  {
559	    iterator __new_start = _M_reserve_elements_at_front(__n);
560	    iterator __old_start = this->_M_impl._M_start;
561	    __pos = this->_M_impl._M_start + __elemsbefore;
562	    try
563	      {
564		if (__elemsbefore >= difference_type(__n))
565		  {
566		    iterator __start_n = (this->_M_impl._M_start
567					  + difference_type(__n));
568		    std::__uninitialized_copy_a(this->_M_impl._M_start,
569						__start_n, __new_start,
570						_M_get_Tp_allocator());
571		    this->_M_impl._M_start = __new_start;
572		    std::copy(__start_n, __pos, __old_start);
573		    std::copy(__first, __last, __pos - difference_type(__n));
574		  }
575		else
576		  {
577		    _ForwardIterator __mid = __first;
578		    std::advance(__mid, difference_type(__n) - __elemsbefore);
579		    std::__uninitialized_copy_copy(this->_M_impl._M_start,
580						   __pos, __first, __mid,
581						   __new_start,
582						   _M_get_Tp_allocator());
583		    this->_M_impl._M_start = __new_start;
584		    std::copy(__mid, __last, __old_start);
585		  }
586	      }
587	    catch(...)
588	      {
589		_M_destroy_nodes(__new_start._M_node,
590				 this->_M_impl._M_start._M_node);
591		__throw_exception_again;
592	      }
593	  }
594        else
595        {
596          iterator __new_finish = _M_reserve_elements_at_back(__n);
597          iterator __old_finish = this->_M_impl._M_finish;
598          const difference_type __elemsafter =
599            difference_type(__length) - __elemsbefore;
600          __pos = this->_M_impl._M_finish - __elemsafter;
601          try
602            {
603              if (__elemsafter > difference_type(__n))
604		{
605		  iterator __finish_n = (this->_M_impl._M_finish
606					 - difference_type(__n));
607		  std::__uninitialized_copy_a(__finish_n,
608					      this->_M_impl._M_finish,
609					      this->_M_impl._M_finish,
610					      _M_get_Tp_allocator());
611		  this->_M_impl._M_finish = __new_finish;
612		  std::copy_backward(__pos, __finish_n, __old_finish);
613		  std::copy(__first, __last, __pos);
614		}
615              else
616		{
617		  _ForwardIterator __mid = __first;
618		  std::advance(__mid, __elemsafter);
619		  std::__uninitialized_copy_copy(__mid, __last, __pos,
620						 this->_M_impl._M_finish,
621						 this->_M_impl._M_finish,
622						 _M_get_Tp_allocator());
623		  this->_M_impl._M_finish = __new_finish;
624		  std::copy(__first, __mid, __pos);
625		}
626            }
627          catch(...)
628            {
629              _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
630			       __new_finish._M_node + 1);
631              __throw_exception_again;
632            }
633        }
634      }
635
636   template<typename _Tp, typename _Alloc>
637     void
638     deque<_Tp, _Alloc>::
639     _M_destroy_data_aux(iterator __first, iterator __last)
640     {
641       for (_Map_pointer __node = __first._M_node + 1;
642	    __node < __last._M_node; ++__node)
643	 std::_Destroy(*__node, *__node + _S_buffer_size(),
644		       _M_get_Tp_allocator());
645
646       if (__first._M_node != __last._M_node)
647	 {
648	   std::_Destroy(__first._M_cur, __first._M_last,
649			 _M_get_Tp_allocator());
650	   std::_Destroy(__last._M_first, __last._M_cur,
651			 _M_get_Tp_allocator());
652	 }
653       else
654	 std::_Destroy(__first._M_cur, __last._M_cur,
655		       _M_get_Tp_allocator());
656     }
657
658  template <typename _Tp, typename _Alloc>
659    void
660    deque<_Tp, _Alloc>::
661    _M_new_elements_at_front(size_type __new_elems)
662    {
663      if (this->max_size() - this->size() < __new_elems)
664	__throw_length_error(__N("deque::_M_new_elements_at_front"));
665
666      const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1)
667				     / _S_buffer_size());
668      _M_reserve_map_at_front(__new_nodes);
669      size_type __i;
670      try
671        {
672          for (__i = 1; __i <= __new_nodes; ++__i)
673            *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node();
674        }
675      catch(...)
676        {
677          for (size_type __j = 1; __j < __i; ++__j)
678            _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j));
679          __throw_exception_again;
680        }
681    }
682
683  template <typename _Tp, typename _Alloc>
684    void
685    deque<_Tp, _Alloc>::
686    _M_new_elements_at_back(size_type __new_elems)
687    {
688      if (this->max_size() - this->size() < __new_elems)
689	__throw_length_error(__N("deque::_M_new_elements_at_back"));
690
691      const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1)
692				     / _S_buffer_size());
693      _M_reserve_map_at_back(__new_nodes);
694      size_type __i;
695      try
696        {
697          for (__i = 1; __i <= __new_nodes; ++__i)
698            *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node();
699        }
700      catch(...)
701        {
702          for (size_type __j = 1; __j < __i; ++__j)
703            _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j));
704          __throw_exception_again;
705        }
706    }
707
708  template <typename _Tp, typename _Alloc>
709    void
710    deque<_Tp, _Alloc>::
711    _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front)
712    {
713      const size_type __old_num_nodes
714	= this->_M_impl._M_finish._M_node - this->_M_impl._M_start._M_node + 1;
715      const size_type __new_num_nodes = __old_num_nodes + __nodes_to_add;
716
717      _Map_pointer __new_nstart;
718      if (this->_M_impl._M_map_size > 2 * __new_num_nodes)
719	{
720	  __new_nstart = this->_M_impl._M_map + (this->_M_impl._M_map_size
721					 - __new_num_nodes) / 2
722	                 + (__add_at_front ? __nodes_to_add : 0);
723	  if (__new_nstart < this->_M_impl._M_start._M_node)
724	    std::copy(this->_M_impl._M_start._M_node,
725		      this->_M_impl._M_finish._M_node + 1,
726		      __new_nstart);
727	  else
728	    std::copy_backward(this->_M_impl._M_start._M_node,
729			       this->_M_impl._M_finish._M_node + 1,
730			       __new_nstart + __old_num_nodes);
731	}
732      else
733	{
734	  size_type __new_map_size = this->_M_impl._M_map_size
735	                             + std::max(this->_M_impl._M_map_size,
736						__nodes_to_add) + 2;
737
738	  _Map_pointer __new_map = this->_M_allocate_map(__new_map_size);
739	  __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2
740	                 + (__add_at_front ? __nodes_to_add : 0);
741	  std::copy(this->_M_impl._M_start._M_node,
742		    this->_M_impl._M_finish._M_node + 1,
743		    __new_nstart);
744	  _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
745
746	  this->_M_impl._M_map = __new_map;
747	  this->_M_impl._M_map_size = __new_map_size;
748	}
749
750      this->_M_impl._M_start._M_set_node(__new_nstart);
751      this->_M_impl._M_finish._M_set_node(__new_nstart + __old_num_nodes - 1);
752    }
753
754  // Overload for deque::iterators, exploiting the "segmented-iterator
755  // optimization".  NB: leave const_iterators alone!
756  template<typename _Tp>
757    void
758    fill(const _Deque_iterator<_Tp, _Tp&, _Tp*>& __first,
759	 const _Deque_iterator<_Tp, _Tp&, _Tp*>& __last, const _Tp& __value)
760    {
761      typedef typename _Deque_iterator<_Tp, _Tp&, _Tp*>::_Self _Self;
762
763      for (typename _Self::_Map_pointer __node = __first._M_node + 1;
764           __node < __last._M_node; ++__node)
765	std::fill(*__node, *__node + _Self::_S_buffer_size(), __value);
766
767      if (__first._M_node != __last._M_node)
768	{
769	  std::fill(__first._M_cur, __first._M_last, __value);
770	  std::fill(__last._M_first, __last._M_cur, __value);
771	}
772      else
773	std::fill(__first._M_cur, __last._M_cur, __value);
774    }
775
776_GLIBCXX_END_NESTED_NAMESPACE
777
778#endif
779