Implement new list functions.
* include/mailutils/list.h (_mu_list_ptr_comparator) (mu_list_insert_list, mu_list_append_list) (mu_list_prepend_list): New prototypes. * libproto/include/list0.h (_mu_list_insert_sublist): New prototype. * mailbox/listlist.c: New function. * mailbox/Makefile.am (libmailutils_la_SOURCES): Add listlist.c. * mailbox/list.c: Remove unnecessary parentheses. (def_comp): Rename to _mu_list_ptr_comparator. Remove static qualifier. All uses updated. (_insert_item): Remove. (mu_list_insert): Use _mu_list_insert_sublist instead of _insert_item. * examples/listop.c (print): Print number of elements. (count): New function. (ins): Use mu_list_insert if only one new element was given, mu_list_insert_list otherwise. (help): Update. (main)<count>: New keyword. * mailbox/testsuite/mailbox/list.exp: Update. Add new tests.
Showing
7 changed files
with
326 additions
and
96 deletions
... | @@ -44,13 +44,20 @@ void | ... | @@ -44,13 +44,20 @@ void |
44 | print (mu_list_t list) | 44 | print (mu_list_t list) |
45 | { | 45 | { |
46 | mu_iterator_t itr; | 46 | mu_iterator_t itr; |
47 | size_t count; | ||
47 | int rc; | 48 | int rc; |
48 | 49 | ||
49 | rc = mu_list_get_iterator (list, &itr); | 50 | rc = mu_list_get_iterator (list, &itr); |
50 | if (rc) | 51 | if (rc) |
51 | lperror ("mu_list_get_iterator", rc); | 52 | lperror ("mu_list_get_iterator", rc); |
52 | 53 | ||
53 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) | 54 | rc = mu_list_count (list, &count); |
55 | if (rc) | ||
56 | lperror ("mu_iterator_current", rc); | ||
57 | |||
58 | printf ("# items: %lu\n", (unsigned long) count); | ||
59 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); | ||
60 | mu_iterator_next (itr)) | ||
54 | { | 61 | { |
55 | char *text; | 62 | char *text; |
56 | 63 | ||
... | @@ -63,6 +70,19 @@ print (mu_list_t list) | ... | @@ -63,6 +70,19 @@ print (mu_list_t list) |
63 | } | 70 | } |
64 | 71 | ||
65 | void | 72 | void |
73 | count (mu_list_t list) | ||
74 | { | ||
75 | size_t n; | ||
76 | int rc; | ||
77 | |||
78 | rc = mu_list_count (list, &n); | ||
79 | if (rc) | ||
80 | lperror ("mu_iterator_current", rc); | ||
81 | else | ||
82 | printf ("%lu\n", (unsigned long) n); | ||
83 | } | ||
84 | |||
85 | void | ||
66 | next (mu_iterator_t itr, char *arg) | 86 | next (mu_iterator_t itr, char *arg) |
67 | { | 87 | { |
68 | int skip = arg ? strtoul (arg, NULL, 0) : 1; | 88 | int skip = arg ? strtoul (arg, NULL, 0) : 1; |
... | @@ -130,41 +150,75 @@ prep (mu_list_t list, int argc, char **argv) | ... | @@ -130,41 +150,75 @@ prep (mu_list_t list, int argc, char **argv) |
130 | } | 150 | } |
131 | } | 151 | } |
132 | 152 | ||
153 | static int | ||
154 | read_list (mu_list_t list, int argc, char **argv) | ||
155 | { | ||
156 | int rc; | ||
157 | |||
158 | for (; argc; argc--, argv++) | ||
159 | { | ||
160 | rc = mu_list_append (list, strdup (*argv)); | ||
161 | if (rc) | ||
162 | break; | ||
163 | } | ||
164 | return rc; | ||
165 | } | ||
166 | |||
133 | void | 167 | void |
134 | ins (mu_list_t list, int argc, char **argv) | 168 | ins (mu_list_t list, int argc, char **argv) |
135 | { | 169 | { |
170 | int an; | ||
136 | int rc; | 171 | int rc; |
137 | char *item; | 172 | char *item; |
138 | char *new_item; | 173 | int insert_before = 0; |
139 | 174 | ||
140 | if (argc < 3 || argc > 4) | 175 | if (argc < 3) |
141 | { | 176 | { |
142 | fprintf (stderr, "ins [before] item new_item?\n"); | 177 | fprintf (stderr, "ins [before] item new_item [new_item*]?\n"); |
143 | return; | 178 | return; |
144 | } | 179 | } |
145 | 180 | ||
146 | if (argc == 4) | 181 | an = 1; |
182 | if (strcmp (argv[1], "before") == 0) | ||
147 | { | 183 | { |
148 | if (strcmp (argv[1], "before")) | 184 | an++; |
149 | { | 185 | insert_before = 1; |
150 | fprintf (stderr, "ins before item new_item?\n"); | ||
151 | return; | ||
152 | } | ||
153 | |||
154 | item = argv[2]; | ||
155 | new_item = argv[3]; | ||
156 | } | 186 | } |
157 | else | 187 | else if (strcmp (argv[1], "after") == 0) |
158 | { | 188 | { |
159 | item = argv[1]; | 189 | an++; |
160 | new_item = argv[2]; | 190 | insert_before = 0; |
161 | } | 191 | } |
192 | |||
193 | item = argv[an++]; | ||
162 | 194 | ||
163 | rc = mu_list_insert (list, item, strdup (new_item), argc == 4); | 195 | if (an + 1 == argc) |
196 | rc = mu_list_insert (list, item, strdup (argv[an]), insert_before); | ||
197 | else | ||
198 | { | ||
199 | mu_list_t tmp; | ||
200 | |||
201 | rc = mu_list_create (&tmp); | ||
202 | if (rc) | ||
203 | { | ||
204 | fprintf (stderr, "creating temp list: %s\n", mu_strerror (rc)); | ||
205 | return; | ||
206 | } | ||
207 | |||
208 | rc = read_list (tmp, argc - an, argv + an); | ||
209 | if (rc) | ||
210 | { | ||
211 | fprintf (stderr, "reading temp list: %s\n", mu_strerror (rc)); | ||
212 | return; | ||
213 | } | ||
214 | rc = mu_list_insert_list (list, item, tmp, insert_before); | ||
215 | mu_list_destroy (&tmp); | ||
216 | } | ||
217 | |||
164 | if (rc) | 218 | if (rc) |
165 | fprintf (stderr, "mu_list_insert: %s\n", mu_strerror (rc)); | 219 | lperror ("mu_list_insert", rc); |
166 | } | 220 | } |
167 | 221 | ||
168 | 222 | ||
169 | void | 223 | void |
170 | repl (mu_list_t list, int argc, char **argv) | 224 | repl (mu_list_t list, int argc, char **argv) |
... | @@ -232,14 +286,15 @@ find (mu_iterator_t itr, char *arg) | ... | @@ -232,14 +286,15 @@ find (mu_iterator_t itr, char *arg) |
232 | void | 286 | void |
233 | help () | 287 | help () |
234 | { | 288 | { |
289 | printf ("count\n"); | ||
235 | printf ("next [count]\n"); | 290 | printf ("next [count]\n"); |
236 | printf ("first\n"); | 291 | printf ("first\n"); |
237 | printf ("find item\n"); | 292 | printf ("find item\n"); |
238 | printf ("del item [item...]\n"); | 293 | printf ("del item [item*]\n"); |
239 | printf ("add item [item...]\n"); | 294 | printf ("add item [item*]\n"); |
240 | printf ("prep item [item...]\n"); | 295 | printf ("prep item [item*]\n"); |
241 | printf ("repl old_item new_item\n"); | 296 | printf ("repl old_item new_item\n"); |
242 | printf ("ins [before] item new_item\n"); | 297 | printf ("ins [before|after] item new_item [new_item*]\n"); |
243 | printf ("print\n"); | 298 | printf ("print\n"); |
244 | printf ("quit\n"); | 299 | printf ("quit\n"); |
245 | printf ("iter num\n"); | 300 | printf ("iter num\n"); |
... | @@ -285,7 +340,9 @@ shell (mu_list_t list) | ... | @@ -285,7 +340,9 @@ shell (mu_list_t list) |
285 | 340 | ||
286 | if (argc > 0) | 341 | if (argc > 0) |
287 | { | 342 | { |
288 | if (strcmp (argv[0], "next") == 0) | 343 | if (strcmp (argv[0], "count") == 0) |
344 | count (list); | ||
345 | else if (strcmp (argv[0], "next") == 0) | ||
289 | next (itr[num], argv[1]); | 346 | next (itr[num], argv[1]); |
290 | else if (strcmp (argv[0], "first") == 0) | 347 | else if (strcmp (argv[0], "first") == 0) |
291 | mu_iterator_first (itr[num]); | 348 | mu_iterator_first (itr[num]); | ... | ... |
... | @@ -41,12 +41,14 @@ extern int mu_list_to_array (mu_list_t list, void **array, size_t count, size_t | ... | @@ -41,12 +41,14 @@ extern int mu_list_to_array (mu_list_t list, void **array, size_t count, size_t |
41 | extern int mu_list_locate (mu_list_t list, void *item, void **ret_item); | 41 | extern int mu_list_locate (mu_list_t list, void *item, void **ret_item); |
42 | extern int mu_list_get_iterator (mu_list_t, mu_iterator_t *); | 42 | extern int mu_list_get_iterator (mu_list_t, mu_iterator_t *); |
43 | 43 | ||
44 | typedef int mu_list_action_t (void* item, void* cbdata); | 44 | typedef int mu_list_action_t (void *item, void *cbdata); |
45 | 45 | ||
46 | extern int mu_list_do (mu_list_t list, mu_list_action_t * action, void *cbdata); | 46 | extern int mu_list_do (mu_list_t list, mu_list_action_t *action, void *cbdata); |
47 | 47 | ||
48 | typedef int (*mu_list_comparator_t) (const void*, const void*); | 48 | typedef int (*mu_list_comparator_t) (const void*, const void*); |
49 | 49 | ||
50 | extern int _mu_list_ptr_comparator (const void*, const void*); | ||
51 | |||
50 | extern mu_list_comparator_t mu_list_set_comparator (mu_list_t, | 52 | extern mu_list_comparator_t mu_list_set_comparator (mu_list_t, |
51 | mu_list_comparator_t); | 53 | mu_list_comparator_t); |
52 | extern int mu_list_get_comparator (mu_list_t, mu_list_comparator_t *); | 54 | extern int mu_list_get_comparator (mu_list_t, mu_list_comparator_t *); |
... | @@ -59,6 +61,11 @@ extern int mu_list_intersect_dup (mu_list_t *, mu_list_t, mu_list_t, | ... | @@ -59,6 +61,11 @@ extern int mu_list_intersect_dup (mu_list_t *, mu_list_t, mu_list_t, |
59 | int (*dup_item) (void **, void *, void *), | 61 | int (*dup_item) (void **, void *, void *), |
60 | void *); | 62 | void *); |
61 | extern int mu_list_intersect (mu_list_t *, mu_list_t, mu_list_t); | 63 | extern int mu_list_intersect (mu_list_t *, mu_list_t, mu_list_t); |
64 | |||
65 | extern int mu_list_insert_list (mu_list_t list, void *item, mu_list_t new_list, | ||
66 | int insert_before); | ||
67 | extern void mu_list_append_list (mu_list_t list, mu_list_t new_list); | ||
68 | extern void mu_list_prepend_list (mu_list_t list, mu_list_t new_list); | ||
62 | 69 | ||
63 | #ifdef __cplusplus | 70 | #ifdef __cplusplus |
64 | } | 71 | } | ... | ... |
... | @@ -51,6 +51,12 @@ struct _mu_list | ... | @@ -51,6 +51,12 @@ struct _mu_list |
51 | struct _mu_iterator *itr; | 51 | struct _mu_iterator *itr; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | extern void _mu_list_insert_sublist (mu_list_t list, | ||
55 | struct list_data *current, | ||
56 | struct list_data *head, | ||
57 | struct list_data *tail, | ||
58 | size_t count, | ||
59 | int insert_before); | ||
54 | 60 | ||
55 | #ifdef __cplusplus | 61 | #ifdef __cplusplus |
56 | } | 62 | } | ... | ... |
... | @@ -40,14 +40,14 @@ mu_list_create (mu_list_t *plist) | ... | @@ -40,14 +40,14 @@ mu_list_create (mu_list_t *plist) |
40 | list = calloc (sizeof (*list), 1); | 40 | list = calloc (sizeof (*list), 1); |
41 | if (list == NULL) | 41 | if (list == NULL) |
42 | return ENOMEM; | 42 | return ENOMEM; |
43 | status = mu_monitor_create (&(list->monitor), 0, list); | 43 | status = mu_monitor_create (&list->monitor, 0, list); |
44 | if (status != 0) | 44 | if (status != 0) |
45 | { | 45 | { |
46 | free (list); | 46 | free (list); |
47 | return status; | 47 | return status; |
48 | } | 48 | } |
49 | list->head.next = &(list->head); | 49 | list->head.next = &list->head; |
50 | list->head.prev = &(list->head); | 50 | list->head.prev = &list->head; |
51 | *plist = list; | 51 | *plist = list; |
52 | return 0; | 52 | return 0; |
53 | } | 53 | } |
... | @@ -62,7 +62,7 @@ mu_list_destroy (mu_list_t *plist) | ... | @@ -62,7 +62,7 @@ mu_list_destroy (mu_list_t *plist) |
62 | struct list_data *previous; | 62 | struct list_data *previous; |
63 | 63 | ||
64 | mu_monitor_wrlock (list->monitor); | 64 | mu_monitor_wrlock (list->monitor); |
65 | for (current = list->head.next; current != &(list->head);) | 65 | for (current = list->head.next; current != &list->head;) |
66 | { | 66 | { |
67 | previous = current; | 67 | previous = current; |
68 | current = current->next; | 68 | current = current->next; |
... | @@ -71,7 +71,7 @@ mu_list_destroy (mu_list_t *plist) | ... | @@ -71,7 +71,7 @@ mu_list_destroy (mu_list_t *plist) |
71 | free (previous); | 71 | free (previous); |
72 | } | 72 | } |
73 | mu_monitor_unlock (list->monitor); | 73 | mu_monitor_unlock (list->monitor); |
74 | mu_monitor_destroy (&(list->monitor), list); | 74 | mu_monitor_destroy (&list->monitor, list); |
75 | free (list); | 75 | free (list); |
76 | *plist = NULL; | 76 | *plist = NULL; |
77 | } | 77 | } |
... | @@ -91,7 +91,7 @@ mu_list_append (mu_list_t list, void *item) | ... | @@ -91,7 +91,7 @@ mu_list_append (mu_list_t list, void *item) |
91 | return ENOMEM; | 91 | return ENOMEM; |
92 | ldata->item = item; | 92 | ldata->item = item; |
93 | mu_monitor_wrlock (list->monitor); | 93 | mu_monitor_wrlock (list->monitor); |
94 | ldata->next = &(list->head); | 94 | ldata->next = &list->head; |
95 | ldata->prev = list->head.prev; | 95 | ldata->prev = list->head.prev; |
96 | last->next = ldata; | 96 | last->next = ldata; |
97 | list->head.prev = ldata; | 97 | list->head.prev = ldata; |
... | @@ -114,7 +114,7 @@ mu_list_prepend (mu_list_t list, void *item) | ... | @@ -114,7 +114,7 @@ mu_list_prepend (mu_list_t list, void *item) |
114 | return ENOMEM; | 114 | return ENOMEM; |
115 | ldata->item = item; | 115 | ldata->item = item; |
116 | mu_monitor_wrlock (list->monitor); | 116 | mu_monitor_wrlock (list->monitor); |
117 | ldata->prev = &(list->head); | 117 | ldata->prev = &list->head; |
118 | ldata->next = list->head.next; | 118 | ldata->next = list->head.next; |
119 | first->prev = ldata; | 119 | first->prev = ldata; |
120 | list->head.next = ldata; | 120 | list->head.next = ldata; |
... | @@ -164,8 +164,8 @@ mu_list_get_comparator (mu_list_t list, mu_list_comparator_t *comp) | ... | @@ -164,8 +164,8 @@ mu_list_get_comparator (mu_list_t list, mu_list_comparator_t *comp) |
164 | return 0; | 164 | return 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | static int | 167 | int |
168 | def_comp (const void *item, const void *value) | 168 | _mu_list_ptr_comparator (const void *item, const void *value) |
169 | { | 169 | { |
170 | return item != value; | 170 | return item != value; |
171 | } | 171 | } |
... | @@ -179,10 +179,10 @@ mu_list_locate (mu_list_t list, void *item, void **ret_item) | ... | @@ -179,10 +179,10 @@ mu_list_locate (mu_list_t list, void *item, void **ret_item) |
179 | 179 | ||
180 | if (list == NULL) | 180 | if (list == NULL) |
181 | return EINVAL; | 181 | return EINVAL; |
182 | comp = list->comp ? list->comp : def_comp; | 182 | comp = list->comp ? list->comp : _mu_list_ptr_comparator; |
183 | mu_monitor_wrlock (list->monitor); | 183 | mu_monitor_wrlock (list->monitor); |
184 | for (previous = &(list->head), current = list->head.next; | 184 | for (previous = &list->head, current = list->head.next; |
185 | current != &(list->head); previous = current, current = current->next) | 185 | current != &list->head; previous = current, current = current->next) |
186 | { | 186 | { |
187 | if (comp (current->item, item) == 0) | 187 | if (comp (current->item, item) == 0) |
188 | { | 188 | { |
... | @@ -196,43 +196,6 @@ mu_list_locate (mu_list_t list, void *item, void **ret_item) | ... | @@ -196,43 +196,6 @@ mu_list_locate (mu_list_t list, void *item, void **ret_item) |
196 | return status; | 196 | return status; |
197 | } | 197 | } |
198 | 198 | ||
199 | static int | ||
200 | _insert_item(mu_list_t list, struct list_data *current, void *new_item, | ||
201 | int insert_before) | ||
202 | { | ||
203 | struct list_data *ldata = calloc (sizeof (*ldata), 1); | ||
204 | if (ldata == NULL) | ||
205 | return ENOMEM; | ||
206 | |||
207 | ldata->item = new_item; | ||
208 | if (insert_before) | ||
209 | { | ||
210 | ldata->prev = current->prev; | ||
211 | ldata->next = current; | ||
212 | if (current->prev != &list->head) | ||
213 | current->prev->next = ldata; | ||
214 | else | ||
215 | list->head.next = ldata; | ||
216 | |||
217 | current->prev = ldata; | ||
218 | } | ||
219 | else | ||
220 | { | ||
221 | ldata->next = current->next; | ||
222 | ldata->prev = current; | ||
223 | |||
224 | if (current->next != &list->head) | ||
225 | current->next->prev = ldata; | ||
226 | else | ||
227 | list->head.prev = ldata; | ||
228 | |||
229 | current->next = ldata; | ||
230 | } | ||
231 | |||
232 | list->count++; | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | int | 199 | int |
237 | mu_list_insert (mu_list_t list, void *item, void *new_item, int insert_before) | 200 | mu_list_insert (mu_list_t list, void *item, void *new_item, int insert_before) |
238 | { | 201 | { |
... | @@ -242,16 +205,27 @@ mu_list_insert (mu_list_t list, void *item, void *new_item, int insert_before) | ... | @@ -242,16 +205,27 @@ mu_list_insert (mu_list_t list, void *item, void *new_item, int insert_before) |
242 | 205 | ||
243 | if (list == NULL) | 206 | if (list == NULL) |
244 | return EINVAL; | 207 | return EINVAL; |
245 | comp = list->comp ? list->comp : def_comp; | 208 | comp = list->comp ? list->comp : _mu_list_ptr_comparator; |
246 | 209 | ||
247 | mu_monitor_wrlock (list->monitor); | 210 | mu_monitor_wrlock (list->monitor); |
248 | for (current = list->head.next; | 211 | for (current = list->head.next; |
249 | current != &(list->head); | 212 | current != &list->head; |
250 | current = current->next) | 213 | current = current->next) |
251 | { | 214 | { |
252 | if (comp (current->item, item) == 0) | 215 | if (comp (current->item, item) == 0) |
253 | { | 216 | { |
254 | status = _insert_item (list, current, new_item, insert_before); | 217 | struct list_data *ldata = calloc (sizeof (*ldata), 1); |
218 | if (ldata == NULL) | ||
219 | status = ENOMEM; | ||
220 | else | ||
221 | { | ||
222 | ldata->item = new_item; | ||
223 | _mu_list_insert_sublist (list, current, | ||
224 | ldata, ldata, | ||
225 | 1, | ||
226 | insert_before); | ||
227 | status = 0; | ||
228 | } | ||
255 | break; | 229 | break; |
256 | } | 230 | } |
257 | } | 231 | } |
... | @@ -268,10 +242,10 @@ mu_list_remove (mu_list_t list, void *item) | ... | @@ -268,10 +242,10 @@ mu_list_remove (mu_list_t list, void *item) |
268 | 242 | ||
269 | if (list == NULL) | 243 | if (list == NULL) |
270 | return EINVAL; | 244 | return EINVAL; |
271 | comp = list->comp ? list->comp : def_comp; | 245 | comp = list->comp ? list->comp : _mu_list_ptr_comparator; |
272 | mu_monitor_wrlock (list->monitor); | 246 | mu_monitor_wrlock (list->monitor); |
273 | for (previous = &(list->head), current = list->head.next; | 247 | for (previous = &list->head, current = list->head.next; |
274 | current != &(list->head); previous = current, current = current->next) | 248 | current != &list->head; previous = current, current = current->next) |
275 | { | 249 | { |
276 | if (comp (current->item, item) == 0) | 250 | if (comp (current->item, item) == 0) |
277 | { | 251 | { |
... | @@ -297,10 +271,10 @@ mu_list_replace (mu_list_t list, void *old_item, void *new_item) | ... | @@ -297,10 +271,10 @@ mu_list_replace (mu_list_t list, void *old_item, void *new_item) |
297 | 271 | ||
298 | if (list == NULL) | 272 | if (list == NULL) |
299 | return EINVAL; | 273 | return EINVAL; |
300 | comp = list->comp ? list->comp : def_comp; | 274 | comp = list->comp ? list->comp : _mu_list_ptr_comparator; |
301 | mu_monitor_wrlock (list->monitor); | 275 | mu_monitor_wrlock (list->monitor); |
302 | for (previous = &(list->head), current = list->head.next; | 276 | for (previous = &list->head, current = list->head.next; |
303 | current != &(list->head); previous = current, current = current->next) | 277 | current != &list->head; previous = current, current = current->next) |
304 | { | 278 | { |
305 | if (comp (current->item, old_item) == 0) | 279 | if (comp (current->item, old_item) == 0) |
306 | { | 280 | { |
... | @@ -325,7 +299,7 @@ mu_list_get (mu_list_t list, size_t indx, void **pitem) | ... | @@ -325,7 +299,7 @@ mu_list_get (mu_list_t list, size_t indx, void **pitem) |
325 | if (pitem == NULL) | 299 | if (pitem == NULL) |
326 | return MU_ERR_OUT_PTR_NULL; | 300 | return MU_ERR_OUT_PTR_NULL; |
327 | mu_monitor_rdlock (list->monitor); | 301 | mu_monitor_rdlock (list->monitor); |
328 | for (current = list->head.next, count = 0; current != &(list->head); | 302 | for (current = list->head.next, count = 0; current != &list->head; |
329 | current = current->next, count++) | 303 | current = current->next, count++) |
330 | { | 304 | { |
331 | if (count == indx) | 305 | if (count == indx) |
... | @@ -340,7 +314,7 @@ mu_list_get (mu_list_t list, size_t indx, void **pitem) | ... | @@ -340,7 +314,7 @@ mu_list_get (mu_list_t list, size_t indx, void **pitem) |
340 | } | 314 | } |
341 | 315 | ||
342 | int | 316 | int |
343 | mu_list_do (mu_list_t list, mu_list_action_t * action, void *cbdata) | 317 | mu_list_do (mu_list_t list, mu_list_action_t *action, void *cbdata) |
344 | { | 318 | { |
345 | mu_iterator_t itr; | 319 | mu_iterator_t itr; |
346 | int status = 0; | 320 | int status = 0; |
... | @@ -350,7 +324,8 @@ mu_list_do (mu_list_t list, mu_list_action_t * action, void *cbdata) | ... | @@ -350,7 +324,8 @@ mu_list_do (mu_list_t list, mu_list_action_t * action, void *cbdata) |
350 | status = mu_list_get_iterator(list, &itr); | 324 | status = mu_list_get_iterator(list, &itr); |
351 | if (status) | 325 | if (status) |
352 | return status; | 326 | return status; |
353 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); mu_iterator_next (itr)) | 327 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); |
328 | mu_iterator_next (itr)) | ||
354 | { | 329 | { |
355 | void *item; | 330 | void *item; |
356 | mu_iterator_current (itr, &item); | 331 | mu_iterator_current (itr, &item); |
... | @@ -386,7 +361,7 @@ mu_list_to_array (mu_list_t list, void **array, size_t count, size_t *pcount) | ... | @@ -386,7 +361,7 @@ mu_list_to_array (mu_list_t list, void **array, size_t count, size_t *pcount) |
386 | struct list_data *current; | 361 | struct list_data *current; |
387 | 362 | ||
388 | for (i = 0, current = list->head.next; | 363 | for (i = 0, current = list->head.next; |
389 | i < total && current != &(list->head); current = current->next) | 364 | i < total && current != &list->head; current = current->next) |
390 | array[i++] = current->item; | 365 | array[i++] = current->item; |
391 | } | 366 | } |
392 | if (pcount) | 367 | if (pcount) |
... | @@ -394,15 +369,15 @@ mu_list_to_array (mu_list_t list, void **array, size_t count, size_t *pcount) | ... | @@ -394,15 +369,15 @@ mu_list_to_array (mu_list_t list, void **array, size_t count, size_t *pcount) |
394 | return 0; | 369 | return 0; |
395 | } | 370 | } |
396 | 371 | ||
397 | /* Computes an intersection of the two lists. The resulting list, | 372 | /* Computes an intersection of two lists and returns it in PDEST. |
398 | stored into PDEST, contains elements from the list A that are | 373 | The resulting list contains elements from A that are |
399 | also encountered in the list B, using the comparison function of | 374 | also encountered in B (as per comparison function of |
400 | the latter. | 375 | the latter). |
401 | 376 | ||
402 | If DUP_ITEM is not NULL, it is used to create copies of the | 377 | If DUP_ITEM is not NULL, it is used to create copies of |
403 | items to be stored in PDEST. In this case, the destroy_item | 378 | items to be stored in PDEST. In this case, the destroy_item |
404 | function of B is also attached to PDEST. Otherwise, if | 379 | function of B is also attached to PDEST. Otherwise, if |
405 | DUP_ITEM is NULL, the pointers to the elements are stored and | 380 | DUP_ITEM is NULL, pointers to elements are stored and |
406 | no destroy_item function is assigned. */ | 381 | no destroy_item function is assigned. */ |
407 | int | 382 | int |
408 | mu_list_intersect_dup (mu_list_t *pdest, mu_list_t a, mu_list_t b, | 383 | mu_list_intersect_dup (mu_list_t *pdest, mu_list_t a, mu_list_t b, | ... | ... |
mailbox/listlist.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2010 Free | ||
3 | Software Foundation, Inc. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 3 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General | ||
16 | Public License along with this library; if not, write to the | ||
17 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | Boston, MA 02110-1301 USA */ | ||
19 | |||
20 | #ifdef HAVE_CONFIG_H | ||
21 | # include <config.h> | ||
22 | #endif | ||
23 | |||
24 | #include <errno.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <string.h> | ||
27 | |||
28 | #include <list0.h> | ||
29 | #include <iterator0.h> | ||
30 | #include <mailutils/errno.h> | ||
31 | |||
32 | void | ||
33 | _mu_list_insert_sublist (mu_list_t list, | ||
34 | struct list_data *current, | ||
35 | struct list_data *head, | ||
36 | struct list_data *tail, | ||
37 | size_t count, | ||
38 | int insert_before) | ||
39 | { | ||
40 | if (insert_before) | ||
41 | { | ||
42 | head->prev = current->prev; | ||
43 | tail->next = current; | ||
44 | if (current->prev != &list->head) | ||
45 | current->prev->next = head; | ||
46 | else | ||
47 | list->head.next = head; | ||
48 | |||
49 | current->prev = tail; | ||
50 | } | ||
51 | else | ||
52 | { | ||
53 | tail->next = current->next; | ||
54 | head->prev = current; | ||
55 | if (current->next != &list->head) | ||
56 | current->next->prev = tail; | ||
57 | else | ||
58 | list->head.prev = tail; | ||
59 | |||
60 | current->next = head; | ||
61 | } | ||
62 | list->count += count; | ||
63 | } | ||
64 | |||
65 | static void | ||
66 | clear_list (mu_list_t list) | ||
67 | { | ||
68 | list->head.next = list->head.prev = &list->head; | ||
69 | list->count = 0; | ||
70 | } | ||
71 | |||
72 | int | ||
73 | mu_list_insert_list (mu_list_t list, void *item, mu_list_t new_list, | ||
74 | int insert_before) | ||
75 | { | ||
76 | struct list_data *current; | ||
77 | mu_list_comparator_t comp; | ||
78 | int status = MU_ERR_NOENT; | ||
79 | |||
80 | if (list == NULL) | ||
81 | return EINVAL; | ||
82 | comp = list->comp ? list->comp : _mu_list_ptr_comparator; | ||
83 | |||
84 | mu_monitor_wrlock (list->monitor); | ||
85 | for (current = list->head.next; | ||
86 | current != &list->head; | ||
87 | current = current->next) | ||
88 | { | ||
89 | if (comp (current->item, item) == 0) | ||
90 | { | ||
91 | _mu_list_insert_sublist (list, current, | ||
92 | new_list->head.next, new_list->head.prev, | ||
93 | new_list->count, | ||
94 | insert_before); | ||
95 | clear_list (new_list); | ||
96 | status = 0; | ||
97 | break; | ||
98 | } | ||
99 | } | ||
100 | mu_monitor_unlock (list->monitor); | ||
101 | return status; | ||
102 | } | ||
103 | |||
104 | void | ||
105 | mu_list_append_list (mu_list_t list, mu_list_t new_list) | ||
106 | { | ||
107 | if (list->count == 0) | ||
108 | { | ||
109 | list->head = new_list->head; | ||
110 | list->count = new_list->count; | ||
111 | } | ||
112 | else | ||
113 | _mu_list_insert_sublist (list, list->head.prev, | ||
114 | new_list->head.next, new_list->head.prev, | ||
115 | new_list->count, | ||
116 | 0); | ||
117 | clear_list (new_list); | ||
118 | } | ||
119 | |||
120 | void | ||
121 | mu_list_prepend_list (mu_list_t list, mu_list_t new_list) | ||
122 | { | ||
123 | if (list->count == 0) | ||
124 | { | ||
125 | list->head = new_list->head; | ||
126 | list->count = new_list->count; | ||
127 | } | ||
128 | else | ||
129 | _mu_list_insert_sublist (list, list->head.next, | ||
130 | new_list->head.next, new_list->head.prev, | ||
131 | new_list->count, | ||
132 | 1); | ||
133 | clear_list (new_list); | ||
134 | } | ||
135 | |||
136 | |||
137 |
... | @@ -50,6 +50,7 @@ mailbox_prog_start "${top_builddir}/examples/listop" | ... | @@ -50,6 +50,7 @@ mailbox_prog_start "${top_builddir}/examples/listop" |
50 | 50 | ||
51 | mailbox_prog_command "add en to tre fire fem" | 51 | mailbox_prog_command "add en to tre fire fem" |
52 | mailbox_prog_test "print" \ | 52 | mailbox_prog_test "print" \ |
53 | "# items: 5" \ | ||
53 | "en" \ | 54 | "en" \ |
54 | "to" \ | 55 | "to" \ |
55 | "tre" \ | 56 | "tre" \ |
... | @@ -78,6 +79,7 @@ prompt_iterator 0 | ... | @@ -78,6 +79,7 @@ prompt_iterator 0 |
78 | prompt_text "fem" | 79 | prompt_text "fem" |
79 | mailbox_prog_test "iter 0" | 80 | mailbox_prog_test "iter 0" |
80 | mailbox_prog_test "print" \ | 81 | mailbox_prog_test "print" \ |
82 | "# items: 3" \ | ||
81 | "en" \ | 83 | "en" \ |
82 | "to" \ | 84 | "to" \ |
83 | "fem" | 85 | "fem" |
... | @@ -85,6 +87,7 @@ mailbox_prog_test "print" \ | ... | @@ -85,6 +87,7 @@ mailbox_prog_test "print" \ |
85 | mailbox_prog_command "prep jeden dwa trzy cztery" | 87 | mailbox_prog_command "prep jeden dwa trzy cztery" |
86 | 88 | ||
87 | mailbox_prog_test "print" \ | 89 | mailbox_prog_test "print" \ |
90 | "# items: 7" \ | ||
88 | "cztery" \ | 91 | "cztery" \ |
89 | "trzy" \ | 92 | "trzy" \ |
90 | "dwa" \ | 93 | "dwa" \ |
... | @@ -110,6 +113,7 @@ mailbox_prog_test "next 2" | ... | @@ -110,6 +113,7 @@ mailbox_prog_test "next 2" |
110 | 113 | ||
111 | mailbox_prog_command "ins jeden un" | 114 | mailbox_prog_command "ins jeden un" |
112 | mailbox_prog_test "print" \ | 115 | mailbox_prog_test "print" \ |
116 | "# items: 7" \ | ||
113 | "3" \ | 117 | "3" \ |
114 | "dwa" \ | 118 | "dwa" \ |
115 | "jeden" \ | 119 | "jeden" \ |
... | @@ -120,6 +124,7 @@ mailbox_prog_test "print" \ | ... | @@ -120,6 +124,7 @@ mailbox_prog_test "print" \ |
120 | 124 | ||
121 | mailbox_prog_command "ins before jeden zero" | 125 | mailbox_prog_command "ins before jeden zero" |
122 | mailbox_prog_test "print" \ | 126 | mailbox_prog_test "print" \ |
127 | "# items: 8" \ | ||
123 | "3" \ | 128 | "3" \ |
124 | "dwa" \ | 129 | "dwa" \ |
125 | "zero" \ | 130 | "zero" \ |
... | @@ -136,6 +141,7 @@ mailbox_prog_command "ins before un cero" | ... | @@ -136,6 +141,7 @@ mailbox_prog_command "ins before un cero" |
136 | mailbox_prog_command "ins un dos" | 141 | mailbox_prog_command "ins un dos" |
137 | 142 | ||
138 | mailbox_prog_test "print" \ | 143 | mailbox_prog_test "print" \ |
144 | "# items: 10" \ | ||
139 | "3" \ | 145 | "3" \ |
140 | "dwa" \ | 146 | "dwa" \ |
141 | "zero" \ | 147 | "zero" \ |
... | @@ -149,6 +155,7 @@ mailbox_prog_test "print" \ | ... | @@ -149,6 +155,7 @@ mailbox_prog_test "print" \ |
149 | 155 | ||
150 | mailbox_prog_command "ins before 3 1" | 156 | mailbox_prog_command "ins before 3 1" |
151 | mailbox_prog_test "print" \ | 157 | mailbox_prog_test "print" \ |
158 | "# items: 11" \ | ||
152 | "1" \ | 159 | "1" \ |
153 | "3" \ | 160 | "3" \ |
154 | "dwa" \ | 161 | "dwa" \ |
... | @@ -163,6 +170,7 @@ mailbox_prog_test "print" \ | ... | @@ -163,6 +170,7 @@ mailbox_prog_test "print" \ |
163 | 170 | ||
164 | mailbox_prog_command "ins before 3 2" | 171 | mailbox_prog_command "ins before 3 2" |
165 | mailbox_prog_test "print" \ | 172 | mailbox_prog_test "print" \ |
173 | "# items: 12" \ | ||
166 | "1" \ | 174 | "1" \ |
167 | "2" \ | 175 | "2" \ |
168 | "3" \ | 176 | "3" \ |
... | @@ -173,9 +181,48 @@ mailbox_prog_test "print" \ | ... | @@ -173,9 +181,48 @@ mailbox_prog_test "print" \ |
173 | "un" \ | 181 | "un" \ |
174 | "dos" \ | 182 | "dos" \ |
175 | "en" \ | 183 | "en" \ |
176 | "to" \ | 184 | "to" \ |
177 | "fem" | 185 | "fem" |
178 | 186 | ||
187 | mailbox_prog_command "ins 3 4 5 6" | ||
188 | mailbox_prog_test "print" \ | ||
189 | "# items: 15" \ | ||
190 | "1" \ | ||
191 | "2" \ | ||
192 | "3" \ | ||
193 | "4" \ | ||
194 | "5" \ | ||
195 | "6" \ | ||
196 | "dwa" \ | ||
197 | "zero" \ | ||
198 | "jeden" \ | ||
199 | "cero" \ | ||
200 | "un" \ | ||
201 | "dos" \ | ||
202 | "en" \ | ||
203 | "to" \ | ||
204 | "fem" | ||
205 | |||
206 | mailbox_prog_command "ins before dwa zero jeden" | ||
207 | mailbox_prog_test "print" \ | ||
208 | "# items: 17" \ | ||
209 | "1" \ | ||
210 | "2" \ | ||
211 | "3" \ | ||
212 | "4" \ | ||
213 | "5" \ | ||
214 | "6" \ | ||
215 | "zero" \ | ||
216 | "jeden" \ | ||
217 | "dwa" \ | ||
218 | "zero" \ | ||
219 | "jeden" \ | ||
220 | "cero" \ | ||
221 | "un" \ | ||
222 | "dos" \ | ||
223 | "en" \ | ||
224 | "to" \ | ||
225 | "fem" | ||
179 | 226 | ||
180 | mailbox_prog_send "quit" | 227 | mailbox_prog_send "quit" |
181 | mailbox_prog_stop | 228 | mailbox_prog_stop | ... | ... |
-
Please register or sign in to post a comment