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