1 // Deque implementation (out of line) -*- C++ -*-
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
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.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
33 * Hewlett-Packard Company
35 * Permission to use, copy, modify, distribute and sell this software
36 * and its documentation for any purpose is hereby granted without fee,
37 * provided that the above copyright notice appear in all copies and
38 * that both that copyright notice and this permission notice appear
39 * in supporting documentation. Hewlett-Packard Company makes no
40 * representations about the suitability of this software for any
41 * purpose. It is provided "as is" without express or implied warranty.
45 * Silicon Graphics Computer Systems, Inc.
47 * Permission to use, copy, modify, distribute and sell this software
48 * and its documentation for any purpose is hereby granted without fee,
49 * provided that the above copyright notice appear in all copies and
50 * that both that copyright notice and this permission notice appear
51 * in supporting documentation. Silicon Graphics makes no
52 * representations about the suitability of this software for any
53 * purpose. It is provided "as is" without express or implied warranty.
57 * This is an internal header file, included by other library headers.
58 * You should not attempt to use it directly.
64 namespace _GLIBCXX_STD
66 template <typename _Tp, typename _Alloc>
69 operator=(const deque& __x)
71 const size_type __len = size();
74 if (__len >= __x.size())
75 erase(std::copy(__x.begin(), __x.end(), this->_M_impl._M_start),
76 this->_M_impl._M_finish);
79 const_iterator __mid = __x.begin() + difference_type(__len);
80 std::copy(__x.begin(), __mid, this->_M_impl._M_start);
81 insert(this->_M_impl._M_finish, __mid, __x.end());
87 template <typename _Tp, typename _Alloc>
88 typename deque<_Tp, _Alloc>::iterator
90 insert(iterator position, const value_type& __x)
92 if (position._M_cur == this->_M_impl._M_start._M_cur)
95 return this->_M_impl._M_start;
97 else if (position._M_cur == this->_M_impl._M_finish._M_cur)
100 iterator __tmp = this->_M_impl._M_finish;
105 return _M_insert_aux(position, __x);
108 template <typename _Tp, typename _Alloc>
109 typename deque<_Tp, _Alloc>::iterator
111 erase(iterator __position)
113 iterator __next = __position;
115 const size_type __index = __position - this->_M_impl._M_start;
116 if (__index < (size() >> 1))
118 std::copy_backward(this->_M_impl._M_start, __position, __next);
123 std::copy(__next, this->_M_impl._M_finish, __position);
126 return this->_M_impl._M_start + __index;
129 template <typename _Tp, typename _Alloc>
130 typename deque<_Tp, _Alloc>::iterator
132 erase(iterator __first, iterator __last)
134 if (__first == this->_M_impl._M_start
135 && __last == this->_M_impl._M_finish)
138 return this->_M_impl._M_finish;
142 const difference_type __n = __last - __first;
143 const difference_type __elems_before = (__first
144 - this->_M_impl._M_start);
145 if (static_cast<size_type>(__elems_before) < (size() - __n) / 2)
147 std::copy_backward(this->_M_impl._M_start, __first, __last);
148 iterator __new_start = this->_M_impl._M_start + __n;
149 std::_Destroy(this->_M_impl._M_start, __new_start,
150 _M_get_Tp_allocator());
151 _M_destroy_nodes(this->_M_impl._M_start._M_node,
152 __new_start._M_node);
153 this->_M_impl._M_start = __new_start;
157 std::copy(__last, this->_M_impl._M_finish, __first);
158 iterator __new_finish = this->_M_impl._M_finish - __n;
159 std::_Destroy(__new_finish, this->_M_impl._M_finish,
160 _M_get_Tp_allocator());
161 _M_destroy_nodes(__new_finish._M_node + 1,
162 this->_M_impl._M_finish._M_node + 1);
163 this->_M_impl._M_finish = __new_finish;
165 return this->_M_impl._M_start + __elems_before;
169 template <typename _Tp, typename _Alloc>
174 for (_Map_pointer __node = this->_M_impl._M_start._M_node + 1;
175 __node < this->_M_impl._M_finish._M_node;
178 std::_Destroy(*__node, *__node + _S_buffer_size(),
179 _M_get_Tp_allocator());
180 _M_deallocate_node(*__node);
183 if (this->_M_impl._M_start._M_node != this->_M_impl._M_finish._M_node)
185 std::_Destroy(this->_M_impl._M_start._M_cur,
186 this->_M_impl._M_start._M_last,
187 _M_get_Tp_allocator());
188 std::_Destroy(this->_M_impl._M_finish._M_first,
189 this->_M_impl._M_finish._M_cur,
190 _M_get_Tp_allocator());
191 _M_deallocate_node(this->_M_impl._M_finish._M_first);
194 std::_Destroy(this->_M_impl._M_start._M_cur,
195 this->_M_impl._M_finish._M_cur,
196 _M_get_Tp_allocator());
198 this->_M_impl._M_finish = this->_M_impl._M_start;
201 template <typename _Tp, class _Alloc>
202 template <typename _InputIterator>
205 _M_assign_aux(_InputIterator __first, _InputIterator __last,
206 std::input_iterator_tag)
208 iterator __cur = begin();
209 for (; __first != __last && __cur != end(); ++__cur, ++__first)
211 if (__first == __last)
214 insert(end(), __first, __last);
217 template <typename _Tp, typename _Alloc>
220 _M_fill_insert(iterator __pos, size_type __n, const value_type& __x)
222 if (__pos._M_cur == this->_M_impl._M_start._M_cur)
224 iterator __new_start = _M_reserve_elements_at_front(__n);
227 std::__uninitialized_fill_a(__new_start, this->_M_impl._M_start,
229 _M_get_Tp_allocator());
230 this->_M_impl._M_start = __new_start;
234 _M_destroy_nodes(__new_start._M_node,
235 this->_M_impl._M_start._M_node);
236 __throw_exception_again;
239 else if (__pos._M_cur == this->_M_impl._M_finish._M_cur)
241 iterator __new_finish = _M_reserve_elements_at_back(__n);
244 std::__uninitialized_fill_a(this->_M_impl._M_finish,
246 _M_get_Tp_allocator());
247 this->_M_impl._M_finish = __new_finish;
251 _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
252 __new_finish._M_node + 1);
253 __throw_exception_again;
257 _M_insert_aux(__pos, __n, __x);
260 template <typename _Tp, typename _Alloc>
263 _M_fill_initialize(const value_type& __value)
268 for (__cur = this->_M_impl._M_start._M_node;
269 __cur < this->_M_impl._M_finish._M_node;
271 std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(),
272 __value, _M_get_Tp_allocator());
273 std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first,
274 this->_M_impl._M_finish._M_cur,
275 __value, _M_get_Tp_allocator());
279 std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur),
280 _M_get_Tp_allocator());
281 __throw_exception_again;
285 template <typename _Tp, typename _Alloc>
286 template <typename _InputIterator>
289 _M_range_initialize(_InputIterator __first, _InputIterator __last,
290 std::input_iterator_tag)
292 this->_M_initialize_map(0);
295 for (; __first != __last; ++__first)
301 __throw_exception_again;
305 template <typename _Tp, typename _Alloc>
306 template <typename _ForwardIterator>
309 _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last,
310 std::forward_iterator_tag)
312 const size_type __n = std::distance(__first, __last);
313 this->_M_initialize_map(__n);
315 _Map_pointer __cur_node;
318 for (__cur_node = this->_M_impl._M_start._M_node;
319 __cur_node < this->_M_impl._M_finish._M_node;
322 _ForwardIterator __mid = __first;
323 std::advance(__mid, _S_buffer_size());
324 std::__uninitialized_copy_a(__first, __mid, *__cur_node,
325 _M_get_Tp_allocator());
328 std::__uninitialized_copy_a(__first, __last,
329 this->_M_impl._M_finish._M_first,
330 _M_get_Tp_allocator());
334 std::_Destroy(this->_M_impl._M_start,
335 iterator(*__cur_node, __cur_node),
336 _M_get_Tp_allocator());
337 __throw_exception_again;
341 // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_last - 1.
342 template <typename _Tp, typename _Alloc>
345 _M_push_back_aux(const value_type& __t)
347 value_type __t_copy = __t;
348 _M_reserve_map_at_back();
349 *(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node();
352 this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t_copy);
353 this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node
355 this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first;
359 _M_deallocate_node(*(this->_M_impl._M_finish._M_node + 1));
360 __throw_exception_again;
364 // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_first.
365 template <typename _Tp, typename _Alloc>
368 _M_push_front_aux(const value_type& __t)
370 value_type __t_copy = __t;
371 _M_reserve_map_at_front();
372 *(this->_M_impl._M_start._M_node - 1) = this->_M_allocate_node();
375 this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node
377 this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1;
378 this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t_copy);
382 ++this->_M_impl._M_start;
383 _M_deallocate_node(*(this->_M_impl._M_start._M_node - 1));
384 __throw_exception_again;
388 // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_first.
389 template <typename _Tp, typename _Alloc>
390 void deque<_Tp, _Alloc>::
393 _M_deallocate_node(this->_M_impl._M_finish._M_first);
394 this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - 1);
395 this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_last - 1;
396 this->_M_impl.destroy(this->_M_impl._M_finish._M_cur);
399 // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1.
400 // Note that if the deque has at least one element (a precondition for this
401 // member function), and if
402 // _M_impl._M_start._M_cur == _M_impl._M_start._M_last,
403 // then the deque must have at least two nodes.
404 template <typename _Tp, typename _Alloc>
405 void deque<_Tp, _Alloc>::
408 this->_M_impl.destroy(this->_M_impl._M_start._M_cur);
409 _M_deallocate_node(this->_M_impl._M_start._M_first);
410 this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1);
411 this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first;
414 template <typename _Tp, typename _Alloc>
415 template <typename _InputIterator>
418 _M_range_insert_aux(iterator __pos,
419 _InputIterator __first, _InputIterator __last,
420 std::input_iterator_tag)
421 { std::copy(__first, __last, std::inserter(*this, __pos)); }
423 template <typename _Tp, typename _Alloc>
424 template <typename _ForwardIterator>
427 _M_range_insert_aux(iterator __pos,
428 _ForwardIterator __first, _ForwardIterator __last,
429 std::forward_iterator_tag)
431 const size_type __n = std::distance(__first, __last);
432 if (__pos._M_cur == this->_M_impl._M_start._M_cur)
434 iterator __new_start = _M_reserve_elements_at_front(__n);
437 std::__uninitialized_copy_a(__first, __last, __new_start,
438 _M_get_Tp_allocator());
439 this->_M_impl._M_start = __new_start;
443 _M_destroy_nodes(__new_start._M_node,
444 this->_M_impl._M_start._M_node);
445 __throw_exception_again;
448 else if (__pos._M_cur == this->_M_impl._M_finish._M_cur)
450 iterator __new_finish = _M_reserve_elements_at_back(__n);
453 std::__uninitialized_copy_a(__first, __last,
454 this->_M_impl._M_finish,
455 _M_get_Tp_allocator());
456 this->_M_impl._M_finish = __new_finish;
460 _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
461 __new_finish._M_node + 1);
462 __throw_exception_again;
466 _M_insert_aux(__pos, __first, __last, __n);
469 template <typename _Tp, typename _Alloc>
470 typename deque<_Tp, _Alloc>::iterator
472 _M_insert_aux(iterator __pos, const value_type& __x)
474 difference_type __index = __pos - this->_M_impl._M_start;
475 value_type __x_copy = __x; // XXX copy
476 if (static_cast<size_type>(__index) < size() / 2)
479 iterator __front1 = this->_M_impl._M_start;
481 iterator __front2 = __front1;
483 __pos = this->_M_impl._M_start + __index;
484 iterator __pos1 = __pos;
486 std::copy(__front2, __pos1, __front1);
491 iterator __back1 = this->_M_impl._M_finish;
493 iterator __back2 = __back1;
495 __pos = this->_M_impl._M_start + __index;
496 std::copy_backward(__pos, __back2, __back1);
502 template <typename _Tp, typename _Alloc>
505 _M_insert_aux(iterator __pos, size_type __n, const value_type& __x)
507 const difference_type __elems_before = __pos - this->_M_impl._M_start;
508 const size_type __length = this->size();
509 value_type __x_copy = __x;
510 if (__elems_before < difference_type(__length / 2))
512 iterator __new_start = _M_reserve_elements_at_front(__n);
513 iterator __old_start = this->_M_impl._M_start;
514 __pos = this->_M_impl._M_start + __elems_before;
517 if (__elems_before >= difference_type(__n))
519 iterator __start_n = (this->_M_impl._M_start
520 + difference_type(__n));
521 std::__uninitialized_copy_a(this->_M_impl._M_start,
522 __start_n, __new_start,
523 _M_get_Tp_allocator());
524 this->_M_impl._M_start = __new_start;
525 std::copy(__start_n, __pos, __old_start);
526 fill(__pos - difference_type(__n), __pos, __x_copy);
530 std::__uninitialized_copy_fill(this->_M_impl._M_start,
532 this->_M_impl._M_start,
534 _M_get_Tp_allocator());
535 this->_M_impl._M_start = __new_start;
536 std::fill(__old_start, __pos, __x_copy);
541 _M_destroy_nodes(__new_start._M_node,
542 this->_M_impl._M_start._M_node);
543 __throw_exception_again;
548 iterator __new_finish = _M_reserve_elements_at_back(__n);
549 iterator __old_finish = this->_M_impl._M_finish;
550 const difference_type __elems_after =
551 difference_type(__length) - __elems_before;
552 __pos = this->_M_impl._M_finish - __elems_after;
555 if (__elems_after > difference_type(__n))
557 iterator __finish_n = (this->_M_impl._M_finish
558 - difference_type(__n));
559 std::__uninitialized_copy_a(__finish_n,
560 this->_M_impl._M_finish,
561 this->_M_impl._M_finish,
562 _M_get_Tp_allocator());
563 this->_M_impl._M_finish = __new_finish;
564 std::copy_backward(__pos, __finish_n, __old_finish);
565 std::fill(__pos, __pos + difference_type(__n), __x_copy);
569 std::__uninitialized_fill_copy(this->_M_impl._M_finish,
570 __pos + difference_type(__n),
572 this->_M_impl._M_finish,
573 _M_get_Tp_allocator());
574 this->_M_impl._M_finish = __new_finish;
575 std::fill(__pos, __old_finish, __x_copy);
580 _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
581 __new_finish._M_node + 1);
582 __throw_exception_again;
587 template <typename _Tp, typename _Alloc>
588 template <typename _ForwardIterator>
591 _M_insert_aux(iterator __pos,
592 _ForwardIterator __first, _ForwardIterator __last,
595 const difference_type __elemsbefore = __pos - this->_M_impl._M_start;
596 const size_type __length = size();
597 if (static_cast<size_type>(__elemsbefore) < __length / 2)
599 iterator __new_start = _M_reserve_elements_at_front(__n);
600 iterator __old_start = this->_M_impl._M_start;
601 __pos = this->_M_impl._M_start + __elemsbefore;
604 if (__elemsbefore >= difference_type(__n))
606 iterator __start_n = (this->_M_impl._M_start
607 + difference_type(__n));
608 std::__uninitialized_copy_a(this->_M_impl._M_start,
609 __start_n, __new_start,
610 _M_get_Tp_allocator());
611 this->_M_impl._M_start = __new_start;
612 std::copy(__start_n, __pos, __old_start);
613 std::copy(__first, __last, __pos - difference_type(__n));
617 _ForwardIterator __mid = __first;
618 std::advance(__mid, difference_type(__n) - __elemsbefore);
619 std::__uninitialized_copy_copy(this->_M_impl._M_start,
620 __pos, __first, __mid,
622 _M_get_Tp_allocator());
623 this->_M_impl._M_start = __new_start;
624 std::copy(__mid, __last, __old_start);
629 _M_destroy_nodes(__new_start._M_node,
630 this->_M_impl._M_start._M_node);
631 __throw_exception_again;
636 iterator __new_finish = _M_reserve_elements_at_back(__n);
637 iterator __old_finish = this->_M_impl._M_finish;
638 const difference_type __elemsafter =
639 difference_type(__length) - __elemsbefore;
640 __pos = this->_M_impl._M_finish - __elemsafter;
643 if (__elemsafter > difference_type(__n))
645 iterator __finish_n = (this->_M_impl._M_finish
646 - difference_type(__n));
647 std::__uninitialized_copy_a(__finish_n,
648 this->_M_impl._M_finish,
649 this->_M_impl._M_finish,
650 _M_get_Tp_allocator());
651 this->_M_impl._M_finish = __new_finish;
652 std::copy_backward(__pos, __finish_n, __old_finish);
653 std::copy(__first, __last, __pos);
657 _ForwardIterator __mid = __first;
658 std::advance(__mid, __elemsafter);
659 std::__uninitialized_copy_copy(__mid, __last, __pos,
660 this->_M_impl._M_finish,
661 this->_M_impl._M_finish,
662 _M_get_Tp_allocator());
663 this->_M_impl._M_finish = __new_finish;
664 std::copy(__first, __mid, __pos);
669 _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1,
670 __new_finish._M_node + 1);
671 __throw_exception_again;
676 template <typename _Tp, typename _Alloc>
679 _M_new_elements_at_front(size_type __new_elems)
681 const size_type __new_nodes
682 = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size();
683 _M_reserve_map_at_front(__new_nodes);
687 for (__i = 1; __i <= __new_nodes; ++__i)
688 *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node();
692 for (size_type __j = 1; __j < __i; ++__j)
693 _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j));
694 __throw_exception_again;
698 template <typename _Tp, typename _Alloc>
701 _M_new_elements_at_back(size_type __new_elems)
703 const size_type __new_nodes
704 = (__new_elems + _S_buffer_size() - 1) / _S_buffer_size();
705 _M_reserve_map_at_back(__new_nodes);
709 for (__i = 1; __i <= __new_nodes; ++__i)
710 *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node();
714 for (size_type __j = 1; __j < __i; ++__j)
715 _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j));
716 __throw_exception_again;
720 template <typename _Tp, typename _Alloc>
723 _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front)
725 const size_type __old_num_nodes
726 = this->_M_impl._M_finish._M_node - this->_M_impl._M_start._M_node + 1;
727 const size_type __new_num_nodes = __old_num_nodes + __nodes_to_add;
729 _Map_pointer __new_nstart;
730 if (this->_M_impl._M_map_size > 2 * __new_num_nodes)
732 __new_nstart = this->_M_impl._M_map + (this->_M_impl._M_map_size
733 - __new_num_nodes) / 2
734 + (__add_at_front ? __nodes_to_add : 0);
735 if (__new_nstart < this->_M_impl._M_start._M_node)
736 std::copy(this->_M_impl._M_start._M_node,
737 this->_M_impl._M_finish._M_node + 1,
740 std::copy_backward(this->_M_impl._M_start._M_node,
741 this->_M_impl._M_finish._M_node + 1,
742 __new_nstart + __old_num_nodes);
746 size_type __new_map_size = this->_M_impl._M_map_size
747 + std::max(this->_M_impl._M_map_size,
750 _Map_pointer __new_map = this->_M_allocate_map(__new_map_size);
751 __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2
752 + (__add_at_front ? __nodes_to_add : 0);
753 std::copy(this->_M_impl._M_start._M_node,
754 this->_M_impl._M_finish._M_node + 1,
756 _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size);
758 this->_M_impl._M_map = __new_map;
759 this->_M_impl._M_map_size = __new_map_size;
762 this->_M_impl._M_start._M_set_node(__new_nstart);
763 this->_M_impl._M_finish._M_set_node(__new_nstart + __old_num_nodes - 1);