/* Copyright (C) 2004 Garrett A. Kajmowicz This file is part of the uClibc++ Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #ifndef __STD_HEADER_LIST #define __STD_HEADER_LIST 1 namespace std{ template > class _UCXXEXPORT list { public: typedef typename Allocator::reference reference; typedef typename Allocator::const_reference const_reference; typedef typename Allocator::size_type size_type; typedef typename Allocator::difference_type difference_type; typedef T value_type; typedef Allocator allocator_type; typedef typename Allocator::pointer pointer; typedef typename Allocator::const_pointer const_pointer; protected: class node; class iter_list; node * list_start; node * list_end; size_type elements; Allocator a; public: typedef iter_list iterator; typedef iter_list const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; explicit list(const Allocator& = Allocator()); explicit list(size_type n, const T& value = T(), const Allocator& = Allocator()); template list(InputIterator first, InputIterator last, const Allocator& al= Allocator()); list(const list& x); ~list(); list& operator=(const list& x){ if(&x == this){ return *this; } clear(); iterator i = x.begin(); while(i != x.end()){ push_back(*i); ++i; } return *this; } template void assign(InputIterator first, InputIterator last); template void assign(Size n, const U& u = U()); allocator_type get_allocator() const; iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; reverse_iterator rbegin(); const_reverse_iterator rbegin() const; reverse_iterator rend(); const_reverse_iterator rend() const; bool empty() const; size_type size() const; size_type max_size() const; void resize(size_type sz, T c = T()); reference front(); const_reference front() const; reference back(); const_reference back() const; void push_front(const T& x); void pop_front(); void push_back(const T& x); void pop_back(); iterator insert(iterator position, const T& x = T()); void insert(iterator position, size_type n, const T& x); template void insert(iterator position, InputIterator first, InputIterator last); iterator erase(iterator position); iterator erase(iterator position, iterator last); void swap(list&); void clear(); void splice(iterator position, list& x); void splice(iterator position, list& x, iterator i); void splice(iterator position, list& x, iterator first, iterator last); void remove(const T& value); template void remove_if(Predicate pred); void unique(); template void unique(BinaryPredicate binary_pred); void merge(list& x); template void merge(list& x, Compare comp); void sort(); template void sort(Compare comp); void reverse(); protected: void swap_nodes(node * x, node * y); }; //Implementations of List //List node template class _UCXXEXPORT list::node{ public: node * previous; node * next; T * val; node(): previous(0), next(0), val(0){ } node(const T & t ): previous(0), next(0), val(0) { val = new T(t); //FIXME use allocator somehow but only call constructor once } node(const T & t, node * p, node * n): previous(p), next(n), val(0) { val = new T(t); } ~node(){ } }; //List iterator template class _UCXXEXPORT list::iter_list : public std::iterator< bidirectional_iterator_tag, T, typename Allocator::difference_type, typename Allocator::pointer, typename Allocator::reference > { private: node * current; public: iter_list():current(0) { } iter_list( typename list::node * n): current(n) { } iter_list(const list::iter_list & l): current(l.current) { } ~iter_list(){ } iter_list & operator=(const list::iter_list & right ){ current = right.current; return *this; } T & operator*(){ return *(current->val); } T * operator->(){ return current->val; } const T & operator*() const{ return *current->val; } const T * operator->() const{ return current->val; } bool operator==(const list::iter_list & right) const { return (current == right.current); } bool operator!=(const list::iter_list & right) const { return (current != right.current); } iter_list & operator++(){ current = current->next; return *this; } iter_list operator++(int){ iter_list temp(current); current = current->next; return temp; } iter_list & operator--(){ current = current->previous; return *this; } iter_list operator--(int){ iter_list temp(current); current = current->previous; return temp; } node * link_struct(){ return current; } iter_list & operator+=(unsigned int n){ for(unsigned int i = 0; i < n; ++i){ current = current->next; } return *this; } iter_list & operator-=(unsigned int n){ for(unsigned int i = 0; i < n; ++i){ current = current->previous; } return *this; } }; template list::list(const Allocator& al) :list_start(0), list_end(0), elements(0), a(al) { //End node list_start = new node(); list_end = list_start; return; } template list::list (typename Allocator::size_type n, const T& value, const Allocator& al) :list_start(0), list_end(0), elements(0), a(al) { //End node list_start = new node(); list_end = list_start; for(typename Allocator::size_type i = 0; i < n ; ++i){ push_back(value); } } template template list::list (InputIterator first, InputIterator last, const Allocator& al) : list_start(0), list_end(0), elements(0), a(al) { list_start = new node(); list_end = list_start; while(first != last){ push_back(*first); ++first; } } template list::list(const list& x) : list_start(0), list_end(0), elements(0), a(x.a) { list_start = new node(); list_end = list_start; iterator i = x.begin(); while(i != x.end()){ push_back( *i); ++i; } } template list::~list(){ while(elements > 0){ pop_front(); } delete list_start->val; #if UCLIBCXX_DEBUG list_start->val = 0; #endif delete list_start; #if UCLIBCXX_DEBUG list_start = 0; list_end = 0; #endif } template void list::swap_nodes(node * x, node * y){ T * v = x->val; x->val = y->val; y->val = v; } template typename list::iterator list::begin() { return iterator(list_start); } template typename list::const_iterator list::begin() const { return const_iterator(list_start); } template typename list::iterator list::end() { return iterator(list_end); } template typename list::const_iterator list::end() const { return const_iterator(list_end); } template typename list::reverse_iterator list::rbegin() { return reverse_iterator(end()); } template typename list::const_reverse_iterator list::rbegin() const { return const_reverse_iterator(end()); } template typename list::reverse_iterator list::rend() { return reverse_iterator(begin()); } template typename list::const_reverse_iterator list::rend() const { return const_reverse_iterator(begin()); } template bool list::empty() const{ return (elements == 0); } template typename list::size_type list::size() const{ return elements; } template typename list::size_type list::max_size() const{ return ((size_type)(-1)) / (sizeof(T) + sizeof(node)); } template void list::resize(typename Allocator::size_type sz, T c){ // if(sz > elements){ for(typename Allocator::size_type i = elements; i < sz; ++i){ push_back(c); } // } // if(sz < elements){ for(typename Allocator::size_type i = elements; i > sz; --i){ pop_back(); } // } } template typename list::reference list::front(){ return *(list_start->val); } template typename list::const_reference list::front() const{ return *(list_start->val); } template typename list::reference list::back(){ return *(list_end->previous->val); } template typename list::const_reference list::back() const{ return *(list_end->previous->val); } template void list::push_front(const T& x){ node * temp = new node(x); list_start->previous = temp; temp->previous = 0; temp->next = list_start; list_start = temp; ++elements; } template void list::pop_front(){ if(elements > 0){ list_start = list_start->next; delete list_start->previous->val; #if UCLIBCXX_DEBUG list_start->previous->val = 0; list_start->previous->next = 0; list_start->previous->previous = 0; #endif delete list_start->previous; list_start->previous = 0; --elements; } } template void list::push_back(const T& x){ if(elements == 0){ //The list is completely empty list_start = new node(x); list_end->previous = list_start; list_start->previous = 0; list_start->next = list_end; elements = 1; }else{ node * temp = new node(x); temp->previous = list_end->previous; temp->next = list_end; list_end->previous->next = temp; list_end->previous = temp; ++elements; } } template void list::pop_back(){ if(elements > 0){ node * temp = list_end->previous; if(temp == list_start){ list_end->previous = 0; list_start = list_end; }else{ temp->previous->next = temp->next; list_end->previous = temp->previous; } delete temp->val; #if UCLIBCXX_DEBUG temp->val = 0; temp->next = 0; temp->previous = 0; #endif delete temp; #if UCLIBCXX_DEBUG temp = 0; #endif --elements; } } template typename list::iterator list::insert(iterator position, const T& x) { node * temp = new node(x); temp->previous = position.link_struct()->previous; temp->next = position.link_struct(); if(temp->previous == 0){ list_start = temp; }else{ position.link_struct()->previous->next = temp; } position.link_struct()->previous = temp; ++elements; --position; return position; } template void list::insert(iterator position, size_type n, const T& x){ for(typename list::size_type i = 0; i < n; ++i){ position = insert(position, x); } } template template void list::insert(iterator position, InputIterator first, InputIterator last) { while(first !=last){ insert(position, *first); ++first; } } template typename list::iterator list::erase(iterator position) { if(position != end() ){ node * temp = position.link_struct(); if(temp == list_start){ position = end(); temp->next->previous = 0; list_start = temp->next; }else{ --position; temp->next->previous = temp->previous; temp->previous->next = temp->next; ++position; } delete temp->val; #if UCLIBCXX_DEBUG temp->next = 0; temp->previous = 0; temp->val = 0; #endif delete temp; #if UCLIBCXX_DEBUG temp = 0; #endif --elements; } return position; } template typename list::iterator list::erase(iterator position, iterator last) { iterator temp = position; while(position !=last){ position = erase(position); } return position; } template void list::swap(list& l){ node * temp; size_type tempel; temp = list_start; list_start = l.list_start; l.list_start = temp; temp = list_end; list_end = l.list_end; l.list_end = temp; tempel = elements; elements = l.elements; l.elements = tempel; } template void list::clear(){ while(elements > 0){ pop_front(); } } template void list::splice(iterator position, list& x) { //Can't add non-existant elements if(x.elements == 0){ return; } elements += x.elements; x.elements = 0; //Chaining to the begining if(position == begin()){ x.list_end->previous->next = list_start; list_start->previous = x.list_end->previous; list_start = x.list_start; x.list_start = x.list_end; x.list_end->previous = 0; return; } //Link everything we need x.list_start->previous = position.link_struct()->previous; position.link_struct()->previous->next = x.list_start; position.link_struct()->previous = x.list_end->previous; x.list_end->previous->next = position.link_struct(); //Clean up the other list x.list_start = x.list_end; x.list_end->previous=0; } template void list::splice(iterator position, list& x, iterator i) { //Invalid conditions if( x.elements == 0 || i == position || position.link_struct() == i.link_struct()->next ){ return; } //Do we need to adjust the begining pointer? if(i == x.begin()){ x.list_start = x.list_start->next; x.list_start->previous = 0; } //Insert at begining special case if(position == begin()){ i.link_struct()->previous->next = i.link_struct()->next; i.link_struct()->next->previous = i.link_struct()->previous; i.link_struct()->previous = 0; i.link_struct()->next = position.link_struct(); position.link_struct()->previous = i.link_struct(); list_start = i.link_struct(); --x.elements; ++elements; return; } if( i.link_struct()->previous != 0){ i.link_struct()->previous->next = i.link_struct()->next; i.link_struct()->next->previous = i.link_struct()->previous; }else{ i.link_struct()->next->previous = 0; x.list_start = i.link_struct()->next; } i.link_struct()->previous = position.link_struct()->previous; position.link_struct()->previous->next = i.link_struct(); i.link_struct()->next = position.link_struct(); position.link_struct()->previous = i.link_struct(); --x.elements; ++elements; } template void list::splice(iterator position, list& x, iterator first, iterator last) { if(x.elements == 0){ return; } iterator temp; while(first != last){ temp = first; ++first; splice(position, x, temp); } } template void list::remove(const T& value){ iterator temp = begin(); while( temp != end() ){ if(*temp == value){ temp = erase(temp); }else{ ++temp; } } } template template void list::remove_if(Predicate pred){ iterator temp = begin(); while( temp != end() ){ if( pred(*temp) ){ temp = erase(temp); }else{ ++temp; } } } template void list::unique(){ equal_to::value_type> p; unique(p); } template template void list::unique(BinaryPredicate binary_pred) { iterator temp1 = begin(); iterator temp2; ++temp1; while( temp1 != end() ){ temp2 = temp1; --temp2; if( binary_pred(*temp1, *temp2) ){ erase(temp1); temp1 = temp2; } ++temp1; } } template void list::merge(list& x){ less::iterator>::value_type> c; merge(x, c); } template template void list::merge(list& x, Compare comp) { iterator source = x.begin(); iterator temp; iterator dest = begin(); while(source != x.end()){ while( dest != end() && comp (*dest, *source) ){ ++dest; } ++elements; --x.elements; temp = source; ++temp; if(dest == begin()){ dest.link_struct()->previous = source.link_struct(); source.link_struct()->next = dest.link_struct(); source.link_struct()->previous = 0; list_start = source.link_struct(); }else{ source.link_struct()->previous = dest.link_struct()->previous; dest.link_struct()->previous->next = source.link_struct(); source.link_struct()->next = dest.link_struct(); dest.link_struct()->previous = source.link_struct(); } source = temp; } //Fix up x; x.list_start = x.list_end; x.list_start->previous = 0; } template void list::sort(){ less::iterator>::value_type> c; sort(c); } template template void list::sort(Compare comp) { typename list::iterator i, j, k; //FIXME - bubble sort if(elements == 0){ return; } i = end(); --i; while(i != begin()){ j = begin(); k = j; ++k; while(j != i){ if( comp(*k, *j) ){ swap_nodes(k.link_struct(), j.link_struct()); } ++j; ++k; } --i; } } template void list::reverse(){ if(elements == 0){ return; } node * current; node * following; node * temp; //Need to move the list_end element to the begining temp = list_end; list_end = temp->previous; list_end->next = 0; list_start->previous = temp; temp->previous = 0; temp->next = list_start; list_start = temp; current = list_start; while( current != list_end ){ following = current->next; //Swap the values pointed to/at with the current node temp = current->next; current->next = current->previous; current->previous = temp; current = following; } //Swap pointers on the end node temp = list_end->next; list_end->next = list_end->previous; list_end->previous = temp; //Swap the fixed pointers temp = list_start; list_start = list_end; list_end = temp; } template bool operator==(const list& x, const list& y){ if(x.size() != y.size()){ return false; } typename list::const_iterator i = x.begin(); typename list::const_iterator j = y.begin(); while(i != x.end()){ if( *i != *j){ return false; } ++i; ++j; } return true; } template bool operator< (const list& x, const list& y){ typename list::const_iterator i = x.begin(); typename list::const_iterator j = y.begin(); while(i != x.end() && j != y.end()){ if( *i < *j){ return true; } if(*j < *i){ return false; } ++i; ++j; } return (i == x.end() && j != y.end()); } template bool operator!=(const list& x, const list& y){ return !(x == y); } template bool operator> (const list& x, const list& y){ typename list::const_iterator i = x.begin(); typename list::const_iterator j = y.begin(); while(i != x.end() && j != y.end()){ if( *i > *j){ return true; } if( *j > *i){ return false; } ++i; ++j; } return (i != x.end() && j == y.end()); } template bool operator>=(const list& x, const list& y){ typename list::const_iterator i = x.begin(); typename list::const_iterator j = y.begin(); while(i != x.end() && j != y.end()){ if( *i >= *j){ return true; } if(*j >= *i){ return false; } ++i; ++j; } return (i != x.end() && j == y.end()); } template bool operator<=(const list& x, const list& y){ typename list::const_iterator i = x.begin(); typename list::const_iterator j = y.begin(); while(i != x.end() && j != y.end()){ if( *i <= *j){ return true; } if(*j <= *i){ return false; } ++i; ++j; } return (i == x.end()); } template void swap(list& x, list& y){ x.swap(y); } } #endif