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