1 | // Singly-linked list implementation -*- C++ -*- |
2 | |
3 | // Copyright (C) 2001-2017 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /* |
26 | * Copyright (c) 1997 |
27 | * Silicon Graphics Computer Systems, Inc. |
28 | * |
29 | * Permission to use, copy, modify, distribute and sell this software |
30 | * and its documentation for any purpose is hereby granted without fee, |
31 | * provided that the above copyright notice appear in all copies and |
32 | * that both that copyright notice and this permission notice appear |
33 | * in supporting documentation. Silicon Graphics makes no |
34 | * representations about the suitability of this software for any |
35 | * purpose. It is provided "as is" without express or implied warranty. |
36 | * |
37 | */ |
38 | |
39 | /** @file ext/slist |
40 | * This file is a GNU extension to the Standard C++ Library (possibly |
41 | * containing extensions from the HP/SGI STL subset). |
42 | */ |
43 | |
44 | #ifndef _SLIST |
45 | #define _SLIST 1 |
46 | |
47 | #include <algorithm> |
48 | #include <bits/allocator.h> |
49 | #include <bits/stl_construct.h> |
50 | #include <bits/stl_uninitialized.h> |
51 | #include <bits/concept_check.h> |
52 | |
53 | namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) |
54 | { |
55 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
56 | |
57 | using std::size_t; |
58 | using std::ptrdiff_t; |
59 | using std::_Construct; |
60 | using std::_Destroy; |
61 | using std::allocator; |
62 | using std::__true_type; |
63 | using std::__false_type; |
64 | |
65 | struct _Slist_node_base |
66 | { |
67 | _Slist_node_base* _M_next; |
68 | }; |
69 | |
70 | inline _Slist_node_base* |
71 | __slist_make_link(_Slist_node_base* __prev_node, |
72 | _Slist_node_base* __new_node) |
73 | { |
74 | __new_node->_M_next = __prev_node->_M_next; |
75 | __prev_node->_M_next = __new_node; |
76 | return __new_node; |
77 | } |
78 | |
79 | inline _Slist_node_base* |
80 | __slist_previous(_Slist_node_base* __head, |
81 | const _Slist_node_base* __node) |
82 | { |
83 | while (__head && __head->_M_next != __node) |
84 | __head = __head->_M_next; |
85 | return __head; |
86 | } |
87 | |
88 | inline const _Slist_node_base* |
89 | __slist_previous(const _Slist_node_base* __head, |
90 | const _Slist_node_base* __node) |
91 | { |
92 | while (__head && __head->_M_next != __node) |
93 | __head = __head->_M_next; |
94 | return __head; |
95 | } |
96 | |
97 | inline void |
98 | __slist_splice_after(_Slist_node_base* __pos, |
99 | _Slist_node_base* __before_first, |
100 | _Slist_node_base* __before_last) |
101 | { |
102 | if (__pos != __before_first && __pos != __before_last) |
103 | { |
104 | _Slist_node_base* __first = __before_first->_M_next; |
105 | _Slist_node_base* __after = __pos->_M_next; |
106 | __before_first->_M_next = __before_last->_M_next; |
107 | __pos->_M_next = __first; |
108 | __before_last->_M_next = __after; |
109 | } |
110 | } |
111 | |
112 | inline void |
113 | __slist_splice_after(_Slist_node_base* __pos, _Slist_node_base* __head) |
114 | { |
115 | _Slist_node_base* __before_last = __slist_previous(__head, 0); |
116 | if (__before_last != __head) |
117 | { |
118 | _Slist_node_base* __after = __pos->_M_next; |
119 | __pos->_M_next = __head->_M_next; |
120 | __head->_M_next = 0; |
121 | __before_last->_M_next = __after; |
122 | } |
123 | } |
124 | |
125 | inline _Slist_node_base* |
126 | __slist_reverse(_Slist_node_base* __node) |
127 | { |
128 | _Slist_node_base* __result = __node; |
129 | __node = __node->_M_next; |
130 | __result->_M_next = 0; |
131 | while(__node) |
132 | { |
133 | _Slist_node_base* __next = __node->_M_next; |
134 | __node->_M_next = __result; |
135 | __result = __node; |
136 | __node = __next; |
137 | } |
138 | return __result; |
139 | } |
140 | |
141 | inline size_t |
142 | __slist_size(_Slist_node_base* __node) |
143 | { |
144 | size_t __result = 0; |
145 | for (; __node != 0; __node = __node->_M_next) |
146 | ++__result; |
147 | return __result; |
148 | } |
149 | |
150 | template <class _Tp> |
151 | struct _Slist_node : public _Slist_node_base |
152 | { |
153 | _Tp _M_data; |
154 | }; |
155 | |
156 | struct _Slist_iterator_base |
157 | { |
158 | typedef size_t size_type; |
159 | typedef ptrdiff_t difference_type; |
160 | typedef std::forward_iterator_tag iterator_category; |
161 | |
162 | _Slist_node_base* _M_node; |
163 | |
164 | _Slist_iterator_base(_Slist_node_base* __x) |
165 | : _M_node(__x) {} |
166 | |
167 | void |
168 | _M_incr() |
169 | { _M_node = _M_node->_M_next; } |
170 | |
171 | bool |
172 | operator==(const _Slist_iterator_base& __x) const |
173 | { return _M_node == __x._M_node; } |
174 | |
175 | bool |
176 | operator!=(const _Slist_iterator_base& __x) const |
177 | { return _M_node != __x._M_node; } |
178 | }; |
179 | |
180 | template <class _Tp, class _Ref, class _Ptr> |
181 | struct _Slist_iterator : public _Slist_iterator_base |
182 | { |
183 | typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; |
184 | typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; |
185 | typedef _Slist_iterator<_Tp, _Ref, _Ptr> _Self; |
186 | |
187 | typedef _Tp value_type; |
188 | typedef _Ptr pointer; |
189 | typedef _Ref reference; |
190 | typedef _Slist_node<_Tp> _Node; |
191 | |
192 | explicit |
193 | _Slist_iterator(_Node* __x) |
194 | : _Slist_iterator_base(__x) {} |
195 | |
196 | _Slist_iterator() |
197 | : _Slist_iterator_base(0) {} |
198 | |
199 | _Slist_iterator(const iterator& __x) |
200 | : _Slist_iterator_base(__x._M_node) {} |
201 | |
202 | reference |
203 | operator*() const |
204 | { return ((_Node*) _M_node)->_M_data; } |
205 | |
206 | pointer |
207 | operator->() const |
208 | { return &(operator*()); } |
209 | |
210 | _Self& |
211 | operator++() |
212 | { |
213 | _M_incr(); |
214 | return *this; |
215 | } |
216 | |
217 | _Self |
218 | operator++(int) |
219 | { |
220 | _Self __tmp = *this; |
221 | _M_incr(); |
222 | return __tmp; |
223 | } |
224 | }; |
225 | |
226 | template <class _Tp, class _Alloc> |
227 | struct _Slist_base |
228 | : public _Alloc::template rebind<_Slist_node<_Tp> >::other |
229 | { |
230 | typedef typename _Alloc::template rebind<_Slist_node<_Tp> >::other |
231 | _Node_alloc; |
232 | typedef _Alloc allocator_type; |
233 | |
234 | allocator_type |
235 | get_allocator() const |
236 | { return *static_cast<const _Node_alloc*>(this); } |
237 | |
238 | _Slist_base(const allocator_type& __a) |
239 | : _Node_alloc(__a) |
240 | { this->_M_head._M_next = 0; } |
241 | |
242 | ~_Slist_base() |
243 | { _M_erase_after(&this->_M_head, 0); } |
244 | |
245 | protected: |
246 | _Slist_node_base _M_head; |
247 | |
248 | _Slist_node<_Tp>* |
249 | _M_get_node() |
250 | { return _Node_alloc::allocate(1); } |
251 | |
252 | void |
253 | _M_put_node(_Slist_node<_Tp>* __p) |
254 | { _Node_alloc::deallocate(__p, 1); } |
255 | |
256 | protected: |
257 | _Slist_node_base* _M_erase_after(_Slist_node_base* __pos) |
258 | { |
259 | _Slist_node<_Tp>* __next = (_Slist_node<_Tp>*) (__pos->_M_next); |
260 | _Slist_node_base* __next_next = __next->_M_next; |
261 | __pos->_M_next = __next_next; |
262 | get_allocator().destroy(&__next->_M_data); |
263 | _M_put_node(__next); |
264 | return __next_next; |
265 | } |
266 | _Slist_node_base* _M_erase_after(_Slist_node_base*, _Slist_node_base*); |
267 | }; |
268 | |
269 | template <class _Tp, class _Alloc> |
270 | _Slist_node_base* |
271 | _Slist_base<_Tp,_Alloc>::_M_erase_after(_Slist_node_base* __before_first, |
272 | _Slist_node_base* __last_node) |
273 | { |
274 | _Slist_node<_Tp>* __cur = (_Slist_node<_Tp>*) (__before_first->_M_next); |
275 | while (__cur != __last_node) |
276 | { |
277 | _Slist_node<_Tp>* __tmp = __cur; |
278 | __cur = (_Slist_node<_Tp>*) __cur->_M_next; |
279 | get_allocator().destroy(&__tmp->_M_data); |
280 | _M_put_node(__tmp); |
281 | } |
282 | __before_first->_M_next = __last_node; |
283 | return __last_node; |
284 | } |
285 | |
286 | /** |
287 | * This is an SGI extension. |
288 | * @ingroup SGIextensions |
289 | * @doctodo |
290 | */ |
291 | template <class _Tp, class _Alloc = allocator<_Tp> > |
292 | class slist : private _Slist_base<_Tp,_Alloc> |
293 | { |
294 | // concept requirements |
295 | __glibcxx_class_requires(_Tp, _SGIAssignableConcept) |
296 | |
297 | private: |
298 | typedef _Slist_base<_Tp,_Alloc> _Base; |
299 | |
300 | public: |
301 | typedef _Tp value_type; |
302 | typedef value_type* pointer; |
303 | typedef const value_type* const_pointer; |
304 | typedef value_type& reference; |
305 | typedef const value_type& const_reference; |
306 | typedef size_t size_type; |
307 | typedef ptrdiff_t difference_type; |
308 | |
309 | typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; |
310 | typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; |
311 | |
312 | typedef typename _Base::allocator_type allocator_type; |
313 | |
314 | allocator_type |
315 | get_allocator() const |
316 | { return _Base::get_allocator(); } |
317 | |
318 | private: |
319 | typedef _Slist_node<_Tp> _Node; |
320 | typedef _Slist_node_base _Node_base; |
321 | typedef _Slist_iterator_base _Iterator_base; |
322 | |
323 | _Node* |
324 | _M_create_node(const value_type& __x) |
325 | { |
326 | _Node* __node = this->_M_get_node(); |
327 | __try |
328 | { |
329 | get_allocator().construct(&__node->_M_data, __x); |
330 | __node->_M_next = 0; |
331 | } |
332 | __catch(...) |
333 | { |
334 | this->_M_put_node(__node); |
335 | __throw_exception_again; |
336 | } |
337 | return __node; |
338 | } |
339 | |
340 | _Node* |
341 | _M_create_node() |
342 | { |
343 | _Node* __node = this->_M_get_node(); |
344 | __try |
345 | { |
346 | get_allocator().construct(&__node->_M_data, value_type()); |
347 | __node->_M_next = 0; |
348 | } |
349 | __catch(...) |
350 | { |
351 | this->_M_put_node(__node); |
352 | __throw_exception_again; |
353 | } |
354 | return __node; |
355 | } |
356 | |
357 | public: |
358 | explicit |
359 | slist(const allocator_type& __a = allocator_type()) |
360 | : _Base(__a) {} |
361 | |
362 | slist(size_type __n, const value_type& __x, |
363 | const allocator_type& __a = allocator_type()) |
364 | : _Base(__a) |
365 | { _M_insert_after_fill(&this->_M_head, __n, __x); } |
366 | |
367 | explicit |
368 | slist(size_type __n) |
369 | : _Base(allocator_type()) |
370 | { _M_insert_after_fill(&this->_M_head, __n, value_type()); } |
371 | |
372 | // We don't need any dispatching tricks here, because |
373 | // _M_insert_after_range already does them. |
374 | template <class _InputIterator> |
375 | slist(_InputIterator __first, _InputIterator __last, |
376 | const allocator_type& __a = allocator_type()) |
377 | : _Base(__a) |
378 | { _M_insert_after_range(&this->_M_head, __first, __last); } |
379 | |
380 | slist(const slist& __x) |
381 | : _Base(__x.get_allocator()) |
382 | { _M_insert_after_range(&this->_M_head, __x.begin(), __x.end()); } |
383 | |
384 | slist& |
385 | operator= (const slist& __x); |
386 | |
387 | ~slist() {} |
388 | |
389 | public: |
390 | // assign(), a generalized assignment member function. Two |
391 | // versions: one that takes a count, and one that takes a range. |
392 | // The range version is a member template, so we dispatch on whether |
393 | // or not the type is an integer. |
394 | |
395 | void |
396 | assign(size_type __n, const _Tp& __val) |
397 | { _M_fill_assign(__n, __val); } |
398 | |
399 | void |
400 | _M_fill_assign(size_type __n, const _Tp& __val); |
401 | |
402 | template <class _InputIterator> |
403 | void |
404 | assign(_InputIterator __first, _InputIterator __last) |
405 | { |
406 | typedef typename std::__is_integer<_InputIterator>::__type _Integral; |
407 | _M_assign_dispatch(__first, __last, _Integral()); |
408 | } |
409 | |
410 | template <class _Integer> |
411 | void |
412 | _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) |
413 | { _M_fill_assign((size_type) __n, (_Tp) __val); } |
414 | |
415 | template <class _InputIterator> |
416 | void |
417 | _M_assign_dispatch(_InputIterator __first, _InputIterator __last, |
418 | __false_type); |
419 | |
420 | public: |
421 | |
422 | iterator |
423 | begin() |
424 | { return iterator((_Node*)this->_M_head._M_next); } |
425 | |
426 | const_iterator |
427 | begin() const |
428 | { return const_iterator((_Node*)this->_M_head._M_next);} |
429 | |
430 | iterator |
431 | end() |
432 | { return iterator(0); } |
433 | |
434 | const_iterator |
435 | end() const |
436 | { return const_iterator(0); } |
437 | |
438 | // Experimental new feature: before_begin() returns a |
439 | // non-dereferenceable iterator that, when incremented, yields |
440 | // begin(). This iterator may be used as the argument to |
441 | // insert_after, erase_after, etc. Note that even for an empty |
442 | // slist, before_begin() is not the same iterator as end(). It |
443 | // is always necessary to increment before_begin() at least once to |
444 | // obtain end(). |
445 | iterator |
446 | before_begin() |
447 | { return iterator((_Node*) &this->_M_head); } |
448 | |
449 | const_iterator |
450 | before_begin() const |
451 | { return const_iterator((_Node*) &this->_M_head); } |
452 | |
453 | size_type |
454 | size() const |
455 | { return __slist_size(this->_M_head._M_next); } |
456 | |
457 | size_type |
458 | max_size() const |
459 | { return size_type(-1); } |
460 | |
461 | bool |
462 | empty() const |
463 | { return this->_M_head._M_next == 0; } |
464 | |
465 | void |
466 | swap(slist& __x) |
467 | { std::swap(this->_M_head._M_next, __x._M_head._M_next); } |
468 | |
469 | public: |
470 | |
471 | reference |
472 | front() |
473 | { return ((_Node*) this->_M_head._M_next)->_M_data; } |
474 | |
475 | const_reference |
476 | front() const |
477 | { return ((_Node*) this->_M_head._M_next)->_M_data; } |
478 | |
479 | void |
480 | push_front(const value_type& __x) |
481 | { __slist_make_link(&this->_M_head, _M_create_node(__x)); } |
482 | |
483 | void |
484 | push_front() |
485 | { __slist_make_link(&this->_M_head, _M_create_node()); } |
486 | |
487 | void |
488 | pop_front() |
489 | { |
490 | _Node* __node = (_Node*) this->_M_head._M_next; |
491 | this->_M_head._M_next = __node->_M_next; |
492 | get_allocator().destroy(&__node->_M_data); |
493 | this->_M_put_node(__node); |
494 | } |
495 | |
496 | iterator |
497 | previous(const_iterator __pos) |
498 | { return iterator((_Node*) __slist_previous(&this->_M_head, |
499 | __pos._M_node)); } |
500 | |
501 | const_iterator |
502 | previous(const_iterator __pos) const |
503 | { return const_iterator((_Node*) __slist_previous(&this->_M_head, |
504 | __pos._M_node)); } |
505 | |
506 | private: |
507 | _Node* |
508 | _M_insert_after(_Node_base* __pos, const value_type& __x) |
509 | { return (_Node*) (__slist_make_link(__pos, _M_create_node(__x))); } |
510 | |
511 | _Node* |
512 | _M_insert_after(_Node_base* __pos) |
513 | { return (_Node*) (__slist_make_link(__pos, _M_create_node())); } |
514 | |
515 | void |
516 | _M_insert_after_fill(_Node_base* __pos, |
517 | size_type __n, const value_type& __x) |
518 | { |
519 | for (size_type __i = 0; __i < __n; ++__i) |
520 | __pos = __slist_make_link(__pos, _M_create_node(__x)); |
521 | } |
522 | |
523 | // Check whether it's an integral type. If so, it's not an iterator. |
524 | template <class _InIterator> |
525 | void |
526 | _M_insert_after_range(_Node_base* __pos, |
527 | _InIterator __first, _InIterator __last) |
528 | { |
529 | typedef typename std::__is_integer<_InIterator>::__type _Integral; |
530 | _M_insert_after_range(__pos, __first, __last, _Integral()); |
531 | } |
532 | |
533 | template <class _Integer> |
534 | void |
535 | _M_insert_after_range(_Node_base* __pos, _Integer __n, _Integer __x, |
536 | __true_type) |
537 | { _M_insert_after_fill(__pos, __n, __x); } |
538 | |
539 | template <class _InIterator> |
540 | void |
541 | _M_insert_after_range(_Node_base* __pos, |
542 | _InIterator __first, _InIterator __last, |
543 | __false_type) |
544 | { |
545 | while (__first != __last) |
546 | { |
547 | __pos = __slist_make_link(__pos, _M_create_node(*__first)); |
548 | ++__first; |
549 | } |
550 | } |
551 | |
552 | public: |
553 | iterator |
554 | insert_after(iterator __pos, const value_type& __x) |
555 | { return iterator(_M_insert_after(__pos._M_node, __x)); } |
556 | |
557 | iterator |
558 | insert_after(iterator __pos) |
559 | { return insert_after(__pos, value_type()); } |
560 | |
561 | void |
562 | insert_after(iterator __pos, size_type __n, const value_type& __x) |
563 | { _M_insert_after_fill(__pos._M_node, __n, __x); } |
564 | |
565 | // We don't need any dispatching tricks here, because |
566 | // _M_insert_after_range already does them. |
567 | template <class _InIterator> |
568 | void |
569 | insert_after(iterator __pos, _InIterator __first, _InIterator __last) |
570 | { _M_insert_after_range(__pos._M_node, __first, __last); } |
571 | |
572 | iterator |
573 | insert(iterator __pos, const value_type& __x) |
574 | { return iterator(_M_insert_after(__slist_previous(&this->_M_head, |
575 | __pos._M_node), |
576 | __x)); } |
577 | |
578 | iterator |
579 | insert(iterator __pos) |
580 | { return iterator(_M_insert_after(__slist_previous(&this->_M_head, |
581 | __pos._M_node), |
582 | value_type())); } |
583 | |
584 | void |
585 | insert(iterator __pos, size_type __n, const value_type& __x) |
586 | { _M_insert_after_fill(__slist_previous(&this->_M_head, __pos._M_node), |
587 | __n, __x); } |
588 | |
589 | // We don't need any dispatching tricks here, because |
590 | // _M_insert_after_range already does them. |
591 | template <class _InIterator> |
592 | void |
593 | insert(iterator __pos, _InIterator __first, _InIterator __last) |
594 | { _M_insert_after_range(__slist_previous(&this->_M_head, __pos._M_node), |
595 | __first, __last); } |
596 | |
597 | public: |
598 | iterator |
599 | erase_after(iterator __pos) |
600 | { return iterator((_Node*) this->_M_erase_after(__pos._M_node)); } |
601 | |
602 | iterator |
603 | erase_after(iterator __before_first, iterator __last) |
604 | { |
605 | return iterator((_Node*) this->_M_erase_after(__before_first._M_node, |
606 | __last._M_node)); |
607 | } |
608 | |
609 | iterator |
610 | erase(iterator __pos) |
611 | { |
612 | return iterator((_Node*) this->_M_erase_after |
613 | (__slist_previous(&this->_M_head, __pos._M_node))); |
614 | } |
615 | |
616 | iterator |
617 | erase(iterator __first, iterator __last) |
618 | { |
619 | return iterator((_Node*) this->_M_erase_after |
620 | (__slist_previous(&this->_M_head, __first._M_node), |
621 | __last._M_node)); |
622 | } |
623 | |
624 | void |
625 | resize(size_type new_size, const _Tp& __x); |
626 | |
627 | void |
628 | resize(size_type new_size) |
629 | { resize(new_size, _Tp()); } |
630 | |
631 | void |
632 | clear() |
633 | { this->_M_erase_after(&this->_M_head, 0); } |
634 | |
635 | public: |
636 | // Moves the range [__before_first + 1, __before_last + 1) to *this, |
637 | // inserting it immediately after __pos. This is constant time. |
638 | void |
639 | splice_after(iterator __pos, |
640 | iterator __before_first, iterator __before_last) |
641 | { |
642 | if (__before_first != __before_last) |
643 | __slist_splice_after(__pos._M_node, __before_first._M_node, |
644 | __before_last._M_node); |
645 | } |
646 | |
647 | // Moves the element that follows __prev to *this, inserting it |
648 | // immediately after __pos. This is constant time. |
649 | void |
650 | splice_after(iterator __pos, iterator __prev) |
651 | { __slist_splice_after(__pos._M_node, |
652 | __prev._M_node, __prev._M_node->_M_next); } |
653 | |
654 | // Removes all of the elements from the list __x to *this, inserting |
655 | // them immediately after __pos. __x must not be *this. Complexity: |
656 | // linear in __x.size(). |
657 | void |
658 | splice_after(iterator __pos, slist& __x) |
659 | { __slist_splice_after(__pos._M_node, &__x._M_head); } |
660 | |
661 | // Linear in distance(begin(), __pos), and linear in __x.size(). |
662 | void |
663 | splice(iterator __pos, slist& __x) |
664 | { |
665 | if (__x._M_head._M_next) |
666 | __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), |
667 | &__x._M_head, |
668 | __slist_previous(&__x._M_head, 0)); } |
669 | |
670 | // Linear in distance(begin(), __pos), and in distance(__x.begin(), __i). |
671 | void |
672 | splice(iterator __pos, slist& __x, iterator __i) |
673 | { __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), |
674 | __slist_previous(&__x._M_head, __i._M_node), |
675 | __i._M_node); } |
676 | |
677 | // Linear in distance(begin(), __pos), in distance(__x.begin(), __first), |
678 | // and in distance(__first, __last). |
679 | void |
680 | splice(iterator __pos, slist& __x, iterator __first, iterator __last) |
681 | { |
682 | if (__first != __last) |
683 | __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), |
684 | __slist_previous(&__x._M_head, __first._M_node), |
685 | __slist_previous(__first._M_node, |
686 | __last._M_node)); |
687 | } |
688 | |
689 | public: |
690 | void |
691 | reverse() |
692 | { |
693 | if (this->_M_head._M_next) |
694 | this->_M_head._M_next = __slist_reverse(this->_M_head._M_next); |
695 | } |
696 | |
697 | void |
698 | remove(const _Tp& __val); |
699 | |
700 | void |
701 | unique(); |
702 | |
703 | void |
704 | merge(slist& __x); |
705 | |
706 | void |
707 | sort(); |
708 | |
709 | template <class _Predicate> |
710 | void |
711 | remove_if(_Predicate __pred); |
712 | |
713 | template <class _BinaryPredicate> |
714 | void |
715 | unique(_BinaryPredicate __pred); |
716 | |
717 | template <class _StrictWeakOrdering> |
718 | void |
719 | merge(slist&, _StrictWeakOrdering); |
720 | |
721 | template <class _StrictWeakOrdering> |
722 | void |
723 | sort(_StrictWeakOrdering __comp); |
724 | }; |
725 | |
726 | template <class _Tp, class _Alloc> |
727 | slist<_Tp, _Alloc>& |
728 | slist<_Tp, _Alloc>::operator=(const slist<_Tp, _Alloc>& __x) |
729 | { |
730 | if (&__x != this) |
731 | { |
732 | _Node_base* __p1 = &this->_M_head; |
733 | _Node* __n1 = (_Node*) this->_M_head._M_next; |
734 | const _Node* __n2 = (const _Node*) __x._M_head._M_next; |
735 | while (__n1 && __n2) |
736 | { |
737 | __n1->_M_data = __n2->_M_data; |
738 | __p1 = __n1; |
739 | __n1 = (_Node*) __n1->_M_next; |
740 | __n2 = (const _Node*) __n2->_M_next; |
741 | } |
742 | if (__n2 == 0) |
743 | this->_M_erase_after(__p1, 0); |
744 | else |
745 | _M_insert_after_range(__p1, const_iterator((_Node*)__n2), |
746 | const_iterator(0)); |
747 | } |
748 | return *this; |
749 | } |
750 | |
751 | template <class _Tp, class _Alloc> |
752 | void |
753 | slist<_Tp, _Alloc>::_M_fill_assign(size_type __n, const _Tp& __val) |
754 | { |
755 | _Node_base* __prev = &this->_M_head; |
756 | _Node* __node = (_Node*) this->_M_head._M_next; |
757 | for (; __node != 0 && __n > 0; --__n) |
758 | { |
759 | __node->_M_data = __val; |
760 | __prev = __node; |
761 | __node = (_Node*) __node->_M_next; |
762 | } |
763 | if (__n > 0) |
764 | _M_insert_after_fill(__prev, __n, __val); |
765 | else |
766 | this->_M_erase_after(__prev, 0); |
767 | } |
768 | |
769 | template <class _Tp, class _Alloc> |
770 | template <class _InputIterator> |
771 | void |
772 | slist<_Tp, _Alloc>::_M_assign_dispatch(_InputIterator __first, |
773 | _InputIterator __last, |
774 | __false_type) |
775 | { |
776 | _Node_base* __prev = &this->_M_head; |
777 | _Node* __node = (_Node*) this->_M_head._M_next; |
778 | while (__node != 0 && __first != __last) |
779 | { |
780 | __node->_M_data = *__first; |
781 | __prev = __node; |
782 | __node = (_Node*) __node->_M_next; |
783 | ++__first; |
784 | } |
785 | if (__first != __last) |
786 | _M_insert_after_range(__prev, __first, __last); |
787 | else |
788 | this->_M_erase_after(__prev, 0); |
789 | } |
790 | |
791 | template <class _Tp, class _Alloc> |
792 | inline bool |
793 | operator==(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) |
794 | { |
795 | typedef typename slist<_Tp,_Alloc>::const_iterator const_iterator; |
796 | const_iterator __end1 = _SL1.end(); |
797 | const_iterator __end2 = _SL2.end(); |
798 | |
799 | const_iterator __i1 = _SL1.begin(); |
800 | const_iterator __i2 = _SL2.begin(); |
801 | while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) |
802 | { |
803 | ++__i1; |
804 | ++__i2; |
805 | } |
806 | return __i1 == __end1 && __i2 == __end2; |
807 | } |
808 | |
809 | |
810 | template <class _Tp, class _Alloc> |
811 | inline bool |
812 | operator<(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) |
813 | { return std::lexicographical_compare(_SL1.begin(), _SL1.end(), |
814 | _SL2.begin(), _SL2.end()); } |
815 | |
816 | template <class _Tp, class _Alloc> |
817 | inline bool |
818 | operator!=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) |
819 | { return !(_SL1 == _SL2); } |
820 | |
821 | template <class _Tp, class _Alloc> |
822 | inline bool |
823 | operator>(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) |
824 | { return _SL2 < _SL1; } |
825 | |
826 | template <class _Tp, class _Alloc> |
827 | inline bool |
828 | operator<=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) |
829 | { return !(_SL2 < _SL1); } |
830 | |
831 | template <class _Tp, class _Alloc> |
832 | inline bool |
833 | operator>=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) |
834 | { return !(_SL1 < _SL2); } |
835 | |
836 | template <class _Tp, class _Alloc> |
837 | inline void |
838 | swap(slist<_Tp, _Alloc>& __x, slist<_Tp, _Alloc>& __y) |
839 | { __x.swap(__y); } |
840 | |
841 | template <class _Tp, class _Alloc> |
842 | void |
843 | slist<_Tp, _Alloc>::resize(size_type __len, const _Tp& __x) |
844 | { |
845 | _Node_base* __cur = &this->_M_head; |
846 | while (__cur->_M_next != 0 && __len > 0) |
847 | { |
848 | --__len; |
849 | __cur = __cur->_M_next; |
850 | } |
851 | if (__cur->_M_next) |
852 | this->_M_erase_after(__cur, 0); |
853 | else |
854 | _M_insert_after_fill(__cur, __len, __x); |
855 | } |
856 | |
857 | template <class _Tp, class _Alloc> |
858 | void |
859 | slist<_Tp, _Alloc>::remove(const _Tp& __val) |
860 | { |
861 | _Node_base* __cur = &this->_M_head; |
862 | while (__cur && __cur->_M_next) |
863 | { |
864 | if (((_Node*) __cur->_M_next)->_M_data == __val) |
865 | this->_M_erase_after(__cur); |
866 | else |
867 | __cur = __cur->_M_next; |
868 | } |
869 | } |
870 | |
871 | template <class _Tp, class _Alloc> |
872 | void |
873 | slist<_Tp, _Alloc>::unique() |
874 | { |
875 | _Node_base* __cur = this->_M_head._M_next; |
876 | if (__cur) |
877 | { |
878 | while (__cur->_M_next) |
879 | { |
880 | if (((_Node*)__cur)->_M_data |
881 | == ((_Node*)(__cur->_M_next))->_M_data) |
882 | this->_M_erase_after(__cur); |
883 | else |
884 | __cur = __cur->_M_next; |
885 | } |
886 | } |
887 | } |
888 | |
889 | template <class _Tp, class _Alloc> |
890 | void |
891 | slist<_Tp, _Alloc>::merge(slist<_Tp, _Alloc>& __x) |
892 | { |
893 | _Node_base* __n1 = &this->_M_head; |
894 | while (__n1->_M_next && __x._M_head._M_next) |
895 | { |
896 | if (((_Node*) __x._M_head._M_next)->_M_data |
897 | < ((_Node*) __n1->_M_next)->_M_data) |
898 | __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next); |
899 | __n1 = __n1->_M_next; |
900 | } |
901 | if (__x._M_head._M_next) |
902 | { |
903 | __n1->_M_next = __x._M_head._M_next; |
904 | __x._M_head._M_next = 0; |
905 | } |
906 | } |
907 | |
908 | template <class _Tp, class _Alloc> |
909 | void |
910 | slist<_Tp, _Alloc>::sort() |
911 | { |
912 | if (this->_M_head._M_next && this->_M_head._M_next->_M_next) |
913 | { |
914 | slist __carry; |
915 | slist __counter[64]; |
916 | int __fill = 0; |
917 | while (!empty()) |
918 | { |
919 | __slist_splice_after(&__carry._M_head, |
920 | &this->_M_head, this->_M_head._M_next); |
921 | int __i = 0; |
922 | while (__i < __fill && !__counter[__i].empty()) |
923 | { |
924 | __counter[__i].merge(__carry); |
925 | __carry.swap(__counter[__i]); |
926 | ++__i; |
927 | } |
928 | __carry.swap(__counter[__i]); |
929 | if (__i == __fill) |
930 | ++__fill; |
931 | } |
932 | |
933 | for (int __i = 1; __i < __fill; ++__i) |
934 | __counter[__i].merge(__counter[__i-1]); |
935 | this->swap(__counter[__fill-1]); |
936 | } |
937 | } |
938 | |
939 | template <class _Tp, class _Alloc> |
940 | template <class _Predicate> |
941 | void slist<_Tp, _Alloc>::remove_if(_Predicate __pred) |
942 | { |
943 | _Node_base* __cur = &this->_M_head; |
944 | while (__cur->_M_next) |
945 | { |
946 | if (__pred(((_Node*) __cur->_M_next)->_M_data)) |
947 | this->_M_erase_after(__cur); |
948 | else |
949 | __cur = __cur->_M_next; |
950 | } |
951 | } |
952 | |
953 | template <class _Tp, class _Alloc> |
954 | template <class _BinaryPredicate> |
955 | void |
956 | slist<_Tp, _Alloc>::unique(_BinaryPredicate __pred) |
957 | { |
958 | _Node* __cur = (_Node*) this->_M_head._M_next; |
959 | if (__cur) |
960 | { |
961 | while (__cur->_M_next) |
962 | { |
963 | if (__pred(((_Node*)__cur)->_M_data, |
964 | ((_Node*)(__cur->_M_next))->_M_data)) |
965 | this->_M_erase_after(__cur); |
966 | else |
967 | __cur = (_Node*) __cur->_M_next; |
968 | } |
969 | } |
970 | } |
971 | |
972 | template <class _Tp, class _Alloc> |
973 | template <class _StrictWeakOrdering> |
974 | void |
975 | slist<_Tp, _Alloc>::merge(slist<_Tp, _Alloc>& __x, |
976 | _StrictWeakOrdering __comp) |
977 | { |
978 | _Node_base* __n1 = &this->_M_head; |
979 | while (__n1->_M_next && __x._M_head._M_next) |
980 | { |
981 | if (__comp(((_Node*) __x._M_head._M_next)->_M_data, |
982 | ((_Node*) __n1->_M_next)->_M_data)) |
983 | __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next); |
984 | __n1 = __n1->_M_next; |
985 | } |
986 | if (__x._M_head._M_next) |
987 | { |
988 | __n1->_M_next = __x._M_head._M_next; |
989 | __x._M_head._M_next = 0; |
990 | } |
991 | } |
992 | |
993 | template <class _Tp, class _Alloc> |
994 | template <class _StrictWeakOrdering> |
995 | void |
996 | slist<_Tp, _Alloc>::sort(_StrictWeakOrdering __comp) |
997 | { |
998 | if (this->_M_head._M_next && this->_M_head._M_next->_M_next) |
999 | { |
1000 | slist __carry; |
1001 | slist __counter[64]; |
1002 | int __fill = 0; |
1003 | while (!empty()) |
1004 | { |
1005 | __slist_splice_after(&__carry._M_head, |
1006 | &this->_M_head, this->_M_head._M_next); |
1007 | int __i = 0; |
1008 | while (__i < __fill && !__counter[__i].empty()) |
1009 | { |
1010 | __counter[__i].merge(__carry, __comp); |
1011 | __carry.swap(__counter[__i]); |
1012 | ++__i; |
1013 | } |
1014 | __carry.swap(__counter[__i]); |
1015 | if (__i == __fill) |
1016 | ++__fill; |
1017 | } |
1018 | |
1019 | for (int __i = 1; __i < __fill; ++__i) |
1020 | __counter[__i].merge(__counter[__i-1], __comp); |
1021 | this->swap(__counter[__fill-1]); |
1022 | } |
1023 | } |
1024 | |
1025 | _GLIBCXX_END_NAMESPACE_VERSION |
1026 | } // namespace |
1027 | |
1028 | namespace std _GLIBCXX_VISIBILITY(default) |
1029 | { |
1030 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
1031 | |
1032 | // Specialization of insert_iterator so that insertions will be constant |
1033 | // time rather than linear time. |
1034 | template <class _Tp, class _Alloc> |
1035 | class insert_iterator<__gnu_cxx::slist<_Tp, _Alloc> > |
1036 | { |
1037 | protected: |
1038 | typedef __gnu_cxx::slist<_Tp, _Alloc> _Container; |
1039 | _Container* container; |
1040 | typename _Container::iterator iter; |
1041 | |
1042 | public: |
1043 | typedef _Container container_type; |
1044 | typedef output_iterator_tag iterator_category; |
1045 | typedef void value_type; |
1046 | typedef void difference_type; |
1047 | typedef void pointer; |
1048 | typedef void reference; |
1049 | |
1050 | insert_iterator(_Container& __x, typename _Container::iterator __i) |
1051 | : container(&__x) |
1052 | { |
1053 | if (__i == __x.begin()) |
1054 | iter = __x.before_begin(); |
1055 | else |
1056 | iter = __x.previous(__i); |
1057 | } |
1058 | |
1059 | insert_iterator<_Container>& |
1060 | operator=(const typename _Container::value_type& __value) |
1061 | { |
1062 | iter = container->insert_after(iter, __value); |
1063 | return *this; |
1064 | } |
1065 | |
1066 | insert_iterator<_Container>& |
1067 | operator*() |
1068 | { return *this; } |
1069 | |
1070 | insert_iterator<_Container>& |
1071 | operator++() |
1072 | { return *this; } |
1073 | |
1074 | insert_iterator<_Container>& |
1075 | operator++(int) |
1076 | { return *this; } |
1077 | }; |
1078 | |
1079 | _GLIBCXX_END_NAMESPACE_VERSION |
1080 | } // namespace |
1081 | |
1082 | #endif |
1083 | |