Raw File
1 /*============================================================================
2 epub2txt v2
3 list.c
4 Copyright (c)2000-2020 Kevin Boone, GPL v3.0
5 ============================================================================*/
6
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <memory.h>
11
12 #if !defined(__MACH__)
13 #include <malloc.h>
14 #endif
15
16 #include <pthread.h>
17 #include "list.h"
18
19 typedef struct _ListItem
20 {
21 struct _ListItem *next;
22 void *data;
23 } ListItem;
24
25 struct _List
26 {
27 pthread_mutex_t mutex;
28 ListItemFreeFn free_fn;
29 ListItem *head;
30 };
31
32 /*==========================================================================
33 list_create
34 *==========================================================================*/
35 List *list_create (ListItemFreeFn free_fn)
36 {
37 List *list = malloc (sizeof (List));
38 memset (list, 0, sizeof (List));
39 list->free_fn = free_fn;
40 pthread_mutex_init (&list->mutex, NULL);
41 return list;
42 }
43
44 /*==========================================================================
45 list_create_strings
46 *==========================================================================*/
47 List *list_create_strings (void)
48 {
49 return list_create (free);
50 }
51
52 /*==========================================================================
53 list_destroy
54 *==========================================================================*/
55 void list_destroy (List *self)
56 {
57 if (!self) return;
58
59 pthread_mutex_lock (&self->mutex);
60 ListItem *l = self->head;
61 while (l)
62 {
63 if (self->free_fn)
64 self->free_fn (l->data);
65 ListItem *temp = l;
66 l = l->next;
67 free (temp);
68 }
69
70 pthread_mutex_unlock (&self->mutex);
71 pthread_mutex_destroy (&self->mutex);
72 free (self);
73 }
74
75
76 /*==========================================================================
77 list_prepend
78 Note that the caller must not modify or free the item added to the list. It
79 will remain on the list until free'd by the list itself, by calling
80 the supplied free function
81 *==========================================================================*/
82 void list_prepend (List *self, void *item)
83 {
84 pthread_mutex_lock (&self->mutex);
85 ListItem *i = malloc (sizeof (ListItem));
86 i->data = item;
87 i->next = NULL;
88
89 if (self->head)
90 {
91 i->next = self->head;
92 self->head = i;
93 }
94 else
95 {
96 self->head = i;
97 }
98 pthread_mutex_unlock (&self->mutex);
99 }
100
101
102 /*==========================================================================
103 list_append
104 Note that the caller must not modify or free the item added to the list. It
105 will remain on the list until free'd by the list itself, by calling
106 the supplied free function
107 *==========================================================================*/
108 void list_append (List *self, void *item)
109 {
110 pthread_mutex_lock (&self->mutex);
111 ListItem *i = malloc (sizeof (ListItem));
112 i->data = item;
113 i->next = NULL;
114
115 if (self->head)
116 {
117 ListItem *l = self->head;
118 while (l->next)
119 l = l->next;
120 l->next = i;
121 }
122 else
123 {
124 self->head = i;
125 }
126 pthread_mutex_unlock (&self->mutex);
127 }
128
129
130 /*==========================================================================
131 list_length
132 *==========================================================================*/
133 int list_length (List *self)
134 {
135 if (!self) return 0;
136
137 pthread_mutex_lock (&self->mutex);
138 ListItem *l = self->head;
139 int i = 0;
140 while (l != NULL)
141 {
142 l = l->next;
143 i++;
144 }
145
146 pthread_mutex_unlock (&self->mutex);
147 return i;
148 }
149
150 /*==========================================================================
151 list_get
152 *==========================================================================*/
153 void *list_get (List *self, int index)
154 {
155 if (!self) return NULL;
156
157 pthread_mutex_lock (&self->mutex);
158 ListItem *l = self->head;
159 int i = 0;
160 while (l != NULL && i != index)
161 {
162 l = l->next;
163 i++;
164 }
165 pthread_mutex_unlock (&self->mutex);
166
167 return l->data;
168 }
169
170
171 /*==========================================================================
172 list_dump
173 *==========================================================================*/
174 void list_dump (List *self)
175 {
176 int i, l = list_length (self);
177 for (i = 0; i < l; i++)
178 {
179 const char *s = list_get (self, i);
180 printf ("%s\n", s);
181 }
182 }
183
184
185 /*==========================================================================
186 list_contains
187 *==========================================================================*/
188 BOOL list_contains (List *self, const void *item, ListCompareFn fn)
189 {
190 if (!self) return FALSE;
191 pthread_mutex_lock (&self->mutex);
192 ListItem *l = self->head;
193 BOOL found = FALSE;
194 while (l != NULL && !found)
195 {
196 if (fn (l->data, item) == 0) found = TRUE;
197 l = l->next;
198 }
199 pthread_mutex_unlock (&self->mutex);
200 return found;
201 }
202
203
204 /*==========================================================================
205 list_contains_string
206 *==========================================================================*/
207 BOOL list_contains_string (List *self, const char *item)
208 {
209 return list_contains (self, item, (ListCompareFn)strcmp);
210 }
211
212
213 /*==========================================================================
214 list_remove
215 IMPORTANT -- The "item" argument cannot be a direct reference to an
216 item already in the list. If that items is removed from the list its
217 memory will be freed. The "item" argument will this be an invalid
218 memory reference, and the program will crash. It is necessary
219 to copy the item first.
220 *==========================================================================*/
221 void list_remove (List *self, const void *item, ListCompareFn fn)
222 {
223 if (!self) return;
224 pthread_mutex_lock (&self->mutex);
225 ListItem *l = self->head;
226 ListItem *last_good = NULL;
227 while (l != NULL)
228 {
229 if (fn (l->data, item) == 0)
230 {
231 if (l == self->head)
232 {
233 self->head = l->next; // l-> next might be null
234 }
235 else
236 {
237 if (last_good) last_good->next = l->next;
238 }
239 self->free_fn (l->data);
240 ListItem *temp = l->next;
241 free (l);
242 l = temp;
243 }
244 else
245 {
246 last_good = l;
247 l = l->next;
248 }
249 }
250 pthread_mutex_unlock (&self->mutex);
251 }
252
253 /*==========================================================================
254 list_remove_string
255 *==========================================================================*/
256 void list_remove_string (List *self, const char *item)
257 {
258 list_remove (self, item, (ListCompareFn)strcmp);
259 }
260
261
262 /*==========================================================================
263 list_clone
264 *==========================================================================*/
265 List *list_clone (List *self, ListCopyFn copyFn)
266 {
267 ListItemFreeFn free_fn = self->free_fn;
268 List *new = list_create (free_fn);
269
270 pthread_mutex_lock (&self->mutex);
271 ListItem *l = self->head;
272 while (l != NULL)
273 {
274 void *data = copyFn (l->data);
275 list_append (new, data);
276 l = l->next;
277 }
278 pthread_mutex_unlock (&self->mutex);
279
280 return new;
281 }
282
283
284
285
Generated by GNU Enscript 1.6.6, and GophHub 1.3.