blob: ae79a0cb92356193e79db2d8e28b92defd23abe3 [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 Tarreau2dd0d472006-06-29 17:53:05 +020021#include <common/list.h>
willy tarreau12350152005-12-18 01:03:27 +010022
23/*****************************************************************************
24* *
25* ------------------------------- list_init ------------------------------ *
26* *
27*****************************************************************************/
28
29void list_init(List *list, void (*destroy)(void *data)) {
30
Willy Tarreaubaaee002006-06-26 02:48:02 +020031 /*********************************************************************
32 * *
33 * Initialize the list. *
34 * *
35 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010036
Willy Tarreaubaaee002006-06-26 02:48:02 +020037 list->size = 0;
38 list->destroy = destroy;
39 list->head = NULL;
40 list->tail = NULL;
41 return;
willy tarreau12350152005-12-18 01:03:27 +010042} /* end list_init() */
43
44/*****************************************************************************
45 * *
46 * ----------------------------- list_destroy ----------------------------- *
47 * *
48 *****************************************************************************/
49
50void list_destroy(List *list) {
51
Willy Tarreaubaaee002006-06-26 02:48:02 +020052 void *data;
53 int rc;
willy tarreau12350152005-12-18 01:03:27 +010054
Willy Tarreaubaaee002006-06-26 02:48:02 +020055 /*********************************************************************
56 * *
57 * Remove each element. *
58 * *
59 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010060
Willy Tarreaubaaee002006-06-26 02:48:02 +020061 while (list_size(list) > 0) {
willy tarreau12350152005-12-18 01:03:27 +010062
Willy Tarreaubaaee002006-06-26 02:48:02 +020063 rc = list_rem_next(list, NULL, (void **)&data);
willy tarreau12350152005-12-18 01:03:27 +010064
Willy Tarreaubaaee002006-06-26 02:48:02 +020065 if (( rc == 0) && (list->destroy != NULL)) {
willy tarreau12350152005-12-18 01:03:27 +010066
Willy Tarreaubaaee002006-06-26 02:48:02 +020067 /*******************************************************************
68 * *
69 * Call a user-defined function to free dynamically allocated data.*
70 * *
71 *******************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010072
Willy Tarreaubaaee002006-06-26 02:48:02 +020073 list->destroy(data);
74 }/* end if() */
75 }/* end while() */
willy tarreau12350152005-12-18 01:03:27 +010076
Willy Tarreaubaaee002006-06-26 02:48:02 +020077 /**************************************************************************
78 * *
79 * No operations are allowed now, but clear the structure as a precaution.*
80 * *
81 **************************************************************************/
willy tarreau12350152005-12-18 01:03:27 +010082
Willy Tarreaubaaee002006-06-26 02:48:02 +020083 memset(list, 0, sizeof(List));
84 return;
willy tarreau12350152005-12-18 01:03:27 +010085} /* void list_destroy(List *list) */
86
87/*****************************************************************************
88 * *
89 * ----------------------------- list_ins_next ---------------------------- *
90 * *
91 *****************************************************************************/
92
93int list_ins_next(List *list, ListElmt *element, const void *data) {
94
Willy Tarreaubaaee002006-06-26 02:48:02 +020095 ListElmt *new_element;
willy tarreau12350152005-12-18 01:03:27 +010096
Willy Tarreaubaaee002006-06-26 02:48:02 +020097 /*********************************************************************
98 * *
99 * Allocate storage for the element. *
100 * *
101 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100102
Willy Tarreaubaaee002006-06-26 02:48:02 +0200103 if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL)
104 return -1;
willy tarreau12350152005-12-18 01:03:27 +0100105
Willy Tarreaubaaee002006-06-26 02:48:02 +0200106 /*********************************************************************
107 * *
108 * Insert the element into the list. *
109 * *
110 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100111
Willy Tarreaubaaee002006-06-26 02:48:02 +0200112 new_element->data = (void *)data;
willy tarreau12350152005-12-18 01:03:27 +0100113
Willy Tarreaubaaee002006-06-26 02:48:02 +0200114 if (element == NULL) {
willy tarreau12350152005-12-18 01:03:27 +0100115
Willy Tarreaubaaee002006-06-26 02:48:02 +0200116 /*************************************************************
117 * *
118 * Handle insertion at the head of the list. *
119 * *
120 *************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100121
Willy Tarreaubaaee002006-06-26 02:48:02 +0200122 if (list_size(list) == 0)
123 list->tail = new_element;
willy tarreau12350152005-12-18 01:03:27 +0100124
Willy Tarreaubaaee002006-06-26 02:48:02 +0200125 new_element->next = list->head;
126 list->head = new_element;
127 }/* end if (element == NULL) */
128 else {
willy tarreau12350152005-12-18 01:03:27 +0100129
Willy Tarreaubaaee002006-06-26 02:48:02 +0200130 /*************************************************************
131 * *
132 * Handle insertion somewhere other than at the head. *
133 * *
134 *************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100135
Willy Tarreaubaaee002006-06-26 02:48:02 +0200136 if (element->next == NULL)
137 list->tail = new_element;
willy tarreau12350152005-12-18 01:03:27 +0100138
Willy Tarreaubaaee002006-06-26 02:48:02 +0200139 new_element->next = element->next;
140 element->next = new_element;
141 }/* end else */
willy tarreau12350152005-12-18 01:03:27 +0100142
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143 /*********************************************************************
144 * *
145 * Adjust the size of the list to account for the inserted element. *
146 * *
147 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100148
Willy Tarreaubaaee002006-06-26 02:48:02 +0200149 list->size++;
150 return 0;
willy tarreau12350152005-12-18 01:03:27 +0100151} /* end list_ins_next() */
152
153/*****************************************************************************
154 * *
155 * ----------------------------- list_rem_next ---------------------------- *
156 * *
157 *****************************************************************************/
158
159int list_rem_next(List *list, ListElmt *element, void **data) {
160
Willy Tarreaubaaee002006-06-26 02:48:02 +0200161 ListElmt *old_element;
willy tarreau12350152005-12-18 01:03:27 +0100162
Willy Tarreaubaaee002006-06-26 02:48:02 +0200163 /*********************************************************************
164 * *
165 * Do not allow removal from an empty list. *
166 * *
167 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169 if (list_size(list) == 0)
170 return -1;
willy tarreau12350152005-12-18 01:03:27 +0100171
Willy Tarreaubaaee002006-06-26 02:48:02 +0200172 /*********************************************************************
173 * *
174 * Remove the element from the list. *
175 * *
176 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100177
Willy Tarreaubaaee002006-06-26 02:48:02 +0200178 if (element == NULL) {
willy tarreau12350152005-12-18 01:03:27 +0100179
Willy Tarreaubaaee002006-06-26 02:48:02 +0200180 /*************************************************************
181 * *
182 * Handle removal from the head of the list. *
183 * *
184 *************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100185
Willy Tarreaubaaee002006-06-26 02:48:02 +0200186 *data = list->head->data;
187 old_element = list->head;
188 list->head = list->head->next;
willy tarreau12350152005-12-18 01:03:27 +0100189
Willy Tarreaubaaee002006-06-26 02:48:02 +0200190 if (list_size(list) == 1)
191 list->tail = NULL;
192 }/* end if (element == NULL) */
193 else {
willy tarreau12350152005-12-18 01:03:27 +0100194
Willy Tarreaubaaee002006-06-26 02:48:02 +0200195 /*************************************************************
196 * *
197 * Handle removal from somewhere other than the head. *
198 * *
199 *************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201 if (element->next == NULL)
202 return -1;
willy tarreau12350152005-12-18 01:03:27 +0100203
Willy Tarreaubaaee002006-06-26 02:48:02 +0200204 *data = element->next->data;
205 old_element = element->next;
206 element->next = element->next->next;
willy tarreau12350152005-12-18 01:03:27 +0100207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208 if (element->next == NULL)
209 list->tail = element;
210 }/* end else */
willy tarreau12350152005-12-18 01:03:27 +0100211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 /*********************************************************************
213 * *
214 * Free the storage allocated by the abstract data type. *
215 * *
216 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100217
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 free(old_element);
willy tarreau12350152005-12-18 01:03:27 +0100219
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 /*********************************************************************
221 * *
222 * Adjust the size of the list to account for the removed element. *
223 * *
224 *********************************************************************/
willy tarreau12350152005-12-18 01:03:27 +0100225
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 list->size--;
227 return 0;
willy tarreau12350152005-12-18 01:03:27 +0100228}
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229
230/*
231 * Local variables:
232 * c-indent-level: 8
233 * c-basic-offset: 8
234 * End:
235 */