aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/eina/src/tests/evas_list.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/eina/src/tests/evas_list.c')
-rw-r--r--libraries/eina/src/tests/evas_list.c1093
1 files changed, 1093 insertions, 0 deletions
diff --git a/libraries/eina/src/tests/evas_list.c b/libraries/eina/src/tests/evas_list.c
new file mode 100644
index 0000000..55e301f
--- /dev/null
+++ b/libraries/eina/src/tests/evas_list.c
@@ -0,0 +1,1093 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h"
3#endif
4
5#include <stdlib.h>
6
7#include "Evas_Data.h"
8#include <evas_mempool.h>
9
10typedef struct _Evas_List_Accounting Evas_List_Accounting;
11
12struct _Evas_List_Accounting
13{
14 Evas_List *last;
15 int count;
16};
17
18static int _evas_list_alloc_error = 0;
19
20static Evas_Mempool _evas_list_mempool =
21{
22 sizeof(Evas_List),
23 320,
24 0, NULL, NULL
25};
26static Evas_Mempool _evas_list_accounting_mempool =
27{
28 sizeof(Evas_List_Accounting),
29 80,
30 0, NULL, NULL
31};
32
33/**
34 * @defgroup Evas_List_Data_Group Linked List Creation Functions
35 *
36 * Functions that add data to an Evas_List.
37 */
38
39/**
40 * Appends the given data to the given linked list.
41 *
42 * The following example code demonstrates how to ensure that the
43 * given data has been successfully appended.
44 *
45 * @code
46 * Evas_List *list = NULL;
47 * extern void *my_data;
48 *
49 * list = evas_list_append(list, my_data);
50 * if (evas_list_alloc_error())
51 * {
52 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
53 * exit(-1);
54 * }
55 * @endcode
56 *
57 * @param list The given list. If @c NULL is given, then a new list
58 * is created.
59 * @param data The data to append.
60 * @return A new list pointer that should be used in place of the one
61 * given to this function if successful. Otherwise, the old
62 * pointer is returned.
63 * @ingroup Evas_List_Data_Group
64 */
65EAPI Evas_List *
66evas_list_append(Evas_List *list, const void *data)
67{
68 Evas_List *l, *new_l;
69
70 _evas_list_alloc_error = 0;
71 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
72 if (!new_l)
73 {
74 _evas_list_alloc_error = 1;
75 return list;
76 }
77
78 new_l->next = NULL;
79 new_l->data = (void *)data;
80 if (!list)
81 {
82 new_l->prev = NULL;
83 new_l->accounting = evas_mempool_malloc(&_evas_list_accounting_mempool,
84 sizeof(Evas_List_Accounting));
85 if (!new_l->accounting)
86 {
87 _evas_list_alloc_error = 1;
88 evas_mempool_free(&_evas_list_mempool, new_l);
89 return list;
90 }
91
92 new_l->accounting->last = new_l;
93 new_l->accounting->count = 1;
94 return new_l;
95 }
96
97 l = list->accounting->last;
98 l->next = new_l;
99 new_l->prev = l;
100 new_l->accounting = list->accounting;
101 list->accounting->last = new_l;
102 list->accounting->count++;
103 return list;
104}
105
106/**
107 * Prepends the given data to the given linked list.
108 *
109 * The following example code demonstrates how to ensure that the
110 * given data has been successfully prepended.
111 *
112 * Example:
113 * @code
114 * Evas_List *list = NULL;
115 * extern void *my_data;
116 *
117 * list = evas_list_prepend(list, my_data);
118 * if (evas_list_alloc_error())
119 * {
120 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
121 * exit(-1);
122 * }
123 * @endcode
124 *
125 * @param list The given list.
126 * @param data The given data.
127 * @return A new list pointer that should be used in place of the one
128 * given to this function, if successful. Otherwise, the old
129 * pointer is returned.
130 * @ingroup Evas_List_Data_Group
131 */
132EAPI Evas_List *
133evas_list_prepend(Evas_List *list, const void *data)
134{
135 Evas_List *new_l;
136
137 _evas_list_alloc_error = 0;
138 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
139 if (!new_l)
140 {
141 _evas_list_alloc_error = 1;
142 return list;
143 }
144
145 new_l->prev = NULL;
146 new_l->data = (void *)data;
147 if (!list)
148 {
149 new_l->next = NULL;
150 new_l->accounting = evas_mempool_malloc(&_evas_list_accounting_mempool,
151 sizeof(Evas_List_Accounting));
152 if (!new_l->accounting)
153 {
154 _evas_list_alloc_error = 1;
155 evas_mempool_free(&_evas_list_mempool, new_l);
156 return list;
157 }
158
159 new_l->accounting->last = new_l;
160 new_l->accounting->count = 1;
161 return new_l;
162 }
163
164 new_l->next = list;
165 list->prev = new_l;
166 new_l->accounting = list->accounting;
167 list->accounting->count++;
168 return new_l;
169}
170
171/**
172 * Inserts the given data into the given linked list after the specified data.
173 *
174 * If @p relative is not in the list, @p data is appended to the end of the
175 * list. If there are multiple instances of @p relative in the list,
176 * @p data is inserted after the first instance.
177 *
178 * The following example code demonstrates how to ensure that the
179 * given data has been successfully inserted.
180 *
181 * @code
182 * Evas_List *list = NULL;
183 * extern void *my_data;
184 * extern void *relative_member;
185 *
186 * list = evas_list_append(list, relative_member);
187 * if (evas_list_alloc_error())
188 * {
189 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
190 * exit(-1);
191 * }
192 * list = evas_list_append_relative(list, my_data, relative_member);
193 * if (evas_list_alloc_error())
194 * {
195 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
196 * exit(-1);
197 * }
198 * @endcode
199 *
200 * @param list The given linked list.
201 * @param data The given data.
202 * @param relative The data to insert after.
203 * @return A new list pointer that should be used in place of the one
204 * given to this function if successful. Otherwise, the old pointer
205 * is returned.
206 * @ingroup Evas_List_Data_Group
207 */
208EAPI Evas_List *
209evas_list_append_relative(Evas_List *list,
210 const void *data,
211 const void *relative)
212{
213 Evas_List *l;
214
215 for (l = list; l; l = l->next)
216 {
217 if (l->data == relative)
218 return evas_list_append_relative_list(list, data, l);
219 }
220 return evas_list_append(list, data);
221}
222
223EAPI Evas_List *
224evas_list_append_relative_list(Evas_List *list,
225 const void *data,
226 Evas_List *relative)
227{
228 Evas_List *new_l;
229
230 if ((!list) || (!relative))
231 return evas_list_append(list, data);
232
233 _evas_list_alloc_error = 0;
234 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
235 if (!new_l)
236 {
237 _evas_list_alloc_error = 1;
238 return list;
239 }
240
241 new_l->data = (void *)data;
242 if (relative->next)
243 {
244 new_l->next = relative->next;
245 relative->next->prev = new_l;
246 }
247 else
248 new_l->next = NULL;
249
250 relative->next = new_l;
251 new_l->prev = relative;
252 new_l->accounting = list->accounting;
253 list->accounting->count++;
254 if (!new_l->next)
255 new_l->accounting->last = new_l;
256
257 return list;
258}
259
260/**
261 * Prepend a data pointer to a linked list before the member specified
262 * @param list The list handle to prepend @p data too
263 * @param data The data pointer to prepend to list @p list before @p relative
264 * @param relative The data pointer before which to insert @p data
265 * @return A new list handle to replace the old one
266
267 * Inserts the given data into the given linked list before the member
268 * specified.
269 *
270 * If @p relative is not in the list, @p data is prepended to the
271 * start of the list. If there are multiple instances of @p relative
272 * in the list, @p data is inserted before the first instance.
273 *
274 * The following code example demonstrates how to ensure that the
275 * given data has been successfully inserted.
276 *
277 * @code
278 * Evas_List *list = NULL;
279 * extern void *my_data;
280 * extern void *relative_member;
281 *
282 * list = evas_list_append(list, relative_member);
283 * if (evas_list_alloc_error())
284 * {
285 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
286 * exit(-1);
287 * }
288 * list = evas_list_prepend_relative(list, my_data, relative_member);
289 * if (evas_list_alloc_error())
290 * {
291 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
292 * exit(-1);
293 * }
294 * @endcode
295 *
296 * @param list The given linked list.
297 * @param data The given data.
298 * @param relative The data to insert before.
299 * @return A new list pointer that should be used in place of the one
300 * given to this function if successful. Otherwise the old pointer
301 * is returned.
302 * @ingroup Evas_List_Data_Group
303 */
304EAPI Evas_List *
305evas_list_prepend_relative(Evas_List *list,
306 const void *data,
307 const void *relative)
308{
309 Evas_List *l;
310
311 _evas_list_alloc_error = 0;
312 for (l = list; l; l = l->next)
313 {
314 if (l->data == relative)
315 return evas_list_prepend_relative_list(list, data, l);
316 }
317 return evas_list_prepend(list, data);
318}
319
320EAPI Evas_List *
321evas_list_prepend_relative_list(Evas_List *list,
322 const void *data,
323 Evas_List *relative)
324{
325 Evas_List *new_l;
326
327 if ((!list) || (!relative))
328 return evas_list_prepend(list, data);
329
330 _evas_list_alloc_error = 0;
331 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
332 if (!new_l)
333 {
334 _evas_list_alloc_error = 1;
335 return list;
336 }
337
338 new_l->data = (void *)data;
339 new_l->prev = relative->prev;
340 new_l->next = relative;
341 if (relative->prev)
342 relative->prev->next = new_l;
343
344 relative->prev = new_l;
345 new_l->accounting = list->accounting;
346 list->accounting->count++;
347 if (new_l->prev)
348 return list;
349
350 return new_l;
351}
352
353/**
354 * @defgroup Evas_List_Remove_Group Linked List Remove Functions
355 *
356 * Functions that remove data from linked lists.
357 */
358
359/**
360 * Removes the first instance of the specified data from the given list.
361 *
362 * If the specified data is not in the given list, nothing is done.
363 *
364 * @param list The given list.
365 * @param data The specified data.
366 * @return A new list pointer that should be used in place of the one
367 * passed to this functions.
368 * @ingroup Evas_List_Remove_Group
369 */
370EAPI Evas_List *
371evas_list_remove(Evas_List *list, const void *data)
372{
373 Evas_List *l;
374
375 for (l = list; l; l = l->next)
376 {
377 if (l->data == data)
378 return evas_list_remove_list(list, l);
379 }
380 return list;
381}
382
383/**
384 * Removes the specified data
385 *
386 * Remove a specified member from a list
387 * @param list The list handle to remove @p remove_list from
388 * @param remove_list The list node which is to be removed
389 * @return A new list handle to replace the old one
390 *
391 * Calling this function takes the list node @p remove_list and removes it
392 * from the list @p list, freeing the list node structure @p remove_list.
393 *
394 * Example:
395 * @code
396 * extern Evas_List *list;
397 * Evas_List *l;
398 * extern void *my_data;
399 *
400 * for (l = list; l; l= l->next)
401 * {
402 * if (l->data == my_data)
403 * {
404 * list = evas_list_remove_list(list, l);
405 * break;
406 * }
407 * }
408 * @endcode
409 * @ingroup Evas_List_Remove_Group
410 */
411EAPI Evas_List *
412evas_list_remove_list(Evas_List *list, Evas_List *remove_list)
413{
414 Evas_List *return_l;
415
416 if (!list)
417 return NULL;
418
419 if (!remove_list)
420 return list;
421
422 if (remove_list->next)
423 remove_list->next->prev = remove_list->prev;
424
425 if (remove_list->prev)
426 {
427 remove_list->prev->next = remove_list->next;
428 return_l = list;
429 }
430 else
431 return_l = remove_list->next;
432
433 if (remove_list == list->accounting->last)
434 list->accounting->last = remove_list->prev;
435
436 list->accounting->count--;
437 if (list->accounting->count == 0)
438 evas_mempool_free(&_evas_list_accounting_mempool, list->accounting);
439
440 evas_mempool_free(&_evas_list_mempool, remove_list);
441 return return_l;
442}
443
444/**
445 * Moves the specified data to the head of the list
446 *
447 * Move a specified member to the head of the list
448 * @param list The list handle to move @p inside
449 * @param move_list The list node which is to be moved
450 * @return A new list handle to replace the old one
451 *
452 * Calling this function takes the list node @p move_list and moves it
453 * to the front of the @p list.
454 *
455 * Example:
456 * @code
457 * extern Evas_List *list;
458 * Evas_List *l;
459 * extern void *my_data;
460 *
461 * for (l = list; l; l= l->next)
462 * {
463 * if (l->data == my_data)
464 * {
465 * list = evas_list_promote_list(list, l);
466 * break;
467 * }
468 * }
469 * @endcode
470 * @ingroup Evas_List_Promote_Group
471 */
472EAPI Evas_List *
473evas_list_promote_list(Evas_List *list, Evas_List *move_list)
474{
475 Evas_List *return_l;
476
477 if (!list)
478 return NULL;
479
480 if (!move_list)
481 return list;
482
483 if (move_list == list)
484 return list;
485
486 if (move_list->next)
487 move_list->next->prev = move_list->prev;
488
489 if (move_list->prev)
490 {
491 move_list->prev->next = move_list->next;
492 return_l = list;
493 }
494 else
495 return_l = move_list->next;
496
497 if (move_list == list->accounting->last)
498 list->accounting->last = move_list->prev;
499
500 move_list->prev = return_l->prev;
501 if (return_l->prev)
502 return_l->prev->next = move_list;
503
504 return_l->prev = move_list;
505 move_list->next = return_l;
506 return move_list;
507}
508
509
510
511/**
512 * @defgroup Evas_List_Find_Group Linked List Find Functions
513 *
514 * Functions that find specified data in a linked list.
515 */
516
517/**
518 * Find a member of a list and return the member
519 * @param list The list handle to search for @p data
520 * @param data The data pointer to find in the list @p list
521 * @return The found member data pointer
522 *
523 * A call to this function will search the list @p list from beginning to end
524 * for the first member whose data pointer is @p data. If it is found, @p data
525 * will be returned, otherwise NULL will be returned.
526 *
527 * Example:
528 * @code
529 * extern Evas_List *list;
530 * extern void *my_data;
531 *
532 * if (evas_list_find(list, my_data) == my_data)
533 * {
534 * printf("Found member %p\n", my_data);
535 * }
536 * @endcode
537 * @ingroup Evas_List_Find_Group
538 */
539EAPI void *
540evas_list_find(const Evas_List *list, const void *data)
541{
542 const Evas_List *l;
543
544 for (l = list; l; l = l->next)
545 {
546 if (l->data == data)
547 return (void *)data;
548 }
549 return NULL;
550}
551
552/**
553 * Find a member of a list and return the list node containing that member
554 * @param list The list handle to search for @p data
555 * @param data The data pointer to find in the list @p list
556 * @return The found members list node
557 *
558 * A call to this function will search the list @p list from beginning to end
559 * for the first member whose data pointer is @p data. If it is found, the
560 * list node containing the specified member will be returned, otherwise NULL
561 * will be returned.
562 *
563 * Example:
564 * @code
565 * extern Evas_List *list;
566 * extern void *my_data;
567 * Evas_List *found_node;
568 *
569 * found_node = evas_list_find_list(list, my_data);
570 * if (found_node)
571 * {
572 * printf("Found member %p\n", found_node->data);
573 * }
574 * @endcode
575 * @ingroup Evas_List_Find_Group
576 */
577EAPI Evas_List *
578evas_list_find_list(const Evas_List *list, const void *data)
579{
580 const Evas_List *l;
581
582 for (l = list; l; l = l->next)
583 {
584 if (l->data == data)
585 return (Evas_List *)l;
586 }
587 return NULL;
588}
589
590/**
591 * Free an entire list and all the nodes, ignoring the data contained
592 * @param list The list to free
593 * @return A NULL pointer
594 *
595 * This function will free all the list nodes in list specified by @p list.
596 *
597 * Example:
598 * @code
599 * extern Evas_List *list;
600 *
601 * list = evas_list_free(list);
602 * @endcode
603 * @ingroup Evas_List_Remove_Group
604 */
605EAPI Evas_List *
606evas_list_free(Evas_List *list)
607{
608 Evas_List *l, *free_l;
609
610 if (!list)
611 return NULL;
612
613 evas_mempool_free(&_evas_list_accounting_mempool, list->accounting);
614 for (l = list; l; )
615 {
616 free_l = l;
617 l = l->next;
618 evas_mempool_free(&_evas_list_mempool, free_l);
619 }
620 return NULL;
621}
622
623/**
624 * @defgroup Evas_List_Traverse_Group Linked List Traverse Functions
625 *
626 * Functions that you can use to traverse a linked list.
627 */
628
629/**
630 * Get the last list node in the list
631 * @param list The list to get the last list node from
632 * @return The last list node in the list @p list
633 *
634 * This function will return the last list node in the list (or NULL if the
635 * list is empty).
636 *
637 * NB: This is a order-1 operation (it takes the same short time regardless of
638 * the length of the list).
639 *
640 * Example:
641 * @code
642 * extern Evas_List *list;
643 * Evas_List *last, *l;
644 *
645 * last = evas_list_last(list);
646 * printf("The list in reverse:\n");
647 * for (l = last; l; l = l->prev)
648 * {
649 * printf("%p\n", l->data);
650 * }
651 * @endcode
652 * @ingroup Evas_List_Traverse_Group
653 */
654EAPI Evas_List *
655evas_list_last(const Evas_List *list)
656{
657 if (!list)
658 return NULL;
659
660 return list->accounting->last;
661}
662
663/**
664 * Get the next list node after the specified list node
665 * @param list The list node to get the next list node from
666 * @return The next list node, or NULL if no next list node exists
667 *
668 * This function returns the next list node after the current one. It is
669 * equivalent to list->next.
670 *
671 * Example:
672 * @code
673 * extern Evas_List *list;
674 * Evas_List *l;
675 *
676 * printf("The list:\n");
677 * for (l = list; l; l = evas_list_next(l))
678 * {
679 * printf("%p\n", l->data);
680 * }
681 * @endcode
682 * @ingroup Evas_List_Traverse_Group
683 */
684EAPI Evas_List *
685evas_list_next(const Evas_List *list)
686{
687 if (!list)
688 return NULL;
689
690 return list->next;
691}
692
693/**
694 * Get the previous list node before the specified list node
695 * @param list The list node to get the previous list node from
696 * @return The previous list node, or NULL if no previous list node exists
697 *
698 * This function returns the previous list node before the current one. It is
699 * equivalent to list->prev.
700 *
701 * Example:
702 * @code
703 * extern Evas_List *list;
704 * Evas_List *last, *l;
705 *
706 * last = evas_list_last(list);
707 * printf("The list in reverse:\n");
708 * for (l = last; l; l = evas_list_prev(l))
709 * {
710 * printf("%p\n", l->data);
711 * }
712 * @endcode
713 * @ingroup Evas_List_Traverse_Group
714 */
715EAPI Evas_List *
716evas_list_prev(const Evas_List *list)
717{
718 if (!list)
719 return NULL;
720
721 return list->prev;
722}
723
724/**
725 * @defgroup Evas_List_General_Group Linked List General Functions
726 *
727 * Miscellaneous functions that work on linked lists.
728 */
729
730/**
731 * Get the list node data member
732 * @param list The list node to get the data member of
733 * @return The data member from the list node @p list
734 *
735 * This function returns the data member of the specified list node @p list.
736 * It is equivalent to list->data.
737 *
738 * Example:
739 * @code
740 * extern Evas_List *list;
741 * Evas_List *l;
742 *
743 * printf("The list:\n");
744 * for (l = list; l; l = evas_list_next(l))
745 * {
746 * printf("%p\n", evas_list_data(l));
747 * }
748 * @endcode
749 * @ingroup Evas_List_General_Group
750 */
751EAPI void *
752evas_list_data(const Evas_List *list)
753{
754 if (!list)
755 return NULL;
756
757 return list->data;
758}
759
760/**
761 * Get the count of the number of items in a list
762 * @param list The list whose count to return
763 * @return The number of members in the list @p list
764 *
765 * This function returns how many members in the specified list: @p list. If
766 * the list is empty (NULL), 0 is returned.
767 *
768 * NB: This is an order-1 operation and takes the same time regardless of the
769 * length of the list.
770 *
771 * Example:
772 * @code
773 * extern Evas_List *list;
774 *
775 * printf("The list has %i members\n", evas_list_count(list));
776 * @endcode
777 * @ingroup Evas_List_General_Group
778 */
779EAPI int
780evas_list_count(const Evas_List *list)
781{
782 if (!list)
783 return 0;
784
785 return list->accounting->count;
786}
787
788/**
789 * Get the nth member's data pointer in a list
790 * @param list The list to get member number @p n from
791 * @param n The number of the element (0 being the first)
792 * @return The data pointer stored in the specified element
793 *
794 * This function returns the data pointer of element number @p n, in the list
795 * @p list. The first element in the array is element number 0. If the element
796 * number @p n does not exist, NULL will be returned.
797 *
798 * Example:
799 * @code
800 * extern Evas_List *list;
801 * extern int number;
802 * void *data;
803 *
804 * data = evas_list_nth(list, number);
805 * if (data)
806 * printf("Element number %i has data %p\n", number, data);
807 * @endcode
808 * @ingroup Evas_List_Find_Group
809 */
810EAPI void *
811evas_list_nth(const Evas_List *list, int n)
812{
813 Evas_List *l;
814
815 l = evas_list_nth_list(list, n);
816 return l ? l->data : NULL;
817}
818
819/**
820 * Get the nth member's list node in a list
821 * @param list The list to get member number @p n from
822 * @param n The number of the element (0 being the first)
823 * @return The list node stored in the numbered element
824 *
825 * This function returns the list node of element number @p n, in the list
826 * @p list. The first element in the array is element number 0. If the element
827 * number @p n does not exist, NULL will be returned.
828 *
829 * Example:
830 * @code
831 * extern Evas_List *list;
832 * extern int number;
833 * Evas_List *nth_list;
834 *
835 * nth_list = evas_list_nth_list(list, number);
836 * if (nth_list)
837 * printf("Element number %i has data %p\n", number, nth_list->data);
838 * @endcode
839 * @ingroup Evas_List_Find_Group
840 */
841EAPI Evas_List *
842evas_list_nth_list(const Evas_List *list, int n)
843{
844 int i;
845 const Evas_List *l;
846
847 /* check for non-existing nodes */
848 if ((!list) || (n < 0) ||
849 (n > (list->accounting->count - 1)))
850 return NULL;
851
852 /* if the node is in the 2nd half of the list, search from the end
853 * else, search from the beginning.
854 */
855 if (n > (list->accounting->count / 2))
856 for (i = list->accounting->count - 1,
857 l = list->accounting->last;
858 l;
859 l = l->prev, i--)
860 {
861 if (i == n)
862 return (Evas_List *)l;
863 }
864 else
865 for (i = 0, l = list; l; l = l->next, i++)
866 {
867 if (i == n)
868 return (Evas_List *)l;
869 }
870
871 return NULL;
872}
873
874/**
875 * @defgroup Evas_List_Ordering_Group Linked List Ordering Functions
876 *
877 * Functions that change the ordering of data in a linked list.
878 */
879
880/**
881 * Reverse all the elements in the list
882 * @param list The list to reverse
883 * @return The list after it has been reversed
884 *
885 * This takes a list @p list, and reverses the order of all elements in the
886 * list, so the last member is now first, and so on.
887 *
888 * Example:
889 * @code
890 * extern Evas_List *list;
891 *
892 * list = evas_list_reverse(list);
893 * @endcode
894 * @ingroup Evas_List_Ordering_Group
895 */
896EAPI Evas_List *
897evas_list_reverse(Evas_List *list)
898{
899 Evas_List *l1, *l2;
900
901 if (!list)
902 return NULL;
903
904 l1 = list;
905 l2 = list->accounting->last;
906 while (l1 != l2)
907 {
908 void *data;
909
910 data = l1->data;
911 l1->data = l2->data;
912 l2->data = data;
913 l1 = l1->next;
914 if (l1 == l2)
915 break;
916
917 l2 = l2->prev;
918 }
919
920 return list;
921}
922
923/**
924 * Sort a list according to the ordering func will return
925 * @param list The list handle to sort
926 * @param size The length of the list to sort
927 * @param func A function pointer that can handle comparing the list data
928 * nodes
929 * @return A new sorted list
930 *
931 * This function sorts your list. The data in your nodes can be arbitrary,
932 * you just have to be smart enough to know what kind of data is in your
933 * lists
934 *
935 * Example:
936 * @code
937 * int
938 * sort_cb(void *d1, void *d2)
939 * {
940 * const char *txt = NULL;
941 * const char *txt2 = NULL;
942 *
943 * if(!d1) return(1);
944 * if(!d2) return(-1);
945 *
946 * return(strcmp((const char*)d1, (const char*)d2));
947 * }
948 * extern Evas_List *list;
949 *
950 * list = evas_list_sort(list, evas_list_count(list), sort_cb);
951 * if (evas_list_alloc_error())
952 * {
953 * fprintf(stderr, "ERROR: Memory is low. List Sorting failed.\n");
954 * exit(-1);
955 * }
956 * @endcode
957 * @ingroup Evas_List_Ordering_Group
958 */
959EAPI Evas_List *
960evas_list_sort(Evas_List *list, int size, int (*func)(void *, void *))
961{
962 Evas_List *last;
963 unsigned int list_number;
964 unsigned int middle;
965 int list_size;
966
967 if (!list || !func)
968 return NULL;
969
970 /* if the caller specified an invalid size, sort the whole list */
971 if ((size <= 0) ||
972 (size > list->accounting->count))
973 size = list->accounting->count;
974
975 last = list->accounting->last;
976 middle = size - size / 2;
977
978 for (list_number = middle, list_size = 1;
979 list_size < middle * 2;
980 list_number >>= 1, list_size <<= 1)
981 {
982 Evas_List *head1 = list;
983 unsigned int limit = size;
984 unsigned int process_list;
985 unsigned int pass_number;
986 unsigned int split_size = list_size;
987
988 for (process_list = 0; process_list < list_number + 1; ++process_list)
989 {
990 Evas_List *head2;
991 unsigned int size_sum;
992 int size1, size2;
993 int i;
994
995 size1 = limit < split_size ? limit : split_size;
996 limit -= size1;
997
998 size2 = limit < split_size ? limit : split_size;
999 limit -= size2;
1000
1001 size_sum = size1 + size2;
1002
1003 for (head2 = head1, i = 0; i < size1; ++i)
1004 head2 = evas_list_next (head2);
1005
1006 for (pass_number = 0; pass_number < size_sum; ++pass_number)
1007 {
1008 Evas_List *next;
1009 Evas_List *prev1;
1010 Evas_List *prev2;
1011
1012 if (size1 == 0 || !head1) /* List1 is empty, head1 is already at the end of the list. So only need to update head2 */
1013 {
1014 for (; pass_number < size_sum; ++pass_number)
1015 head2 = evas_list_next (head2);
1016 break;
1017 }
1018 else
1019 if (size2 == 0 || !head2) /* List2 is empty, just leave */
1020 break;
1021 else
1022 if (func (head1->data, head2->data) < 0)
1023 {
1024 head1 = evas_list_next (head1);
1025 --size1;
1026 }
1027 else
1028 {
1029 next = evas_list_next (head2);
1030 prev1 = evas_list_prev (head1);
1031 prev2 = evas_list_prev (head2);
1032
1033 if (next)
1034 next->prev = prev2;
1035
1036 if (prev1)
1037 prev1->next = head2;
1038
1039 if (prev2)
1040 prev2->next = next;
1041
1042 head2->prev = prev1;
1043 head2->next = head1;
1044 head1->prev = head2;
1045
1046 --size2;
1047
1048 if (head1 == list)
1049 list = head2;
1050
1051 if (head2 == last)
1052 last = prev2;
1053
1054 head2 = next;
1055 }
1056 }
1057 head1 = head2;
1058 }
1059 }
1060
1061 list->accounting->last = last;
1062 return list;
1063}
1064/**
1065 * Return the memory allocation failure flag after any operation needin allocation
1066 * @return The state of the allocation flag
1067 *
1068 * This function returns the state of the memory allocation flag. This flag is
1069 * set if memory allocations during evas_list_append(), evas_list_prepend(),
1070 * evas_list_append_relative(), or evas_list_prepend_relative() fail. If they
1071 * do fail, 1 will be returned, otherwise 0 will be returned. The flag will
1072 * remain in its current state until the next call that requires allocation
1073 * is called, and is then reset.
1074 *
1075 * Example:
1076 * @code
1077 * Evas_List *list = NULL;
1078 * extern void *my_data;
1079 *
1080 * list = evas_list_append(list, my_data);
1081 * if (evas_list_alloc_error())
1082 * {
1083 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
1084 * exit(-1);
1085 * }
1086 * @endcode
1087 * @ingroup Evas_List_General_Group
1088 */
1089EAPI int
1090evas_list_alloc_error(void)
1091{
1092 return _evas_list_alloc_error;
1093}