22 |
#include <stdlib.h> |
#include <stdlib.h> |
23 |
#include <mem.h> |
#include <mem.h> |
24 |
#include <list.h> |
#include <list.h> |
25 |
|
#include <assert.h> |
26 |
|
|
27 |
struct list_entry { |
struct list_entry { |
28 |
struct list_entry *next; |
struct list_entry *next; |
31 |
|
|
32 |
struct list { |
struct list { |
33 |
size_t count; |
size_t count; |
34 |
struct list_entry *head, *tail, *cur, *next; |
struct list_entry *head, *tail; |
35 |
|
struct iterator *itr; |
36 |
|
}; |
37 |
|
|
38 |
|
struct iterator { |
39 |
|
struct iterator *next; |
40 |
|
LIST *list; |
41 |
|
struct list_entry *cur; |
42 |
}; |
}; |
43 |
|
|
44 |
struct list * |
struct list * |
45 |
list_create() |
list_create() |
46 |
{ |
{ |
47 |
struct list *p = emalloc(sizeof(*p)); |
struct list *p = emalloc(sizeof(*p)); |
48 |
p->head = p->tail = p->cur = p->next = NULL; |
p->head = p->tail = NULL; |
49 |
|
p->itr = NULL; |
50 |
return p; |
return p; |
51 |
} |
} |
52 |
|
|
70 |
*plist = NULL; |
*plist = NULL; |
71 |
} |
} |
72 |
|
|
73 |
void |
void * |
74 |
list_iterate(struct list *list, list_iterator_t itr, void *data) |
iterator_current(ITERATOR *ip) |
75 |
{ |
{ |
76 |
if (!list) |
if (!ip) |
77 |
return; |
return NULL; |
78 |
for (list->cur = list->head; list->cur; list->cur = list->next) { |
return ip->cur ? ip->cur->data : NULL; |
|
list->next = list->cur->next; |
|
|
if (itr(list->cur->data, data)) |
|
|
break; |
|
|
} |
|
79 |
} |
} |
80 |
|
|
81 |
void * |
ITERATOR * |
82 |
list_current(struct list *list) |
iterator_create(LIST *list) |
83 |
{ |
{ |
84 |
|
ITERATOR *itr; |
85 |
|
|
86 |
if (!list) |
if (!list) |
87 |
return NULL; |
return NULL; |
88 |
return list->cur ? list->cur->data : NULL; |
itr = emalloc(sizeof(*itr)); |
89 |
|
itr->list = list; |
90 |
|
itr->cur = NULL; |
91 |
|
itr->next = list->itr; |
92 |
|
list->itr = itr; |
93 |
|
return itr; |
94 |
} |
} |
95 |
|
|
96 |
|
void |
97 |
|
iterator_destroy(ITERATOR **ip) |
98 |
|
{ |
99 |
|
ITERATOR *itr, *prev; |
100 |
|
|
101 |
|
if (!ip || !*ip) |
102 |
|
return; |
103 |
|
for (itr = (*ip)->list->itr, prev = NULL; |
104 |
|
itr; |
105 |
|
prev = itr, itr = itr->next) |
106 |
|
if (*ip == itr) |
107 |
|
break; |
108 |
|
if (itr) { |
109 |
|
if (prev) |
110 |
|
prev->next = itr->next; |
111 |
|
else |
112 |
|
itr->list->itr = itr->next; |
113 |
|
efree(itr); |
114 |
|
*ip = NULL; |
115 |
|
} |
116 |
|
|
117 |
|
} |
118 |
|
|
119 |
void * |
void * |
120 |
list_first(struct list *list) |
iterator_first(ITERATOR *ip) |
121 |
{ |
{ |
122 |
if (!list) |
if (!ip) |
123 |
return NULL; |
return NULL; |
124 |
list->cur = list->head; |
ip->cur = ip->list->head; |
125 |
if (list->cur) |
return iterator_current(ip); |
|
list->next = list->cur->next; |
|
|
return list_current(list); |
|
126 |
} |
} |
127 |
|
|
128 |
void * |
void * |
129 |
list_next(struct list *list) |
iterator_next(ITERATOR *ip) |
130 |
{ |
{ |
131 |
if (!list || !list->next) |
if (!ip || !ip->cur) |
132 |
return NULL; |
return NULL; |
133 |
list->cur = list->next; |
ip->cur = ip->cur->next; |
134 |
if (list->cur) |
return iterator_current(ip); |
|
list->next = list->cur->next; |
|
|
return list_current(list); |
|
135 |
} |
} |
136 |
|
|
137 |
|
static void |
138 |
|
_iterator_advance(ITERATOR *ip, struct list_entry *e) |
139 |
|
{ |
140 |
|
for (; ip; ip = ip->next) |
141 |
|
if (ip->cur == e) |
142 |
|
ip->cur = e->next; |
143 |
|
} |
144 |
|
|
145 |
void * |
void * |
146 |
list_item(struct list *list, size_t n) |
list_item(struct list *list, size_t n) |
147 |
{ |
{ |
166 |
{ |
{ |
167 |
struct list_entry *ep; |
struct list_entry *ep; |
168 |
|
|
169 |
|
assert(list!=NULL); |
170 |
if (!list) |
if (!list) |
171 |
return; |
return; |
172 |
ep = emalloc(sizeof(*ep)); |
ep = emalloc(sizeof(*ep)); |
203 |
} |
} |
204 |
|
|
205 |
void * |
void * |
206 |
list_locate(struct list *list, void *data, list_comp_t cmp) |
list_remove(struct list *list, void *data, list_comp_t cmp) |
207 |
{ |
{ |
208 |
|
struct list_entry *p, *prev; |
209 |
|
|
210 |
if (!list) |
if (!list) |
211 |
return NULL; |
return NULL; |
212 |
|
if (!list->head) |
213 |
|
return NULL; |
214 |
if (!cmp) |
if (!cmp) |
215 |
cmp = cmp_ptr; |
cmp = cmp_ptr; |
216 |
for (list->cur = list->head; list->cur; list->cur = list->cur->next) |
for (p = list->head, prev = NULL; p; prev = p, p = p->next) |
217 |
if (cmp(list->cur->data, data) == 0) |
if (cmp(p->data, data) == 0) |
218 |
break; |
break; |
219 |
return list_current(list); |
_iterator_advance(list->itr, p); |
220 |
} |
if (p == list->head) { |
|
|
|
|
static struct list_entry * |
|
|
_list_remove_item(struct list *list, struct list_entry *item) |
|
|
{ |
|
|
struct list_entry *p = NULL; |
|
|
if (item == list->head) { |
|
221 |
list->head = list->head->next; |
list->head = list->head->next; |
222 |
if (!list->head) |
if (!list->head) |
223 |
list->tail = NULL; |
list->tail = NULL; |
224 |
} else { |
} else |
225 |
for (p = list->head; p && p->next != item; p = p->next) |
prev->next = p->next; |
226 |
; |
|
227 |
p->next = item->next; |
if (p == list->tail) |
228 |
if (item == list->tail) |
list->tail = prev; |
|
list->tail = p; |
|
|
} |
|
229 |
|
|
230 |
efree(item); |
efree(p); |
231 |
list->count--; |
list->count--; |
232 |
return p; |
|
233 |
|
return data; |
234 |
} |
} |
235 |
|
|
236 |
void * |
void |
237 |
list_remove_current(struct list *list) |
list_iterate(struct list *list, list_iterator_t func, void *data) |
238 |
{ |
{ |
239 |
struct list_entry *cur; |
ITERATOR *itr; |
240 |
void *data; |
void *p; |
241 |
|
|
242 |
if (!list || !list->cur) |
if (!list) |
243 |
return NULL; |
return; |
244 |
|
itr = iterator_create(list); |
245 |
cur = list->cur; |
if (!itr) |
246 |
data = cur->data; |
return; |
247 |
if (list->cur == list->head) { |
for (p = iterator_first(itr); p; p = iterator_next(itr)) { |
248 |
list->cur = cur->next; |
if (func(p, data)) |
249 |
_list_remove_item(list, cur); |
break; |
250 |
} else |
} |
251 |
list->cur = _list_remove_item(list, cur); |
iterator_destroy(&itr); |
|
if (list->cur) |
|
|
list->next = list->cur->next; |
|
|
else |
|
|
list->next = NULL; |
|
|
return data; |
|
252 |
} |
} |
253 |
|
|
254 |
void * |
void * |
255 |
list_remove(struct list *list, void *data, list_comp_t cmp) |
list_locate(struct list *list, void *data, list_comp_t cmp) |
256 |
{ |
{ |
257 |
struct list_entry *p; |
struct list_entry *cur; |
|
|
|
258 |
if (!list) |
if (!list) |
259 |
return NULL; |
return NULL; |
|
if (!list->head) |
|
|
return NULL; |
|
260 |
if (!cmp) |
if (!cmp) |
261 |
cmp = cmp_ptr; |
cmp = cmp_ptr; |
262 |
for (p = list->head; p; p = p->next) |
for (cur = list->head; cur; cur = cur->next) |
263 |
if (cmp(p->data, data) == 0) |
if (cmp(cur->data, data) == 0) |
264 |
break; |
break; |
265 |
if (p == list->cur) |
return cur ? cur->data : NULL; |
|
return list_remove_current(list); |
|
|
else if (p) |
|
|
_list_remove_item(list, p); |
|
|
if (list->cur) |
|
|
list->next = list->cur->next; |
|
|
else |
|
|
list->next = NULL; |
|
|
return data; |
|
266 |
} |
} |
267 |
|
|
|
void |
|
|
list_append_list(struct list *a, struct list *b) |
|
|
{ |
|
|
if (a->tail) { |
|
|
a->tail->next = b->head; |
|
|
a->tail = b->tail; |
|
|
} else { |
|
|
a->head = b->head; |
|
|
a->tail = b->tail; |
|
|
} |
|
|
a->count += b->count; |
|
|
|
|
|
b->head = b->tail = b->cur = NULL; |
|
|
} |
|
|
|
|
|
|
|
268 |
|
|