Commit 5781e1f6 5781e1f68d451a0930060f166a376ba38a88fad2 by Sergey Poznyakoff

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.
1 parent 2cb1d357
...@@ -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 }
......
...@@ -86,6 +86,7 @@ libmailutils_la_SOURCES = \ ...@@ -86,6 +86,7 @@ libmailutils_la_SOURCES = \
86 ipsrv.c\ 86 ipsrv.c\
87 kwd.c\ 87 kwd.c\
88 list.c\ 88 list.c\
89 listlist.c\
89 locale.c\ 90 locale.c\
90 locker.c\ 91 locker.c\
91 mailbox.c\ 92 mailbox.c\
......
...@@ -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,
......
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
......