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 |
|
int advanced; |
43 |
}; |
}; |
44 |
|
|
45 |
struct list * |
struct list * |
46 |
list_create() |
list_create() |
47 |
{ |
{ |
48 |
struct list *p = xmalloc(sizeof(*p)); |
struct list *p = xmalloc(sizeof(*p)); |
49 |
p->head = p->tail = p->cur = p->next = NULL; |
p->head = p->tail = NULL; |
50 |
|
p->itr = NULL; |
51 |
return p; |
return p; |
52 |
} |
} |
53 |
|
|
64 |
struct list_entry *next = p->next; |
struct list_entry *next = p->next; |
65 |
if (user_free) |
if (user_free) |
66 |
user_free(p->data, data); |
user_free(p->data, data); |
67 |
free(p); |
xfree(p); |
68 |
p = next; |
p = next; |
69 |
} |
} |
70 |
free(*plist); |
xfree(*plist); |
71 |
*plist = NULL; |
*plist = NULL; |
72 |
} |
} |
73 |
|
|
74 |
void |
void * |
75 |
list_iterate(struct list *list, list_iterator_t itr, void *data) |
iterator_current(ITERATOR *ip) |
76 |
{ |
{ |
77 |
if (!list) |
if (!ip) |
78 |
return; |
return NULL; |
79 |
for (list->cur = list->head; list->cur; list->cur = list->next) { |
return ip->cur ? ip->cur->data : NULL; |
|
list->next = list->cur->next; |
|
|
itr(list->cur->data, data); |
|
|
} |
|
80 |
} |
} |
81 |
|
|
82 |
void * |
ITERATOR * |
83 |
list_current(struct list *list) |
iterator_create(LIST *list) |
84 |
{ |
{ |
85 |
|
ITERATOR *itr; |
86 |
|
|
87 |
if (!list) |
if (!list) |
88 |
return NULL; |
return NULL; |
89 |
return list->cur ? list->cur->data : NULL; |
itr = xmalloc(sizeof(*itr)); |
90 |
|
itr->list = list; |
91 |
|
itr->cur = NULL; |
92 |
|
itr->next = list->itr; |
93 |
|
itr->advanced = 0; |
94 |
|
list->itr = itr; |
95 |
|
return itr; |
96 |
} |
} |
97 |
|
|
98 |
|
void |
99 |
|
iterator_destroy(ITERATOR **ip) |
100 |
|
{ |
101 |
|
ITERATOR *itr, *prev; |
102 |
|
|
103 |
|
if (!ip || !*ip) |
104 |
|
return; |
105 |
|
for (itr = (*ip)->list->itr, prev = NULL; |
106 |
|
itr; |
107 |
|
prev = itr, itr = itr->next) |
108 |
|
if (*ip == itr) |
109 |
|
break; |
110 |
|
if (itr) { |
111 |
|
if (prev) |
112 |
|
prev->next = itr->next; |
113 |
|
else |
114 |
|
itr->list->itr = itr->next; |
115 |
|
xfree(itr); |
116 |
|
*ip = NULL; |
117 |
|
} |
118 |
|
|
119 |
|
} |
120 |
|
|
121 |
void * |
void * |
122 |
list_first(struct list *list) |
iterator_first(ITERATOR *ip) |
123 |
{ |
{ |
124 |
if (!list) |
if (!ip) |
125 |
return NULL; |
return NULL; |
126 |
list->cur = list->head; |
ip->cur = ip->list->head; |
127 |
if (list->cur) |
ip->advanced = 0; |
128 |
list->next = list->cur->next; |
return iterator_current(ip); |
|
return list_current(list); |
|
129 |
} |
} |
130 |
|
|
131 |
void * |
void * |
132 |
list_next(struct list *list) |
iterator_next(ITERATOR *ip) |
133 |
{ |
{ |
134 |
if (!list || !list->next) |
if (!ip || !ip->cur) |
135 |
return NULL; |
return NULL; |
136 |
list->cur = list->next; |
if (!ip->advanced) |
137 |
if (list->cur) |
ip->cur = ip->cur->next; |
138 |
list->next = list->cur->next; |
ip->advanced = 0; |
139 |
return list_current(list); |
return iterator_current(ip); |
140 |
} |
} |
141 |
|
|
142 |
|
static void |
143 |
|
_iterator_advance(ITERATOR *ip, struct list_entry *e) |
144 |
|
{ |
145 |
|
for (; ip; ip = ip->next) { |
146 |
|
if (ip->cur == e) { |
147 |
|
ip->cur = e->next; |
148 |
|
ip->advanced++; |
149 |
|
} |
150 |
|
} |
151 |
|
} |
152 |
|
|
153 |
void * |
void * |
154 |
list_item(struct list *list, size_t n) |
list_item(struct list *list, size_t n) |
155 |
{ |
{ |
206 |
static int |
static int |
207 |
cmp_ptr(void *a, void *b) |
cmp_ptr(void *a, void *b) |
208 |
{ |
{ |
209 |
return a == b; |
return a != b; |
210 |
} |
} |
211 |
|
|
212 |
void * |
void * |
213 |
list_locate(struct list *list, void *data, list_comp_t cmp) |
list_remove(struct list *list, void *data, list_comp_t cmp) |
214 |
{ |
{ |
215 |
|
struct list_entry *p, *prev; |
216 |
|
|
217 |
if (!list) |
if (!list) |
218 |
return NULL; |
return NULL; |
219 |
|
if (!list->head) |
220 |
|
return NULL; |
221 |
if (!cmp) |
if (!cmp) |
222 |
cmp = cmp_ptr; |
cmp = cmp_ptr; |
223 |
for (list->cur = list->head; list->cur; list->cur = list->cur->next) |
for (p = list->head, prev = NULL; p; prev = p, p = p->next) |
224 |
if (cmp(list->cur->data, data) == 0) |
if (cmp(p->data, data) == 0) |
225 |
break; |
break; |
226 |
return list_current(list); |
|
227 |
} |
if (!p) |
228 |
|
return 0; |
229 |
static struct list_entry * |
_iterator_advance(list->itr, p); |
230 |
_list_remove_item(struct list *list, struct list_entry *item) |
if (p == list->head) { |
|
{ |
|
|
struct list_entry *p = NULL; |
|
|
if (item == list->head) { |
|
231 |
list->head = list->head->next; |
list->head = list->head->next; |
232 |
if (!list->head) |
if (!list->head) |
233 |
list->tail = NULL; |
list->tail = NULL; |
234 |
} else { |
} else |
235 |
for (p = list->head; p && p->next != item; p = p->next) |
prev->next = p->next; |
236 |
; |
|
237 |
p->next = item->next; |
if (p == list->tail) |
238 |
if (item == list->tail) |
list->tail = prev; |
239 |
list->tail = p; |
|
240 |
} |
xfree(p); |
|
|
|
|
free(item); |
|
241 |
list->count--; |
list->count--; |
242 |
return p; |
|
243 |
|
return data; |
244 |
} |
} |
245 |
|
|
246 |
void * |
void |
247 |
list_remove_current(struct list *list) |
list_iterate(struct list *list, list_iterator_t func, void *data) |
248 |
{ |
{ |
249 |
struct list_entry *cur; |
ITERATOR *itr; |
250 |
void *data; |
void *p; |
251 |
|
|
252 |
if (!list || !list->cur) |
if (!list) |
253 |
return NULL; |
return; |
254 |
|
itr = iterator_create(list); |
255 |
cur = list->cur; |
if (!itr) |
256 |
data = cur->data; |
return; |
257 |
if (list->cur == list->head) { |
for (p = iterator_first(itr); p; p = iterator_next(itr)) { |
258 |
list->cur = cur->next; |
if (func(p, data)) |
259 |
_list_remove_item(list, cur); |
break; |
260 |
} else |
} |
261 |
list->cur = _list_remove_item(list, cur); |
iterator_destroy(&itr); |
|
return data; |
|
262 |
} |
} |
263 |
|
|
264 |
void * |
void * |
265 |
list_remove(struct list *list, void *data, list_comp_t cmp) |
list_locate(struct list *list, void *data, list_comp_t cmp) |
266 |
{ |
{ |
267 |
struct list_entry *p; |
struct list_entry *cur; |
|
|
|
268 |
if (!list) |
if (!list) |
269 |
return NULL; |
return NULL; |
|
if (!list->head) |
|
|
return NULL; |
|
270 |
if (!cmp) |
if (!cmp) |
271 |
cmp = cmp_ptr; |
cmp = cmp_ptr; |
272 |
for (p = list->head; p; p = p->next) |
for (cur = list->head; cur; cur = cur->next) |
273 |
if (cmp(p->data, data) == 0) |
if (cmp(cur->data, data) == 0) |
274 |
break; |
break; |
275 |
if (p == list->cur) |
return cur ? cur->data : NULL; |
|
return list_remove_current(list); |
|
|
else |
|
|
_list_remove_item(list, p); |
|
|
return data; |
|
|
} |
|
|
|
|
|
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; |
|
276 |
} |
} |
277 |
|
|
278 |
/* EOF */ |
/* EOF */ |