#ifndef _LIST
#define _LIST
#ifndef _LINK
#include "link.h"
#endif
#ifndef _GLIBCXX_IOSTREAM
#include <iostream>
#endif
#ifndef __EXCEPTION__
#include <exception>
#endif
class iteratorexception: public std::exception
{
virtual const char* what() const throw()
{
return "Bad iterator reference (iterator was NULL)";
}
} nulliterator;
class indexexception: public std::exception
{
virtual const char* what() const throw()
{
return "Error, the index was out of range";
}
} badindex;
template <typename T>
class basic_list
{
typedef basic_link<T> link;
typedef basic_list<T> list;
typedef link* plink;
plink head, tail;
size_t size;
public:
class iterator;
const static size_t npos= -1;
basic_list()
: head(NULL), tail(NULL), size(0)
{}
basic_list( const T &_value )
: head(new link(_value)), tail(head), size(1)
{}
basic_list( const link &_link )
: head(new link(_link.value)), tail(head), size(1)
{}
basic_list( const list &_list )
: head(NULL), tail(NULL), size(0)
{
for( iterator position = _list.head; !position.null(); position++ )
this->append(*position);
}
~basic_list()
{
iterator position (head);
while( !position.null() )
{
delete position++.element;
}
}
// Data methods
iterator begin()
{
iterator iter(head);
return iter;
}
iterator end()
{
iterator iter(tail);
return iter;
}
const char* type() { return typeid(T).name(); }
bool empty() { return ( this->size == 0 ); }
size_t length() { return this->size; }
// Modifier methods
list& clear()
{
iterator position (head);
while( !position.null() )
{
delete position++.element;
}
head= tail= NULL;
size= 0;
return *this;
}
void swap( list &_list )
{
list temp(_list);
_list.assign(*this);
this->assign(temp);
}
// Assignment methods
list& assign( list _list )
{
this->clear();
this->append(_list);
return *this;
}
list& assign( list _list, size_t _pos, size_t _n= npos )
{
this->clear();
try
{
this->append(_list.sublist( _pos, _n ));
}
catch( std::exception &e )
{
throw e;
}
return *this;
}
list& assign( size_t _n, const T &_value )
{
this->clear();
for( size_t i = 0; i < _n; i++ )
this->append(_value);
return *this;
}
list& assign( size_t _n, const link &_link )
{
this->clear();
for( size_t i = 0; i < _n; i++ )
this->append(_link.value);
return *this;
}
list& assign( iterator _first, iterator _last )
{
this->clear();
iterator current= _first, end= _last+1; // _last+1 to include the _last
while( !current.null() && current != end )
this->append(*current++);
return*this;
}
// Insertion methods
list& insert( size_t _pos, const T &_value )
{
if( _pos >= size )
throw badindex;
plink position= &this->at(_pos);
plink new_link= new link( _value, position->previous, position );
if( position == head )
head= position->previous= new_link;
else
position->previous= position->previous->next= new_link;
return *this;
}
list& insert( size_t _pos, const link &_link )
{
if( _pos >= size )
throw badindex;
plink position= &this->at(_pos);
plink new_link= new link( _link.value, position->previous, position );
if( position == head )
head= position->previous= new_link;
else
position->previous= position->previous->next= new_link;
return *this;
}
list& insert( size_t _pos, size_t _n, const T &_value )
{
if( _pos >= size )
throw badindex;
for( size_t i = 0; i < _n; i++ )
this->append( _pos, _value );
return *this;
}
list& insert( size_t _pos, size_t _n, const link &_link )
{
if( _pos >= size )
throw badindex;
T _value= _link.value;
for( size_t i = 0; i < _n; i++ )
this->append( _pos, _value );
return *this;
}
list& insert( size_t _pos, const list &_list )
{
if( _pos >= size )
throw badindex;
for( iterator position = _list.head; !position.null(); position++, _pos++ )
this->insert( _pos, *position );
return *this;
}
list& insert( size_t _pos1, list _list, size_t _pos2, size_t _n= npos )
{
if( _pos1 >= size )
throw badindex;
try
{
this->insert( _pos1, _list.sublist( _pos2, _n ) );
}
catch( std::exception &e )
{
throw e;
}
return *this;
}
// Appending methods
list& append( const T &_value )
{
plink new_link= new link(_value, tail);
if( size == 0 )
tail= head= new_link;
else
tail= tail->next= new_link;
size++;
return *this;
}
list& append( const link &_link )
{
plink new_link= new link(_link.value, tail);
if( size == 0 )
tail= head= new_link;
else
tail= tail->next= new_link;
size++;
return *this;
}
list& append( const list &_list )
{
iterator position= _list.head;
size_t count= _list.size;
for( size_t i = 0; i < count; i++ )
this->append(*position++);
return *this;
}
list& operator+= ( const T &_value )
{
plink new_link= new link(_value, tail);
if( size == 0 )
tail= head= new_link;
else
tail= tail->next= new_link;
size++;
return *this;
}
list& operator+= ( const link &_link )
{
plink new_link= new link(_link.value, tail);
if( size == 0 )
tail= head= new_link;
else
tail= tail->next= new_link;
size++;
return *this;
}
list& operator+= ( const list _list )
{
for( iterator position = _list.head; !position.null(); position++ )
this->append(*position);
return *this;
}
// Access Methods
link& at( size_t _pos )
{
if( _pos >= size )
throw badindex;
iterator position(head);
return *(position+_pos);
}
link& operator[] ( size_t _pos )
{
if( _pos >= size )
throw badindex;
iterator position(head);
return *(position+_pos);
}
// Operation methods
size_t find( const T &_value, size_t _pos )
{
if( _pos >= size )
throw badindex;
iterator position(&this->at(_pos));
while( !position.null() && _value != *position++ )
if( *position == _value )
return _pos;
else
_pos++;
return npos;
}
size_t find( const link &_link, size_t _pos )
{
if( _pos >= size )
throw badindex;
iterator position(&this->at(_pos));
while( !position.null() && _link.value != *position++ )
if( *position == _link.value )
return _pos;
else
_pos++;
return npos;
}
list sublist( size_t _pos, size_t _n= npos )
{
if( _pos >= size )
throw badindex;
list temp;
iterator position(&this->at(_pos));
for( size_t i = 0; i < npos && !position.null(); i++, position++ )
temp.append(*position);
return temp;
}
// Output method
template <typename CharT>
friend std::basic_ostream<CharT>& operator<< ( std::basic_ostream<CharT> &out, const list &_list )
{
if( _list.size > 0 )
{
out << "{ ";
iterator start(_list.head), end(_list.tail);
for( iterator position= start; !position.null(); position++ )
{
if( typeid(T) == typeid(char) )
out << '\'' << *position << '\'';
else if( typeid(T) == typeid(char*) || typeid(T) == typeid(std::string) )
out << '\"' << *position << '\"';
else
out << *position;
out << ( position != end ? ", " : " }" );
}
}
return out;
}
};
template <typename T>
struct basic_list<T>::iterator
{
plink element;
// Constructors
iterator()
: element(NULL)
{}
iterator( plink _link )
: element(_link)
{}
iterator( const iterator &_iter )
: element(_iter.element)
{}
bool null() { return ( this->element == NULL ); }
// Operators
link& operator* ()
{
if( element == NULL )
throw nulliterator;
return *element;
}
// Problem, find out how to declare operator->
// operator-> ()
link& operator[] ( size_t _offset )
{
if( element == NULL )
throw nulliterator;
iterator temp(*this);
for( size_t i = 0; i < _offset; i++ )
{
if( temp.element == NULL )
throw nulliterator;
temp.element= temp.element->next;
}
return *temp.element;
}
bool operator== ( const iterator &_iter ) { return ( this->element == _iter.element ); }
bool operator!= ( const iterator &_iter ) { return ( this->element != _iter.element ); }
bool operator== ( const plink _link ) { return ( this->element == _link ); }
bool operator!= ( const plink _link ) { return ( this->element != _link ); }
iterator operator+ ( const size_t &_n )
{
iterator temp(*this);
for( size_t i = 0; i < _n; i++ )
{
if( temp.element == NULL )
throw nulliterator;
temp.element= temp.element->next;
}
return temp;
}
iterator operator- ( const size_t &_n )
{
iterator temp(*this);
for( size_t i = 0; i < _n; i++ )
{
if( temp.element == NULL )
throw nulliterator;
temp.element= temp.element->previous;
}
return temp;
}
iterator& operator+= ( const size_t &_n )
{
for( size_t i = 0; i < _n; i++ )
{
if( this->element == NULL )
throw nulliterator;
this->element= this->element->next;
}
return *this;
}
iterator& operator-= ( const size_t &_n )
{
for( size_t i = 0; i < _n; i++ )
{
if( this->element == NULL )
throw nulliterator;
this->element= this->element->previous;
}
return *this;
}
iterator& operator= ( const iterator &_iter )
{
this->element= _iter.element;
return *this;
}
iterator& operator= ( link *_link )
{
this->element= _link;
return *this;
}
iterator& operator++ ()
{
if( element == NULL )
throw nulliterator;
element= element->next;
return *this;
}
iterator operator++ ( int )
{
if( element == NULL )
throw nulliterator;
iterator current (*this);
element= element->next;
return current;
}
iterator& operator-- ()
{
if( element == NULL )
throw nulliterator;
element= element->previous;
return *this;
}
iterator operator-- ( int )
{
if( element == NULL )
throw nulliterator;
iterator current (*this);
element= element->previous;
return current;
}
/*void* operator new ( size_t size)
{
this->element= new link
}
void operator delete (void *p)
{
free(p);
}*/
};
typedef basic_list<int> intlist;
typedef basic_list<double> doublelist;
typedef basic_list<char> charlist;
typedef basic_list<bool> boollist;
#ifdef _GLIBCXX_STRING
typedef basic_list<std::string> stringlist;
#define slist stringlist
#define strlist stringlist
#endif
#define ilist intlist
#define dlist doublelist
#define dbllist doublelist
#define clist charlist
#define blist boollist
#endif /* _LINK */