Generalized list and hash handling functions
[tinc] / lib / list.c
1 /*
2     list.c -- functions to deal with double linked lists
3     Copyright (C) 2000 Ivo Timmermans <itimmermans@bigfoot.com>
4                   2000 Guus Sliepen <guus@sliepen.warande.net>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id: list.c,v 1.1 2000/10/20 16:44:32 zarq Exp $
21 */
22
23 #include "config.h"
24
25 #include <string.h>
26
27 #include <error.h>
28 #include <list.h>
29 #include <xalloc.h>
30
31 #include <system.h>
32
33 /*
34   list_new
35
36   Initialize a new list.
37 */
38 list_t *list_new(void)
39 {
40   list_t *list;
41
42   list = xmalloc_and_zero(sizeof(list_t));
43   return list;
44 }
45
46 /*
47   list_delete
48
49   Delete the element pointed to by idx from the list.
50 */
51 list_node_t *list_delete(list_t *list, list_node_t *idx)
52 {
53   list_node_t *res;
54   
55   if(!list)
56     return NULL;
57   if(!idx)
58     return NULL;
59
60   if(list->callbacks->delete != NULL)
61     if(list->callbacks->delete(idx->data))
62       error(ERR_WARNING, N_("List callback[delete] failed for %08lx - freeing anyway"), idx->data);
63   
64   free(idx->data);
65   
66   if(idx->prev == NULL)
67     /* First element in list */
68     {
69       res = idx->next;
70       list->head = idx->next;
71     }
72   if(idx->next == NULL)
73     /* Last element in list */
74     {
75       res = NULL;
76       list->tail = idx->prev;
77     }
78   if(idx->prev != NULL && idx->next != NULL)
79     /* Neither first nor last element */
80     {
81       idx->prev->next = idx->next;
82       idx->next->prev = idx->prev;
83     }
84   if(list->head == NULL)
85     list->tail = NULL;
86   else
87     if(list->tail == NULL)
88       list->head = NULL;
89   free(idx);
90   return res;
91 }
92
93 /*
94   list_forall_nodes
95
96   Call function() on each element in the list.  If this function
97   returns non-zero, the element will be removed from the list.
98 */
99 void list_forall_nodes(list_t *list, int (*function)(void *data))
100 {
101   list_node_t *p;
102   int res;
103   
104   if(!list)       /* no list given */
105     return;
106   if(!function)   /* no function given */
107     return;
108   if(!list->head) /* list is empty */
109     return;
110   for(p = list->head; p != NULL; p = p->next)
111     {
112       res = function(p->data);
113       if(res != 0)
114         p = list_delete(list, p);
115     }
116 }
117
118 /*
119   list_destroy
120
121   Free all datastructures contained in this list.  It uses the delete
122   callback for this list to free each element.
123 */
124 void list_destroy(list_t *list)
125 {
126   if(!list)
127     return;
128   list_destroy_nodes(list);
129   free(list);
130 }
131
132 /*
133   list_append
134
135   Append a new node to the list that points to data.
136 */
137 list_append(list_t *list, void *data)
138 {
139   list_node_t *n;
140
141   n = xmalloc_and_zero(sizeof(list_node_t));
142   n->data = data;
143   n->prev = list->tail;
144   list->tail->next = n;
145   list->tail = n;
146 }