Remove some wrong assert's.
[vsc-common.git] / misc / list.c
1 /*
2  * list.c: Library of miscellaneous stuff for other libvsc* libraries
3  *
4  * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library 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 GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19  */
20
21 #include <stdlib.h>
22
23 #include "../include/libvscmisc/assert.h"
24 #include "../include/libvscmisc/error.h"
25 #include "../include/libvscmisc/list.h"
26
27 /**
28  * Returns the last item from the list.
29  */
30 struct VscList * /* last_item */
31 vsc_list_get_last (struct VscList *list)
32 {
33         struct VscList *item;
34
35         if (list == NULL) {
36                 return NULL;
37         }
38
39         item = list;
40
41         while (item->next != NULL) {
42                 item = item->next;
43         }
44
45         return item;
46 }
47
48 /**
49  * Appends a duplicate of the item to the list.
50  *
51  * If an error occurs then the list is untouched.
52  */
53 void
54 vsc_list_append (struct VscError *error, struct VscList **list,
55                  struct VscList *item,
56                  VscList_DuplicateFunction duplicate_function)
57 {
58         struct VscList *duplicate = NULL;
59
60         VSC__ASSERT (error != NULL);
61         VSC__ASSERT (! error->occured);
62         VSC__ASSERT (item != NULL);
63         VSC__ASSERT (duplicate_function != NULL);
64
65         duplicate = duplicate_function (error, item);
66
67         if (error->occured) {
68                 VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
69                 return;
70         }
71
72         if (*list == NULL) {
73                 *list = duplicate;
74                 return;
75         }
76
77         vsc_list_get_last (*list)->next = duplicate;
78 }
79
80 struct VscList * /* list_duplicate */
81 vsc_list_duplicate (struct VscError *error, const struct VscList *list,
82                     VscList_DuplicateFunction duplicate_function,
83                     VscList_FreeFunction free_function)
84 {
85         struct VscList *item = NULL;
86         struct VscList *list_duplicate = NULL;
87
88         VSC__ASSERT (error != NULL);
89         VSC__ASSERT (! error->occured);
90         VSC__ASSERT (duplicate_function != NULL);
91         VSC__ASSERT (free_function != NULL);
92
93         for (item = (struct VscList *) list; item != NULL; item = item->next) {
94                 vsc_list_append (error, &list_duplicate, item, duplicate_function);
95
96                 if (error->occured) {
97                         VSC__APPEND_ERROR0 (error, VSC__ERROR_CODE__TRACE);
98
99                         vsc_list_free (&list_duplicate, free_function);
100
101                         return NULL;
102                 }
103         }
104
105         return list_duplicate;
106 }
107
108 /**
109  * Looks up an item in the list.
110  *
111  * The first item for that the match function returns TRUE is returned. If no
112  * match occurs NULL is returned.
113  */
114 struct VscList * /* item */
115 vsc_list_lookup (const struct VscList *list,
116                  VscList_MatchFunction match_function, void *match_data)
117 {
118         struct VscList *item = NULL;
119
120         VSC__ASSERT (match_function != NULL);
121
122         for (item = (struct VscList *) list; item != NULL; item = item->next) {
123                 if (match_function (item, match_data)) {
124                         return item;
125                 }
126         }
127
128         return NULL;
129 }
130
131 /**
132  * Removes the item from the list and frees it.
133  *
134  * If the list becomes empty then the pointer to the list is set to NULL.
135  *
136  * If the item is not in the list then the list is untouched.
137  */
138 void
139 vsc_list_remove (struct VscList **list, struct VscList *item,
140                  VscList_FreeFunction free_function)
141 {
142         struct VscList *previous_item = NULL;
143         struct VscList *current_item = NULL;
144
145         VSC__ASSERT (list != NULL);
146         VSC__ASSERT (item != NULL);
147         VSC__ASSERT (free_function != NULL);
148
149         for (current_item = *list; current_item != NULL;
150              current_item = current_item->next) {
151                 if (current_item == item) {
152                         if (previous_item != NULL) {
153                                 previous_item->next = current_item->next;
154                                 current_item->next = NULL;
155
156                                 free_function (&current_item);
157
158                                 return;
159                         } else {
160                                 *list = current_item->next;
161                                 current_item->next = NULL;
162
163                                 free_function (&current_item);
164
165                                 return;
166                         }
167                 }
168
169                 previous_item = current_item;
170         }
171 }
172
173 /**
174  * Recursively frees the list and set the list pointer to NULL.
175  */
176 void
177 vsc_list_free (struct VscList **list, VscList_FreeFunction free_function)
178 {
179         struct VscList *item;
180         struct VscList *next_item;
181
182         VSC__ASSERT (list != NULL);
183         VSC__ASSERT (free_function != NULL);
184
185         if (*list == NULL) {
186                 return;
187         }
188
189         item = *list;
190         *list = NULL;
191
192         do {
193                 next_item = item->next;
194
195                 free_function (&item);
196
197                 item = next_item;
198         } while (item != NULL);
199 }