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