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

/* enums specifying which part of the list to reset to */
enum {	LLIST_HEAD,
		LLIST_TAIL
};


/* single node for the doubly-linked list */
typedef struct LLIST_NODE
{
	struct LLIST_NODE	*next;		/* pointer to next node */
	struct LLIST_NODE	*prev;		/* pointer to previous node */
	void				*data;		/* pointer to data block */
} llist_node;


/* structure containing all information on linked list - do NOT access directly, instead use API calls */
typedef struct LLIST
{
	llist_node	*head;				/* pointer to head node of list */
	llist_node	*tail;				/* pointer to tail node of list */
	llist_node	*current;			/* pointer to current node of list */
	int			elements;			/* number of elements (nodes) in list */
} llist;


/*	llist_init() initialises 'list'.  
 *
 *	llist_init() returns 1 upon successful initialisation, and 0 upon failure.
 */
int llist_init(llist *list);


/*	llist_add_tail() adds a node containing 'data' to the tail of 'list'. 
 *
 *	llist_add_tail() returns 1 upon success, and 0 upon failure.
 */
int llist_add_tail(llist *list, void *data);


/*	llist_add_head() adds a node containing 'data' to the head of 'list'.
 *
 *	llist_add_head() returns 1 upon success, and 0 upon failure.
 */
int llist_add_head(llist *list, void *data);


/*	llist_reset_current() resets the current pointer for 'list' to either
 *	the head of 'list', if 'list_pos' is LLIST_HEAD, or to the tail of
 *	'list', if 'list_pos' is LLIST_TAIL.
 *
 *	llist_reset_current() returns 1 upon success, and 0 upon failure.
 */
int llist_reset_current(llist *list, int list_pos);


/*	llist_get_current() returns a pointer to the data contained by the
 *	current node of 'list', or NULL if 'list' is NULL or empty.
 */
void *llist_get_current(llist *list);


/*	llist_get_elements() returns the number of elements in 'list', or
 *	-1 upon failure.
 */
int llist_get_elements(llist *list);


/*	llist_delete_current() deletes the current node of 'list', making the
 *	new current node point to the node previous to the one deleted.
 *
 *	If 'free_data' is non-zero, then the data block in the node will
 *	be free()d as well.
 *
 *	llist_delete_current() returns 1 upon success, and 0 upon failure.
 */
int llist_delete_current(llist *list, int free_data);


/*	llist_next() moves the current node of 'list' to the next node in the
 *	list.
 *
 *	llist_next() returns 1 upon success, and 0 upon failure.
 */
int llist_next(llist *list);


/*	llist_delete_list() deletes all data associated with 'list', except
 *	for the llist structure itself.
 *
 *	If 'free_data' is non-zero, then the data block in each node will
 *	be free()d as well.
 *
 *	llist_delete_list() returns 1 upon success, and 0 upon failure.
 */	
int llist_delete_list(llist *list, int free_data);

