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