// Simple Linked List (not to be confused with the Standard template library versions!
// SLinkedList and SNode are declared in the sute namespace to avoid such compiler confusion
// but i don't think their are any SLinkedLists out there anyway.


#ifndef _SLINKEDLIST

#define _SLINKEDLIST


#ifndef BOOL

	typedef bool BOOL;
	#define TRUE 1
	#define FALSE 0

#endif

namespace sute{


template <class K, class T>
class SNode{

	public:

		SNode(){}
		SNode(K* akey, T* avalue);
		~SNode();
	
		void set(T* avalue);
	
		T* get_value();
		K* get_key();
	// member variables
	
		SNode* next_node;
		SNode* last_node;
	
	private:

		K* key;
		T* value; 
};


// END OF CLASS DECLARATION




//////////////////////////////////////////////////

template <class K, class T>
class SLinkedList{


	public:

		SLinkedList();
			
		~SLinkedList();
		
		void add(T avalue);
		void add(K akey, T avalue);
		int size();
		void restore_iterator();
		T get_next();
		T get(const K akey);
		BOOL KeyExists(const K akey);
		int remove(const K akey);
		
	private:

		SNode<K, T>* get_node(const K akey);
	
		SNode<K, T>* head; 
		SNode<K, T>* current;
		int number;
		int flag;
};

// end of Declaration of SLinkedList


} // end of namespace 


template <class K, class T>
sute::SNode<K, T>::SNode(K* akey, T* avalue){

	key=akey;
	value=avalue;
}
		


template <class K, class T>
sute::SNode<K, T>::~SNode(){

	if (value!=0) delete value;
	
	if (next_node!=0) delete next_node;

	
}



template <class K, class T>
void sute::SNode<K, T>::set(T* avalue){

	delete value;
	value=avalue;
}		



template <class K, class T>
T* sute::SNode<K, T>::get_value(){

return value;
}


template <class K, class T>
K* sute::SNode<K, T>::get_key(){

return key;
}

//////////////////////////////////////////////////




template <class K, class T>
sute::SLinkedList<K, T>::SLinkedList(){

	number=0;
	head=0;
	current=0;
	flag=0;
}



template <class K, class T>
sute::SLinkedList<K, T>::~SLinkedList(){

	if (head !=0)
		delete head;

}



template <class K, class T>
void sute::SLinkedList<K, T>::add(const T avalue){

	T* nv=0;
	SNode<K, T>* temp =0;

	try{
		nv = new T;
		*nv=avalue;
		temp = new SNode<K, T>(0,nv);  // make the current node a valued node
		if (head!=0) head->last_node = temp;  // make the old head's last_node the new head
		temp->next_node = head;  // make the new head's next_node the old head
		head = temp; // because head, initially is null from constructor, the tail will
					 // always have that null to look for to end iteration
		number++;
	}
	catch(...){
		return;
	}
}



template <class K, class T>
void sute::SLinkedList<K, T>::add(const K akey, const T avalue){
	
	T* nv=0;
	K* nk=0;
	SNode<K, T>* temp =0;

	try{
		nv = new T;
		*nv=avalue;
		nk = new K;
		*nk=akey;
		temp = new SNode<K, T>(nk, nv);  // make the current node a valued node
		if (head!=0) head->last_node = temp;  // make the old head's last_node the new head
		temp->next_node = head;   // make the new head's next_node the old head
		head = temp; // because head, initially is null from constructor, the tail will
					 // always have that null to look for to end iteration
		number++;
	}
	catch(...){
		return;
	}
}



template <class K, class T>
int sute::SLinkedList<K, T>::size()
{
	return number;
}



template <class K, class T>
void sute::SLinkedList<K, T>::restore_iterator()
{
	current=head;
	flag=0;
}



template <class K, class T>
T sute::SLinkedList<K, T>::get_next(){

	if (flag==0){
		current=head;
		flag=1;
	}

	if (current==0){
		current = head;
		flag = 0;
		return 0;
	}

	T* value=0;

	value=current->get_value();
	current=current->next_node;
	return *value;		
}


template <class K, class T>
T sute::SLinkedList<K, T>::get(const K akey){

	T* value=0;
	SNode<K, T>* temp;

	if ((temp=get_node(akey))!=0){
		value = temp->get_value();
	}
	else return 0;

	return *value;
}


template <class K, class T>
BOOL sute::SLinkedList<K, T>::KeyExists(const K akey){

	SNode<K, T>* temp;

	if ((temp=get_node(akey))!=0){
		return TRUE;
	}
	else return FALSE;
}


template <class K, class T>
sute::SNode<K, T>* sute::SLinkedList<K, T>::get_node(const K akey){

	SNode<K, T>* wnode=0;
	SNode<K, T>* temp = head;
	K* tkey = 0;

	while (temp && !wnode){
		
		tkey = temp->get_key();
		if (*tkey == akey){
			wnode = temp;
		}
		temp=temp->next_node;
	}

return wnode;
}


template <class K, class T>
int sute::SLinkedList<K, T>::remove(const K akey){

	SNode<K, T>* temp =0;

	if ((temp=get_node(akey))!=0){
		
		if (temp==head)	head = temp->next_node;
		
		else{
				temp->last_node->next_node = temp->next_node;
				temp->next_node->last_node = temp->last_node;
		}
		temp->next_node=0;
		delete temp;
		number--;
	}
	else return 0;

	return 1;
}


#endif