f509e216df9bd5f59f9c073390dcf22872725542
[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.2.6 2000/11/22 23:09:38 guus Exp $
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <syslog.h>
28
29 #include <list.h>
30 #include <xalloc.h>
31
32 #include <system.h>
33
34 /*
35   list_new
36
37   Initialize a new list.
38 */
39 list_t *list_new(void)
40 {
41   list_t *list;
42
43   list = xmalloc_and_zero(sizeof(list_t));
44   return list;
45 }
46
47 /*
48   list_delete
49
50   Delete the element pointed to by idx from the list.
51 */
52 void list_delete(list_t *list, list_node_t *idx)
53 {
54   if(!list || !idx)
55     return;
56
57   if(list->callbacks->delete != NULL)
58     if(list->callbacks->delete(idx->data))
59       syslog(LOG_WARNING, _("List callback[delete] failed for %08lx - freeing anyway"), idx->data);
60   
61   free(idx->data);
62   
63   if(idx->prev == NULL)
64     /* First element in list */
65     {
66       list->head = idx->next;
67     }
68   if(idx->next == NULL)
69     /* Last element in list */
70     {
71       list->tail = idx->prev;
72     }
73   if(idx->prev != NULL && idx->next != NULL)
74     /* Neither first nor last element */
75     {
76       idx->prev->next = idx->next;
77       idx->next->prev = idx->prev;
78     }
79   if(list->head == NULL)
80     list->tail = NULL;
81   else
82     if(list->tail == NULL)
83       list->head = NULL;
84
85   free(idx);
86 }
87
88 /*
89   list_forall_nodes
90
91   Call function() on each element in the list.  If this function
92   returns non-zero, the element will be removed from the list.
93 */
94 void list_forall_nodes(list_t *list, int (*function)(void *data))
95 {
96   list_node_t *p, *next;
97   int res;
98   
99   if(!list)       /* no list given */
100     return;
101   if(!function)   /* no function given */
102     return;
103   if(!list->head) /* list is empty */
104     return;
105   for(p = list->head; p != NULL; p = next)
106     {
107       next = p->next;
108       res = function(p->data);
109       if(res != 0)
110         list_delete(list, p);
111     }
112 }
113
114 /*
115   list_destroy
116
117   Free all datastructures contained in this list.  It uses the delete
118   callback for this list to free each element.
119 */
120 void list_destroy(list_t *list)
121 {
122   if(!list)
123     return;
124 /*  list_destroy_nodes(list); */
125   free(list);
126 }
127
128 /*
129   list_append
130
131   Append a new node to the list that points to data.
132 */
133 void list_append(list_t *list, void *data)
134 {
135   list_node_t *n;
136
137   n = xmalloc_and_zero(sizeof(list_node_t));
138   n->data = data;
139   n->prev = list->tail;
140   if(list->tail)
141     list->tail->next = n;
142   list->tail = n;
143 }