typedef struct _list {
struct _list* plPrev;
struct _list* plNext;
void* p;
} list;
int ListCreate( list *pl ) {
pl->plPrev = pl->plNext = pl;
pl->p = NULL;
return 0;
}
list *ListInsert( list *pl, void *p ) {
list *plNew;
if ( (plNew = (list*)malloc( sizeof( *plNew ))) == NULL )
return NULL;
plNew->p = p;
plNew->plNext = pl;
plNew->plPrev = pl->plPrev;
pl->plPrev = plNew;
plNew->plPrev->plNext = plNew;
return plNew;
}
void ListDelete( list *pl ) {
pl->plPrev->plNext = pl->plNext;
pl->plNext->plPrev = pl->plPrev;
free( pl );
}
void ListDeleteAll( const list *pl ) {
while( pl->plNext->p )
{
free(pl->plNext->p);
ListDelete( pl->plNext );
}
}
------------------------------------------------------------------------
typedef struct psListNode
{
struct psListNode
*next, /**< \internal */
*prev; /**< \internal */
void
*value; /**< \internal */
} PSListNode;
/** \typedef PSListNode
* \brief Typedef for psListNode structure. * \ingroup pslist
*/
/** \struct psList list.h ps/ps.h
* \brief psList structure.
* \ingroup pslist
*/
typedef struct psList
{
PSListNode
*first, /**< \internal */
*last; /**< \internal */
long
numNodes;
PSListDestroyFunc
destroyFunc; /**< \internal */
} PSList;
#include <stdio.h>
#include <stdlib.h>
#include "ps/list.h"
/**
* \brief Allocates and initializes a new PSList.
*
* \param destroyFunc pointer to a function to destroy/free the data
* to be stored in the list. May be set to NULL to indicate that the
* data should not be destroyed (i.e. the list doesn't own the data or
* items are statically allocated, etc.).
*
* \returns a pointer to a new PSList on success or NULL on failure.
* \sa psListFree().
* \ingroup pslist
*/
PSList *
psListAlloc(PSListDestroyFunc destroyFunc)
{
PSList
*tempList;
if((tempList = calloc(1, sizeof(PSList))) != NULL)
tempList->destroyFunc = destroyFunc;
return(tempList);
}
/**
* \brief Frees up a PSList.
*
* Calls the destroyFunc() on each piece of data if not NULL.
*
* \param list pointer to PSList to be freed.
* \returns nothing.
* \sa psListAlloc().
* \ingroup pslist
*/
void
psListFree(PSList *list)
{
PSListNode
*nextNode,
*node;
if(!list)
return;
for(node = list->first; node; node = nextNode)
{
nextNode = node->next;
if(list->destroyFunc)
list->destroyFunc(node->value);
free(node);
}
free(list);
}
/**
* \brief Creates and inserts a new PSListNode into \c list in front of
* \c node.
*
* \param list pointer to PSList in which to insert node.
* \param node pointer to node to insert in front of.
* \param value pointer to data to be stored.
*
* \returns a pointer to the new node on success or NULL on failure.
* \ingroup pslist
*/
PSListNode *
psListInsert(PSList *list, PSListNode *node, void *value)
{
PSListNode
*newNode;
if(!list)
return(NULL);
if((newNode = calloc(1, sizeof(PSListNode))) != NULL)
{
newNode->value = value;
if(node)
{
if(node->prev)
{
newNode->next = node;
newNode->prev = node->prev;
node->prev = newNode;
newNode->prev->next = newNode;
}
else
{
newNode->next = list->first;
if(list->first)
list->first->prev = newNode;
list->first = newNode;
if(!list->last)
list->last = newNode;
}
}
else
{
if(list->last)
{
newNode->prev = list->last;
list->last->next = newNode;
}
list->last = newNode;
if(!list->first)
list->first = newNode;
}
list->numNodes++;
}
return(newNode);
}
/**
* \brief Deletes the specifed \c node (and data) from \c list.
*
* Calls the destroyFunc on the data if not NULL.
*
* \param list pointer to PSList.
* \param node pointer to node to delete.
*
* \returns nothing.
* \ingroup pslist
*/
void
psListDelete(PSList *list, PSListNode *node)
{
if(!list || !node)
return;
if(node->prev)
node->prev->next = node->next;
else
if((list->first = node->next) != NULL)
list->first->prev = NULL;
if(node->next)
node->next->prev = node->prev;
else
if((list->last = node->prev) != NULL)
list->last->next = NULL;
if(list->destroyFunc)
list->destroyFunc(node->value);
list->numNodes--;
free(node);
}
/**
* \brief Gets the first node in \c list.
*
* \param list pointer to PSList.
*
* \returns a pointer to the first node in \c list if the list has a first
* node or NULL if not (the list is empty).
* \ingroup pslist
*/
PSListNode *
psListFirst(PSList *list)
{
if(list)
return(list->first);
return(NULL);
}
/**
* \brief Gets the last node in \c list.
*
* \param list pointer to PSList.
*
* \returns a pointer to the last node in \c list if the list has a last
* node or NULL if not (the list is empty).
* \ingroup pslist
*/
PSListNode *
psListLast(PSList *list)
{
if(list)
return(list->last);
return(NULL);
}
/**
* \brief Gets the next node (following \c node) in \c list.
*
* \param list pointer to PSList.
* \param node pointer to node.
*
* \returns A pointer to the node following \c node if one exists or NULL
* if not (end of list).
* \ingroup pslist
*/
PSListNode *
psListNext(PSList *list, PSListNode *node)
{
if(list && node)
return(node->next);
return(NULL);
}
/**
* \brief Gets the previous node (before \c node) in \c list.
*
* \param list pointer to PSList.
* \param node pointer to node.
*
* \returns A pointer to the node previous to \c node if one exists or NULL
* if not (beginning of list).
* \ingroup pslist
*/
PSListNode *
psListPrev(PSList *list, PSListNode *node)
{
if(list && node)
return(node->prev);
return(NULL);
}
/**
* \brief Gets the number of nodes (items) in \c list.
*
* \param list pointer to PSList.
*
* \returns the number of items in \c list.
* \ingroup pslist
*/
long
psListNumNodes(PSList *list)
{
if(list)
return(list->numNodes);
return(0);
}
/**
* \brief Gets the value stored in \c list at \c node.
*
* \param list pointer to PSList.
* \param node pointer to node from which to retieve data.
*
* \returns the data stored in the specified node.
* \ingroup pslist
*/
void *
psListGetValue(PSList *list, PSListNode *node)
{
if(list && node)
return(node->value);
return(NULL);
}
/**
* \brief Get the nodeNum'th node in \c list.
*
* \returns a pointer to the nodeNum'th node in \c list or NULL if the
* node doesn't exist.
* \ingroup pslist
*/
PSListNode *
psListGetNode(PSList *list, long nodeNum)
{
PSListNode
*node;
if(!list || nodeNum < 0 || nodeNum > list->numNodes)
return(NULL);
node = psListFirst(list);
while(node && --nodeNum)
node = psListNext(list, node);
return(node);
}