/***********************************************************************
gutenfetch - query and fetch electronic texts from Project Gutenberg
Copyright (C) 2001, 2002, 2003 Russell Francis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
Last updated on $Date: 2004/03/21 05:14:18 $ by $Author: johntabularasa $.
***********************************************************************/
#include "stddefs.h"
#include "list.h"
#if (HAVE_ASSERT_H == 1)
# include <assert.h>
#endif
#if (HAVE_STDIO_H == 1)
# include <stdio.h>
#endif
#if (HAVE_STDLIB_H == 1)
# include <stdlib.h>
#endif
#if (HAVE_STRING_H == 1)
# include <string.h>
#endif
#if (HAVE_STRINGS_H == 1)
# include <strings.h>
#endif
/**
* create a list node.
*
* Create a list node to be used only from list.c.
*
* @param data The data to store in the node.
* @return The list node which was created, will never be NULL.
*/
static list_t*
list_make_node(
void *data)
{
list_t *list = (list_t*)malloc(sizeof(list_t));
if (list == NULL) {
fprintf(stderr, _("Unable to allocate %u bytes of memory."),
sizeof(list_t));
abort();
}
list->next = NULL;
list->prev = NULL;
list->data = data;
return list;
}
/**
* add an item to the front of the list.
*
* @param list An element of the list which we wish to add
* the item to.
* @param data The data to prepend to the list.
* @return A valid list node. Will never be NULL.
*/
list_t*
list_prepend(
list_t *list,
void *data)
{
list_t *ret_list = list_make_node( data );
if (list != NULL) {
list = list_first(list);
assert( list->prev == NULL );
list->prev = (list_ptr_t)ret_list;
ret_list->next = (list_ptr_t)list;
}
return ret_list;
}
/**
* Append an item to the list.
*
* @param list A node of the list we wish to append an
* item to.
* @param data The data we wish to append to the list.
* @return A valid list node. This will never be NULL.
*/
list_t*
list_append(
list_t *list,
void *data)
{
list_t *ret_list = list_make_node( data );
if (list != NULL) {
list = list_last(list);
assert ( list->next == NULL );
list->next = (list_ptr_t)ret_list;
ret_list->prev = (list_ptr_t)list;
}
return ret_list;
}
/**
* Get the previous node.
*
* @param list A list node.
* @return The previous node or NULL if none exists.
*/
list_t*
list_previous(
list_t *list)
{
return (list_t*)((list != NULL) ? list->prev : NULL);
}
/**
* Get the next node.
*
* @param list A list node.
* @return The next node or NULL if none exists.
*/
list_t*
list_next(
list_t *list)
{
return (list_t*)((list != NULL) ? list->next : NULL);
}
/**
* Get the first node of the list.
*
* @param list A list node.
* @return The first list node in the list.
*/
list_t*
list_first(list_t *list)
{
if (list == NULL)
return NULL;
if (list->prev == NULL)
return list;
return list_first( (list_t*)list->prev );
}
/**
* Get the last node in the list.
*
* @param list A list node.
* @return The list node in the list.
*/
list_t*
list_last(list_t *list)
{
if (list == NULL)
return NULL;
if (list->next == NULL)
return list;
return list_last( (list_t*)list->next );
}
/**
* Destroy a list
*
* Destroy all nodes in a list and optionally
* call a function to destroy the data held in
* the list node.
*
* @param list The list to obliterate.
* @param data_destroy_func The function to call
* with the list node data as a parameter.
* should free all resources held by data.
*/
void
list_remove_all(
list_t *list,
void (*data_destroy_func)(void*))
{
list_t *last_node;
list = list_first(list);
while (list != NULL) {
if ((list->data != NULL) && (data_destroy_func != NULL))
data_destroy_func(list->data);
last_node = list;
list = (list_t*)list->next;
FREE_NULL(last_node);
}
}
/**
* Remove the node from the list
*
* @param list The node we wish to remove from the list.
* @param data_destroy_func The function to be called to free the data or NULL
* @return A valid node in the list or NULL if the list is empty.
*/
list_t*
list_remove_node(list_t *list, void (*data_destroy_func)(void*))
{
list_t *prev, *next;
if (list == NULL)
return NULL;
if (data_destroy_func != NULL)
data_destroy_func(list->data);
prev = list_previous(list);
next = list_next(list);
FREE_NULL(list);
// update the previous node link
if (prev != NULL) {
prev->next = (list_ptr_t)next;
list = prev;
}
// update the next node link;
if (next != NULL) {
next->prev = (list_ptr_t)prev;
list = next;
}
return list;
}
syntax highlighted by Code2HTML, v. 0.9.1