blob: f23686aa36b8d3193bfbd91ef72cb1c43e8a49ac [file] [log] [blame]
willy tarreau12350152005-12-18 01:03:27 +01001/*
2 This File is copied from
3
4 http://www.oreilly.com/catalog/masteralgoc/index.html
5 Mastering Algorithms with C
6 By Kyle Loudon
7 ISBN: 1-56592-453-3
8 Publishd by O'Reilly
9
10 */
11
12/*****************************************************************************
13 * *
14 * -------------------------------- list.c -------------------------------- *
15 * *
16 *****************************************************************************/
17
18#include <stdlib.h>
19#include <string.h>
20
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020021#include <common/config.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020022#include <common/list.h>
willy tarreau12350152005-12-18 01:03:27 +010023
24/*****************************************************************************
25* *
26* ------------------------------- list_init ------------------------------ *
27* *
28*****************************************************************************/
29
30void list_init(List *list, void (*destroy)(void *data)) {
31
Willy Tarreaubaaee002006-06-26 02:48:02 +020032 /*********************************************************************
33 * *
34 * Initialize the list. *
35 * *
36 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010037
Willy Tarreaubaaee002006-06-26 02:48:02 +020038 list->size = 0;
39 list->destroy = destroy;
40 list->head = NULL;
41 list->tail = NULL;
42 return;
willy tarreau12350152005-12-18 01:03:27 +010043} /* end list_init() */
44
45/*****************************************************************************
46 * *
47 * ----------------------------- list_destroy ----------------------------- *
48 * *
49 *****************************************************************************/
50
51void list_destroy(List *list) {
52
Willy Tarreaubaaee002006-06-26 02:48:02 +020053 void *data;
54 int rc;
willy tarreau12350152005-12-18 01:03:27 +010055
Willy Tarreaubaaee002006-06-26 02:48:02 +020056 /*********************************************************************
57 * *
58 * Remove each element. *
59 * *
60 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010061
Willy Tarreaubaaee002006-06-26 02:48:02 +020062 while (list_size(list) > 0) {
willy tarreau12350152005-12-18 01:03:27 +010063
Willy Tarreaubaaee002006-06-26 02:48:02 +020064 rc = list_rem_next(list, NULL, (void **)&data);
willy tarreau12350152005-12-18 01:03:27 +010065
Willy Tarreaubaaee002006-06-26 02:48:02 +020066 if (( rc == 0) && (list->destroy != NULL)) {
willy tarreau12350152005-12-18 01:03:27 +010067
Willy Tarreaubaaee002006-06-26 02:48:02 +020068 /*******************************************************************
69 * *
70 * Call a user-defined function to free dynamically allocated data.*
71 * *
72 *******************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010073
Willy Tarreaubaaee002006-06-26 02:48:02 +020074 list->destroy(data);
75 }/* end if() */
76 }/* end while() */
willy tarreau12350152005-12-18 01:03:27 +010077
Willy Tarreaubaaee002006-06-26 02:48:02 +020078 /**************************************************************************
79 * *
80 * No operations are allowed now, but clear the structure as a precaution.*
81 * *
82 **************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010083
Willy Tarreaubaaee002006-06-26 02:48:02 +020084 memset(list, 0, sizeof(List));
85 return;
willy tarreau12350152005-12-18 01:03:27 +010086} /* void list_destroy(List *list) */
87
88/*****************************************************************************
89 * *
90 * ----------------------------- list_ins_next ---------------------------- *
91 * *
92 *****************************************************************************/
93
94int list_ins_next(List *list, ListElmt *element, const void *data) {
95
Willy Tarreaubaaee002006-06-26 02:48:02 +020096 ListElmt *new_element;
willy tarreau12350152005-12-18 01:03:27 +010097
Willy Tarreaubaaee002006-06-26 02:48:02 +020098 /*********************************************************************
99 * *
100 * Allocate storage for the element. *
101 * *
102 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100103
Willy Tarreaubaaee002006-06-26 02:48:02 +0200104 if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL)
105 return -1;
willy tarreau12350152005-12-18 01:03:27 +0100106
Willy Tarreaubaaee002006-06-26 02:48:02 +0200107 /*********************************************************************
108 * *
109 * Insert the element into the list. *
110 * *
111 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100112
Willy Tarreaubaaee002006-06-26 02:48:02 +0200113 new_element->data = (void *)data;
willy tarreau12350152005-12-18 01:03:27 +0100114
Willy Tarreaubaaee002006-06-26 02:48:02 +0200115 if (element == NULL) {
willy tarreau12350152005-12-18 01:03:27 +0100116
Willy Tarreaubaaee002006-06-26 02:48:02 +0200117 /*************************************************************
118 * *
119 * Handle insertion at the head of the list. *
120 * *
121 *************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100122
Willy Tarreaubaaee002006-06-26 02:48:02 +0200123 if (list_size(list) == 0)
124 list->tail = new_element;
willy tarreau12350152005-12-18 01:03:27 +0100125
Willy Tarreaubaaee002006-06-26 02:48:02 +0200126 new_element->next = list->head;
127 list->head = new_element;
128 }/* end if (element == NULL) */
129 else {
willy tarreau12350152005-12-18 01:03:27 +0100130
Willy Tarreaubaaee002006-06-26 02:48:02 +0200131 /*************************************************************
132 * *
133 * Handle insertion somewhere other than at the head. *
134 * *
135 *************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100136
Willy Tarreaubaaee002006-06-26 02:48:02 +0200137 if (element->next == NULL)
138 list->tail = new_element;
willy tarreau12350152005-12-18 01:03:27 +0100139
Willy Tarreaubaaee002006-06-26 02:48:02 +0200140 new_element->next = element->next;
141 element->next = new_element;
142 }/* end else */
willy tarreau12350152005-12-18 01:03:27 +0100143
Willy Tarreaubaaee002006-06-26 02:48:02 +0200144 /*********************************************************************
145 * *
146 * Adjust the size of the list to account for the inserted element. *
147 * *
148 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100149
Willy Tarreaubaaee002006-06-26 02:48:02 +0200150 list->size++;
151 return 0;
willy tarreau12350152005-12-18 01:03:27 +0100152} /* end list_ins_next() */
153
154/*****************************************************************************
155 * *
156 * ----------------------------- list_rem_next ---------------------------- *
157 * *
158 *****************************************************************************/
159
160int list_rem_next(List *list, ListElmt *element, void **data) {
161
Willy Tarreaubaaee002006-06-26 02:48:02 +0200162 ListElmt *old_element;
willy tarreau12350152005-12-18 01:03:27 +0100163
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164 /*********************************************************************
165 * *
166 * Do not allow removal from an empty list. *
167 * *
168 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100169
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170 if (list_size(list) == 0)
171 return -1;
willy tarreau12350152005-12-18 01:03:27 +0100172
Willy Tarreaubaaee002006-06-26 02:48:02 +0200173 /*********************************************************************
174 * *
175 * Remove the element from the list. *
176 * *
177 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100178
Willy Tarreaubaaee002006-06-26 02:48:02 +0200179 if (element == NULL) {
willy tarreau12350152005-12-18 01:03:27 +0100180
Willy Tarreaubaaee002006-06-26 02:48:02 +0200181 /*************************************************************
182 * *
183 * Handle removal from the head of the list. *
184 * *
185 *************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100186
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187 *data = list->head->data;
188 old_element = list->head;
189 list->head = list->head->next;
willy tarreau12350152005-12-18 01:03:27 +0100190
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191 if (list_size(list) == 1)
192 list->tail = NULL;
193 }/* end if (element == NULL) */
194 else {
willy tarreau12350152005-12-18 01:03:27 +0100195
Willy Tarreaubaaee002006-06-26 02:48:02 +0200196 /*************************************************************
197 * *
198 * Handle removal from somewhere other than the head. *
199 * *
200 *************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100201
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202 if (element->next == NULL)
203 return -1;
willy tarreau12350152005-12-18 01:03:27 +0100204
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205 *data = element->next->data;
206 old_element = element->next;
207 element->next = element->next->next;
willy tarreau12350152005-12-18 01:03:27 +0100208
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209 if (element->next == NULL)
210 list->tail = element;
211 }/* end else */
willy tarreau12350152005-12-18 01:03:27 +0100212
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213 /*********************************************************************
214 * *
215 * Free the storage allocated by the abstract data type. *
216 * *
217 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100218
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 free(old_element);
willy tarreau12350152005-12-18 01:03:27 +0100220
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 /*********************************************************************
222 * *
223 * Adjust the size of the list to account for the removed element. *
224 * *
225 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 list->size--;
228 return 0;
willy tarreau12350152005-12-18 01:03:27 +0100229}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
231/*
232 * Local variables:
233 * c-indent-level: 8
234 * c-basic-offset: 8
235 * End:
236 */