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
5 *
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.
10 *
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.
15 *
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/>.
19 *
20 * This file incorporates work covered by the following copyright and
21 * permission notice:
22 *
23 * Copyright (C) 2004 ncn
24 * Copyright (C) 2006 Sebastian Dransfeld
25 * Copyright (C) 2007 Christopher Michael
26 *
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:
33
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.
43
44 * Please see the OLD-COPYING.PLAIN for a plain-english explanation of this notice
45 * and it's intent.
46
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.
53 */
54
55
56 #ifdef HAVE_CONFIG_H
57 # include "config.h"
58 #endif
59
60 #include <stdlib.h>
61 #include <stdio.h>
62 #include <string.h>
63 #include <time.h>
64
65 #include "eina_config.h"
66 #include "eina_private.h"
67 #include "eina_log.h"
68 #include "eina_mempool.h"
69
70 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
71 #include "eina_safety_checks.h"
72 #include "eina_list.h"
73 #include "eina_freeq.h"
74
75
76 /*============================================================================*
77 * Local *
78 *============================================================================*/
79
80 /**
81 * @cond LOCAL
82 */
83
84 static const char EINA_MAGIC_LIST_ITERATOR_STR[] = "Eina List Iterator";
85 static const char EINA_MAGIC_LIST_ACCESSOR_STR[] = "Eina List Accessor";
86 #ifdef EINA_LIST_MAGIC
87 static const char EINA_MAGIC_LIST_STR[] = "Eina List";
88 static const char EINA_MAGIC_LIST_ACCOUNTING_STR[] = "Eina List Accounting";
89
90
91 #define EINA_MAGIC_CHECK_LIST(d, ...) \
92 do { \
93 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST)) \
94 { \
95 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST); \
96 return __VA_ARGS__; \
97 } \
98 } while(0)
99
100 #define EINA_MAGIC_CHECK_LIST_GOTO(d, label) \
101 do { \
102 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST)) \
103 { \
104 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST); \
105 goto label; \
106 } \
107 } while(0)
108
109 #define EINA_MAGIC_CHECK_LIST_ACCOUNTING(d) \
110 do { \
111 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ACCOUNTING)) \
112 { \
113 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ACCOUNTING); \
114 return; \
115 } \
116 } while(0)
117 #endif
118
119 #define EINA_MAGIC_CHECK_LIST_ITERATOR(d, ...) \
120 do { \
121 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ITERATOR)) \
122 { \
123 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ITERATOR); \
124 return __VA_ARGS__; \
125 } \
126 } while(0)
127
128 #define EINA_MAGIC_CHECK_LIST_ACCESSOR(d, ...) \
129 do { \
130 if (!EINA_MAGIC_CHECK(d, EINA_MAGIC_LIST_ACCESSOR)) \
131 { \
132 EINA_MAGIC_FAIL(d, EINA_MAGIC_LIST_ACCESSOR); \
133 return __VA_ARGS__; \
134 } \
135 } while(0)
136
137
138 #define EINA_LIST_SORT_STACK_SIZE 32
139
140 typedef struct _Eina_Iterator_List Eina_Iterator_List;
141 typedef struct _Eina_Accessor_List Eina_Accessor_List;
142
143 struct _Eina_Iterator_List
144 {
145 Eina_Iterator iterator;
146
147 const Eina_List *head;
148 const Eina_List *current;
149 EINA_MAGIC
150 };
151
152 struct _Eina_Accessor_List
153 {
154 Eina_Accessor accessor;
155
156 const Eina_List *head;
157 const Eina_List *current;
158
159 unsigned int index;
160 EINA_MAGIC
161 };
162
163 static Eina_Mempool *_eina_list_mp = NULL;
164 static Eina_Mempool *_eina_list_accounting_mp = NULL;
165 static int _eina_list_log_dom = -1;
166
167 #ifdef ERR
168 #undef ERR
169 #endif
170 #define ERR(...) EINA_LOG_DOM_ERR(_eina_list_log_dom, __VA_ARGS__)
171
172 #ifdef DBG
173 #undef DBG
174 #endif
175 #define DBG(...) EINA_LOG_DOM_DBG(_eina_list_log_dom, __VA_ARGS__)
176
177 static inline Eina_List_Accounting *
_eina_list_mempool_accounting_new(EINA_UNUSED Eina_List * list)178 _eina_list_mempool_accounting_new(EINA_UNUSED Eina_List *list)
179 {
180 Eina_List_Accounting *tmp;
181
182 tmp =
183 eina_mempool_malloc(_eina_list_accounting_mp,
184 sizeof (Eina_List_Accounting));
185 if (!tmp)
186 return NULL;
187 #ifdef EINA_LIST_MAGIC
188 EINA_MAGIC_SET(tmp, EINA_MAGIC_LIST_ACCOUNTING);
189 #endif
190 return tmp;
191 }
192
193 static void
_eina_list_accounting_free(void * accounting)194 _eina_list_accounting_free(void *accounting)
195 {
196 eina_mempool_free(_eina_list_accounting_mp, accounting);
197 }
198
199 static void
_eina_list_list_free(void * list)200 _eina_list_list_free(void *list)
201 {
202 eina_mempool_free(_eina_list_mp, list);
203 }
204
205 static inline void
_eina_list_mempool_accounting_free(Eina_List_Accounting * accounting)206 _eina_list_mempool_accounting_free(Eina_List_Accounting *accounting)
207 {
208 #ifdef EINA_LIST_MAGIC
209 EINA_MAGIC_CHECK_LIST_ACCOUNTING(accounting);
210 EINA_MAGIC_SET(accounting, EINA_MAGIC_NONE);
211 #endif
212 eina_freeq_ptr_main_add(accounting, _eina_list_accounting_free, sizeof(*accounting));
213 }
214
215 static inline Eina_List *
_eina_list_mempool_list_new(Eina_List * before,Eina_List * after)216 _eina_list_mempool_list_new(Eina_List *before, Eina_List *after)
217 {
218 Eina_List *tmp;
219
220 tmp = eina_mempool_malloc_near(_eina_list_mp, before, after, sizeof (Eina_List));
221 if (!tmp)
222 return NULL;
223 #ifdef EINA_LIST_MAGIC
224 EINA_MAGIC_SET(tmp, EINA_MAGIC_LIST);
225 #endif
226 return tmp;
227 }
228 static inline void
_eina_list_mempool_list_free(Eina_List * list)229 _eina_list_mempool_list_free(Eina_List *list)
230 {
231 #ifdef EINA_LIST_MAGIC
232 EINA_MAGIC_CHECK_LIST(list);
233 #endif
234 if (list->accounting)
235 {
236 list->accounting->count--;
237 if (list->accounting->count == 0)
238 _eina_list_mempool_accounting_free(list->accounting);
239 }
240 #ifdef EINA_LIST_MAGIC
241 EINA_MAGIC_SET(list, EINA_MAGIC_NONE);
242 #endif
243 eina_freeq_ptr_main_add(list, _eina_list_list_free, sizeof(*list));
244 }
245
246 static Eina_List *
_eina_list_setup_accounting(Eina_List * list)247 _eina_list_setup_accounting(Eina_List *list)
248 {
249 #ifdef EINA_LIST_MAGIC
250 EINA_MAGIC_CHECK_LIST(list, NULL);
251 #endif
252 list->accounting = _eina_list_mempool_accounting_new(list);
253 if (!list->accounting)
254 goto on_error;
255
256 list->accounting->last = list;
257 list->accounting->count = 1;
258
259 return list;
260
261 on_error:
262 _eina_list_mempool_list_free(list);
263 return NULL;
264 }
265
266 static inline void
_eina_list_update_accounting(Eina_List * list,Eina_List * new_list)267 _eina_list_update_accounting(Eina_List *list, Eina_List *new_list)
268 {
269 #ifdef EINA_LIST_MAGIC
270 EINA_MAGIC_CHECK_LIST(list);
271 EINA_MAGIC_CHECK_LIST(new_list);
272 #endif
273 list->accounting->count++;
274 new_list->accounting = list->accounting;
275 }
276
277 #if 0
278 static Eina_Mempool2 _eina_list_mempool =
279 {
280 sizeof(Eina_List),
281 320,
282 0, NULL, NULL
283 };
284 static Eina_Mempool2 _eina_list_accounting_mempool =
285 {
286 sizeof(Eina_List_Accounting),
287 80,
288 0, NULL, NULL
289 };
290 #endif
291
292 static Eina_Bool
eina_list_iterator_next(Eina_Iterator_List * it,void ** data)293 eina_list_iterator_next(Eina_Iterator_List *it, void **data)
294 {
295 EINA_MAGIC_CHECK_LIST_ITERATOR(it, EINA_FALSE);
296 if (!it->current)
297 return EINA_FALSE;
298
299 *data = eina_list_data_get(it->current);
300
301 it->current = eina_list_next(it->current);
302
303 return EINA_TRUE;
304 }
305
306 static Eina_Bool
eina_list_iterator_prev(Eina_Iterator_List * it,void ** data)307 eina_list_iterator_prev(Eina_Iterator_List *it, void **data)
308 {
309 EINA_MAGIC_CHECK_LIST_ITERATOR(it, EINA_FALSE);
310 if (!it->current)
311 return EINA_FALSE;
312
313 *data = eina_list_data_get(it->current);
314
315 it->current = eina_list_prev(it->current);
316
317 return EINA_TRUE;
318 }
319
320 static Eina_List *
eina_list_iterator_get_container(Eina_Iterator_List * it)321 eina_list_iterator_get_container(Eina_Iterator_List *it)
322 {
323 EINA_MAGIC_CHECK_LIST_ITERATOR(it, NULL);
324 return (Eina_List *)it->head;
325 }
326
327 static void
eina_list_iterator_free(Eina_Iterator_List * it)328 eina_list_iterator_free(Eina_Iterator_List *it)
329 {
330 EINA_MAGIC_CHECK_LIST_ITERATOR(it);
331 MAGIC_FREE(it);
332 }
333
334 static Eina_Bool
eina_list_accessor_get_at(Eina_Accessor_List * it,unsigned int idx,void ** data)335 eina_list_accessor_get_at(Eina_Accessor_List *it, unsigned int idx, void **data)
336 {
337 const Eina_List *over;
338 unsigned int middle;
339 unsigned int i;
340
341 EINA_MAGIC_CHECK_LIST_ACCESSOR(it, EINA_FALSE);
342 if (idx >= eina_list_count(it->head))
343 return EINA_FALSE;
344
345 if (it->index == idx)
346 over = it->current;
347 else if (idx > it->index)
348 {
349 /* After current position. */
350 middle = ((eina_list_count(it->head) - it->index) >> 1) + it->index;
351
352 if (idx > middle)
353 /* Go backward from the end. */
354 for (i = eina_list_count(it->head) - 1,
355 over = eina_list_last(it->head);
356 i > idx && over;
357 --i, over = eina_list_prev(over))
358 ;
359 else
360 /* Go forward from current. */
361 for (i = it->index, over = it->current;
362 i < idx && over;
363 ++i, over = eina_list_next(over))
364 ;
365 }
366 else
367 {
368 /* Before current position. */
369 middle = it->index >> 1;
370
371 if (idx > middle)
372 /* Go backward from current. */
373 for (i = it->index, over = it->current;
374 i > idx && over;
375 --i, over = eina_list_prev(over))
376 ;
377 else
378 /* Go forward from start. */
379 for (i = 0, over = it->head;
380 i < idx && over;
381 ++i, over = eina_list_next(over))
382 ;
383 }
384
385 if (!over)
386 return EINA_FALSE;
387
388 it->current = over;
389 it->index = idx;
390
391 *data = eina_list_data_get(it->current);
392 return EINA_TRUE;
393 }
394
395 static Eina_List *
eina_list_accessor_get_container(Eina_Accessor_List * it)396 eina_list_accessor_get_container(Eina_Accessor_List *it)
397 {
398 EINA_MAGIC_CHECK_LIST_ACCESSOR(it, NULL);
399 return (Eina_List *)it->head;
400 }
401
402 static void
eina_list_accessor_free(Eina_Accessor_List * it)403 eina_list_accessor_free(Eina_Accessor_List *it)
404 {
405 EINA_MAGIC_CHECK_LIST_ACCESSOR(it);
406 MAGIC_FREE(it);
407 }
408
409 static Eina_Accessor*
eina_list_accessor_clone(Eina_Accessor_List * list)410 eina_list_accessor_clone(Eina_Accessor_List *list)
411 {
412 Eina_Accessor_List *ac;
413
414 EINA_MAGIC_CHECK_LIST_ACCESSOR(list, NULL);
415 EINA_SAFETY_ON_NULL_RETURN_VAL(list, NULL);
416
417 ac = calloc(1, sizeof (Eina_Accessor_List));
418 if (!ac) return NULL;
419
420 memcpy(ac, list, sizeof(Eina_Accessor_List));
421
422 return &ac->accessor;
423 }
424
425 static Eina_List *
eina_list_sort_rebuild_prev(Eina_List * list)426 eina_list_sort_rebuild_prev(Eina_List *list)
427 {
428 Eina_List *prev = NULL;
429
430 #ifdef EINA_LIST_MAGIC
431 EINA_MAGIC_CHECK_LIST(list, NULL);
432 #endif
433 for (; list; list = list->next)
434 {
435 list->prev = prev;
436 prev = list;
437 }
438
439 return prev;
440 }
441
442 static Eina_List *
eina_list_sort_merge(Eina_List * a,Eina_List * b,Eina_Compare_Cb func)443 eina_list_sort_merge(Eina_List *a, Eina_List *b, Eina_Compare_Cb func)
444 {
445 Eina_List *first, *last;
446
447 if (func(a->data, b->data) < 0)
448 a = (last = first = a)->next;
449 else
450 b = (last = first = b)->next;
451
452 while (a && b)
453 if (func(a->data, b->data) < 0)
454 a = (last = last->next = a)->next;
455 else
456 b = (last = last->next = b)->next;
457
458 last->next = a ? a : b;
459
460 return first;
461 }
462
463 /**
464 * @endcond
465 */
466
467 /*============================================================================*
468 * Global *
469 *============================================================================*/
470
471 static int _eina_list_init = 0;
472
473 /**
474 * @internal
475 * @brief Initialize the list module.
476 *
477 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
478 *
479 * This function sets up the list module of Eina. It is called by
480 * eina_init().
481 *
482 * This function creates mempool to speed up list node and accounting
483 * management, using EINA_MEMPOOL environment variable if it is set to
484 * choose the memory pool type to use.
485 *
486 * @see eina_init()
487 */
488 Eina_Bool
eina_list_init(void)489 eina_list_init(void)
490 {
491 const char *choice, *tmp;
492
493 if ((_eina_list_init++) > 0)
494 return _eina_list_init;
495
496 _eina_list_log_dom = eina_log_domain_register("eina_list",
497 EINA_LOG_COLOR_DEFAULT);
498 if (_eina_list_log_dom < 0)
499 {
500 EINA_LOG_ERR("Could not register log domain: eina_list");
501 return EINA_FALSE;
502 }
503
504 #ifdef EINA_DEFAULT_MEMPOOL
505 choice = "pass_through";
506 #else
507 choice = "chained_mempool";
508 #endif
509 tmp = getenv("EINA_MEMPOOL");
510 if (tmp && tmp[0])
511 choice = tmp;
512
513 _eina_list_mp = eina_mempool_add
514 (choice, "list", NULL, sizeof(Eina_List), 128);
515 if (!_eina_list_mp)
516 {
517 ERR("ERROR: Mempool for list cannot be allocated in list init.");
518 goto on_init_fail;
519 }
520
521 _eina_list_accounting_mp = eina_mempool_add
522 (choice, "list_accounting", NULL, sizeof(Eina_List_Accounting), 16);
523 if (!_eina_list_accounting_mp)
524 {
525 ERR(
526 "ERROR: Mempool for list accounting cannot be allocated in list init.");
527 eina_mempool_del(_eina_list_mp);
528 goto on_init_fail;
529 }
530
531 #define EMS(n) eina_magic_string_static_set(n, n ## _STR)
532 #ifdef EINA_LIST_MAGIC
533 EMS(EINA_MAGIC_LIST);
534 EMS(EINA_MAGIC_LIST_ACCOUNTING);
535 #endif
536 EMS(EINA_MAGIC_LIST_ITERATOR);
537 EMS(EINA_MAGIC_LIST_ACCESSOR);
538 #undef EMS
539
540 return EINA_TRUE;
541
542 on_init_fail:
543 eina_log_domain_unregister(_eina_list_log_dom);
544 _eina_list_log_dom = -1;
545 return EINA_FALSE;
546 }
547
548 /**
549 * @internal
550 * @brief Shut down the list module.
551 *
552 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
553 *
554 * This function shuts down the list module set up by
555 * eina_list_init(). It is called by eina_shutdown().
556 *
557 * @see eina_shutdown()
558 */
559 Eina_Bool
eina_list_shutdown(void)560 eina_list_shutdown(void)
561 {
562 if ((--_eina_list_init) != 0)
563 {
564 if (_eina_list_init < 0) _eina_list_init = 0;
565 return _eina_list_init;
566 }
567
568 eina_freeq_clear(eina_freeq_main_get());
569 eina_mempool_del(_eina_list_accounting_mp);
570 eina_mempool_del(_eina_list_mp);
571 _eina_list_accounting_mp = NULL;
572 _eina_list_mp = NULL;
573
574 eina_log_domain_unregister(_eina_list_log_dom);
575 _eina_list_log_dom = -1;
576 return EINA_TRUE;
577 }
578
579 /*============================================================================*
580 * API *
581 *============================================================================*/
582
583 EAPI Eina_List *
eina_list_append(Eina_List * list,const void * data)584 eina_list_append(Eina_List *list, const void *data)
585 {
586 Eina_List *l, *new_l;
587
588 new_l = _eina_list_mempool_list_new(NULL, list);
589 if (!new_l) return list;
590
591 new_l->next = NULL;
592 new_l->data = (void *)data;
593 if (!list)
594 {
595 new_l->prev = NULL;
596 return _eina_list_setup_accounting(new_l);
597 }
598
599 #ifdef EINA_LIST_MAGIC
600 EINA_MAGIC_CHECK_LIST_GOTO(list, on_error);
601 #endif
602 l = list->accounting->last;
603 list->accounting->last = new_l;
604
605 l->next = new_l;
606 new_l->prev = l;
607
608 _eina_list_update_accounting(list, new_l);
609 return list;
610 #ifdef EINA_LIST_MAGIC
611 on_error:
612 _eina_list_mempool_list_free(new_l);
613 return NULL;
614 #endif
615 }
616
617 EAPI Eina_List *
eina_list_prepend(Eina_List * list,const void * data)618 eina_list_prepend(Eina_List *list, const void *data)
619 {
620 Eina_List *new_l;
621
622 new_l = _eina_list_mempool_list_new(list, NULL);
623 if (!new_l) return list;
624
625 new_l->prev = NULL;
626 new_l->next = list;
627 new_l->data = (void *)data;
628
629 if (!list)
630 return _eina_list_setup_accounting(new_l);
631
632 #ifdef EINA_LIST_MAGIC
633 EINA_MAGIC_CHECK_LIST_GOTO(list, on_error);
634 #endif
635 list->prev = new_l;
636
637 _eina_list_update_accounting(list, new_l);
638
639 return new_l;
640
641 #ifdef EINA_LIST_MAGIC
642 on_error:
643 _eina_list_mempool_list_free(new_l);
644 return NULL;
645 #endif
646 }
647
648 EAPI Eina_List *
eina_list_append_relative(Eina_List * list,const void * data,const void * relative)649 eina_list_append_relative(Eina_List *list,
650 const void *data,
651 const void *relative)
652 {
653 Eina_List *l;
654 void *list_data;
655
656 #ifdef EINA_LIST_MAGIC
657 if (list)
658 EINA_MAGIC_CHECK_LIST(list, NULL);
659 #endif
660 EINA_LIST_FOREACH(list, l, list_data)
661 {
662 if (list_data == relative)
663 return eina_list_append_relative_list(list, data, l);
664 }
665
666 return eina_list_append(list, data);
667 }
668
669 EAPI Eina_List *
eina_list_append_relative_list(Eina_List * list,const void * data,Eina_List * relative)670 eina_list_append_relative_list(Eina_List *list,
671 const void *data,
672 Eina_List *relative)
673 {
674 Eina_List *new_l;
675
676 if ((!list) || (!relative))
677 return eina_list_append(list, data);
678
679 #ifdef EINA_LIST_MAGIC
680 EINA_MAGIC_CHECK_LIST(relative, NULL);
681 #endif
682
683 new_l = _eina_list_mempool_list_new(relative, relative->next);
684 if (!new_l) return list;
685
686 new_l->next = relative->next;
687 new_l->data = (void *)data;
688
689 if (relative->next)
690 relative->next->prev = new_l;
691
692 relative->next = new_l;
693 new_l->prev = relative;
694
695 _eina_list_update_accounting(list, new_l);
696
697 if (!new_l->next)
698 new_l->accounting->last = new_l;
699
700 return list;
701 }
702
703 EAPI Eina_List *
eina_list_prepend_relative(Eina_List * list,const void * data,const void * relative)704 eina_list_prepend_relative(Eina_List *list,
705 const void *data,
706 const void *relative)
707 {
708 Eina_List *l;
709 void *list_data;
710
711 #ifdef EINA_LIST_MAGIC
712 if (list)
713 EINA_MAGIC_CHECK_LIST(list, NULL);
714 #endif
715 EINA_LIST_FOREACH(list, l, list_data)
716 {
717 if (list_data == relative)
718 return eina_list_prepend_relative_list(list, data, l);
719 }
720 return eina_list_prepend(list, data);
721 }
722
723 EAPI Eina_List *
eina_list_prepend_relative_list(Eina_List * list,const void * data,Eina_List * relative)724 eina_list_prepend_relative_list(Eina_List *list,
725 const void *data,
726 Eina_List *relative)
727 {
728 Eina_List *new_l;
729
730 if ((!list) || (!relative))
731 return eina_list_prepend(list, data);
732
733 #ifdef EINA_LIST_MAGIC
734 EINA_MAGIC_CHECK_LIST(relative, NULL);
735 #endif
736 new_l = _eina_list_mempool_list_new(relative->prev, relative);
737 if (!new_l) return list;
738
739 new_l->prev = relative->prev;
740 new_l->next = relative;
741 new_l->data = (void *)data;
742
743 if (relative->prev)
744 relative->prev->next = new_l;
745
746 relative->prev = new_l;
747
748 _eina_list_update_accounting(list, new_l);
749
750 if (new_l->prev)
751 return list;
752
753 return new_l;
754 }
755
756 EAPI Eina_List *
eina_list_sorted_insert(Eina_List * list,Eina_Compare_Cb func,const void * data)757 eina_list_sorted_insert(Eina_List *list, Eina_Compare_Cb func, const void *data)
758 {
759 Eina_List *lnear;
760 int cmp;
761
762 if (!list)
763 return eina_list_append(NULL, data);
764
765 lnear = eina_list_search_sorted_near_list(list, func, data, &cmp);
766 if (cmp < 0)
767 return eina_list_append_relative_list(list, data, lnear);
768 else
769 return eina_list_prepend_relative_list(list, data, lnear);
770 }
771
772 EAPI Eina_List *
eina_list_remove(Eina_List * list,const void * data)773 eina_list_remove(Eina_List *list, const void *data)
774 {
775 Eina_List *l;
776
777 #ifdef EINA_LIST_MAGIC
778 if (list)
779 EINA_MAGIC_CHECK_LIST(list, NULL);
780 #endif
781 l = eina_list_data_find_list(list, data);
782 return eina_list_remove_list(list, l);
783 }
784
785 EAPI Eina_List *
eina_list_remove_list(Eina_List * list,Eina_List * remove_list)786 eina_list_remove_list(Eina_List *list, Eina_List *remove_list)
787 {
788 Eina_List *return_l;
789
790 if (!list)
791 return NULL;
792
793 if (!remove_list)
794 return list;
795
796 #ifdef EINA_LIST_MAGIC
797 EINA_MAGIC_CHECK_LIST(remove_list, NULL);
798 #endif
799 if (remove_list->next)
800 remove_list->next->prev = remove_list->prev;
801
802 if (remove_list->prev)
803 {
804 remove_list->prev->next = remove_list->next;
805 return_l = list;
806 }
807 else
808 return_l = remove_list->next;
809
810 if (remove_list == remove_list->accounting->last)
811 {
812 #ifdef EINA_LIST_MAGIC
813 EINA_MAGIC_CHECK_LIST(list, NULL);
814 #endif
815 list->accounting->last = remove_list->prev;
816 }
817
818 _eina_list_mempool_list_free(remove_list);
819 return return_l;
820 }
821
822 EAPI Eina_List *
eina_list_free(Eina_List * list)823 eina_list_free(Eina_List *list)
824 {
825 Eina_List *l, *free_l;
826
827 if (!list)
828 return NULL;
829
830 #ifdef EINA_LIST_MAGIC
831 EINA_MAGIC_CHECK_LIST(list, NULL);
832 #endif
833 for (l = list; l; )
834 {
835 free_l = l;
836 l = l->next;
837
838 _eina_list_mempool_list_free(free_l);
839 }
840
841 return NULL;
842 }
843
844 EAPI Eina_List *
eina_list_promote_list(Eina_List * list,Eina_List * move_list)845 eina_list_promote_list(Eina_List *list, Eina_List *move_list)
846 {
847 if (!list)
848 return NULL;
849
850 if (!move_list)
851 {
852 return list; /* Promoting head to be head. */
853
854 }
855
856 if (move_list == list)
857 return list;
858
859 if (move_list->next == list)
860 return move_list;
861
862 #ifdef EINA_LIST_MAGIC
863 EINA_MAGIC_CHECK_LIST(list, NULL);
864 EINA_MAGIC_CHECK_LIST(move_list, NULL);
865 #endif
866 /* Remove the promoted item from the list. */
867 if (!move_list->prev)
868 move_list->next->prev = NULL;
869 else
870 {
871 move_list->prev->next = move_list->next;
872 if (move_list == list->accounting->last)
873 list->accounting->last = move_list->prev;
874 else
875 move_list->next->prev = move_list->prev;
876 }
877
878 /* Add the promoted item in the list. */
879 move_list->next = list;
880 move_list->prev = list->prev;
881 list->prev = move_list;
882 if (move_list->prev)
883 move_list->prev->next = move_list;
884
885 return move_list;
886 }
887
888 EAPI Eina_List *
eina_list_demote_list(Eina_List * list,Eina_List * move_list)889 eina_list_demote_list(Eina_List *list, Eina_List *move_list)
890 {
891 if (!list)
892 return NULL;
893
894 if (!move_list)
895 {
896 return list; /* Demoting tail to be tail. */
897
898 }
899
900 if (move_list == list->accounting->last)
901 return list;
902
903 #ifdef EINA_LIST_MAGIC
904 EINA_MAGIC_CHECK_LIST(list, NULL);
905 EINA_MAGIC_CHECK_LIST(move_list, NULL);
906 #endif
907 /* Update pointer list if necessary. */
908 if (list == move_list)
909 {
910 list = move_list->next; /* Remove the demoted item from the list. */
911
912 }
913
914 if (move_list->prev)
915 move_list->prev->next = move_list->next;
916
917 move_list->next->prev = move_list->prev;
918 /* Add the demoted item in the list. */
919 move_list->prev = list->accounting->last;
920 move_list->prev->next = move_list;
921 move_list->next = NULL;
922 list->accounting->last = move_list;
923
924 return list;
925 }
926
927 EAPI void *
eina_list_data_find(const Eina_List * list,const void * data)928 eina_list_data_find(const Eina_List *list, const void *data)
929 {
930 if (eina_list_data_find_list(list, data))
931 return (void *)data;
932
933 return NULL;
934 }
935
936 EAPI Eina_Bool
eina_list_move(Eina_List ** to,Eina_List ** from,void * data)937 eina_list_move(Eina_List **to, Eina_List **from, void *data)
938 {
939 Eina_List *l;
940
941 EINA_SAFETY_ON_NULL_RETURN_VAL(to, EINA_FALSE);
942 EINA_SAFETY_ON_NULL_RETURN_VAL(from, EINA_FALSE);
943 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
944
945 #ifdef EINA_LIST_MAGIC
946 if (*to) EINA_MAGIC_CHECK_LIST(*to, EINA_FALSE);
947 EINA_MAGIC_CHECK_LIST(*from, EINA_FALSE);
948 #endif
949 l = eina_list_data_find_list(*from, data);
950 EINA_SAFETY_ON_NULL_RETURN_VAL(l, EINA_FALSE);
951
952 *to = eina_list_append(*to, data);
953 *from = eina_list_remove_list(*from, l);
954 return EINA_TRUE;
955 }
956
957 EAPI Eina_Bool
eina_list_move_list(Eina_List ** to,Eina_List ** from,Eina_List * data)958 eina_list_move_list(Eina_List **to, Eina_List **from, Eina_List *data)
959 {
960 EINA_SAFETY_ON_NULL_RETURN_VAL(to, EINA_FALSE);
961 EINA_SAFETY_ON_NULL_RETURN_VAL(from, EINA_FALSE);
962 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
963
964 #ifdef EINA_LIST_MAGIC
965 if (*to) EINA_MAGIC_CHECK_LIST(*to, EINA_FALSE);
966 EINA_MAGIC_CHECK_LIST(*from, EINA_FALSE);
967 EINA_MAGIC_CHECK_LIST(data, EINA_FALSE);
968 #endif
969 *to = eina_list_append(*to, data->data);
970 *from = eina_list_remove_list(*from, data);
971 return EINA_TRUE;
972 }
973
974 EAPI Eina_List *
eina_list_data_find_list(const Eina_List * list,const void * data)975 eina_list_data_find_list(const Eina_List *list, const void *data)
976 {
977 const Eina_List *l;
978 void *list_data;
979
980 #ifdef EINA_LIST_MAGIC
981 if (list)
982 EINA_MAGIC_CHECK_LIST(list, NULL);
983 #endif
984 EINA_LIST_FOREACH(list, l, list_data)
985 {
986 if (list_data == data)
987 return (Eina_List *)l;
988 }
989
990 return NULL;
991 }
992
993 EAPI void *
eina_list_nth(const Eina_List * list,unsigned int n)994 eina_list_nth(const Eina_List *list, unsigned int n)
995 {
996 Eina_List *l;
997 if (!list) return NULL;
998
999 if (n == 0) return list->data;
1000
1001 l = eina_list_nth_list(list, n);
1002 return l ? l->data : NULL;
1003 }
1004
1005 EAPI Eina_List *
eina_list_nth_list(const Eina_List * list,unsigned int n)1006 eina_list_nth_list(const Eina_List *list, unsigned int n)
1007 {
1008 const Eina_List *l;
1009 unsigned int i;
1010
1011 #ifdef EINA_LIST_MAGIC
1012 if (list)
1013 EINA_MAGIC_CHECK_LIST(list, NULL);
1014 #endif
1015 /* check for non-existing nodes */
1016 if ((!list) || (n > (list->accounting->count - 1)))
1017 return NULL;
1018
1019 /* if the node is in the 2nd half of the list, search from the end
1020 * else, search from the beginning.
1021 */
1022 if (n > (list->accounting->count / 2))
1023 for (i = list->accounting->count - 1,
1024 l = list->accounting->last;
1025 l;
1026 l = l->prev, i--)
1027 {
1028 if (i == n)
1029 return (Eina_List *)l;
1030 }
1031 else
1032 for (i = 0, l = list; l; l = l->next, i++)
1033 {
1034 if (i == n)
1035 return (Eina_List *)l;
1036 }
1037
1038 abort();
1039 }
1040
1041 EAPI Eina_List *
eina_list_reverse(Eina_List * list)1042 eina_list_reverse(Eina_List *list)
1043 {
1044 Eina_List *l1, *l2;
1045
1046 if (!list)
1047 return NULL;
1048
1049 #ifdef EINA_LIST_MAGIC
1050 EINA_MAGIC_CHECK_LIST(list, NULL);
1051 #endif
1052 l1 = list;
1053 l2 = list->accounting->last;
1054 while (l1 != l2)
1055 {
1056 void *data;
1057
1058 data = l1->data;
1059 l1->data = l2->data;
1060 l2->data = data;
1061 l1 = l1->next;
1062 if (l1 == l2)
1063 break;
1064
1065 l2 = l2->prev;
1066 }
1067
1068 return list;
1069 }
1070
1071 EAPI Eina_List *
eina_list_reverse_clone(const Eina_List * list)1072 eina_list_reverse_clone(const Eina_List *list)
1073 {
1074 const Eina_List *l;
1075 Eina_List *lclone;
1076 void *data;
1077
1078 if (!list)
1079 return NULL;
1080
1081 #ifdef EINA_LIST_MAGIC
1082 EINA_MAGIC_CHECK_LIST(list, NULL);
1083 #endif
1084 lclone = NULL;
1085 EINA_LIST_FOREACH(list, l, data)
1086 lclone = eina_list_prepend(lclone, data);
1087
1088 return lclone;
1089 }
1090
1091 EAPI Eina_List *
eina_list_clone(const Eina_List * list)1092 eina_list_clone(const Eina_List *list)
1093 {
1094 const Eina_List *l;
1095 Eina_List *lclone;
1096 void *data;
1097
1098 if (!list)
1099 return NULL;
1100
1101 #ifdef EINA_LIST_MAGIC
1102 EINA_MAGIC_CHECK_LIST(list, NULL);
1103 #endif
1104 lclone = NULL;
1105 EINA_LIST_FOREACH(list, l, data)
1106 lclone = eina_list_append(lclone, data);
1107
1108 return lclone;
1109 }
1110
1111 EAPI Eina_List *
eina_list_sort(Eina_List * list,unsigned int limit,Eina_Compare_Cb func)1112 eina_list_sort(Eina_List *list, unsigned int limit, Eina_Compare_Cb func)
1113 {
1114 unsigned int i = 0;
1115 unsigned int n = 0;
1116 Eina_List *tail = list;
1117 Eina_List *unsort = NULL;
1118 Eina_List *stack[EINA_LIST_SORT_STACK_SIZE];
1119
1120 EINA_SAFETY_ON_NULL_RETURN_VAL(func, list);
1121 if (!list)
1122 return NULL;
1123
1124 #ifdef EINA_LIST_MAGIC
1125 EINA_MAGIC_CHECK_LIST(list, NULL);
1126 #endif
1127 /* if the caller specified an invalid limit, sort the whole list */
1128 if ((limit == 0) ||
1129 (limit > list->accounting->count))
1130 limit = list->accounting->count;
1131
1132 if (limit != list->accounting->count)
1133 {
1134 unsort = eina_list_nth_list(list, limit);
1135 if (unsort)
1136 unsort->prev->next = NULL;
1137 }
1138
1139 while (tail)
1140 {
1141 unsigned int idx, tmp;
1142
1143 Eina_List *a = tail;
1144 Eina_List *b = tail->next;
1145
1146 if (!b)
1147 {
1148 stack[i++] = a;
1149 break;
1150 }
1151
1152 tail = b->next;
1153
1154 if (func(a->data, b->data) < 0)
1155 ((stack[i++] = a)->next = b)->next = 0;
1156 else
1157 ((stack[i++] = b)->next = a)->next = 0;
1158
1159 tmp = n++;
1160 for (idx = n ^ tmp; idx &= idx - 1; i--)
1161 stack[i - 2] = eina_list_sort_merge(stack[i - 2], stack[i - 1], func);
1162 }
1163
1164 while (i-- > 1)
1165 stack[i - 1] = eina_list_sort_merge(stack[i - 1], stack[i], func);
1166
1167 list = stack[0];
1168 tail = eina_list_sort_rebuild_prev(list);
1169
1170 if (unsort)
1171 {
1172 tail->next = unsort;
1173 unsort->prev = tail;
1174 }
1175 else
1176 list->accounting->last = tail;
1177
1178 return list;
1179 }
1180
1181 EAPI Eina_List *
eina_list_shuffle(Eina_List * list,Eina_Random_Cb func)1182 eina_list_shuffle(Eina_List *list, Eina_Random_Cb func)
1183 {
1184 unsigned int n, i, j;
1185 Eina_List_Accounting *accounting;
1186 Eina_List *shuffled_list, *shuffled_last, *li;
1187
1188 if (!list)
1189 return NULL;
1190
1191 #ifdef EINA_LIST_MAGIC
1192 EINA_MAGIC_CHECK_LIST(list, NULL);
1193 #endif
1194 accounting = list->accounting;
1195 n = accounting->count;
1196 shuffled_list = shuffled_last = NULL;
1197
1198 if (n == 0)
1199 return NULL;
1200
1201 if (n == 1)
1202 return list;
1203
1204 while (n > 1)
1205 {
1206 if (func)
1207 i = func(0, (n - 1));
1208 else
1209 i = (int) ((float)n*rand()/(RAND_MAX+1.0));
1210
1211 if(i == 0)
1212 {
1213 li = list;
1214 list = list->next;
1215 }
1216 else if (i == (n - 1) || i == n)
1217 {
1218 li = accounting->last;
1219 accounting->last = li->prev;
1220 }
1221 else
1222 {
1223 if (i > (n / 2))
1224 for (j = n - 1,
1225 li = accounting->last;
1226 j!=i;
1227 li = li->prev, j--);
1228 else
1229 for (j = 0,
1230 li = list;
1231 j!=i;
1232 li = li->next, j++);
1233
1234 li->prev->next = li->next;
1235 li->next->prev = li->prev;
1236 }
1237
1238 n--;
1239
1240 if (shuffled_list == NULL)
1241 {
1242 li->prev = NULL;
1243 shuffled_list = li;
1244 shuffled_last = li;
1245 }
1246 else
1247 {
1248 shuffled_last->next = li;
1249 li->prev = shuffled_last;
1250 shuffled_last = li;
1251 }
1252 }
1253
1254 list->next = NULL;
1255 list->prev = shuffled_last;
1256 shuffled_last->next = list;
1257
1258 accounting->last = list;
1259 shuffled_list->accounting = accounting;
1260
1261 return shuffled_list;
1262 }
1263
1264 EAPI Eina_List *
eina_list_merge(Eina_List * left,Eina_List * right)1265 eina_list_merge(Eina_List *left, Eina_List *right)
1266 {
1267 unsigned int n_left, n_right;
1268
1269 if (!left)
1270 return right;
1271
1272 if (!right)
1273 return left;
1274
1275 left->accounting->last->next = right;
1276 right->prev = left->accounting->last;
1277
1278 n_left = left->accounting->count;
1279 n_right = right->accounting->count;
1280
1281 if (n_left >= n_right)
1282 {
1283 Eina_List *itr = right;
1284 left->accounting->last = right->accounting->last;
1285 left->accounting->count += n_right;
1286
1287 _eina_list_mempool_accounting_free(right->accounting);
1288
1289 do
1290 {
1291 itr->accounting = left->accounting;
1292 itr = itr->next;
1293 }
1294 while (itr);
1295 }
1296 else
1297 {
1298 Eina_List *itr = left->accounting->last;
1299 right->accounting->count += n_left;
1300
1301 _eina_list_mempool_accounting_free(left->accounting);
1302
1303 do
1304 {
1305 itr->accounting = right->accounting;
1306 itr = itr->prev;
1307 }
1308 while (itr);
1309 }
1310
1311 return left;
1312 }
1313
1314
1315 EAPI Eina_List *
eina_list_split_list(Eina_List * list,Eina_List * relative,Eina_List ** right)1316 eina_list_split_list(Eina_List *list, Eina_List *relative, Eina_List **right)
1317 {
1318 Eina_List *next;
1319 Eina_List *itr;
1320
1321 if(!right)
1322 return list;
1323
1324 *right = NULL;
1325
1326 if (!list)
1327 return NULL;
1328
1329 if (!relative)
1330 {
1331 *right = list;
1332 return NULL;
1333 }
1334
1335 if (relative == eina_list_last(list))
1336 return list;
1337
1338 next = eina_list_next(relative);
1339 next->prev = NULL;
1340 next->accounting = _eina_list_mempool_accounting_new(next);
1341 next->accounting->last = list->accounting->last;
1342 next->accounting->count = 0;
1343 *right = next;
1344
1345 itr = next;
1346 do
1347 {
1348 itr->accounting = next->accounting;
1349 next->accounting->count++;
1350 itr = itr->next;
1351 }
1352 while (itr);
1353
1354 relative->next = NULL;
1355 list->accounting->last = relative;
1356 list->accounting->count = list->accounting->count - next->accounting->count;
1357
1358 return list;
1359 }
1360
1361 EAPI Eina_List *
eina_list_sorted_merge(Eina_List * left,Eina_List * right,Eina_Compare_Cb func)1362 eina_list_sorted_merge(Eina_List *left, Eina_List *right, Eina_Compare_Cb func)
1363 {
1364 Eina_List *ret;
1365 Eina_List *current;
1366
1367 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1368
1369 if (!left)
1370 return right;
1371
1372 if (!right)
1373 return left;
1374
1375 if (func(left->data, right->data) < 0)
1376 {
1377 ret = left;
1378 current = left;
1379 left = left->next;
1380 ret->accounting->count += right->accounting->count;
1381
1382 _eina_list_mempool_accounting_free(right->accounting);
1383 }
1384 else
1385 {
1386 ret = right;
1387 current = right;
1388 right = right->next;
1389 ret->accounting->count += left->accounting->count;
1390
1391 _eina_list_mempool_accounting_free(left->accounting);
1392 }
1393
1394 while (left && right)
1395 {
1396 if (func(left->data, right->data) < 0)
1397 {
1398 current->next = left;
1399 left->prev = current;
1400 left = left->next;
1401 }
1402 else
1403 {
1404 current->next = right;
1405 right->prev = current;
1406 right = right->next;
1407 }
1408
1409 current = current->next;
1410 current->accounting = ret->accounting;
1411 }
1412
1413 if (left)
1414 {
1415 current->next = left;
1416 left->prev = current;
1417 current->accounting = ret->accounting;
1418 }
1419
1420 if (right)
1421 {
1422 current->next = right;
1423 right->prev = current;
1424 current->accounting = ret->accounting;
1425 }
1426
1427 while (current->next)
1428 {
1429 current = current->next;
1430 current->accounting = ret->accounting;
1431 }
1432
1433 ret->accounting->last = current;
1434
1435 return ret;
1436 }
1437
1438 EAPI Eina_List *
eina_list_search_sorted_near_list(const Eina_List * list,Eina_Compare_Cb func,const void * data,int * result_cmp)1439 eina_list_search_sorted_near_list(const Eina_List *list,
1440 Eina_Compare_Cb func,
1441 const void *data,
1442 int *result_cmp)
1443 {
1444 const Eina_List *ct;
1445 unsigned int inf, sup, cur;
1446 int cmp;
1447
1448 if (!list)
1449 {
1450 if (result_cmp)
1451 *result_cmp = 0;
1452
1453 return NULL;
1454 }
1455
1456 if (list->accounting->count == 1)
1457 {
1458 if (result_cmp)
1459 *result_cmp = func(list->data, data);
1460
1461 return (Eina_List *)list;
1462 }
1463
1464 /* list walk is expensive, do quick check: tail */
1465 ct = list->accounting->last;
1466 cmp = func(ct->data, data);
1467 if (cmp <= 0)
1468 goto end;
1469
1470 /* list walk is expensive, do quick check: head */
1471 ct = list;
1472 cmp = func(ct->data, data);
1473 if (cmp >= 0)
1474 goto end;
1475
1476 /* inclusive bounds */
1477 inf = 1;
1478 sup = list->accounting->count - 2;
1479 cur = 1;
1480 ct = list->next;
1481
1482 /* no loop, just compare if comparison value is important to caller */
1483 if (inf > sup)
1484 {
1485 if (result_cmp)
1486 cmp = func(ct->data, data);
1487
1488 goto end;
1489 }
1490
1491 while (inf <= sup)
1492 {
1493 unsigned int tmp = cur;
1494 cur = inf + ((sup - inf) >> 1);
1495 if (tmp < cur)
1496 for (; tmp != cur; tmp++, ct = ct->next) ;
1497 else if (tmp > cur)
1498 for (; tmp != cur; tmp--, ct = ct->prev) ;
1499
1500 cmp = func(ct->data, data);
1501 if (cmp == 0)
1502 break;
1503 else if (cmp < 0)
1504 inf = cur + 1;
1505 else
1506 {
1507 if (cur > 0)
1508 sup = cur - 1;
1509 else
1510 break;
1511 }
1512 }
1513
1514 end:
1515 if (result_cmp)
1516 *result_cmp = cmp;
1517
1518 return (Eina_List *)ct;
1519 }
1520
1521 EAPI Eina_List *
eina_list_search_sorted_list(const Eina_List * list,Eina_Compare_Cb func,const void * data)1522 eina_list_search_sorted_list(const Eina_List *list,
1523 Eina_Compare_Cb func,
1524 const void *data)
1525 {
1526 Eina_List *lnear;
1527 int cmp;
1528
1529 lnear = eina_list_search_sorted_near_list(list, func, data, &cmp);
1530 if (!lnear)
1531 return NULL;
1532
1533 if (cmp == 0)
1534 return lnear;
1535
1536 return NULL;
1537 }
1538
1539
1540 EAPI void *
eina_list_search_sorted(const Eina_List * list,Eina_Compare_Cb func,const void * data)1541 eina_list_search_sorted(const Eina_List *list,
1542 Eina_Compare_Cb func,
1543 const void *data)
1544 {
1545 return eina_list_data_get(eina_list_search_sorted_list(list, func, data));
1546 }
1547
1548 EAPI Eina_List *
eina_list_search_unsorted_list(const Eina_List * list,Eina_Compare_Cb func,const void * data)1549 eina_list_search_unsorted_list(const Eina_List *list,
1550 Eina_Compare_Cb func,
1551 const void *data)
1552 {
1553 const Eina_List *l;
1554 void *d;
1555
1556 EINA_LIST_FOREACH(list, l, d)
1557 {
1558 if (!func(d, data))
1559 return (Eina_List *)l;
1560 }
1561 return NULL;
1562 }
1563
1564 EAPI void *
eina_list_search_unsorted(const Eina_List * list,Eina_Compare_Cb func,const void * data)1565 eina_list_search_unsorted(const Eina_List *list,
1566 Eina_Compare_Cb func,
1567 const void *data)
1568 {
1569 return eina_list_data_get(eina_list_search_unsorted_list(list, func, data));
1570 }
1571
1572
1573 EAPI Eina_Iterator *
eina_list_iterator_new(const Eina_List * list)1574 eina_list_iterator_new(const Eina_List *list)
1575 {
1576 Eina_Iterator_List *it;
1577
1578 it = calloc(1, sizeof (Eina_Iterator_List));
1579 if (!it) return NULL;
1580
1581 EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR);
1582 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1583
1584 it->head = list;
1585 it->current = list;
1586
1587 it->iterator.version = EINA_ITERATOR_VERSION;
1588 it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_next);
1589 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1590 eina_list_iterator_get_container);
1591 it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free);
1592
1593 return &it->iterator;
1594 }
1595
1596 EAPI Eina_Iterator *
eina_list_iterator_reversed_new(const Eina_List * list)1597 eina_list_iterator_reversed_new(const Eina_List *list)
1598 {
1599 Eina_Iterator_List *it;
1600
1601 it = calloc(1, sizeof (Eina_Iterator_List));
1602 if (!it) return NULL;
1603
1604 EINA_MAGIC_SET(it, EINA_MAGIC_LIST_ITERATOR);
1605 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1606
1607 it->head = eina_list_last(list);
1608 it->current = it->head;
1609
1610 it->iterator.version = EINA_ITERATOR_VERSION;
1611 it->iterator.next = FUNC_ITERATOR_NEXT(eina_list_iterator_prev);
1612 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(
1613 eina_list_iterator_get_container);
1614 it->iterator.free = FUNC_ITERATOR_FREE(eina_list_iterator_free);
1615
1616 return &it->iterator;
1617 }
1618
1619 EAPI Eina_Accessor *
eina_list_accessor_new(const Eina_List * list)1620 eina_list_accessor_new(const Eina_List *list)
1621 {
1622 Eina_Accessor_List *ac;
1623
1624 EINA_SAFETY_ON_NULL_RETURN_VAL(list, NULL);
1625
1626 ac = calloc(1, sizeof (Eina_Accessor_List));
1627 if (!ac) return NULL;
1628
1629 EINA_MAGIC_SET(ac, EINA_MAGIC_LIST_ACCESSOR);
1630 EINA_MAGIC_SET(&ac->accessor, EINA_MAGIC_ACCESSOR);
1631
1632 ac->head = list;
1633 ac->current = list;
1634 ac->index = 0;
1635
1636 ac->accessor.version = EINA_ACCESSOR_VERSION;
1637 ac->accessor.get_at = FUNC_ACCESSOR_GET_AT(eina_list_accessor_get_at);
1638 ac->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(
1639 eina_list_accessor_get_container);
1640 ac->accessor.free = FUNC_ACCESSOR_FREE(eina_list_accessor_free);
1641 ac->accessor.clone = FUNC_ACCESSOR_CLONE(eina_list_accessor_clone);
1642
1643 return &ac->accessor;
1644 }
1645
1646 EAPI int
eina_list_data_idx(const Eina_List * list,void * data)1647 eina_list_data_idx(const Eina_List *list, void *data)
1648 {
1649 const Eina_List *l;
1650 void *list_data;
1651 int ret = 0;
1652
1653 if (!list) return -1;
1654 #ifdef EINA_LIST_MAGIC
1655 EINA_MAGIC_CHECK_LIST(list, -1);
1656 #endif
1657 EINA_LIST_FOREACH(list, l, list_data)
1658 {
1659 if (list_data == data)
1660 return ret;
1661 ret++;
1662 }
1663
1664 return -1;
1665 }
1666