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