#if !defined(PS_LIST_H)
#define PS_LIST_H

/** \file psList.h
 *  \brief Support for doubly linked lists
 *  \ingroup DataGroup
 */

/** Doubly-linked list element */
typedef struct psListElem {
   struct psListElem *prev;		///< previous link in list
   struct psListElem *next;		///< next link in list
   void *data;				///< real data item
} psListElem;

/** Doubly-linked list */
typedef struct {
   unsigned int size;			///< number of elements on list
   psListElem *head;			///< first element on list (may be NULL)
   psListElem *tail;			///< last element on list (may be NULL)
   psListElem *iter;			///< iteration cursor
   unsigned int iterIndex;		///< the numeric position of the iteration cursor in the list
   pthread_mutex_t lock;		///< mutex to lock a node during changes
} psList;

/** Special values of index into list */
enum {
   PS_LIST_HEAD = 0,			///< at head
   PS_LIST_TAIL = -1,			///< at tail
   PS_LIST_UNKNOWN = -2,		///< unknown position
   PS_LIST_PREV = -3,			///< previous element
   PS_LIST_NEXT = -4			///< next element
};

/** Functions **************************************************************/
/** \addtogroup DataGroup General Data Container Utilities  
 *  \{
 */

/** Constructor */
psList *psListAlloc(void *data)		///< initial data item; may be NULL
;

/**** List maintainence functions ****/

/** Add to list */
bool *psListAdd(psList *list,		///< list to add to (may be NULL)
		int location,		///< index, PS_LIST_HEAD, or PS_LIST_TAIL
		void *data)		///< data item to add
;

/** Remove from a list */
bool *psListRemove(psList *list,	///< list to remove element from
		   int location,	///< index of item, or PS_LIST_UNKNOWN, PS_LIST_NEXT, PS_LIST_PREV
		   void *data)		///< data item to remove
;

/** Retrieve from a list */
void *psListGet(const psList *list,	///< list to retrieve element from
		int location)		///< index of item, or PS_LIST_NEXT, PS_LIST_PREV, PS_LIST_UNKNOWN
;

/** Convert doubly-linked list to an array of (void *) */
psArray *psListToArray(psList *list)	///< List to convert
;

/** Convert array to a doubly-linked list */
psList *psArrayToList(psArray *array) ///< array of (void *) to convert
;

/** Sort a list. */
psList *psListSort(psList *list,	///< List to sort
		   int (*compare)(const void **a, const void **b) // Function to compare two list elements
    );

/** Set the iterator */
void psListSetIterator(psList *list,	///< list to retrieve element from
		       int iterator,	///< the desired iterator
		       int location)	///< index, PS_LIST_HEAD, or PS_LIST_TAIL
;

/** Get next element relative to iter */
void *psListGetNext(psList *list,	///< list to retrieve element from
		    int iterator)	///< the desired iterator
;

/** Get prev element relative to iter */
void *psListGetPrevious(psList *list,	///< list to retrieve element from
			int iterator)	///< the desired iterator
;

/* \} */ // End of DataGroup Functions

#endif
