/*
 * Copyright (c) 2004-2005 Endace Technology Ltd, Hamilton, New Zealand.
 * All rights reserved.
 *
 * This source code is proprietary to Endace Technology Limited and no part
 * of it may be redistributed, published or disclosed except as outlined in
 * the written contract supplied with this product.
 *
 * $Id: list.c 1091 2005-02-09 03:19:21Z koryn $
 */

#include <stdlib.h>
#include "list.h"

list_t * listNew () {
	list_t * list;
	list = (list_t *) malloc (sizeof(list_t));
	list->first = NULL;
	list->last  = NULL;
	list->ptr   = NULL;
	list->size  = 0;
	return list;
}

/* Add an element at the end of the list */
void listAdd (list_t *list, void *elem, int type) {
	list_elem_t *node;
	
	node = (list_elem_t *) malloc (sizeof(list_elem_t));
	node->next = NULL;
	if (list->last != NULL) list->last->next = node;
	else list->first = node;
	node->prev = list->last;
	list->last = node;
	list->size++;
	
	node->type = type;
	node->elem = elem;
}

/* Add an element at the beginning of the list */
void listAddFirst (list_t *list, void *elem, int type) {
	list_elem_t *node;
	
	node = (list_elem_t *) malloc (sizeof(list_elem_t));
	node->prev = NULL;
	if (list->first != NULL) list->first->prev = node;
	else list->last = node;
	node->next = list->first;
	list->first = node;
	list->size++;
	
	node->type = type;
	node->elem = elem;
}

/* Remove first element */
void listRemoveFirst (list_t *list) {
	list_elem_t *aux;
	if (list->size > 0) {
		if (list->ptr == list->first)
			list->ptr = NULL;
		if (list->first->next != NULL) {
			list->first->next->prev = NULL;
			aux = list->first;
			list->first = list->first->next;
			free(aux);
		} else {
			free(list->first);
			list->first = NULL;
			list->last  = NULL;
		}
		list->size--;
	}
}

/* Remove last element */
void listRemoveLast (list_t *list) {
	list_elem_t *aux;
	if (list->size > 0) {
		if (list->ptr == list->last)
			list->ptr = NULL;
		if (list->last->prev != NULL) {
			list->last->prev->next = NULL;
			aux = list->last;
			list->last = list->last->prev;
			free(aux);
		} else {
			free(list->last);
			list->last  = NULL;
			list->first = NULL;
		}
		list->size--;
	}
}

/* Remove element at pointer (ptr) position */
void listRemovePtr (list_t *list) {
	list_elem_t * aux;
	if (list->ptr != NULL) {
		if (list->first == list->ptr) list->first = list->ptr->next;
		if (list->last  == list->ptr) list->last  = list->ptr->prev;
		if (list->ptr->next != NULL) list->ptr->next->prev = list->ptr->prev;
		if (list->ptr->prev != NULL) list->ptr->prev->next = list->ptr->next;
		aux = list->ptr;
		list->ptr = list->ptr->next;
		free(aux);
		(list->size)--;
	}
}

/* Return pointer to first element */
void * listGetFirst (list_t *list) {
	if (list->first != NULL)
		return (list->first->elem);
	else
		return NULL;
}

/* Return type of first element */
int listGetFirstType (list_t *list) {
	if (list->first != NULL)
		return (list->first->type);
	else
		return -1;
}

/* Return pointer to last element */
void * listGetLast (list_t *list) {
	if (list->last != NULL)
		return (list->last->elem);
	else
		return NULL;
}

/* Return type of last element */
int listGetLastType (list_t *list) {
	if (list->last != NULL)
		return (list->last->type);
	else
		return -1;
}

/* Get list size */
int listGetSize (list_t *list) {
	return list->size;
}

/* Move pointer to the beginning */
void listPtrBegin (list_t *list) {
	if (list != NULL) list->ptr = list->first;
}

/* Move pointer one position towards the end */
void listPtrNext (list_t *list) {
	if (list->ptr != NULL) {
		list->ptr = list->ptr->next;
	}
}

/* Get element at pointer */
void * listGetPtrElem (list_t *list) {
	if (list->ptr != NULL)
		return list->ptr->elem;
	else
		return NULL;
}

/* Get element type at pointer */
int listGetPtrType (list_t *list) {
	if (list->ptr != NULL)
		return list->ptr->type;
	else
		return -1;
}

/* Has the list more elements beyond the pointer? */
int listHasMoreElements (list_t *list) {
	if (list != NULL && list->ptr != NULL)
		return 1;
	else
		return 0;
}


