1
/* Copyright (C) 2004 Garrett A. Kajmowicz
3
This file is part of the uClibc++ Library.
5
This library is free software; you can redistribute it and/or
6
modify it under the terms of the GNU Lesser General Public
7
License as published by the Free Software Foundation; either
8
version 2.1 of the License, or (at your option) any later version.
10
This library is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
15
You should have received a copy of the GNU Lesser General Public
16
License along with this library; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24
#ifndef __STD_HEADER_LIST
25
#define __STD_HEADER_LIST 1
27
#pragma GCC visibility push(default)
31
template <class T, class Allocator = allocator<T> > class _UCXXEXPORT list {
33
typedef typename Allocator::reference reference;
34
typedef typename Allocator::const_reference const_reference;
35
typedef typename Allocator::size_type size_type;
36
typedef typename Allocator::difference_type difference_type;
38
typedef Allocator allocator_type;
39
typedef typename Allocator::pointer pointer;
40
typedef typename Allocator::const_pointer const_pointer;
53
typedef iter_list iterator;
54
typedef iter_list const_iterator;
55
typedef std::reverse_iterator<iterator> reverse_iterator;
56
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
58
explicit list(const Allocator& = Allocator());
59
explicit list(size_type n, const T& value = T(), const Allocator& = Allocator());
60
template <class InputIterator> list(InputIterator first, InputIterator last,
61
const Allocator& al= Allocator());
62
list(const list<T,Allocator>& x);
65
list<T,Allocator>& operator=(const list<T,Allocator>& x){
70
iterator i = x.begin();
78
template <class InputIterator> void assign(InputIterator first, InputIterator last);
79
template <class Size, class U> void assign(Size n, const U& u = U());
80
allocator_type get_allocator() const;
83
const_iterator begin() const;
85
const_iterator end() const;
86
reverse_iterator rbegin();
87
const_reverse_iterator rbegin() const;
88
reverse_iterator rend();
89
const_reverse_iterator rend() const;
92
size_type size() const;
93
size_type max_size() const;
94
void resize(size_type sz, T c = T());
97
const_reference front() const;
99
const_reference back() const;
101
void push_front(const T& x);
103
void push_back(const T& x);
105
iterator insert(iterator position, const T& x = T());
106
void insert(iterator position, size_type n, const T& x);
107
template <class InputIterator> void insert(iterator position, InputIterator first, InputIterator last);
108
iterator erase(iterator position);
109
iterator erase(iterator position, iterator last);
110
void swap(list<T,Allocator>&);
113
void splice(iterator position, list<T,Allocator>& x);
114
void splice(iterator position, list<T,Allocator>& x, iterator i);
115
void splice(iterator position, list<T,Allocator>& x, iterator first, iterator last);
116
void remove(const T& value);
117
template <class Predicate> void remove_if(Predicate pred);
119
template <class BinaryPredicate> void unique(BinaryPredicate binary_pred);
120
void merge(list<T,Allocator>& x);
121
template <class Compare> void merge(list<T,Allocator>& x, Compare comp);
123
template <class Compare> void sort(Compare comp);
126
void swap_nodes(node * x, node * y);
130
//Implementations of List
133
template <class T, class Allocator> class _UCXXEXPORT list<T, Allocator>::node{
139
node(): previous(0), next(0), val(0){ }
140
node(const T & t ): previous(0), next(0), val(0) {
142
//FIXME use allocator somehow but only call constructor once
144
node(const T & t, node * p, node * n): previous(p), next(n), val(0) {
151
template <class T, class Allocator> class _UCXXEXPORT list<T, Allocator>::iter_list
152
: public std::iterator<
153
bidirectional_iterator_tag,
155
typename Allocator::difference_type,
156
typename Allocator::pointer,
157
typename Allocator::reference
163
iter_list():current(0) { }
164
iter_list( typename list<T, Allocator>::node * n): current(n) { }
165
iter_list(const list<T, Allocator>::iter_list & l): current(l.current) { }
168
iter_list & operator=(const list<T, Allocator>::iter_list & right ){
169
current = right.current;
174
return *(current->val);
179
const T & operator*() const{
180
return *current->val;
182
const T * operator->() const{
186
bool operator==(const list<T, Allocator>::iter_list & right) const {
187
return (current == right.current);
190
bool operator!=(const list<T, Allocator>::iter_list & right) const {
191
return (current != right.current);
194
iter_list & operator++(){
195
current = current->next;
199
iter_list operator++(int){
200
iter_list temp(current);
201
current = current->next;
204
iter_list & operator--(){
205
current = current->previous;
209
iter_list operator--(int){
210
iter_list temp(current);
211
current = current->previous;
214
node * link_struct(){
217
iter_list & operator+=(unsigned int n){
218
for(unsigned int i = 0; i < n; ++i){
219
current = current->next;
223
iter_list & operator-=(unsigned int n){
224
for(unsigned int i = 0; i < n; ++i){
225
current = current->previous;
232
template<class T, class Allocator> list<T, Allocator>::list(const Allocator& al)
233
:list_start(0), list_end(0), elements(0), a(al)
236
list_start = new node();
237
list_end = list_start;
241
template<class T, class Allocator> list<T, Allocator>::list
242
(typename Allocator::size_type n, const T& value, const Allocator& al)
243
:list_start(0), list_end(0), elements(0), a(al)
246
list_start = new node();
247
list_end = list_start;
249
for(typename Allocator::size_type i = 0; i < n ; ++i){
254
template<class T, class Allocator> template <class InputIterator>
255
list<T, Allocator>::list
256
(InputIterator first, InputIterator last, const Allocator& al)
257
: list_start(0), list_end(0), elements(0), a(al)
259
list_start = new node();
260
list_end = list_start;
261
while(first != last){
267
template<class T, class Allocator> list<T, Allocator>::list(const list<T,Allocator>& x)
268
: list_start(0), list_end(0), elements(0), a(x.a)
270
list_start = new node();
271
list_end = list_start;
273
iterator i = x.begin();
280
template<class T, class Allocator> list<T, Allocator>::~list(){
284
delete list_start->val;
296
template<class T, class Allocator> void list<T, Allocator>::swap_nodes(node * x, node * y){
302
template<class T, class Allocator> typename list<T, Allocator>::iterator
303
list<T, Allocator>::begin()
305
return iterator(list_start);
309
template<class T, class Allocator> typename list<T, Allocator>::const_iterator
310
list<T, Allocator>::begin() const
312
return const_iterator(list_start);
316
template<class T, class Allocator> typename list<T, Allocator>::iterator
317
list<T, Allocator>::end()
319
return iterator(list_end);
322
template<class T, class Allocator> typename list<T, Allocator>::const_iterator
323
list<T, Allocator>::end() const
325
return const_iterator(list_end);
328
template<class T, class Allocator> typename list<T, Allocator>::reverse_iterator
329
list<T, Allocator>::rbegin()
331
return reverse_iterator(end());
334
template<class T, class Allocator> typename list<T, Allocator>::const_reverse_iterator
335
list<T, Allocator>::rbegin() const
337
return const_reverse_iterator(end());
340
template<class T, class Allocator> typename list<T, Allocator>::reverse_iterator
341
list<T, Allocator>::rend()
343
return reverse_iterator(begin());
346
template<class T, class Allocator> typename list<T, Allocator>::const_reverse_iterator
347
list<T, Allocator>::rend() const
349
return const_reverse_iterator(begin());
352
template<class T, class Allocator> bool list<T, Allocator>::empty() const{
353
return (elements == 0);
355
template<class T, class Allocator> typename list<T, Allocator>::size_type list<T, Allocator>::size() const{
358
template<class T, class Allocator> typename list<T, Allocator>::size_type list<T, Allocator>::max_size() const{
359
return ((size_type)(-1)) / (sizeof(T) + sizeof(node));
361
template<class T, class Allocator> void list<T, Allocator>::resize(typename Allocator::size_type sz, T c){
362
// if(sz > elements){
363
for(typename Allocator::size_type i = elements; i < sz; ++i){
367
// if(sz < elements){
368
for(typename Allocator::size_type i = elements; i > sz; --i){
374
template<class T, class Allocator> typename list<T, Allocator>::reference list<T, Allocator>::front(){
375
return *(list_start->val);
377
template<class T, class Allocator> typename list<T, Allocator>::const_reference list<T, Allocator>::front() const{
378
return *(list_start->val);
380
template<class T, class Allocator> typename list<T, Allocator>::reference list<T, Allocator>::back(){
381
return *(list_end->previous->val);
383
template<class T, class Allocator> typename list<T, Allocator>::const_reference list<T, Allocator>::back() const{
384
return *(list_end->previous->val);
388
template<class T, class Allocator> void list<T, Allocator>::push_front(const T& x){
389
node * temp = new node(x);
390
list_start->previous = temp;
392
temp->next = list_start;
397
template<class T, class Allocator> void list<T, Allocator>::pop_front(){
399
list_start = list_start->next;
400
delete list_start->previous->val;
402
list_start->previous->val = 0;
403
list_start->previous->next = 0;
404
list_start->previous->previous = 0;
406
delete list_start->previous;
407
list_start->previous = 0;
412
template<class T, class Allocator> void list<T, Allocator>::push_back(const T& x){
414
//The list is completely empty
415
list_start = new node(x);
416
list_end->previous = list_start;
417
list_start->previous = 0;
418
list_start->next = list_end;
421
node * temp = new node(x);
422
temp->previous = list_end->previous;
423
temp->next = list_end;
424
list_end->previous->next = temp;
425
list_end->previous = temp;
430
template<class T, class Allocator> void list<T, Allocator>::pop_back(){
432
node * temp = list_end->previous;
433
if(temp == list_start){
434
list_end->previous = 0;
435
list_start = list_end;
437
temp->previous->next = temp->next;
438
list_end->previous = temp->previous;
455
template<class T, class Allocator> typename list<T, Allocator>::iterator
456
list<T, Allocator>::insert(iterator position, const T& x)
458
node * temp = new node(x);
460
temp->previous = position.link_struct()->previous;
461
temp->next = position.link_struct();
463
if(temp->previous == 0){
466
position.link_struct()->previous->next = temp;
469
position.link_struct()->previous = temp;
476
template<class T, class Allocator> void list<T, Allocator>::insert(iterator position, size_type n, const T& x){
477
for(typename list<T, Allocator>::size_type i = 0; i < n; ++i){
478
position = insert(position, x);
482
template<class T, class Allocator> template <class InputIterator> void
483
list<T, Allocator>::insert(iterator position, InputIterator first, InputIterator last)
486
insert(position, *first);
490
template<class T, class Allocator> typename list<T, Allocator>::iterator
491
list<T, Allocator>::erase(iterator position)
493
if(position != end() ){
494
node * temp = position.link_struct();
495
if(temp == list_start){
497
temp->next->previous = 0;
498
list_start = temp->next;
501
temp->next->previous = temp->previous;
502
temp->previous->next = temp->next;
519
template<class T, class Allocator> typename list<T, Allocator>::iterator
520
list<T, Allocator>::erase(iterator position, iterator last)
522
iterator temp = position;
523
while(position !=last){
524
position = erase(position);
528
template<class T, class Allocator> void list<T, Allocator>::swap(list<T,Allocator>& l){
533
list_start = l.list_start;
537
list_end = l.list_end;
541
elements = l.elements;
544
template<class T, class Allocator> void list<T, Allocator>::clear(){
550
template<class T, class Allocator>
551
void list<T, Allocator>::splice(iterator position, list<T,Allocator>& x)
554
//Can't add non-existant elements
559
elements += x.elements;
563
//Chaining to the begining
564
if(position == begin()){
565
x.list_end->previous->next = list_start;
566
list_start->previous = x.list_end->previous;
568
list_start = x.list_start;
570
x.list_start = x.list_end;
571
x.list_end->previous = 0;
576
//Link everything we need
577
x.list_start->previous = position.link_struct()->previous;
578
position.link_struct()->previous->next = x.list_start;
580
position.link_struct()->previous = x.list_end->previous;
581
x.list_end->previous->next = position.link_struct();
583
//Clean up the other list
585
x.list_start = x.list_end;
586
x.list_end->previous=0;
590
template<class T, class Allocator>
591
void list<T, Allocator>::splice(iterator position, list<T,Allocator>& x, iterator i)
594
if( x.elements == 0 || i == position || position.link_struct() == i.link_struct()->next ){
599
//Do we need to adjust the begining pointer?
601
x.list_start = x.list_start->next;
602
x.list_start->previous = 0;
606
//Insert at begining special case
607
if(position == begin()){
609
i.link_struct()->previous->next = i.link_struct()->next;
610
i.link_struct()->next->previous = i.link_struct()->previous;
612
i.link_struct()->previous = 0;
613
i.link_struct()->next = position.link_struct();
614
position.link_struct()->previous = i.link_struct();
616
list_start = i.link_struct();
623
if( i.link_struct()->previous != 0){
624
i.link_struct()->previous->next = i.link_struct()->next;
625
i.link_struct()->next->previous = i.link_struct()->previous;
627
i.link_struct()->next->previous = 0;
628
x.list_start = i.link_struct()->next;
631
i.link_struct()->previous = position.link_struct()->previous;
632
position.link_struct()->previous->next = i.link_struct();
634
i.link_struct()->next = position.link_struct();
635
position.link_struct()->previous = i.link_struct();
641
template<class T, class Allocator>
642
void list<T, Allocator>::splice(iterator position, list<T,Allocator>& x,
643
iterator first, iterator last)
650
while(first != last){
653
splice(position, x, temp);
658
template<class T, class Allocator> void list<T, Allocator>::remove(const T& value){
659
iterator temp = begin();
660
while( temp != end() ){
670
template<class T, class Allocator> template <class Predicate> void list<T, Allocator>::remove_if(Predicate pred){
671
iterator temp = begin();
672
while( temp != end() ){
682
template<class T, class Allocator> void list<T, Allocator>::unique(){
683
equal_to<typename iterator_traits<iterator>::value_type> p;
687
template<class T, class Allocator> template <class BinaryPredicate>
688
void list<T, Allocator>::unique(BinaryPredicate binary_pred)
690
iterator temp1 = begin();
693
while( temp1 != end() ){
696
if( binary_pred(*temp1, *temp2) ){
704
template<class T, class Allocator> void list<T, Allocator>::merge(list<T,Allocator>& x){
705
less<typename iterator_traits<typename list<T, Allocator>::iterator>::value_type> c;
709
template<class T, class Allocator> template <class Compare>
710
void list<T, Allocator>::merge(list<T,Allocator>& x, Compare comp)
712
iterator source = x.begin();
714
iterator dest = begin();
716
while(source != x.end()){
717
while( dest != end() && comp (*dest, *source) ){
727
dest.link_struct()->previous = source.link_struct();
728
source.link_struct()->next = dest.link_struct();
729
source.link_struct()->previous = 0;
730
list_start = source.link_struct();
732
source.link_struct()->previous = dest.link_struct()->previous;
733
dest.link_struct()->previous->next = source.link_struct();
734
source.link_struct()->next = dest.link_struct();
735
dest.link_struct()->previous = source.link_struct();
741
x.list_start = x.list_end;
742
x.list_start->previous = 0;
745
template<class T, class Allocator> void list<T, Allocator>::sort(){
746
less<typename iterator_traits<typename list<T, Allocator>::iterator>::value_type> c;
750
template<class T, class Allocator> template <class Compare>
751
void list<T, Allocator>::sort(Compare comp)
753
typename list<T, Allocator>::iterator i, j, k;
755
//FIXME - bubble sort
769
swap_nodes(k.link_struct(), j.link_struct());
779
template<class T, class Allocator> void list<T, Allocator>::reverse(){
788
//Need to move the list_end element to the begining
791
list_end = temp->previous;
794
list_start->previous = temp;
796
temp->next = list_start;
799
current = list_start;
801
while( current != list_end ){
802
following = current->next;
804
//Swap the values pointed to/at with the current node
805
temp = current->next;
806
current->next = current->previous;
807
current->previous = temp;
812
//Swap pointers on the end node
813
temp = list_end->next;
814
list_end->next = list_end->previous;
815
list_end->previous = temp;
818
//Swap the fixed pointers
820
list_start = list_end;
825
template <class T, class Allocator>
826
bool operator==(const list<T,Allocator>& x, const list<T,Allocator>& y){
827
if(x.size() != y.size()){
830
typename list<T,Allocator>::const_iterator i = x.begin();
831
typename list<T,Allocator>::const_iterator j = y.begin();
843
template <class T, class Allocator>
844
bool operator< (const list<T,Allocator>& x, const list<T,Allocator>& y){
845
typename list<T,Allocator>::const_iterator i = x.begin();
846
typename list<T,Allocator>::const_iterator j = y.begin();
847
while(i != x.end() && j != y.end()){
857
return (i == x.end() && j != y.end());
860
template <class T, class Allocator>
861
bool operator!=(const list<T,Allocator>& x, const list<T,Allocator>& y){
865
template <class T, class Allocator>
866
bool operator> (const list<T,Allocator>& x, const list<T,Allocator>& y){
867
typename list<T,Allocator>::const_iterator i = x.begin();
868
typename list<T,Allocator>::const_iterator j = y.begin();
869
while(i != x.end() && j != y.end()){
879
return (i != x.end() && j == y.end());
882
template <class T, class Allocator>
883
bool operator>=(const list<T,Allocator>& x, const list<T,Allocator>& y){
884
typename list<T,Allocator>::const_iterator i = x.begin();
885
typename list<T,Allocator>::const_iterator j = y.begin();
886
while(i != x.end() && j != y.end()){
896
return (i != x.end() && j == y.end());
899
template <class T, class Allocator>
900
bool operator<=(const list<T,Allocator>& x, const list<T,Allocator>& y){
901
typename list<T,Allocator>::const_iterator i = x.begin();
902
typename list<T,Allocator>::const_iterator j = y.begin();
903
while(i != x.end() && j != y.end()){
913
return (i == x.end());
916
template <class T, class Allocator>
917
void swap(list<T,Allocator>& x, list<T,Allocator>& y){
923
#pragma GCC visibility pop