1 /* EINA - EFL data type library
2 * Copyright (C) 2002-2008 Carsten Haitzler, Gustavo Sverzut Barbieri, Tilman Sauerbeck,
3 * Vincent Torri, Cedric Bail, Jorge Luis Zapata Muga,
4 * Corey Donohoe, Arnaud de Turckheim, Alexandre Becoulet
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library;
18 * if not, see <http://www.gnu.org/licenses/>.
20 * This file incorporates work covered by the following copyright and
23 * Copyright (C) 2004 ncn
24 * Copyright (C) 2006 Sebastian Dransfeld
25 * Copyright (C) 2007 Christopher Michael
27 * Permission is hereby granted, free of charge, to any person obtaining a copy
28 * of this software and associated documentation files (the "Software"), to
29 * deal in the Software without restriction, including without limitation the
30 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
31 * sell copies of the Software, and to permit persons to whom the Software is
32 * furnished to do so, subject to the following conditions:
34 * The above copyright notice and this permission notice shall be included in
35 * all copies of the Software and its Copyright notices. In addition publicly
36 * documented acknowledgment must be given that this software has been used if no
37 * source code of this software is made available publicly. This includes
38 * acknowledgments in either Copyright notices, Manuals, Publicity and Marketing
39 * documents or any documentation provided with any product containing this
40 * software. This License does not apply to any software that links to the
41 * libraries provided by this software (statically or dynamically), but only to
42 * the software provided.
44 * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice
47 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
50 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
51 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
52 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
68 #include "eina_config.h"
69 #include "eina_private.h"
70 #include "eina_error.h"
72 #include "eina_mempool.h"
74 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
75 #include "eina_safety_checks.h"
76 #include "eina_list.h"
79 /*============================================================================*
81 *============================================================================*/
87 static const char EINA_MAGIC_LIST_STR[] = "Eina List";
88 static const char EINA_MAGIC_LIST_ITERATOR_STR[] = "Eina List Iterator";
89 static const char EINA_MAGIC_LIST_ACCESSOR_STR[] = "Eina List Accessor";
90 static const char EINA_MAGIC_LIST_ACCOUNTING_STR[] = "Eina List Accounting";
93 #define EINA_MAGIC_CHECK_LIST(d, ...) \
95 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST)) \
97 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST); \
102 #define EINA_MAGIC_CHECK_LIST_ITERATOR(d, ...) \
104 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ITERATOR)) \
106 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ITERATOR); \
107 return __VA_ARGS__; \
111 #define EINA_MAGIC_CHECK_LIST_ACCESSOR(d, ...) \
113 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ACCESSOR)) \
115 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ACCESSOR); \
116 return __VA_ARGS__; \
120 #define EINA_MAGIC_CHECK_LIST_ACCOUNTING(d) \
122 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ACCOUNTING)) \
124 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ACCOUNTING); \
129 #define EINA_LIST_SORT_STACK_SIZE 32
131 typedef struct _Eina_Iterator_List Eina_Iterator_List;
132 typedef struct _Eina_Accessor_List Eina_Accessor_List;
134 struct _Eina_Iterator_List
136 Eina_Iterator iterator;
138 const Eina_List *head;
139 const Eina_List *current;
144 struct _Eina_Accessor_List
146 Eina_Accessor accessor;
148 const Eina_List *head;
149 const Eina_List *current;
156 static Eina_Mempool *_eina_list_mp = NULL;
157 static Eina_Mempool *_eina_list_accounting_mp = NULL;
158 static int _eina_list_log_dom = -1;
163 #define ERR(...) EINA_LOG_DOM_ERR(_eina_list_log_dom, __VA_ARGS__)
168 #define DBG(...) EINA_LOG_DOM_DBG(_eina_list_log_dom, __VA_ARGS__)
170 static inline Eina_List_Accounting *
171 _eina_list_mempool_accounting_new(__UNUSED__ Eina_List *list)
173 Eina_List_Accounting *tmp;
176 eina_mempool_malloc(_eina_list_accounting_mp,
177 sizeof (Eina_List_Accounting));
181 EINA_MAGIC_SET(tmp, EINA_MAGIC_LIST_ACCOUNTING);
186 _eina_list_mempool_accounting_free(Eina_List_Accounting *accounting)
188 EINA_MAGIC_CHECK_LIST_ACCOUNTING(accounting);
190 EINA_MAGIC_SET(accounting, EINA_MAGIC_NONE);
191 eina_mempool_free(_eina_list_accounting_mp, accounting);
194 static inline Eina_List *
195 _eina_list_mempool_list_new(__UNUSED__ Eina_List *list)
199 tmp = eina_mempool_malloc(_eina_list_mp, sizeof (Eina_List));
203 EINA_MAGIC_SET(tmp, EINA_MAGIC_LIST);
208 _eina_list_mempool_list_free(Eina_List *list)
210 EINA_MAGIC_CHECK_LIST(list);
212 list->accounting->count--;
213 if (list->accounting->count == 0)
214 _eina_list_mempool_accounting_free(list->accounting);
216 EINA_MAGIC_SET(list, EINA_MAGIC_NONE);
217 eina_mempool_free(_eina_list_mp, list);
221 _eina_list_setup_accounting(Eina_List *list)
223 EINA_MAGIC_CHECK_LIST(list, NULL);
225 list->accounting = _eina_list_mempool_accounting_new(list);
226 if (!list->accounting)
229 list->accounting->last = list;
230 list->accounting->count = 1;
235 _eina_list_mempool_list_free(list);
240 _eina_list_update_accounting(Eina_List *list, Eina_List *new_list)
242 EINA_MAGIC_CHECK_LIST(list);
243 EINA_MAGIC_CHECK_LIST(new_list);
245 list->accounting->count++;
246 new_list->accounting = list->accounting;
250 static Eina_Mempool2 _eina_list_mempool =
256 static Eina_Mempool2 _eina_list_accounting_mempool =
258 sizeof(Eina_List_Accounting),
265 eina_list_iterator_next(Eina_Iterator_List *it, void **data)
267 EINA_MAGIC_CHECK_LIST_ITERATOR(it, EINA_FALSE);
272 *data = eina_list_data_get(it->current);
274 it->current = eina_list_next(it->current);
280 eina_list_iterator_prev(Eina_Iterator_List *it, void **data)
282 EINA_MAGIC_CHECK_LIST_ITERATOR(it, EINA_FALSE);
287 *data = eina_list_data_get(it->current);
289 it->current = eina_list_prev(it->current);
295 eina_list_iterator_get_container(Eina_Iterator_List *it)
297 EINA_MAGIC_CHECK_LIST_ITERATOR(it, NULL);
299 return (Eina_List *)it->head;
303 eina_list_iterator_free(Eina_Iterator_List *it)
305 EINA_MAGIC_CHECK_LIST_ITERATOR(it);
311 eina_list_accessor_get_at(Eina_Accessor_List *it, unsigned int idx, void **data)
313 const Eina_List *over;
317 EINA_MAGIC_CHECK_LIST_ACCESSOR(it, EINA_FALSE);
319 if (idx >= eina_list_count(it->head))
322 if (it->index == idx)
324 else if (idx > it->index)
326 /* After current position. */
327 middle = ((eina_list_count(it->head) - it->index) >> 1) + it->index;
330 /* Go backward from the end. */
331 for (i = eina_list_count(it->head) - 1,
332 over = eina_list_last(it->head);
334 --i, over = eina_list_prev(over))
337 /* Go forward from current. */
338 for (i = it->index, over = it->current;
340 ++i, over = eina_list_next(over))
345 /* Before current position. */
346 middle = it->index >> 1;
349 /* Go backward from current. */
350 for (i = it->index, over = it->current;
352 --i, over = eina_list_prev(over))
355 /* Go forward from start. */
356 for (i = 0, over = it->head;
358 ++i, over = eina_list_next(over))
368 *data = eina_list_data_get(it->current);
373 eina_list_accessor_get_container(Eina_Accessor_List *it)
375 EINA_MAGIC_CHECK_LIST_ACCESSOR(it, NULL);
377 return (Eina_List *)it->head;
381 eina_list_accessor_free(Eina_Accessor_List *it)
383 EINA_MAGIC_CHECK_LIST_ACCESSOR(it);
389 eina_list_sort_rebuild_prev(Eina_List *list)
391 Eina_List *prev = NULL;
393 EINA_MAGIC_CHECK_LIST(list, NULL);
395 for (; list; list = list->next)
405 eina_list_sort_merge(Eina_List *a, Eina_List *b, Eina_Compare_Cb func)
407 Eina_List *first, *last;
409 if (func(a->data, b->data) < 0)
410 a = (last = first = a)->next;
412 b = (last = first = b)->next;
415 if (func(a->data, b->data) < 0)
416 a = (last = last->next = a)->next;
418 b = (last = last->next = b)->next;
420 last->next = a ? a : b;
429 /*============================================================================*
431 *============================================================================*/
435 * @brief Initialize the list module.
437 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
439 * This function sets up the list module of Eina. It is called by
442 * This function creates mempool to speed up list node and accounting
443 * management, using EINA_MEMPOOL environment variable if it is set to
444 * choose the memory pool type to use.
451 const char *choice, *tmp;
453 _eina_list_log_dom = eina_log_domain_register("eina_list",
454 EINA_LOG_COLOR_DEFAULT);
455 if (_eina_list_log_dom < 0)
457 EINA_LOG_ERR("Could not register log domain: eina_list");
461 #ifdef EINA_DEFAULT_MEMPOOL
462 choice = "pass_through";
464 choice = "chained_mempool";
466 tmp = getenv("EINA_MEMPOOL");
470 _eina_list_mp = eina_mempool_add
471 (choice, "list", NULL, sizeof(Eina_List), 128);
474 ERR("ERROR: Mempool for list cannot be allocated in list init.");
478 _eina_list_accounting_mp = eina_mempool_add
479 (choice, "list_accounting", NULL, sizeof(Eina_List_Accounting), 16);
480 if (!_eina_list_accounting_mp)
483 "ERROR: Mempool for list accounting cannot be allocated in list init.");
484 eina_mempool_del(_eina_list_mp);
488 #define EMS(n) eina_magic_string_static_set(n, n ## _STR)
489 EMS(EINA_MAGIC_LIST);
490 EMS(EINA_MAGIC_LIST_ITERATOR);
491 EMS(EINA_MAGIC_LIST_ACCESSOR);
492 EMS(EINA_MAGIC_LIST_ACCOUNTING);
498 eina_log_domain_unregister(_eina_list_log_dom);
499 _eina_list_log_dom = -1;
505 * @brief Shut down the list module.
507 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
509 * This function shuts down the list module set up by
510 * eina_list_init(). It is called by eina_shutdown().
512 * @see eina_shutdown()
515 eina_list_shutdown(void)
517 eina_mempool_del(_eina_list_accounting_mp);
518 eina_mempool_del(_eina_list_mp);
520 eina_log_domain_unregister(_eina_list_log_dom);
521 _eina_list_log_dom = -1;
525 /*============================================================================*
527 *============================================================================*/
530 eina_list_append(Eina_List *list, const void *data)
532 Eina_List *l, *new_l;
535 new_l = _eina_list_mempool_list_new(list);
540 new_l->data = (void *)data;
544 return _eina_list_setup_accounting(new_l);
547 EINA_MAGIC_CHECK_LIST(list, NULL);
549 l = list->accounting->last;
550 list->accounting->last = new_l;
555 _eina_list_update_accounting(list, new_l);
560 eina_list_prepend(Eina_List *list, const void *data)
565 new_l = _eina_list_mempool_list_new(list);
571 new_l->data = (void *)data;
574 return _eina_list_setup_accounting(new_l);
576 EINA_MAGIC_CHECK_LIST(list, NULL);
580 _eina_list_update_accounting(list, new_l);
586 eina_list_append_relative(Eina_List *list,
588 const void *relative)
594 EINA_MAGIC_CHECK_LIST(list, NULL);
596 EINA_LIST_FOREACH(list, l, list_data)
598 if (list_data == relative)
599 return eina_list_append_relative_list(list, data, l);
602 return eina_list_append(list, data);
606 eina_list_append_relative_list(Eina_List *list,
612 if ((!list) || (!relative))
613 return eina_list_append(list, data);
616 new_l = _eina_list_mempool_list_new(list);
620 EINA_MAGIC_CHECK_LIST(relative, NULL);
621 new_l->next = relative->next;
622 new_l->data = (void *)data;
625 relative->next->prev = new_l;
627 relative->next = new_l;
628 new_l->prev = relative;
630 _eina_list_update_accounting(list, new_l);
633 new_l->accounting->last = new_l;
639 eina_list_prepend_relative(Eina_List *list,
641 const void *relative)
647 EINA_MAGIC_CHECK_LIST(list, NULL);
649 EINA_LIST_FOREACH(list, l, list_data)
651 if (list_data == relative)
652 return eina_list_prepend_relative_list(list, data, l);
654 return eina_list_prepend(list, data);
658 eina_list_prepend_relative_list(Eina_List *list,
664 if ((!list) || (!relative))
665 return eina_list_prepend(list, data);
668 new_l = _eina_list_mempool_list_new(list);
672 EINA_MAGIC_CHECK_LIST(relative, NULL);
674 new_l->prev = relative->prev;
675 new_l->next = relative;
676 new_l->data = (void *)data;
679 relative->prev->next = new_l;
681 relative->prev = new_l;
683 _eina_list_update_accounting(list, new_l);
692 eina_list_sorted_insert(Eina_List *list, Eina_Compare_Cb func, const void *data)
698 return eina_list_append(NULL, data);
700 lnear = eina_list_search_sorted_near_list(list, func, data, &cmp);
702 return eina_list_append_relative_list(list, data, lnear);
704 return eina_list_prepend_relative_list(list, data, lnear);
708 eina_list_remove(Eina_List *list, const void *data)
713 EINA_MAGIC_CHECK_LIST(list, NULL);
715 l = eina_list_data_find_list(list, data);
716 return eina_list_remove_list(list, l);
720 eina_list_remove_list(Eina_List *list, Eina_List *remove_list)
730 EINA_MAGIC_CHECK_LIST(remove_list, NULL);
732 if (remove_list->next)
733 remove_list->next->prev = remove_list->prev;
735 if (remove_list->prev)
737 remove_list->prev->next = remove_list->next;
741 return_l = remove_list->next;
743 if (remove_list == remove_list->accounting->last)
745 EINA_MAGIC_CHECK_LIST(list, NULL);
746 list->accounting->last = remove_list->prev;
749 _eina_list_mempool_list_free(remove_list);
754 eina_list_free(Eina_List *list)
756 Eina_List *l, *free_l;
761 EINA_MAGIC_CHECK_LIST(list, NULL);
768 _eina_list_mempool_list_free(free_l);
775 eina_list_promote_list(Eina_List *list, Eina_List *move_list)
782 return list; /* Promoting head to be head. */
786 if (move_list == list)
789 if (move_list->next == list)
792 EINA_MAGIC_CHECK_LIST(list, NULL);
793 EINA_MAGIC_CHECK_LIST(move_list, NULL);
795 /* Remove the promoted item from the list. */
796 if (!move_list->prev)
797 move_list->next->prev = NULL;
800 move_list->prev->next = move_list->next;
801 if (move_list == list->accounting->last)
802 list->accounting->last = move_list->prev;
804 move_list->next->prev = move_list->prev;
807 /* Add the promoted item in the list. */
808 move_list->next = list;
809 move_list->prev = list->prev;
810 list->prev = move_list;
812 move_list->prev->next = move_list;
818 eina_list_demote_list(Eina_List *list, Eina_List *move_list)
825 return list; /* Demoting tail to be tail. */
829 if (move_list == list->accounting->last)
832 EINA_MAGIC_CHECK_LIST(list, NULL);
833 EINA_MAGIC_CHECK_LIST(move_list, NULL);
835 /* Update pointer list if necessary. */
836 if (list == move_list)
838 list = move_list->next; /* Remove the demoted item from the list. */
843 move_list->prev->next = move_list->next;
845 move_list->next->prev = move_list->prev;
846 /* Add the demoted item in the list. */
847 move_list->prev = list->accounting->last;
848 move_list->prev->next = move_list;
849 move_list->next = NULL;
850 list->accounting->last = move_list;
856 eina_list_data_find(const Eina_List *list, const void *data)
858 if (eina_list_data_find_list(list, data))
865 eina_list_move(Eina_List **to, Eina_List **from, void *data)
869 EINA_SAFETY_ON_NULL_RETURN_VAL(to, EINA_FALSE);
870 EINA_SAFETY_ON_NULL_RETURN_VAL(from, EINA_FALSE);
871 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
873 if (*to) EINA_MAGIC_CHECK_LIST(*to, EINA_FALSE);
874 EINA_MAGIC_CHECK_LIST(*from, EINA_FALSE);
876 l = eina_list_data_find_list(*from, data);
877 EINA_SAFETY_ON_NULL_RETURN_VAL(l, EINA_FALSE);
879 *to = eina_list_append(*to, data);
880 *from = eina_list_remove_list(*from, l);
885 eina_list_move_list(Eina_List **to, Eina_List **from, Eina_List *data)
887 EINA_SAFETY_ON_NULL_RETURN_VAL(to, EINA_FALSE);
888 EINA_SAFETY_ON_NULL_RETURN_VAL(from, EINA_FALSE);
890 if (*to) EINA_MAGIC_CHECK_LIST(*to, EINA_FALSE);
891 EINA_MAGIC_CHECK_LIST(*from, EINA_FALSE);
892 EINA_MAGIC_CHECK_LIST(data, EINA_FALSE);
894 *to = eina_list_append(*to, data->data);
895 *from = eina_list_remove_list(*from, data);
900 eina_list_data_find_list(const Eina_List *list, const void *data)
906 EINA_MAGIC_CHECK_LIST(list, NULL);
908 EINA_LIST_FOREACH(list, l, list_data)
910 if (list_data == data)
911 return (Eina_List *)l;
918 eina_list_nth(const Eina_List *list, unsigned int n)
922 l = eina_list_nth_list(list, n);
923 return l ? l->data : NULL;
927 eina_list_nth_list(const Eina_List *list, unsigned int n)
933 EINA_MAGIC_CHECK_LIST(list, NULL);
935 /* check for non-existing nodes */
936 if ((!list) || (n > (list->accounting->count - 1)))
939 /* if the node is in the 2nd half of the list, search from the end
940 * else, search from the beginning.
942 if (n > (list->accounting->count / 2))
943 for (i = list->accounting->count - 1,
944 l = list->accounting->last;
949 return (Eina_List *)l;
952 for (i = 0, l = list; l; l = l->next, i++)
955 return (Eina_List *)l;
962 eina_list_reverse(Eina_List *list)
969 EINA_MAGIC_CHECK_LIST(list, NULL);
972 l2 = list->accounting->last;
991 eina_list_reverse_clone(const Eina_List *list)
1000 EINA_MAGIC_CHECK_LIST(list, NULL);
1003 EINA_LIST_FOREACH(list, l, data)
1004 lclone = eina_list_prepend(lclone, data);
1010 eina_list_clone(const Eina_List *list)
1019 EINA_MAGIC_CHECK_LIST(list, NULL);
1022 EINA_LIST_FOREACH(list, l, data)
1023 lclone = eina_list_append(lclone, data);
1029 eina_list_sort(Eina_List *list, unsigned int limit, Eina_Compare_Cb func)
1033 Eina_List *tail = list;
1034 Eina_List *unsort = NULL;
1035 Eina_List *stack[EINA_LIST_SORT_STACK_SIZE];
1037 EINA_SAFETY_ON_NULL_RETURN_VAL(func, list);
1041 EINA_MAGIC_CHECK_LIST(list, NULL);
1043 /* if the caller specified an invalid limit, sort the whole list */
1045 (limit > list->accounting->count))
1046 limit = list->accounting->count;
1048 if (limit != list->accounting->count)
1050 unsort = eina_list_nth_list(list, limit);
1052 unsort->prev->next = NULL;
1057 unsigned int idx, tmp;
1059 Eina_List *a = tail;
1060 Eina_List *b = tail->next;
1070 if (func(a->data, b->data) < 0)
1071 ((stack[i++] = a)->next = b)->next = 0;
1073 ((stack[i++] = b)->next = a)->next = 0;
1076 for (idx = n ^ tmp; idx &= idx - 1; i--)
1077 stack[i - 2] = eina_list_sort_merge(stack[i - 2], stack[i - 1], func);
1081 stack[i - 1] = eina_list_sort_merge(stack[i - 1], stack[i], func);
1084 tail = eina_list_sort_rebuild_prev(list);
1088 tail->next = unsort;
1089 unsort->prev = tail;
1092 list->accounting->last = tail;
1098 eina_list_merge(Eina_List *left, Eina_List *right)
1100 unsigned int n_left, n_right;
1108 left->accounting->last->next = right;
1109 right->prev = left->accounting->last;
1111 n_left = left->accounting->count;
1112 n_right = right->accounting->count;
1114 if (n_left >= n_right)
1116 Eina_List *itr = right;
1117 left->accounting->last = right->accounting->last;
1118 left->accounting->count += n_right;
1120 _eina_list_mempool_accounting_free(right->accounting);
1124 itr->accounting = left->accounting;
1131 Eina_List *itr = left->accounting->last;
1132 right->accounting->count += n_left;
1134 _eina_list_mempool_accounting_free(left->accounting);
1138 itr->accounting = right->accounting;
1149 eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right)
1168 if (relative == eina_list_last(list))
1171 next = eina_list_next(relative);
1173 next->accounting = _eina_list_mempool_accounting_new(next);
1174 next->accounting->last = list->accounting->last;
1175 next->accounting->count = 0;
1181 itr->accounting = next->accounting;
1182 next->accounting->count++;
1187 relative->next = NULL;
1188 list->accounting->last = relative;
1189 list->accounting->count = list->accounting->count - next->accounting->count;
1195 eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func)
1200 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1208 if (func(left->data, right->data) < 0)
1213 ret->accounting->count += right->accounting->count;
1215 _eina_list_mempool_accounting_free(right->accounting);
1221 right = right->next;
1222 ret->accounting->count += left->accounting->count;
1224 _eina_list_mempool_accounting_free(left->accounting);
1227 while (left && right)
1229 if (func(left->data, right->data) < 0)
1231 current->next = left;
1232 left->prev = current;
1237 current->next = right;
1238 right->prev = current;
1239 right = right->next;
1242 current = current->next;
1243 current->accounting = ret->accounting;
1248 current->next = left;
1249 left->prev = current;
1250 current->accounting = ret->accounting;
1255 current->next = right;
1256 right->prev = current;
1257 current->accounting = ret->accounting;
1260 while (current->next)
1262 current = current->next;
1263 current->accounting = ret->accounting;
1266 ret->accounting->last = current;
1272 eina_list_search_sorted_near_list(const Eina_List *list,
1273 Eina_Compare_Cb func,
1277 const Eina_List *ct;
1278 unsigned int inf, sup, cur;
1289 if (list->accounting->count == 1)
1292 *result_cmp = func(list->data, data);
1294 return (Eina_List *)list;
1297 /* list walk is expensive, do quick check: tail */
1298 ct = list->accounting->last;
1299 cmp = func(ct->data, data);
1303 /* list walk is expensive, do quick check: head */
1305 cmp = func(ct->data, data);
1309 /* inclusive bounds */
1311 sup = list->accounting->count - 2;
1315 /* no loop, just compare if comparison value is important to caller */
1319 cmp = func(ct->data, data);
1326 unsigned int tmp = cur;
1327 cur = inf + ((sup - inf) >> 1);
1329 for (; tmp != cur; tmp++, ct = ct->next) ;
1331 for (; tmp != cur; tmp--, ct = ct->prev) ;
1333 cmp = func(ct->data, data);
1353 return (Eina_List *)ct;
1357 eina_list_search_sorted_list(const Eina_List *list,
1358 Eina_Compare_Cb func,
1364 lnear = eina_list_search_sorted_near_list(list, func, data, &cmp);
1376 eina_list_search_sorted(const Eina_List *list,
1377 Eina_Compare_Cb func,
1380 return eina_list_data_get(eina_list_search_sorted_list(list, func, data));
1384 eina_list_search_unsorted_list(const Eina_List *list,
1385 Eina_Compare_Cb func,
1391 EINA_LIST_FOREACH(list, l, d)
1394 return (Eina_List *)l;
1400 eina_list_search_unsorted(const Eina_List *list,
1401 Eina_Compare_Cb func,
1404 return eina_list_data_get(eina_list_search_unsorted_list(list, func, data));
1408 EAPI Eina_Iterator *
1409 eina_list_iterator_new(const Eina_List *list)
1411 Eina_Iterator_List *it;
1414 it = calloc(1, sizeof (Eina_Iterator_List));
1417 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1421 EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR);
1422 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1427 it->iterator.version = EINA_ITERATOR_VERSION;
1428 it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_next);
1429 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1430 eina_list_iterator_get_container);
1431 it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free);
1433 return &it->iterator;
1436 EAPI Eina_Iterator *
1437 eina_list_iterator_reversed_new(const Eina_List *list)
1439 Eina_Iterator_List *it;
1442 it = calloc(1, sizeof (Eina_Iterator_List));
1445 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1449 EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR);
1450 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1452 it->head = eina_list_last(list);
1453 it->current = it->head;
1455 it->iterator.version = EINA_ITERATOR_VERSION;
1456 it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_prev);
1457 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1458 eina_list_iterator_get_container);
1459 it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free);
1461 return &it->iterator;
1464 EAPI Eina_Accessor *
1465 eina_list_accessor_new(const Eina_List *list)
1467 Eina_Accessor_List *ac;
1470 ac = calloc(1, sizeof (Eina_Accessor_List));
1473 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
1477 EINA_MAGIC_SET(ac, EINA_MAGIC_LIST_ACCESSOR);
1478 EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR);
1484 ac->accessor.version = EINA_ACCESSOR_VERSION;
1485 ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_list_accessor_get_at);
1486 ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(
1487 eina_list_accessor_get_container);
1488 ac->accessor.free = FUNC_ACCESSOR_FREE(eina_list_accessor_free);
1490 return &ac->accessor;