// LinkedListIter.h

// This file declares (and defines some elements of) a singly linked list.
// Some source code is inlined for efficiency.  It also demonstrates the
// use of an Iterator class for traversing the list (container), thus
// implementing the container/iterator idiom common in the STL.

// Author: Dr. Jeff Blessing

#define WIN32_LEAN_AND_MEAN			// speeds up non-MFC builds
#include <cstdlib>					// defines NULL
#include <iostream>					// used when overloading <<
using namespace std;

// Declare the List classes so the Node class can forward reference it.

class LinkedList;
class LinkedListIter;

// The Node class defines the elements in the list.

class Node
{
public:
	Node(double d=0, Node* p=NULL): data(d), next(p) { }
private:
	double	data;
	Node*	next;
	friend class LinkedList;
	friend class LinkedListIter;
	friend ostream& operator<<(ostream& os, const LinkedList& src);
};

// The LinkedList class declares the list properties and forward
// references the LinkedListIter (iterator) class


class LinkedList		// container class declaration
{
public:
	LinkedList();		// constructor
	void add(double d);	// adds to the end of the list
	double getNext();	// returns the next element
	void start();		// resets the pointer to start of list
	~LinkedList();		// destructor
	LinkedList(const LinkedList& src);	// copy constructor
	LinkedList& operator=(const LinkedList& src);	// assign. op.
	friend ostream& operator<<(ostream& os, const LinkedList& src);
	friend class LinkedListIter;		// mutual friends
	LinkedListIter begin();
	LinkedListIter end();
private:
	Node*	head;		// start of list pointer
	Node*	tail;		// end of list pointer
	Node*	ptr;		// current element pointer
};

// The Linked List Iterator class implements the iterator pattern.

class LinkedListIter	// "forward" iterator class declaration
{
public:
	LinkedListIter(LinkedList& src);	// only available c'tor
	LinkedListIter& operator++();		// prefix ++
	LinkedListIter operator++(int);		// postfix ++
	const double operator*() const;		// dereference op.
	// Notice that the default copy constructor will do just fine,
	// but I had to implement the assign. op. to appease Visual C++.
	LinkedListIter& operator=(const LinkedListIter& src);
	friend bool operator!=(const LinkedListIter& left, const LinkedListIter& right);
	friend class LinkedList;			// mutual friends
private:
	LinkedListIter();	// nobody else gets to create a default iterator!
	LinkedList& list;
	Node* ptr;
};

// The linked list implementation follows:

inline LinkedList::LinkedList()
{
	// create header cell
	head = tail = ptr = new Node();
//	ptr->next = NULL;
}

inline void LinkedList::add(double d)
{
	// add to end of the list
	tail->next = new Node();
	tail = tail->next;
	tail->data = d;
//	tail->next = NULL;
}

inline double LinkedList::getNext()
{
	ptr = ptr->next;
	return ptr->data;
}

inline void LinkedList::start()
{
	ptr = head;
}

inline LinkedList::~LinkedList()
{
	// loop thru list destroying nodes
	start();
	while (ptr != NULL)
	{
		Node *tmp = ptr->next;

		delete ptr;
		ptr = tmp;
	}
}

// The LinkedListIter implementation follows:

inline LinkedListIter::LinkedListIter(LinkedList& src):
	list(src), ptr(src.ptr) { }

inline LinkedListIter LinkedList::begin()
{
	start();		// Start at the beginning...
	getNext();		// and skip the header cell.
	return LinkedListIter(*this);
}

inline LinkedListIter LinkedList::end()
{
	LinkedListIter iter(*this);

	iter.ptr = this->tail;
	return iter;
}

inline LinkedListIter& LinkedListIter::operator++()		// prefix ++ def'n
{
	if (ptr->next != NULL)
		ptr = ptr->next;
	return *this;
}

inline LinkedListIter LinkedListIter::operator++(int)	// postfix ++
{
	LinkedListIter iter(*this);		// copy c'tor call!

	if (ptr->next != NULL)
		ptr = ptr->next;
	return iter;
}

inline const double LinkedListIter::operator*() const
{
	return ptr->data;
}

// Appease the Visual C++ compiler!
inline LinkedListIter& LinkedListIter::operator=(const LinkedListIter& src)
{
	list = src.list;
	ptr = src.ptr;
	return *this;
}

inline bool operator!=(const LinkedListIter& left, const LinkedListIter& right)
{
	// The &'s are needed because list is a reference type (not a pointer type)!
	return (&(left.list) != &(right.list)) || (left.ptr != right.ptr);
}
