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