K&R style braces
[tinc] / lib / list.c
1 /*
2     list.c -- functions to deal with double linked lists
3     Copyright (C) 2000-2005 Ivo Timmermans
4                   2000-2006 Guus Sliepen <guus@tinc-vpn.org>
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$
21 */
22
23 #include "system.h"
24
25 #include "list.h"
26 #include "xalloc.h"
27
28 /* (De)constructors */
29
30 list_t *list_alloc(list_action_t delete) {
31         list_t *list;
32
33         list = xmalloc_and_zero(sizeof(list_t));
34         list->delete = delete;
35
36         return list;
37 }
38
39 void list_free(list_t *list) {
40         free(list);
41 }
42
43 list_node_t *list_alloc_node(void) {
44         return xmalloc_and_zero(sizeof(list_node_t));
45 }
46
47 void list_free_node(list_t *list, list_node_t *node) {
48         if(node->data && list->delete)
49                 list->delete(node->data);
50
51         free(node);
52 }
53
54 /* Insertion and deletion */
55
56 list_node_t *list_insert_head(list_t *list, void *data) {
57         list_node_t *node;
58
59         node = list_alloc_node();
60
61         node->data = data;
62         node->prev = NULL;
63         node->next = list->head;
64         list->head = node;
65
66         if(node->next)
67                 node->next->prev = node;
68         else
69                 list->tail = node;
70
71         list->count++;
72
73         return node;
74 }
75
76 list_node_t *list_insert_tail(list_t *list, void *data) {
77         list_node_t *node;
78
79         node = list_alloc_node();
80
81         node->data = data;
82         node->next = NULL;
83         node->prev = list->tail;
84         list->tail = node;
85
86         if(node->prev)
87                 node->prev->next = node;
88         else
89                 list->head = node;
90
91         list->count++;
92
93         return node;
94 }
95
96 void list_unlink_node(list_t *list, list_node_t *node) {
97         if(node->prev)
98                 node->prev->next = node->next;
99         else
100                 list->head = node->next;
101
102         if(node->next)
103                 node->next->prev = node->prev;
104         else
105                 list->tail = node->prev;
106
107         list->count--;
108 }
109
110 void list_delete_node(list_t *list, list_node_t *node) {
111         list_unlink_node(list, node);
112         list_free_node(list, node);
113 }
114
115 void list_delete_head(list_t *list) {
116         list_delete_node(list, list->head);
117 }
118
119 void list_delete_tail(list_t *list) {
120         list_delete_node(list, list->tail);
121 }
122
123 /* Head/tail lookup */
124
125 void *list_get_head(list_t *list) {
126         if(list->head)
127                 return list->head->data;
128         else
129                 return NULL;
130 }
131
132 void *list_get_tail(list_t *list) {
133         if(list->tail)
134                 return list->tail->data;
135         else
136                 return NULL;
137 }
138
139 /* Fast list deletion */
140
141 void list_delete_list(list_t *list) {
142         list_node_t *node, *next;
143
144         for(node = list->head; node; node = next) {
145                 next = node->next;
146                 list_free_node(list, node);
147         }
148
149         list_free(list);
150 }
151
152 /* Traversing */
153
154 void list_foreach_node(list_t *list, list_action_node_t action) {
155         list_node_t *node, *next;
156
157         for(node = list->head; node; node = next) {
158                 next = node->next;
159                 action(node);
160         }
161 }
162
163 void list_foreach(list_t *list, list_action_t action) {
164         list_node_t *node, *next;
165
166         for(node = list->head; node; node = next) {
167                 next = node->next;
168                 if(node->data)
169                         action(node->data);
170         }
171 }