
/*********************************************************************
----------------------------------------------------------------------

	tools

----------------------------------------------------------------------
*********************************************************************/

#include <string.h>
#include <stdio.h>

#include <exec/lists.h>
#include <dos/dos.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/utility.h>

#include "global.h"


/*********************************************************************

	s' = StrDup(s)

*********************************************************************/

char *StrDup(char *s)
{
	char *s2 = NULL;

	if (s)
	{
		int l = strlen(s);
		if (s2 = Malloc(l+1))
		{
			strcpy(s2, s);
		}
	}
	
	return s2;
}



/*********************************************************************

	node = DeleteNode(node)

	delete a named node

*********************************************************************/

void DeleteNode(struct Node *node)
{
	if (node)
	{
		Free(node->ln_Name);
		Free(node);
	}
}


/*********************************************************************

	node = CreateNode(char *name)

	create a named node

*********************************************************************/

struct Node *CreateNode(char *name)
{
	struct Node *node;
	BOOL success = FALSE;

	if (node = Malloclear(sizeof(struct Node)))
	{
		node->ln_Type = NT_USER;
		node->ln_Pri = 0;
		if (node->ln_Name = StrDup(name))
		{
			success = TRUE;
		}
	}
	
	if (!success)
	{
		DeleteNode(node);
		node = NULL;
	}
	
	return node;
}




/*********************************************************************

	list = CreateList(void)

	create a double linked list

*********************************************************************/

struct List *CreateList(void)
{
	struct List *list;

	if (list = Malloc(sizeof(struct List)))
	{
		NewList(list);
	}
	
	return list;
}



/*********************************************************************

	DeleteList(void)

	free a list

*********************************************************************/

void DeleteList(struct List *list)
{
	if (list)
	{
		struct Node *node;
		while (!IsListEmpty(list))
		{
			if (node = list->lh_Head)
			{
				Remove(node);
				DeleteNode(node);
			}
		}
		Free(list);
	}
}



/*********************************************************************

	list = AllocStringArray(entries)
	create a stringarray with a given number of entries

*********************************************************************/

char **AllocStringArray(int num)
{
	return Malloclear((num + 1) * sizeof(char *));
}



/*********************************************************************

	FreeStringArray(list)
	delete a list of strings

*********************************************************************/

void FreeStringArray(char **list)
{
	if (list)
	{
		char **p = list;
		while(*p)
		{
			Free(*p++);
		}
		Free(list);
	}
}


/*********************************************************************

	list = DupStringArray(list)

	create a duplicate of a stringarray

*********************************************************************/

char **DupStringArray(char **list)
{
	char **newlist = NULL;
	if (list)
	{
		int i, num = 0;
		char **p = list;

		while (*p++) num++;

		if (newlist = AllocStringArray(num))
		{	
			for (i = 0; i < num; ++i)
			{
				if (!(newlist[i] = StrDup(list[i])))
				{
					FreeStringArray(newlist);
					newlist = NULL;
					break;
				}
			}
		}
	}
	
	return newlist;
}


/*********************************************************************

	sl = CreateStringArray(...)

	create a stringarray with given initializers

*********************************************************************/

char **CreateStringArray(char *s, ...)
{
	char **sl;
	char **t;
	int c = 1;
	
	t = &s;
	while (*t++)
	{
		c++;
	}

	if (sl = Malloclear(c * sizeof(char *)))
	{
		int i = 0;
		BOOL success = TRUE;
		t = &s;
		while (*t && success)
		{
			success = !!(sl[i++] = StrDup(*t));
			t++;
		}
		
		if (!success)
		{
			FreeStringArray(sl);
			sl = NULL;
		}
	}

	return sl;
}

/*********************************************************************

	comp = StriCmp(s1, s2)
	
	localized, case-insensitive string comparison,
	handles NULL strings

*********************************************************************/

LONG StriCmp(char *s1, char *s2)
{
	if (s1 && s2)
	{
		return Stricmp(s1, s2);
	}

	if (s1 == NULL && s2 == NULL)
	{
		return 0;
	}
	
	return -1;
}



/*********************************************************************

	count = CountListEntries(list)

	count number of entries in a list

*********************************************************************/

int CountListEntries(struct List *list)
{
	int count = 0;

	if (list)
	{
		if (!IsListEmpty(list))
		{
			struct Node *node;
			struct Node *nextnode;

			node = list->lh_Head;
			while (nextnode = node->ln_Succ)
			{
				count++;
				node = nextnode;
			}
		}
	}

	return count;
}



/*********************************************************************

	stringlist = CreateStringArrayFromList(list)

	create a stringarray from a list

*********************************************************************/

char **CreateStringArrayFromList(struct List *list)
{
	char **array = NULL;

	int count;

	if (count = CountListEntries(list))
	{
		if (array = AllocStringArray(count))
		{
			struct Node *node;
			struct Node *nextnode;
			int i = 0;
			BOOL success = TRUE;

			node = list->lh_Head;
			while ((nextnode = node->ln_Succ) && success)
			{
				success = !!(array[i++] = StrDup(node->ln_Name));
				node = nextnode;
			}
			
			if (!success)
			{
				FreeStringArray(array);
				array = NULL;
			}
		}
	}

	return array;
}

/*********************************************************************

	size = FileSize(filename);

*********************************************************************/

long FileSize(char *filename)
{
	long filesize = -1;

	if (filename)
	{
		BPTR lock;
		if (lock = Lock(filename, ACCESS_READ))
		{
			struct FileInfoBlock *fib;

			if (fib = AllocDosObject(DOS_FIB, NULL))
			{
				if (Examine(lock, fib))
				{
					if (fib->fib_DirEntryType < 0)
					{
						filesize = fib->fib_Size;
					}
				}

				FreeDosObject(DOS_FIB, fib);
			}

			UnLock(lock);	
		}
	}

	return filesize;
}
