/*  slist.c   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */
#include <string.h>
#include "portable.h"
#include "slist.h"
#include "errcode.h"

Entity SingleList::GetFirst()
{
	if (Last) if (Last->Next) return (Last->Next)->Entry ;
	return 0;
}

Entity SingleList::GetLast()
{
	if (Last) return Last->Entry ;
	return 0 ;
}

ErrCode SingleList::Insert(Entity a)
{
	if (Last)  Last->Next = new SingleLink(a,Last->Next) ;
	else {
		Last = new SingleLink(a,0);
		Last->Next = Last ;
	}
	return OK;
}

ErrCode SingleList::Append(Entity a)
{
	if (Last) Last = Last->Next = new SingleLink(a,Last->Next) ;
	else {
		Last = new SingleLink(a,0);
		Last->Next = Last ;
	}
	return OK;
}

Entity SingleList::Pop()
{
	if (Last == 0) return 0 ;
	SingleLink * Previous = Last->Next ;
	if (Previous == Last) {
		Entity Return = Previous->Entry ;
		delete Last ;
		Previous = Last = 0;
		return Return ;
	}
	while (Previous->Next != Last) Previous = Previous->Next ;
	Previous->Next = Last->Next ;
	Entity Return = Last->Entry ;
	delete Last ;
	Last = Previous ;
	return Return ;
}

Entity SingleList::Get()
{
	if (Last == 0) return 0;
	SingleLink * First = Last->Next ;
	Entity Return = First->Entry ;
	if (First == Last) Last = 0;
	else Last->Next = First->Next ;
	delete First ;
	return Return ;
}

void SingleList::Clear()
{
	SingleLink * link = Last ;
	if (!link) return ;
	do {
		SingleLink * l = link ;
		link = link->Next ;
		// LogOut << "Clear Deleting " << (void *)  l << "\n" ;
		if (l) delete l ;
	} while (link!= Last) ;
	Last = 0 ;
}


int SingleList::Size() const
{
	SingleListIterator Iter(*this);
	int Sz = 0;
	while (Iter.Next()) Sz++;
	return Sz;
}

ErrCode SingleList::RemoveEntry (Entity Entry)
{
	SingleListIterator Iter(*this);
	if (!Last) return Warning ;
	SingleLink * Previous = Last ;
	Entity Ent;
	while(Ent = Iter.Next()) if (Ent == Entry) {
		SingleLink * Save = Previous->Next ;
		Previous->Next = Iter.CurrentEntry->Next ;
		if (Last == Save) Last = Previous ;
		if (Last == Save) Last = 0;
		delete Save ;
		return OK ;
	} else Previous = Previous->Next ;
	return Warning ;
}
		


Entity SingleListIterator::Next()
{
	SingleLink * Link ;
	if (!CurrentList) return 0;
	if (!CurrentList->Last) return 0;
	if ( !CurrentEntry )
		Link = CurrentEntry = CurrentList->Last->Next ;
			// Last->Next is First in list
	else {
		CurrentEntry = CurrentEntry->Next ;
		Link = (CurrentEntry == CurrentList->Last->Next) ?
			0 : CurrentEntry ;
	}
	return Link ? Link->Entry : 0 ;
}


ErrCode ConstSingleList::Insert(ConstEntity a)
{
	if (Last)  Last->Next = new ConstSingleLink(a,Last->Next) ;
	else {
		Last = new ConstSingleLink(a,0);
		Last->Next = Last ;
	}
	return OK;
}

ErrCode ConstSingleList::Append(ConstEntity a)
{
	if (Last) Last = Last->Next = new ConstSingleLink(a,Last->Next) ;
	else {
		Last = new ConstSingleLink(a,0);
		Last->Next = Last ;
	}
	return OK;
}


ConstEntity ConstSingleList::Pop()
{
	if (Last == 0) return 0 ;
	ConstSingleLink * Previous = Last->Next ;
	if (Previous == Last) {
		ConstEntity Return = Last->Entry ;
		delete Last ;
		Last = 0;
		return Return ;
	}
	while (Previous->Next != Last) Previous = Previous->Next ;
	Previous->Next = Last->Next ;
	ConstEntity Return = Last->Entry ;
	delete Last ;
	Last = Previous ;
	return Return ;
}


ConstEntity ConstSingleList::Get()
{
	if (Last == 0) return 0;
	ConstSingleLink * First = Last->Next ;
	ConstEntity Return = First->Entry ;
	if (First == Last) Last = 0 ;
	else Last->Next = First->Next ;
	delete First ;
	return Return ;
}

void ConstSingleList::Clear()
{
	ConstSingleLink * link = Last ;
	if (!link) return ;
	do {
		ConstSingleLink * l = link ;
		link = link->Next ;
		// LogOut << "Const Clear Deleting " << (void *)  l << "\n" ;
		if (l) delete l ;
	} while (link!= Last) ;
	Last = 0 ;
}

int ConstSingleList::Size() const
{
	ConstSingleListIterator Iter(*this);
	int Sz = 0;
	while (Iter.Next()) Sz++;
	return Sz;
}


ConstEntity ConstSingleListIterator::Next()
{
	ConstSingleLink * Link ;
	if (!CurrentList) return 0;
	if (!CurrentList->Last) return 0;
	if ( !CurrentEntry )
		Link = CurrentEntry = CurrentList->Last->Next ;
			// Last->Next is First in list
	else {
		CurrentEntry = CurrentEntry->Next ;
		Link = (CurrentEntry == CurrentList->Last->Next) ?
			0 : CurrentEntry ;
	}
	return Link ? Link->Entry : 0 ;
}

int ConstStringList::IsInList(const char * Check)
{
	ConstStringListIterator Next(*this);
	const char * Entry ;
	while (Entry = Next()) if(!strcmp(Entry,Check)) return 1;
	return 0;
}

int StringList::IsInList(const char * Check)
{
	StringListIterator Next(*this);
	const char * Entry ;
	while (Entry = Next()) if(!strcmp(Entry,Check)) return 1;
	return 0;
}

ErrCode SingleList::Append(SingleList * lst)
{
	Entity ent ;
	ErrCode Check ;
	while (ent = lst->Get()) 
		if ((Check = Append(ent)) != OK) return Check ;
	delete lst ;
	return OK ;
}

ErrCode ConstSingleList::Append(ConstSingleList * lst)
{
	ConstEntity ent ;
	ErrCode Check ;
	while (ent = lst->Get()) 
		if ((Check = Append(ent)) != OK) return Check ;
	delete lst ;
	return OK ;
}


