- Changed list routines to give it the same look'n'feel as the rbl and
[tinc] / lib / list.c
index 5358f19..d317622 100644 (file)
     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 2000/10/20 16:44:32 zarq Exp $
+    $Id: list.c,v 1.1.2.7 2001/01/07 15:24:52 guus Exp $
 */
 
 #include "config.h"
 
-#include <string.h>
+#include <stdlib.h>
 
-#include <error.h>
-#include <list.h>
 #include <xalloc.h>
-
 #include <system.h>
 
-/*
-  list_new
+#include "list.h"
 
-  Initialize a new list.
-*/
-list_t *list_new(void)
+/* (De)constructors */
+
+list_t *list_alloc(list_action_t delete)
 {
   list_t *list;
 
   list = xmalloc_and_zero(sizeof(list_t));
+  list->delete = delete;
+
   return list;
 }
 
-/*
-  list_delete
+void list_free(list_t *list)
+{
+  free(list);
+}
 
-  Delete the element pointed to by idx from the list.
-*/
-list_node_t *list_delete(list_t *list, list_node_t *idx)
+list_node_t *list_alloc_node(void)
 {
-  list_node_t *res;
+  list_node_t *node;
   
-  if(!list)
-    return NULL;
-  if(!idx)
-    return NULL;
+  node = xmalloc_and_zero(sizeof(list_node_t));
+  
+  return node;
+}
+
+void list_free_node(list_t *list, list_node_t *node)
+{
+  if(node->data && list->delete)
+    list->delete(node->data);
+  
+  free(node->data);
+}
+
+/* Insertion and deletion */
 
-  if(list->callbacks->delete != NULL)
-    if(list->callbacks->delete(idx->data))
-      error(ERR_WARNING, N_("List callback[delete] failed for %08lx - freeing anyway"), idx->data);
+list_node_t *list_insert_head(list_t *list, void *data)
+{
+  list_node_t *node;
   
-  free(idx->data);
+  node = list_alloc_node();
   
-  if(idx->prev == NULL)
-    /* First element in list */
-    {
-      res = idx->next;
-      list->head = idx->next;
-    }
-  if(idx->next == NULL)
-    /* Last element in list */
-    {
-      res = NULL;
-      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;
+  node->data = data;
+  node->prev = NULL;
+  node->next = list->head;
+  list->head = node;
+  
+  if(node->next)
+    node->next->prev = node;
   else
-    if(list->tail == NULL)
-      list->head = NULL;
-  free(idx);
-  return res;
+    list->tail = node;
+
+  return node;
 }
 
-/*
-  list_forall_nodes
+list_node_t *list_insert_tail(list_t *list, void *data)
+{
+  list_node_t *node;
+  
+  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;
 
-  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))
+  return node;
+}
+
+void list_unlink_node(list_t *list, list_node_t *node)
 {
-  list_node_t *p;
-  int res;
+  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;
+}
+
+void list_delete_node(list_t *list, list_node_t *node)
+{
+  list_unlink_node(list, node);
+  list_free_node(list, node);
+}
+
+void list_delete_head(list_t *list)
+{
+  list_delete_node(list, list->head);
+}
+
+void list_delete_tail(list_t *list)
+{
+  list_delete_node(list, list->tail);
+}
+
+/* Head/tail lookup */
+
+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;
   
-  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 = p->next)
+  for(node = list->head; node; node = next)
     {
-      res = function(p->data);
-      if(res != 0)
-       p = list_delete(list, p);
+      next = node->next;
+      list_free_node(list, node);
     }
+
+  list_free(list);
 }
 
-/*
-  list_destroy
+/* Traversing */
 
-  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_foreach_node(list_t *list, list_action_node_t action)
 {
-  if(!list)
-    return;
-  list_destroy_nodes(list);
-  free(list);
-}
+  list_node_t *node, *next;
 
-/*
-  list_append
+  for(node = list->head; node; node = next)
+    {
+      next = node->next;
+      action(node);
+    }
+}
 
-  Append a new node to the list that points to data.
-*/
-list_append(list_t *list, void *data)
+void list_foreach(list_t *list, list_action_t action)
 {
-  list_node_t *n;
+  list_node_t *node, *next;
 
-  n = xmalloc_and_zero(sizeof(list_node_t));
-  n->data = data;
-  n->prev = list->tail;
-  list->tail->next = n;
-  list->tail = n;
+  for(node = list->head; node; node = next)
+    {
+      next = node->next;
+      if(node->data)
+        action(node->data);
+    }
 }