Hi Eddie,

Attached an alternative based on linked list implementation from CS book
"Data Structures and Problem Solving Using C++" which closely follows
standard library. Havent been tested thoroughly though. Named DList as I am
using Jason's implementation elsewhere as well.

Beyers

On 3/12/07, Eddie Kohler <[EMAIL PROTECTED]> wrote:

I like Jason's linked list, but I also wish that a couple of its aspects
were
different.  In particular, I wish that it was, by default, an "intrinsic"
linked list: i.e., List<T> would use properties like T.next and T.prev
.  Also
the interface needs an audit to make sure it follows the C++ standard
library
interface as much as possible.  Perhaps I'll send more info on this
soon...I
had wanted to really think it through first.

Eddie


Beyers Cronje wrote:
> Hi Jason,
>
> Just to let you know been using your list class as well, it works
> beautifully. I haven't picked up any issues with my use so far.
>
> Eddie, any chance you could include this or something simmilar in Click
?
>
> Regards
>
> Beyers Cronje
>
> On 1/29/07, *Jason Park* <[EMAIL PROTECTED]
> <mailto:[EMAIL PROTECTED]>> wrote:
>
>     HI,
>
>
>
>     Here I attach double linkedlist for click that Beyers mentioned.
>
>     I was fixed trivially since I posted.
>
>     It works well, but I don't know whether click has plan to include in
it.
>
>
>
>     Please put them into these locations.
>
>     include/click/list.hh
>
>     elements/test/listtest.hh
>
>     elements/test/listtest.cc
>
>
>
>     In addition to List, I'm working multi index container (memory db)
for
>     click. If someone or click needs it,
>
>     I'll post it. It's similar to the thing of Boost Multi-index
>     <http://www.boost.org/libs/multi_index/doc/index.html
>     <http://www.boost.org/libs/multi_index/doc/index.html>>  Containers
>     Library
>     and including MPL like (THE BOOST MPL
>     <http://www.boost.org/libs/mpl/doc/index.html>  LIBRARY) also.
>
>
>
>     Bye.
>
>
>
>     Jason Park.
>
>       _____
>
>     From: Beyers Cronje [mailto:[EMAIL PROTECTED]
>     <mailto:[EMAIL PROTECTED]>]
>     Sent: Monday, January 29, 2007 4:28 AM
>     To: [EMAIL PROTECTED] <mailto:
[EMAIL PROTECTED]>
>     Cc: [EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>;
>     Jason Park
>     Subject: Re: [Click] LinkedList in click
>
>
>
>     Hi Roberto,
>
>     See previous post by Jason.
>
https://amsterdam.lcs.mit.edu/pipermail/click/2006-October/005255.html
>
>     I havent used his patch so it's maybe best if Jason comments
directly.
>
>     Beyers
>
>     On 1/28/07, Roberto Riggio <[EMAIL PROTECTED]
>     <mailto:[EMAIL PROTECTED]>> wrote:
>
>     Hi,
>
>     as in the subject, are there any plans to include a (double)
>     linkedlist in
>     click?
>
>     Bye
>     Roberto
>
>     --
>     ========================================
>     Roberto Riggio, Ph. D. Student
>     CREATE-NET
>     via Solteri 38
>     38100 -- Trento (Italy)
>     tel: +39.0461.82.85.84
>     fax: +39.0461.42.11.57
>     e-mail: [EMAIL PROTECTED]
>     <mailto:[EMAIL PROTECTED]>
>     web page: http://dit.unitn.it/~riggio/
>     =======================================
>     _______________________________________________
>     click mailing list
>     click@amsterdam.lcs.mit.edu
>     <mailto:click@amsterdam.lcs.mit.edu>  <mailto:
click@amsterdam.lcs.mit.edu
>     <mailto:click@amsterdam.lcs.mit.edu>>
>     https://amsterdam.lcs.mit.edu/mailman/listinfo/click
>
>
>
>
>     _______________________________________________
>     click mailing list
>     click@amsterdam.lcs.mit.edu <mailto:click@amsterdam.lcs.mit.edu>
>     https://amsterdam.lcs.mit.edu/mailman/listinfo/click
>
>
>

#ifndef CLICK_DLIST_HH
#define CLICK_DLIST_HH

template <class T>
class ListNode;

template <class T>
class ConstListIter;

template <class T>
class ListIter;

template <class T>
class DList
{
	public:
		typedef ListIter<T> iterator;
		typedef ConstListIter<T> const_iterator;
		
		DList();
		~DList();
		
		DList(const DList& rhs);
		const DList & operator=(const DList& rhs);
		
		iterator begin();
		const_iterator begin() const;
		iterator end();
		const_iterator end() const;
		
		int size() const;
		bool empty() const;
		
		T& front();
		const T& front() const;
		T& back();
		const T& back() const;
		
		void push_front(const T& e);
		void push_back(const T& e);
		void pop_front();
		void pop_back();
		
		iterator insert(iterator itr, const T& e);
		iterator erase(iterator itr);
		iterator erase(iterator start, iterator end);
		
		friend class ConstListIter<T>;
		friend class ListIter<T>;
		
	private:
		typedef ListNode<T> node;
		
		int _n;
		node *_head;
		node *_tail;
		
		void init();
		void makeEmpty();
};


template <class T>
class ListNode
{
	private:
		ListNode(const T &d = T(), ListNode *p = NULL, ListNode *n = NULL) :
			_data(d), _prev(p), _next(n) { }
		
		T _data;
		ListNode *_prev;
		ListNode *_next;
		
		friend class ConstListIter<T>;
		friend class ListIter<T>;
		friend class DList<T>;
};

template <class T>
class ConstListIter
{
	public:
		ConstListIter();
		virtual ~ConstListIter() { }
		
		virtual const T& operator*() const;
		ConstListIter& operator++();
		ConstListIter operator++(int);
		ConstListIter& operator--();
		ConstListIter operator--(int);
		
		bool operator==(const ConstListIter& rhs) const;
		bool operator!=(const ConstListIter& rhs) const;
		
	protected:
		typedef ListNode<T> node;
		node *_head;
		node *_current;
		
		friend class DList<T>;
		void assertIsInitialized() const;
		void assertIsValid() const;
		void assertCanAdvance() const;
		void assertCanRetreat() const;
		T& retrieve() const;
		
		ConstListIter(const DList<T>& source, node *p);
};


template <class T>
class ListIter : public ConstListIter<T>
{
	public:
		ListIter();
		
		T& operator*();
		const T& operator*() const;
		ListIter& operator++();
		ListIter operator++(int);
		ListIter& operator--();
		ListIter operator--(int);
		
		T& value();
		
	protected:
		typedef ListNode<T> node;
		friend class DList<T>;
		
		ListIter(const DList<T>& source, node *p);
};

#endif
#include "dlist.hh"

template <class T>
DList<T>::DList()
{
	init();
}

template <class T>
void DList<T>::init()
{
	_n = 0;
	_head = new node;
	_tail = new node;
	_head->_next = _tail;
	_tail->_prev = _head;
}

template <class T>
DList<T>::~DList()
{
	makeEmpty();
	delete _head;
	delete _tail;
}

template <class T>
void DList<T>::makeEmpty()
{
	while (!empty())
		pop_front();
}

template <class T>
DList<T>::DList(const DList<T>& rhs)
{
	init();
	*this = rhs;
}

template <class T>
const DList<T>& DList<T>::operator=(const DList& rhs)
{
	if (this == &rhs)
		return *this;
	
	makeEmpty();
	const_iterator itr = rhs.begin();
	while (itr != rhs.end())
		push_back(*itr++);
	return *this;
}

template <class T>
typename DList<T>::iterator DList<T>::begin()
{
	iterator itr(*this, _head);
	return ++itr;
}

template <class T>
typename DList<T>::const_iterator DList<T>::begin() const
{		
	const_iterator itr(*this, _head);
	return ++itr;
}

template <class T>
typename DList<T>::iterator DList<T>::end()
{
	return iterator(*this, _tail);
}

template <class T>
typename DList<T>::const_iterator DList<T>::end() const
{
	return const_iterator(*this, _tail);
}

template <class T>
int DList<T>::size() const
{
	return _n;
}

template <class T>
bool DList<T>::empty() const
{
	return size() == 0;
}

template <class T>
T& DList<T>::front()
{
	return *begin();
}

template <class T>
const T& DList<T>::front() const
{
	return *begin();
}

template <class T>
T& DList<T>::back()
{
	return *--end();
}

template <class T>
const T& DList<T>::back() const
{
	return *--end();
}

template <class T>
void DList<T>::push_front(const T& e)
{
	insert(begin(), e);
}

template <class T>
void DList<T>::push_back(const T& e)
{
	insert(end(), e);
}

template <class T>
void DList<T>::pop_front()
{
	erase(begin());
}

template <class T>
void DList<T>::pop_back()
{
	erase(--end());
}

// Insert e before itr
template <class T>
typename DList<T>::iterator DList<T>::insert(iterator itr, const T& e)
{
	itr.assertIsValid();
	assert(itr._head == _head);	// itr is not in this list
	
	node *p = itr._current;
	p->_prev->_next = new node(e, p->_prev, p);
	p->_prev = p->_prev->_next;
	_n++;
	return iterator(*this, p->_prev);
}

// Erase item at itr
template <class T>
typename DList<T>::iterator DList<T>::erase(iterator itr)
{
	itr.assertIsValid();
	assert(itr != end());
	assert(itr._head == _head);
	
	node *p = itr._current;
	iterator retVal(*this, p->_next);
	p->_prev->_next = p->_next;
	p->_next->_prev = p->_prev;
	delete p;
	_n--;
	return retVal;
}

// Erate items in the range (from, to)
template <class T>
typename DList<T>::iterator DList<T>::erase(iterator from, iterator to)
{
	for (iterator itr = from; itr != to; )
		itr = erase(itr);
	return to;
}

template <class T>
ConstListIter<T>::ConstListIter() : _head(NULL), _current(NULL)
{
}

template <class T>
ConstListIter<T>::ConstListIter(const DList<T>& source, node *p)
	: _head(source._head), _current(p)
{
}

template <class T>
ListIter<T>::ListIter()
{
}

template <class T>
ListIter<T>::ListIter(const DList<T>& source, node *p)
	: ConstListIter<T>(source, p)
{
}

template <class T>
void ConstListIter<T>::assertIsInitialized() const
{
	assert(_head != NULL && _current != NULL);
}

template <class T>
void ConstListIter<T>::assertIsValid() const
{
	assertIsInitialized();
	assert(_current != _head);
}

template <class T>
void ConstListIter<T>::assertCanAdvance() const
{
	assertIsInitialized();
	assert(_current->_next != NULL);
}

template <class T>
void ConstListIter<T>::assertCanRetreat() const
{
	assertIsValid();
	assert(_current->_prev != _head);
}

template <class T>
const T& ConstListIter<T>::operator*() const
{
	return retrieve();
}

template <class T>
const T& ListIter<T>::operator*() const
{
	return ConstListIter<T>::operator*();
}

template <class T>
T& ListIter<T>::operator*()
{
	return ConstListIter<T>::retrieve();
}

template <class T>
T& ConstListIter<T>::retrieve() const
{
	assertIsValid();
	assert(_current->_next != NULL);
	
	return _current->_data;
}

// prefix
template <class T>
ConstListIter<T>& ConstListIter<T>::operator++()
{
	assertCanAdvance();
	_current = _current->_next;
	return *this;
}

// postfix
template <class T>
ConstListIter<T> ConstListIter<T>::operator++(int)
{
	ConstListIter<T> old = *this;
	++(*this);
	return old;
}

// prefix
template <class T>
ListIter<T>& ListIter<T>::operator++()
{
	ConstListIter<T>::assertCanAdvance();
	ConstListIter<T>::_current = ConstListIter<T>::_current->_next;
	return *this;
}

// postfix
template <class T>
ListIter<T> ListIter<T>::operator++(int)
{
	ListIter<T> old = *this;
	++(*this);
	return old;
}

// prefix
template <class T>
ConstListIter<T>& ConstListIter<T>::operator--()
{
	assertCanRetreat();
	_current = _current->_prev;
	return *this;
}

// postfix
template <class T>
ConstListIter<T> ConstListIter<T>::operator--(int)
{
	ConstListIter<T> old = *this;
	--(*this);
	return old;
}

// prefix
template <class T>
ListIter<T>& ListIter<T>::operator--()
{
	ConstListIter<T>::assertCanRetreat();
	ConstListIter<T>::_current = ConstListIter<T>::_current->_prev;
	return *this;
}
		
// postfix
template <class T>
ListIter<T> ListIter<T>::operator--(int)
{
	ListIter<T> old = *this;
	--(*this);
	return old;
}
		
template <class T>
bool ConstListIter<T>::operator==(const ConstListIter& rhs) const
{
	return _current == rhs._current;
}

template <class T>
bool ConstListIter<T>::operator!=(const ConstListIter& rhs) const
{
	return !(*this == rhs);
}


template <class T>
T& ListIter<T>::value()
{
	return ConstListIter<T>::retrieve();
}
_______________________________________________
click mailing list
click@amsterdam.lcs.mit.edu
https://amsterdam.lcs.mit.edu/mailman/listinfo/click

Reply via email to