2 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
11 #include "Evas_Data.h"
12 #include <evas_mempool.h>
14 typedef struct _Evas_List_Accounting Evas_List_Accounting;
16 struct _Evas_List_Accounting
22 static int _evas_list_alloc_error = 0;
24 static Evas_Mempool _evas_list_mempool =
30 static Evas_Mempool _evas_list_accounting_mempool =
32 sizeof(Evas_List_Accounting),
38 * @defgroup Evas_List_Data_Group Linked List Creation Functions
40 * Functions that add data to an Evas_List.
44 * Appends the given data to the given linked list.
46 * The following example code demonstrates how to ensure that the
47 * given data has been successfully appended.
50 * Evas_List *list = NULL;
51 * extern void *my_data;
53 * list = evas_list_append(list, my_data);
54 * if (evas_list_alloc_error())
56 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
61 * @param list The given list. If @c NULL is given, then a new list
63 * @param data The data to append.
64 * @return A new list pointer that should be used in place of the one
65 * given to this function if successful. Otherwise, the old
66 * pointer is returned.
67 * @ingroup Evas_List_Data_Group
70 evas_list_append(Evas_List *list, const void *data)
74 _evas_list_alloc_error = 0;
75 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
78 _evas_list_alloc_error = 1;
82 new_l->data = (void *)data;
86 new_l->accounting = evas_mempool_malloc(&_evas_list_accounting_mempool, sizeof(Evas_List_Accounting));
87 if (!new_l->accounting)
89 _evas_list_alloc_error = 1;
90 evas_mempool_free(&_evas_list_mempool, new_l);
93 new_l->accounting->last = new_l;
94 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;
145 new_l->data = (void *)data;
149 new_l->accounting = evas_mempool_malloc(&_evas_list_accounting_mempool, sizeof(Evas_List_Accounting));
150 if (!new_l->accounting)
152 _evas_list_alloc_error = 1;
153 evas_mempool_free(&_evas_list_mempool, new_l);
156 new_l->accounting->last = new_l;
157 new_l->accounting->count = 1;
162 new_l->accounting = list->accounting;
163 list->accounting->count++;
168 * Inserts the given data into the given linked list after the specified data.
170 * If @p relative is not in the list, @p data is appended to the end of the
171 * list. If there are multiple instances of @p relative in the list,
172 * @p data is inserted after the first instance.
174 * The following example code demonstrates how to ensure that the
175 * given data has been successfully inserted.
178 * Evas_List *list = NULL;
179 * extern void *my_data;
180 * extern void *relative_member;
182 * list = evas_list_append(list, relative_member);
183 * if (evas_list_alloc_error())
185 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
188 * list = evas_list_append_relative(list, my_data, relative_member);
189 * if (evas_list_alloc_error())
191 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
196 * @param list The given linked list.
197 * @param data The given data.
198 * @param relative The data to insert after.
199 * @return A new list pointer that should be used in place of the one
200 * given to this function if successful. Otherwise, the old pointer
202 * @ingroup Evas_List_Data_Group
205 evas_list_append_relative(Evas_List *list, const void *data, const void *relative)
209 for (l = list; l; l = l->next)
211 if (l->data == relative)
212 return evas_list_append_relative_list(list, data, l);
214 return evas_list_append(list, data);
218 evas_list_append_relative_list(Evas_List *list, const void *data, Evas_List *relative)
222 if ((!list) || (!relative)) return evas_list_append(list, data);
223 _evas_list_alloc_error = 0;
224 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
227 _evas_list_alloc_error = 1;
230 new_l->data = (void *)data;
233 new_l->next = relative->next;
234 relative->next->prev = new_l;
239 relative->next = new_l;
240 new_l->prev = relative;
241 new_l->accounting = list->accounting;
242 list->accounting->count++;
244 new_l->accounting->last = new_l;
249 * Prepend a data pointer to a linked list before the memeber specified
250 * @param list The list handle to prepend @p data too
251 * @param data The data pointer to prepend to list @p list before @p relative
252 * @param relative The data pointer before which to insert @p data
253 * @return A new list handle to replace the old one
255 * Inserts the given data into the given linked list before the member
258 * If @p relative is not in the list, @p data is prepended to the
259 * start of the list. If there are multiple instances of @p relative
260 * in the list, @p data is inserted before the first instance.
262 * The following code example demonstrates how to ensure that the
263 * given data has been successfully inserted.
266 * Evas_List *list = NULL;
267 * extern void *my_data;
268 * extern void *relative_member;
270 * list = evas_list_append(list, relative_member);
271 * if (evas_list_alloc_error())
273 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
276 * list = evas_list_prepend_relative(list, my_data, relative_member);
277 * if (evas_list_alloc_error())
279 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
284 * @param list The given linked list.
285 * @param data The given data.
286 * @param relative The data to insert before.
287 * @return A new list pointer that should be used in place of the one
288 * given to this function if successful. Otherwise the old pointer
290 * @ingroup Evas_List_Data_Group
293 evas_list_prepend_relative(Evas_List *list, const void *data, const void *relative)
297 _evas_list_alloc_error = 0;
298 for (l = list; l; l = l->next)
300 if (l->data == relative)
301 return evas_list_prepend_relative_list(list, data, l);
303 return evas_list_prepend(list, data);
307 evas_list_prepend_relative_list(Evas_List *list, const void *data, Evas_List *relative)
311 if ((!list) || (!relative)) return evas_list_prepend(list, data);
312 _evas_list_alloc_error = 0;
313 new_l = evas_mempool_malloc(&_evas_list_mempool, sizeof(Evas_List));
316 _evas_list_alloc_error = 1;
319 new_l->data = (void *)data;
320 new_l->prev = relative->prev;
321 new_l->next = relative;
322 if (relative->prev) relative->prev->next = new_l;
323 relative->prev = new_l;
324 new_l->accounting = list->accounting;
325 list->accounting->count++;
332 * @defgroup Evas_List_Remove_Group Linked List Remove Functions
334 * Functions that remove data from linked lists.
338 * Removes the first instance of the specified data from the given list.
340 * If the specified data is not in the given list, nothing is done.
342 * @param list The given list.
343 * @param data The specified data.
344 * @return A new list pointer that should be used in place of the one
345 * passed to this functions.
346 * @ingroup Evas_List_Remove_Group
349 evas_list_remove(Evas_List *list, const void *data)
353 for (l = list; l; l = l->next)
356 return evas_list_remove_list(list, l);
362 * Removes the specified data
364 * Remove a specified member from a list
365 * @param list The list handle to remove @p remove_list from
366 * @param remove_list The list node which is to be removed
367 * @return A new list handle to replace the old one
369 * Calling this function takes the list node @p remove_list and removes it
370 * from the list @p list, freeing the list node structure @p remove_list.
374 * extern Evas_List *list;
376 * extern void *my_data;
378 * for (l = list; l; l= l->next)
380 * if (l->data == my_data)
382 * list = evas_list_remove_list(list, l);
387 * @ingroup Evas_List_Remove_Group
390 evas_list_remove_list(Evas_List *list, Evas_List *remove_list)
394 if (!list) return NULL;
395 if (!remove_list) return list;
396 if (remove_list->next) remove_list->next->prev = remove_list->prev;
397 if (remove_list->prev)
399 remove_list->prev->next = remove_list->next;
403 return_l = remove_list->next;
404 if (remove_list == list->accounting->last)
405 list->accounting->last = remove_list->prev;
406 list->accounting->count--;
407 if (list->accounting->count == 0)
408 evas_mempool_free(&_evas_list_accounting_mempool, list->accounting);
409 evas_mempool_free(&_evas_list_mempool, remove_list);
414 * Moves the specified data to the head of the list
416 * Move a specified member to the head of the list
417 * @param list The list handle to move @p inside
418 * @param move_list The list node which is to be moved
419 * @return A new list handle to replace the old one
421 * Calling this function takes the list node @p move_list and moves it
422 * to the front of the @p list.
426 * extern Evas_List *list;
428 * extern void *my_data;
430 * for (l = list; l; l= l->next)
432 * if (l->data == my_data)
434 * list = evas_list_promote_list(list, l);
439 * @ingroup Evas_List_Promote_Group
442 evas_list_promote_list(Evas_List *list, Evas_List *move_list)
446 if (!list) return NULL;
447 if (!move_list) return list;
448 if (move_list == list) return list;
449 if (move_list->next) move_list->next->prev = move_list->prev;
452 move_list->prev->next = move_list->next;
456 return_l = move_list->next;
457 if (move_list == list->accounting->last)
458 list->accounting->last = move_list->prev;
459 move_list->prev = return_l->prev;
461 return_l->prev->next = move_list;
462 return_l->prev = move_list;
463 move_list->next = return_l;
470 * @defgroup Evas_List_Find_Group Linked List Find Functions
472 * Functions that find specified data in a linked list.
476 * Find a member of a list and return the member
477 * @param list The list handle to search for @p data
478 * @param data The data pointer to find in the list @p list
479 * @return The found member data pointer
481 * A call to this function will search the list @p list from beginning to end
482 * for the first member whose data pointer is @p data. If it is found, @p data
483 * will be returned, otherwise NULL will be returned.
487 * extern Evas_List *list;
488 * extern void *my_data;
490 * if (evas_list_find(list, my_data) == my_data)
492 * printf("Found member %p\n", my_data);
495 * @ingroup Evas_List_Find_Group
498 evas_list_find(const Evas_List *list, const void *data)
502 for (l = list; l; l = l->next)
504 if (l->data == data) return (void *)data;
510 * Find a member of a list and return the list node containing that member
511 * @param list The list handle to search for @p data
512 * @param data The data pointer to find in the list @p list
513 * @return The found members list node
515 * A call to this function will search the list @p list from beginning to end
516 * for the first member whose data pointer is @p data. If it is found, the
517 * list node containing the specified member will be returned, otherwise NULL
522 * extern Evas_List *list;
523 * extern void *my_data;
524 * Evas_List *found_node;
526 * found_node = evas_list_find_list(list, my_data);
529 * printf("Found member %p\n", found_node->data);
532 * @ingroup Evas_List_Find_Group
535 evas_list_find_list(const Evas_List *list, const void *data)
539 for (l = list; l; l = l->next)
541 if (l->data == data) return (Evas_List *)l;
547 * Free an entire list and all the nodes, ignoring the data contained
548 * @param list The list to free
549 * @return A NULL pointer
551 * This function will free all the list nodes in list specified by @p list.
555 * extern Evas_List *list;
557 * list = evas_list_free(list);
559 * @ingroup Evas_List_Remove_Group
562 evas_list_free(Evas_List *list)
564 Evas_List *l, *free_l;
566 if (!list) return NULL;
567 evas_mempool_free(&_evas_list_accounting_mempool, list->accounting);
572 evas_mempool_free(&_evas_list_mempool, free_l);
578 * @defgroup Evas_List_Traverse_Group Linked List Traverse Functions
580 * Functions that you can use to traverse a linked list.
584 * Get the last list node in the list
585 * @param list The list to get the last list node from
586 * @return The last list node in the list @p list
588 * This function will return the last list node in the list (or NULL if the
591 * NB: This is a order-1 operation (it takes the same short time regardless of
592 * the length of the list).
596 * extern Evas_List *list;
597 * Evas_List *last, *l;
599 * last = evas_list_last(list);
600 * printf("The list in reverse:\n");
601 * for (l = last; l; l = l->prev)
603 * printf("%p\n", l->data);
606 * @ingroup Evas_List_Traverse_Group
609 evas_list_last(const Evas_List *list)
611 if (!list) return NULL;
612 return list->accounting->last;
616 * Get the next list node after the specified list node
617 * @param list The list node to get the next list node from
618 * @return The next list node, or NULL if no next list node exists
620 * This function returns the next list node after the current one. It is
621 * equivalent to list->next.
625 * extern Evas_List *list;
628 * printf("The list:\n");
629 * for (l = list; l; l = evas_list_next(l))
631 * printf("%p\n", l->data);
634 * @ingroup Evas_List_Traverse_Group
637 evas_list_next(const Evas_List *list)
639 if (!list) return NULL;
644 * Get the previous list node before the specified list node
645 * @param list The list node to get the previous list node from
646 * @return The previous list node, or NULL if no previous list node exists
648 * This function returns the previous list node before the current one. It is
649 * equivalent to list->prev.
653 * extern Evas_List *list;
654 * Evas_List *last, *l;
656 * last = evas_list_last(list);
657 * printf("The list in reverse:\n");
658 * for (l = last; l; l = evas_list_prev(l))
660 * printf("%p\n", l->data);
663 * @ingroup Evas_List_Traverse_Group
666 evas_list_prev(const Evas_List *list)
668 if (!list) return NULL;
673 * @defgroup Evas_List_General_Group Linked List General Functions
675 * Miscellaneous functions that work on linked lists.
679 * Get the list node data member
680 * @param list The list node to get the data member of
681 * @return The data member from the list node @p list
683 * This function returns the data member of the specified list node @p list.
684 * It is equivalent to list->data.
688 * extern Evas_List *list;
691 * printf("The list:\n");
692 * for (l = list; l; l = evas_list_next(l))
694 * printf("%p\n", evas_list_data(l));
697 * @ingroup Evas_List_General_Group
700 evas_list_data(const Evas_List *list)
702 if (!list) return NULL;
707 * Get the count of the number of items in a list
708 * @param list The list whose count to return
709 * @return The number of members in the list @p list
711 * This function returns how many members in the specified list: @p list. If
712 * the list is empty (NULL), 0 is returned.
714 * NB: This is an order-1 operation and takes the same tiem regardless of the
715 * length of the list.
719 * extern Evas_List *list;
721 * printf("The list has %i members\n", evas_list_count(list));
723 * @ingroup Evas_List_General_Group
726 evas_list_count(const Evas_List *list)
729 return list->accounting->count;
733 * Get the nth member's data pointer in a list
734 * @param list The list to get member number @p n from
735 * @param n The number of the element (0 being the first)
736 * @return The data pointer stored in the specified element
738 * This function returns the data pointer of element number @p n, in the list
739 * @p list. The first element in the array is element number 0. If the element
740 * number @p n does not exist, NULL will be returned.
744 * extern Evas_List *list;
748 * data = evas_list_nth(list, number);
750 * printf("Element number %i has data %p\n", number, data);
752 * @ingroup Evas_List_Find_Group
755 evas_list_nth(const Evas_List *list, int n)
759 l = evas_list_nth_list(list, n);
760 return l ? l->data : NULL;
764 * Get the nth member's list node in a list
765 * @param list The list to get member number @p n from
766 * @param n The number of the element (0 being the first)
767 * @return The list node stored in the numbered element
769 * This function returns the list node of element number @p n, in the list
770 * @p list. The first element in the array is element number 0. If the element
771 * number @p n does not exist, NULL will be returned.
775 * extern Evas_List *list;
777 * Evas_List *nth_list;
779 * nth_list = evas_list_nth_list(list, number);
781 * printf("Element number %i has data %p\n", number, nth_list->data);
783 * @ingroup Evas_List_Find_Group
786 evas_list_nth_list(const Evas_List *list, int n)
791 /* check for non-existing nodes */
792 if ((!list) || (n < 0) ||
793 (n > (list->accounting->count - 1)))
796 /* if the node is in the 2nd half of the list, search from the end
797 * else, search from the beginning.
799 if (n > (list->accounting->count / 2))
801 for (i = list->accounting->count - 1,
802 l = list->accounting->last;
806 if (i == n) return (Evas_List *)l;
811 for (i = 0, l = list; l; l = l->next, i++)
813 if (i == n) return (Evas_List *)l;
820 * @defgroup Evas_List_Ordering_Group Linked List Ordering Functions
822 * Functions that change the ordering of data in a linked list.
826 * Reverse all the elements in the list
827 * @param list The list to reverse
828 * @return The list after it has been reversed
830 * This takes a list @p list, and reverses the order of all elements in the
831 * list, so the last member is now first, and so on.
835 * extern Evas_List *list;
837 * list = evas_list_reverse(list);
839 * @ingroup Evas_List_Ordering_Group
842 evas_list_reverse(Evas_List *list)
846 if (!list) return NULL;
848 l2 = list->accounting->last;
865 * Sort a list according to the ordering func will return
866 * @param list The list handle to sort
867 * @param size The length of the list to sort
868 * @param func A function pointer that can handle comparing the list data
870 * @return A new sorted list
872 * This function sorts your list. The data in your nodes can be arbitrary,
873 * you just have to be smart enough to know what kind of data is in your
879 * sort_cb(void *d1, void *d2)
881 * const char *txt = NULL;
882 * const char *txt2 = NULL;
885 * if(!d2) return(-1);
887 * return(strcmp((const char*)d1, (const char*)d2));
889 * extern Evas_List *list;
891 * list = evas_list_sort(list, evas_list_count(list), sort_cb);
892 * if (evas_list_alloc_error())
894 * fprintf(stderr, "ERROR: Memory is low. List Sorting failed.\n");
898 * @ingroup Evas_List_Ordering_Group
901 evas_list_sort(Evas_List *list, int size, int (*func)(void *, void *))
904 unsigned int list_number;
911 /* if the caller specified an invalid size, sort the whole list */
913 (size > list->accounting->count))
914 size = list->accounting->count;
916 last = list->accounting->last;
917 middle = size - size / 2;
919 for (list_number = middle, list_size = 1;
920 list_size < middle * 2;
921 list_number >>= 1, list_size <<= 1)
923 Evas_List *head1 = list;
924 unsigned int limit = size;
925 unsigned int process_list;
926 unsigned int pass_number;
927 unsigned int split_size = list_size;
929 for (process_list = 0; process_list < list_number + 1; ++process_list)
932 unsigned int size_sum;
936 size1 = limit < split_size ? limit : split_size;
939 size2 = limit < split_size ? limit : split_size;
942 size_sum = size1 + size2;
944 for (head2 = head1, i = 0; i < size1; ++i)
945 head2 = evas_list_next (head2);
947 for (pass_number = 0; pass_number < size_sum; ++pass_number)
953 if (size1 == 0 || head1 == NULL) /* List1 is empty, head1 is already at the end of the list. So only need to update head2 */
955 for (; pass_number < size_sum; ++pass_number)
956 head2 = evas_list_next (head2);
960 if (size2 == 0 || head2 == NULL) /* List2 is empty, just leave */
963 if (func (head1->data, head2->data) < 0)
965 head1 = evas_list_next (head1);
970 next = evas_list_next (head2);
971 prev1 = evas_list_prev (head1);
972 prev2 = evas_list_prev (head2);
999 list->accounting->last = last;
1003 * Return the memory allocation failure flag after any operation needin allocation
1004 * @return The state of the allocation flag
1006 * This function returns the state of the memory allocation flag. This flag is
1007 * set if memory allocations during evas_list_append(), evas_list_prepend(),
1008 * evas_list_append_relative(), or evas_list_prepend_relative() fail. If they
1009 * do fail, 1 will be returned, otherwise 0 will be returned. The flag will
1010 * remain in its current state until the next call that requires allocation
1011 * is called, and is then reset.
1015 * Evas_List *list = NULL;
1016 * extern void *my_data;
1018 * list = evas_list_append(list, my_data);
1019 * if (evas_list_alloc_error())
1021 * fprintf(stderr, "ERROR: Memory is low. List allocation failed.\n");
1025 * @ingroup Evas_List_General_Group
1028 evas_list_alloc_error(void)
1030 return _evas_list_alloc_error;