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