8 #include <evas_mempool.h>
10 typedef struct _Evas_List_Accounting Evas_List_Accounting;
12 struct _Evas_List_Accounting
18 static int _evas_list_alloc_error = 0;
20 static Evas_Mempool _evas_list_mempool =
26 static Evas_Mempool _evas_list_accounting_mempool =
28 sizeof(Evas_List_Accounting),
34 * @defgroup Evas_List_Data_Group Linked List Creation Functions
36 * Functions that add data to an Evas_List.
40 * Appends the given data to the given linked list.
42 * The following example code demonstrates how to ensure that the
43 * given data has been successfully appended.
46 * Evas_List *list = NULL;
47 * extern void *my_data;
49 * list = evas_list_append(list, my_data);
50 * if (evas_list_alloc_error())
52 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
57 * @param list The given list. If @c NULL is given, then a new list
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
66 evas_list_append(Evas_List *list, const void *data)
70 _evas_list_alloc_error = 0;
71 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
74 _evas_list_alloc_error = 1;
79 new_l->data = (void *)data;
83 new_l->accounting = evas_mempool_malloc(&_evas_list_accounting_mempool,
84 sizeof(Evas_List_Accounting));
85 if (!new_l->accounting)
87 _evas_list_alloc_error = 1;
88 evas_mempool_free(&_evas_list_mempool, new_l);
92 new_l->accounting->last = new_l;
93 new_l->accounting->count = 1;
97 l = list->accounting->last;
100 new_l->accounting = list->accounting;
101 list->accounting->last = new_l;
102 list->accounting->count++;
107 * Prepends the given data to the given linked list.
109 * The following example code demonstrates how to ensure that the
110 * given data has been successfully prepended.
114 * Evas_List *list = NULL;
115 * extern void *my_data;
117 * list = evas_list_prepend(list, my_data);
118 * if (evas_list_alloc_error())
120 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
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
133 evas_list_prepend(Evas_List *list, const void *data)
137 _evas_list_alloc_error = 0;
138 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
141 _evas_list_alloc_error = 1;
146 new_l->data = (void *)data;
150 new_l->accounting = evas_mempool_malloc(&_evas_list_accounting_mempool,
151 sizeof(Evas_List_Accounting));
152 if (!new_l->accounting)
154 _evas_list_alloc_error = 1;
155 evas_mempool_free(&_evas_list_mempool, new_l);
159 new_l->accounting->last = new_l;
160 new_l->accounting->count = 1;
166 new_l->accounting = list->accounting;
167 list->accounting->count++;
172 * Inserts the given data into the given linked list after the specified data.
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.
178 * The following example code demonstrates how to ensure that the
179 * given data has been successfully inserted.
182 * Evas_List *list = NULL;
183 * extern void *my_data;
184 * extern void *relative_member;
186 * list = evas_list_append(list, relative_member);
187 * if (evas_list_alloc_error())
189 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
192 * list = evas_list_append_relative(list, my_data, relative_member);
193 * if (evas_list_alloc_error())
195 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
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
206 * @ingroup Evas_List_Data_Group
209 evas_list_append_relative(Evas_List *list,
211 const void *relative)
215 for (l = list; l; l = l->next)
217 if (l->data == relative)
218 return evas_list_append_relative_list(list, data, l);
220 return evas_list_append(list, data);
224 evas_list_append_relative_list(Evas_List *list,
230 if ((!list) || (!relative))
231 return evas_list_append(list, data);
233 _evas_list_alloc_error = 0;
234 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
237 _evas_list_alloc_error = 1;
241 new_l->data = (void *)data;
244 new_l->next = relative->next;
245 relative->next->prev = new_l;
250 relative->next = new_l;
251 new_l->prev = relative;
252 new_l->accounting = list->accounting;
253 list->accounting->count++;
255 new_l->accounting->last = new_l;
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
267 * Inserts the given data into the given linked list before the member
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.
274 * The following code example demonstrates how to ensure that the
275 * given data has been successfully inserted.
278 * Evas_List *list = NULL;
279 * extern void *my_data;
280 * extern void *relative_member;
282 * list = evas_list_append(list, relative_member);
283 * if (evas_list_alloc_error())
285 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
288 * list = evas_list_prepend_relative(list, my_data, relative_member);
289 * if (evas_list_alloc_error())
291 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
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
302 * @ingroup Evas_List_Data_Group
305 evas_list_prepend_relative(Evas_List *list,
307 const void *relative)
311 _evas_list_alloc_error = 0;
312 for (l = list; l; l = l->next)
314 if (l->data == relative)
315 return evas_list_prepend_relative_list(list, data, l);
317 return evas_list_prepend(list, data);
321 evas_list_prepend_relative_list(Evas_List *list,
327 if ((!list) || (!relative))
328 return evas_list_prepend(list, data);
330 _evas_list_alloc_error = 0;
331 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
334 _evas_list_alloc_error = 1;
338 new_l->data = (void *)data;
339 new_l->prev = relative->prev;
340 new_l->next = relative;
342 relative->prev->next = new_l;
344 relative->prev = new_l;
345 new_l->accounting = list->accounting;
346 list->accounting->count++;
354 * @defgroup Evas_List_Remove_Group Linked List Remove Functions
356 * Functions that remove data from linked lists.
360 * Removes the first instance of the specified data from the given list.
362 * If the specified data is not in the given list, nothing is done.
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
371 evas_list_remove(Evas_List *list, const void *data)
375 for (l = list; l; l = l->next)
378 return evas_list_remove_list(list, l);
384 * Removes the specified data
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
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.
396 * extern Evas_List *list;
398 * extern void *my_data;
400 * for (l = list; l; l= l->next)
402 * if (l->data == my_data)
404 * list = evas_list_remove_list(list, l);
409 * @ingroup Evas_List_Remove_Group
412 evas_list_remove_list(Evas_List *list, Evas_List *remove_list)
422 if (remove_list->next)
423 remove_list->next->prev = remove_list->prev;
425 if (remove_list->prev)
427 remove_list->prev->next = remove_list->next;
431 return_l = remove_list->next;
433 if (remove_list == list->accounting->last)
434 list->accounting->last = remove_list->prev;
436 list->accounting->count--;
437 if (list->accounting->count == 0)
438 evas_mempool_free(&_evas_list_accounting_mempool, list->accounting);
440 evas_mempool_free(&_evas_list_mempool, remove_list);
445 * Moves the specified data to the head of the list
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
452 * Calling this function takes the list node @p move_list and moves it
453 * to the front of the @p list.
457 * extern Evas_List *list;
459 * extern void *my_data;
461 * for (l = list; l; l= l->next)
463 * if (l->data == my_data)
465 * list = evas_list_promote_list(list, l);
470 * @ingroup Evas_List_Promote_Group
473 evas_list_promote_list(Evas_List *list, Evas_List *move_list)
483 if (move_list == list)
487 move_list->next->prev = move_list->prev;
491 move_list->prev->next = move_list->next;
495 return_l = move_list->next;
497 if (move_list == list->accounting->last)
498 list->accounting->last = move_list->prev;
500 move_list->prev = return_l->prev;
502 return_l->prev->next = move_list;
504 return_l->prev = move_list;
505 move_list->next = return_l;
512 * @defgroup Evas_List_Find_Group Linked List Find Functions
514 * Functions that find specified data in a linked list.
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
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.
529 * extern Evas_List *list;
530 * extern void *my_data;
532 * if (evas_list_find(list, my_data) == my_data)
534 * printf("Found member %p\n", my_data);
537 * @ingroup Evas_List_Find_Group
540 evas_list_find(const Evas_List *list, const void *data)
544 for (l = list; l; l = l->next)
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
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
565 * extern Evas_List *list;
566 * extern void *my_data;
567 * Evas_List *found_node;
569 * found_node = evas_list_find_list(list, my_data);
572 * printf("Found member %p\n", found_node->data);
575 * @ingroup Evas_List_Find_Group
578 evas_list_find_list(const Evas_List *list, const void *data)
582 for (l = list; l; l = l->next)
585 return (Evas_List *)l;
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
595 * This function will free all the list nodes in list specified by @p list.
599 * extern Evas_List *list;
601 * list = evas_list_free(list);
603 * @ingroup Evas_List_Remove_Group
606 evas_list_free(Evas_List *list)
608 Evas_List *l, *free_l;
613 evas_mempool_free(&_evas_list_accounting_mempool, list->accounting);
618 evas_mempool_free(&_evas_list_mempool, free_l);
624 * @defgroup Evas_List_Traverse_Group Linked List Traverse Functions
626 * Functions that you can use to traverse a linked list.
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
634 * This function will return the last list node in the list (or NULL if the
637 * NB: This is a order-1 operation (it takes the same short time regardless of
638 * the length of the list).
642 * extern Evas_List *list;
643 * Evas_List *last, *l;
645 * last = evas_list_last(list);
646 * printf("The list in reverse:\n");
647 * for (l = last; l; l = l->prev)
649 * printf("%p\n", l->data);
652 * @ingroup Evas_List_Traverse_Group
655 evas_list_last(const Evas_List *list)
660 return list->accounting->last;
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
668 * This function returns the next list node after the current one. It is
669 * equivalent to list->next.
673 * extern Evas_List *list;
676 * printf("The list:\n");
677 * for (l = list; l; l = evas_list_next(l))
679 * printf("%p\n", l->data);
682 * @ingroup Evas_List_Traverse_Group
685 evas_list_next(const Evas_List *list)
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
698 * This function returns the previous list node before the current one. It is
699 * equivalent to list->prev.
703 * extern Evas_List *list;
704 * Evas_List *last, *l;
706 * last = evas_list_last(list);
707 * printf("The list in reverse:\n");
708 * for (l = last; l; l = evas_list_prev(l))
710 * printf("%p\n", l->data);
713 * @ingroup Evas_List_Traverse_Group
716 evas_list_prev(const Evas_List *list)
725 * @defgroup Evas_List_General_Group Linked List General Functions
727 * Miscellaneous functions that work on linked lists.
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
735 * This function returns the data member of the specified list node @p list.
736 * It is equivalent to list->data.
740 * extern Evas_List *list;
743 * printf("The list:\n");
744 * for (l = list; l; l = evas_list_next(l))
746 * printf("%p\n", evas_list_data(l));
749 * @ingroup Evas_List_General_Group
752 evas_list_data(const Evas_List *list)
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
765 * This function returns how many members in the specified list: @p list. If
766 * the list is empty (NULL), 0 is returned.
768 * NB: This is an order-1 operation and takes the same time regardless of the
769 * length of the list.
773 * extern Evas_List *list;
775 * printf("The list has %i members\n", evas_list_count(list));
777 * @ingroup Evas_List_General_Group
780 evas_list_count(const Evas_List *list)
785 return list->accounting->count;
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
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.
800 * extern Evas_List *list;
804 * data = evas_list_nth(list, number);
806 * printf("Element number %i has data %p\n", number, data);
808 * @ingroup Evas_List_Find_Group
811 evas_list_nth(const Evas_List *list, int n)
815 l = evas_list_nth_list(list, n);
816 return l ? l->data : NULL;
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
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.
831 * extern Evas_List *list;
833 * Evas_List *nth_list;
835 * nth_list = evas_list_nth_list(list, number);
837 * printf("Element number %i has data %p\n", number, nth_list->data);
839 * @ingroup Evas_List_Find_Group
842 evas_list_nth_list(const Evas_List *list, int n)
847 /* check for non-existing nodes */
848 if ((!list) || (n < 0) ||
849 (n > (list->accounting->count - 1)))
852 /* if the node is in the 2nd half of the list, search from the end
853 * else, search from the beginning.
855 if (n > (list->accounting->count / 2))
856 for (i = list->accounting->count - 1,
857 l = list->accounting->last;
862 return (Evas_List *)l;
865 for (i = 0, l = list; l; l = l->next, i++)
868 return (Evas_List *)l;
875 * @defgroup Evas_List_Ordering_Group Linked List Ordering Functions
877 * Functions that change the ordering of data in a linked list.
881 * Reverse all the elements in the list
882 * @param list The list to reverse
883 * @return The list after it has been reversed
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.
890 * extern Evas_List *list;
892 * list = evas_list_reverse(list);
894 * @ingroup Evas_List_Ordering_Group
897 evas_list_reverse(Evas_List *list)
905 l2 = list->accounting->last;
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
929 * @return A new sorted list
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
938 * sort_cb(void *d1, void *d2)
940 * const char *txt = NULL;
941 * const char *txt2 = NULL;
944 * if(!d2) return(-1);
946 * return(strcmp((const char*)d1, (const char*)d2));
948 * extern Evas_List *list;
950 * list = evas_list_sort(list, evas_list_count(list), sort_cb);
951 * if (evas_list_alloc_error())
953 * fprintf(stderr, "ERROR: Memory is low. List Sorting failed.\n");
957 * @ingroup Evas_List_Ordering_Group
960 evas_list_sort(Evas_List *list, int size, int (*func)(void *, void *))
963 unsigned int list_number;
965 unsigned int list_size;
970 /* if the caller specified an invalid size, sort the whole list */
972 (size > list->accounting->count))
973 size = list->accounting->count;
975 last = list->accounting->last;
976 middle = size - size / 2;
978 for (list_number = middle, list_size = 1;
979 list_size < middle * 2;
980 list_number >>= 1, list_size <<= 1)
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;
988 for (process_list = 0; process_list < list_number + 1; ++process_list)
991 unsigned int size_sum;
995 size1 = limit < split_size ? limit : split_size;
998 size2 = limit < split_size ? limit : split_size;
1001 size_sum = size1 + size2;
1003 for (head2 = head1, i = 0; i < size1; ++i)
1004 head2 = evas_list_next (head2);
1006 for (pass_number = 0; pass_number < size_sum; ++pass_number)
1012 if (size1 == 0 || !head1) /* List1 is empty, head1 is already at the end of the list. So only need to update head2 */
1014 for (; pass_number < size_sum; ++pass_number)
1015 head2 = evas_list_next (head2);
1019 if (size2 == 0 || !head2) /* List2 is empty, just leave */
1022 if (func (head1->data, head2->data) < 0)
1024 head1 = evas_list_next (head1);
1029 next = evas_list_next (head2);
1030 prev1 = evas_list_prev (head1);
1031 prev2 = evas_list_prev (head2);
1037 prev1->next = head2;
1042 head2->prev = prev1;
1043 head2->next = head1;
1044 head1->prev = head2;
1061 list->accounting->last = last;
1065 * Return the memory allocation failure flag after any operation needin allocation
1066 * @return The state of the allocation flag
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.
1077 * Evas_List *list = NULL;
1078 * extern void *my_data;
1080 * list = evas_list_append(list, my_data);
1081 * if (evas_list_alloc_error())
1083 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
1087 * @ingroup Evas_List_General_Group
1090 evas_list_alloc_error(void)
1092 return _evas_list_alloc_error;