/*
list.c -- functions to deal with double linked lists
- Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>
- 2000 Guus Sliepen <guus@sliepen.warande.net>
+ Copyright (C) 2000-2003 Ivo Timmermans <ivo@o2w.nl>
+ 2000-2003 Guus Sliepen <guus@sliepen.eu.org>
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
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- $Id: list.c,v 1.1.2.5 2000/11/22 22:18:03 guus Exp $
+ $Id: list.c,v 1.1.2.17 2003/08/28 21:05:09 guus Exp $
*/
-#include "config.h"
+#include "system.h"
-#include <malloc.h>
-#include <string.h>
-#include <syslog.h>
+#include "list.h"
+#include "xalloc.h"
-#include <list.h>
-#include <xalloc.h>
+/* (De)constructors */
-#include <system.h>
+list_t *list_alloc(list_action_t delete)
+{
+ list_t *list;
-/*
- list_new
+ list = xmalloc_and_zero(sizeof(list_t));
+ list->delete = delete;
- Initialize a new list.
-*/
-list_t *list_new(void)
+ return list;
+}
+
+void list_free(list_t *list)
+{
+ free(list);
+}
+
+list_node_t *list_alloc_node(void)
+{
+ return xmalloc_and_zero(sizeof(list_node_t));
+}
+
+void list_free_node(list_t *list, list_node_t *node)
{
- list_t *list;
+ if(node->data && list->delete)
+ list->delete(node->data);
- list = xmalloc_and_zero(sizeof(list_t));
- return list;
+ free(node);
}
-/*
- list_delete
+/* Insertion and deletion */
- Delete the element pointed to by idx from the list.
-*/
-void list_delete(list_t *list, list_node_t *idx)
+list_node_t *list_insert_head(list_t *list, void *data)
{
- if(!list || !idx)
- return;
-
- if(list->callbacks->delete != NULL)
- if(list->callbacks->delete(idx->data))
- syslog(LOG_WARNING, _("List callback[delete] failed for %08lx - freeing anyway"), idx->data);
-
- free(idx->data);
-
- if(idx->prev == NULL)
- /* First element in list */
- {
- list->head = idx->next;
- }
- if(idx->next == NULL)
- /* Last element in list */
- {
- list->tail = idx->prev;
- }
- if(idx->prev != NULL && idx->next != NULL)
- /* Neither first nor last element */
- {
- idx->prev->next = idx->next;
- idx->next->prev = idx->prev;
- }
- if(list->head == NULL)
- list->tail = NULL;
- else
- if(list->tail == NULL)
- list->head = NULL;
-
- free(idx);
+ list_node_t *node;
+
+ node = list_alloc_node();
+
+ node->data = data;
+ node->prev = NULL;
+ node->next = list->head;
+ list->head = node;
+
+ if(node->next)
+ node->next->prev = node;
+ else
+ list->tail = node;
+
+ list->count++;
+
+ return node;
}
-/*
- list_forall_nodes
+list_node_t *list_insert_tail(list_t *list, void *data)
+{
+ list_node_t *node;
- Call function() on each element in the list. If this function
- returns non-zero, the element will be removed from the list.
-*/
-void list_forall_nodes(list_t *list, int (*function)(void *data))
+ node = list_alloc_node();
+
+ node->data = data;
+ node->next = NULL;
+ node->prev = list->tail;
+ list->tail = node;
+
+ if(node->prev)
+ node->prev->next = node;
+ else
+ list->head = node;
+
+ list->count++;
+
+ return node;
+}
+
+void list_unlink_node(list_t *list, list_node_t *node)
+{
+ if(node->prev)
+ node->prev->next = node->next;
+ else
+ list->head = node->next;
+
+ if(node->next)
+ node->next->prev = node->prev;
+ else
+ list->tail = node->prev;
+
+ list->count--;
+}
+
+void list_delete_node(list_t *list, list_node_t *node)
{
- list_node_t *p, *next;
- int res;
-
- if(!list) /* no list given */
- return;
- if(!function) /* no function given */
- return;
- if(!list->head) /* list is empty */
- return;
- for(p = list->head; p != NULL; p = next)
- {
- next = p->next;
- res = function(p->data);
- if(res != 0)
- list_delete(list, p);
- }
+ list_unlink_node(list, node);
+ list_free_node(list, node);
}
-/*
- list_destroy
+void list_delete_head(list_t *list)
+{
+ list_delete_node(list, list->head);
+}
- Free all datastructures contained in this list. It uses the delete
- callback for this list to free each element.
-*/
-void list_destroy(list_t *list)
+void list_delete_tail(list_t *list)
{
- if(!list)
- return;
-/* list_destroy_nodes(list); */
- free(list);
+ list_delete_node(list, list->tail);
}
-/*
- list_append
+/* Head/tail lookup */
- Append a new node to the list that points to data.
-*/
-void list_append(list_t *list, void *data)
+void *list_get_head(list_t *list)
+{
+ if(list->head)
+ return list->head->data;
+ else
+ return NULL;
+}
+
+void *list_get_tail(list_t *list)
+{
+ if(list->tail)
+ return list->tail->data;
+ else
+ return NULL;
+}
+
+/* Fast list deletion */
+
+void list_delete_list(list_t *list)
+{
+ list_node_t *node, *next;
+
+ for(node = list->head; node; node = next) {
+ next = node->next;
+ list_free_node(list, node);
+ }
+
+ list_free(list);
+}
+
+/* Traversing */
+
+void list_foreach_node(list_t *list, list_action_node_t action)
{
- list_node_t *n;
-
- n = xmalloc_and_zero(sizeof(list_node_t));
- n->data = data;
- n->prev = list->tail;
- if(list->tail)
- list->tail->next = n;
- list->tail = n;
+ list_node_t *node, *next;
+
+ for(node = list->head; node; node = next) {
+ next = node->next;
+ action(node);
+ }
+}
+
+void list_foreach(list_t *list, list_action_t action)
+{
+ list_node_t *node, *next;
+
+ for(node = list->head; node; node = next) {
+ next = node->next;
+ if(node->data)
+ action(node->data);
+ }
}