chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / src / e16-ecore_list.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler and various contributors (see AUTHORS)
3  *
4  * Copyright (C) Nathan Ingersoll (author)
5  * Copyright (C) Ibukun Olumuyiwa (ewd -> ecore)
6  * Copyright (C) Dan Sinclair     (various cleanups)
7  * Copyright (C) Kim Woelders     (e16 port/additions)
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to
11  * deal in the Software without restriction, including without limitation the
12  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13  * sell copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies of the Software, its documentation and marketing & publicity
18  * materials, and acknowledgment shall be given in the documentation, materials
19  * and software packages that this Software was used.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28 /*
29  * Most of this was snatched from e17/libs/ecore/src/lib/ecore/ecore_list.c
30  * revision 1.21, and associated header files.
31  * The pertinent AUTHORS list is e17/libs/ecore/AUTHORS.
32  */
33 #include <stdlib.h>
34 #include <string.h>
35 #include "e16-ecore_list.h"
36
37 #ifndef FALSE
38 #define FALSE 0
39 #endif
40 #ifndef TRUE
41 #define TRUE 1
42 #endif
43
44 #if !USE_ECORE
45
46 struct _ecore_list_node {
47    void               *data;
48    struct _ecore_list_node *next;
49 };
50
51 struct _ecore_list {
52    Ecore_List_Node    *first;   /* The first node in the list */
53    Ecore_List_Node    *last;    /* The last node in the list */
54    Ecore_List_Node    *current; /* The current node in the list */
55
56    Ecore_Free_Cb       free_func;       /* The callback to free data in nodes */
57
58    int                 nodes;   /* The number of nodes in the list */
59    int                 index;   /* The position from the front of the
60                                  * list of current node */
61 };
62
63 /* convenience macros for checking pointer parameters for non-NULL */
64 #define ecore_print_warning(txt, s)
65
66 #undef CHECK_PARAM_POINTER
67 #define CHECK_PARAM_POINTER(sparam, param) \
68     if (!(param)) { \
69         ecore_print_warning(__FUNCTION__, sparam); \
70         return; \
71     }
72
73 #define CHECK_PARAM_POINTER_RETURN(sparam, param, ret) \
74     if (!(param)) { \
75         ecore_print_warning(__FUNCTION__, sparam); \
76         return ret; \
77     }
78
79 /* Return information about the list */
80 static void        *_ecore_list_current(Ecore_List * list);
81
82 /* Adding functions */
83 static int          _ecore_list_insert(Ecore_List * list,
84                                        Ecore_List_Node * node);
85 static int          _ecore_list_append_0(Ecore_List * list,
86                                          Ecore_List_Node * node);
87 static int          _ecore_list_prepend_0(Ecore_List * list,
88                                           Ecore_List_Node * node);
89
90 /* Remove functions */
91 static void        *_ecore_list_remove_0(Ecore_List * list);
92 static void        *_ecore_list_first_remove(Ecore_List * list);
93 static void        *_ecore_list_last_remove(Ecore_List * list);
94
95 /* Basic traversal functions */
96 static void        *_ecore_list_next(Ecore_List * list);
97 static void        *_ecore_list_last_goto(Ecore_List * list);
98 static void        *_ecore_list_first_goto(Ecore_List * list);
99 static void        *_ecore_list_goto(Ecore_List * list, const void *data);
100 static void        *_ecore_list_index_goto(Ecore_List * list, int indx);
101
102 /* Iterative function */
103 static int          _ecore_list_for_each(Ecore_List * list,
104                                          Ecore_For_Each function,
105                                          void *user_data);
106 static void        *_ecore_list_find(Ecore_List * list,
107                                      Ecore_Compare_Cb function,
108                                      const void *user_data);
109
110 /**
111  * @defgroup Ecore_Data_List_Creation_Group List Creation/Destruction Functions
112  *
113  * Functions that create, initialize and destroy Ecore_Lists.
114  */
115
116 /**
117  * Create and initialize a new list.
118  * @return  A new initialized list on success, @c NULL on failure.
119  * @ingroup Ecore_Data_List_Creation_Group
120  */
121 EAPI Ecore_List    *
122 ecore_list_new(void)
123 {
124    Ecore_List         *list;
125
126    list = (Ecore_List *) malloc(sizeof(Ecore_List));
127    if (!list)
128       return NULL;
129
130    if (!ecore_list_init(list))
131      {
132         free(list);
133         return NULL;
134      }
135
136    return list;
137 }
138
139 /**
140  * Initialize a list to some sane starting values.
141  * @param   list The list to initialize.
142  * @return  @c TRUE if successful, @c FALSE if an error occurs.
143  * @ingroup Ecore_Data_List_Creation_Group
144  */
145 EAPI int
146 ecore_list_init(Ecore_List * list)
147 {
148    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
149
150    memset(list, 0, sizeof(Ecore_List));
151
152    return TRUE;
153 }
154
155 /**
156  * Free a list and all of it's nodes.
157  * @param   list The list to be freed.
158  * @ingroup Ecore_Data_List_Creation_Group
159  */
160 EAPI void
161 ecore_list_destroy(Ecore_List * list)
162 {
163    void               *data;
164
165    CHECK_PARAM_POINTER("list", list);
166
167    while (list->first)
168      {
169         data = _ecore_list_first_remove(list);
170         if (list->free_func)
171            list->free_func(data);
172      }
173
174    free(list);
175 }
176
177 /**
178  * Set the function for freeing data.
179  * @param  list      The list that will use this function when nodes are
180  *                   destroyed.
181  * @param  free_func The function that will free the key data.
182  * @return @c TRUE on successful set, @c FALSE otherwise.
183  */
184 EAPI int
185 ecore_list_free_cb_set(Ecore_List * list, Ecore_Free_Cb free_func)
186 {
187    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
188
189    list->free_func = free_func;
190
191    return TRUE;
192 }
193
194 /**
195  * Checks the list for any nodes.
196  * @param  list  The list to check for nodes
197  * @return @c TRUE if no nodes in list, @c FALSE if the list contains nodes
198  */
199 EAPI int
200 ecore_list_empty_is(Ecore_List * list)
201 {
202    int                 ret = TRUE;
203
204    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
205
206    if (list->nodes)
207       ret = FALSE;
208
209    return ret;
210 }
211
212 /**
213  * Returns the number of the current node.
214  * @param  list The list to return the number of the current node.
215  * @return The number of the current node in the list.
216  */
217 EAPI int
218 ecore_list_index(Ecore_List * list)
219 {
220    int                 ret;
221
222    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
223
224    ret = list->index;
225
226    return ret;
227 }
228
229 /**
230  * Find the number of nodes in the list.
231  * @param  list The list to find the number of nodes
232  * @return The number of nodes in the list.
233  */
234 EAPI int
235 ecore_list_count(Ecore_List * list)
236 {
237    int                 ret = 0;
238
239    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
240
241    ret = list->nodes;
242
243    return ret;
244 }
245
246 /**
247 @defgroup Ecore_Data_List_Add_Item_Group List Item Adding Functions
248
249 Functions that are used to add nodes to an Ecore_List.
250 */
251
252 /**
253  * Append data to the list.
254  * @param   list The list.
255  * @param   data The data to append.
256  * @return  @c FALSE if an error occurs, @c TRUE if appended successfully
257  * @ingroup Ecore_Data_List_Add_Item_Group
258  */
259 EAPI int
260 ecore_list_append(Ecore_List * list, void *data)
261 {
262    int                 ret;
263    Ecore_List_Node    *node;
264
265    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
266
267    node = ecore_list_node_new();
268    node->data = data;
269
270    ret = _ecore_list_append_0(list, node);
271
272    return ret;
273 }
274
275 /* For adding items to the end of the list */
276 static int
277 _ecore_list_append_0(Ecore_List * list, Ecore_List_Node * end)
278 {
279    if (list->last)
280       list->last->next = end;
281
282    list->last = end;
283
284    if (list->first == NULL)
285      {
286         list->first = end;
287         list->index = 0;
288         list->current = NULL;
289      }
290
291    if (list->index >= list->nodes)
292       list->index++;
293
294    list->nodes++;
295
296    return TRUE;
297 }
298
299 /**
300  * Prepend data to the beginning of the list.
301  * @param  list The list.
302  * @param  data The data to prepend.
303  * @return @c FALSE if an error occurs, @c TRUE if prepended successfully.
304  * @ingroup Ecore_Data_List_Add_Item_Group
305  */
306 EAPI int
307 ecore_list_prepend(Ecore_List * list, void *data)
308 {
309    int                 ret;
310    Ecore_List_Node    *node;
311
312    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
313
314    node = ecore_list_node_new();
315    node->data = data;
316
317    ret = _ecore_list_prepend_0(list, node);
318
319    return ret;
320 }
321
322 /* For adding items to the beginning of the list */
323 static int
324 _ecore_list_prepend_0(Ecore_List * list, Ecore_List_Node * start)
325 {
326    /* Put it at the beginning of the list */
327    start->next = list->first;
328
329    list->first = start;
330
331    /* If no last node, then the first node is the last node */
332    if (list->last == NULL)
333       list->last = list->first;
334
335    list->nodes++;
336    list->index++;
337
338    return TRUE;
339 }
340
341 /**
342  * Insert data in front of the current point in the list.
343  * @param   list The list to hold the inserted @p data.
344  * @param   data The data to insert into @p list.
345  * @return  @c FALSE if there is an error, @c TRUE on success
346  * @ingroup Ecore_Data_List_Add_Item_Group
347  */
348 EAPI int
349 ecore_list_insert(Ecore_List * list, void *data)
350 {
351    int                 ret;
352    Ecore_List_Node    *node;
353
354    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
355
356    node = ecore_list_node_new();
357    node->data = data;
358
359    ret = _ecore_list_insert(list, node);
360
361    return ret;
362 }
363
364 /* For adding items in front of the current position in the list */
365 static int
366 _ecore_list_insert(Ecore_List * list, Ecore_List_Node * new_node)
367 {
368    /*
369     * If the current point is at the beginning of the list, then it's the
370     * same as prepending it to the list.
371     */
372    if (list->current == list->first)
373       return _ecore_list_prepend_0(list, new_node);
374
375    if (list->current == NULL)
376      {
377         int                 ret_value;
378
379         ret_value = _ecore_list_append_0(list, new_node);
380         list->current = list->last;
381
382         return ret_value;
383      }
384
385    /* Setup the fields of the new node */
386    new_node->next = list->current;
387
388    /* And hook the node into the list */
389    _ecore_list_index_goto(list, ecore_list_index(list) - 1);
390
391    list->current->next = new_node;
392
393    /* Now move the current item to the inserted item */
394    list->current = new_node;
395    list->index++;
396    list->nodes++;
397
398    return TRUE;
399 }
400
401 /**
402 @defgroup Ecore_Data_List_Remove_Item_Group List Item Removing Functions
403
404 Functions that remove nodes from an Ecore_List.
405 */
406
407 /**
408  * Remove the current item from the list.
409  * @param   list The list to remove the current item
410  * @return  A pointer to the removed data on success, @c NULL on failure.
411  * @ingroup Ecore_Data_List_Remove_Item_Group
412  */
413 EAPI void          *
414 ecore_list_remove(Ecore_List * list)
415 {
416    void               *ret;
417
418    CHECK_PARAM_POINTER_RETURN("list", list, NULL);
419
420    ret = _ecore_list_remove_0(list);
421
422    return ret;
423 }
424
425 /* Remove the current item from the list */
426 static void        *
427 _ecore_list_remove_0(Ecore_List * list)
428 {
429    void               *ret = NULL;
430    Ecore_List_Node    *old;
431
432    if (!list)
433       return NULL;
434
435    if (ecore_list_empty_is(list))
436       return NULL;
437
438    if (!list->current)
439       return NULL;
440
441    if (list->current == list->first)
442       return _ecore_list_first_remove(list);
443
444    if (list->current == list->last)
445       return _ecore_list_last_remove(list);
446
447    old = list->current;
448
449    _ecore_list_index_goto(list, list->index - 1);
450
451    list->current->next = old->next;
452    old->next = NULL;
453    ret = old->data;
454    old->data = NULL;
455
456    _ecore_list_next(list);
457
458    ecore_list_node_destroy(old, NULL);
459    list->nodes--;
460
461    return ret;
462 }
463
464 /**
465  * Remove and free the data in lists current position.
466  * @param   list The list to remove and free the current item.
467  * @return  @c TRUE on success, @c FALSE on error
468  * @ingroup Ecore_Data_List_Remove_Item_Group
469  */
470 EAPI int
471 ecore_list_remove_destroy(Ecore_List * list)
472 {
473    void               *data;
474
475    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
476
477    data = _ecore_list_remove_0(list);
478    if (list->free_func)
479       list->free_func(data);
480
481    return TRUE;
482 }
483
484 /**
485  * Remove the first item from the list.
486  * @param   list The list to remove the current item
487  * @return  Returns a pointer to the removed data on success, @c NULL on
488  *          failure.
489  * @ingroup Ecore_Data_List_Remove_Item_Group
490  */
491 EAPI void          *
492 ecore_list_first_remove(Ecore_List * list)
493 {
494    void               *ret;
495
496    CHECK_PARAM_POINTER_RETURN("list", list, NULL);
497
498    ret = _ecore_list_first_remove(list);
499
500    return ret;
501 }
502
503 /* Remove the first item from the list */
504 static void        *
505 _ecore_list_first_remove(Ecore_List * list)
506 {
507    void               *ret = NULL;
508    Ecore_List_Node    *old;
509
510    if (!list)
511       return NULL;
512
513    if (ecore_list_empty_is(list))
514       return NULL;
515
516    old = list->first;
517
518    list->first = list->first->next;
519
520    if (list->current == old)
521       list->current = list->first;
522    else
523       (list->index ? list->index-- : 0);
524
525    if (list->last == old)
526       list->last = list->first;
527
528    ret = old->data;
529    old->data = NULL;
530
531    ecore_list_node_destroy(old, NULL);
532    list->nodes--;
533
534    return ret;
535 }
536
537 /**
538  * Remove the last item from the list.
539  * @param   list The list to remove the last node from
540  * @return  A pointer to the removed data on success, @c NULL on failure.
541  * @ingroup Ecore_Data_List_Remove_Item_Group
542  */
543 EAPI void          *
544 ecore_list_last_remove(Ecore_List * list)
545 {
546    void               *ret;
547
548    CHECK_PARAM_POINTER_RETURN("list", list, NULL);
549
550    ret = _ecore_list_last_remove(list);
551
552    return ret;
553 }
554
555 /* Remove the last item from the list */
556 static void        *
557 _ecore_list_last_remove(Ecore_List * list)
558 {
559    void               *ret = NULL;
560    Ecore_List_Node    *old, *prev;
561
562    if (!list)
563       return NULL;
564
565    if (ecore_list_empty_is(list))
566       return NULL;
567
568    old = list->last;
569    if (list->current == old)
570       list->current = NULL;
571
572    if (list->first == old)
573       list->first = NULL;
574    for (prev = list->first; prev && prev->next != old; prev = prev->next)
575       ;
576    list->last = prev;
577    if (prev)
578       prev->next = NULL;
579
580    old->next = NULL;
581    ret = old->data;
582    old->data = NULL;
583
584    ecore_list_node_destroy(old, NULL);
585    list->nodes--;
586
587    return ret;
588 }
589
590 /**
591 @defgroup Ecore_Data_List_Traverse_Group List Traversal Functions
592
593 Functions that can be used to traverse an Ecore_List.
594 */
595
596 /**
597  * Make the current item the item with the given index number.
598  * @param   list  The list.
599  * @param   indx  The position to move the current item.
600  * @return  A pointer to new current item on success, @c NULL on failure.
601  * @ingroup Ecore_Data_List_Traverse_Group
602  */
603 EAPI void          *
604 ecore_list_index_goto(Ecore_List * list, int indx)
605 {
606    void               *ret;
607
608    CHECK_PARAM_POINTER_RETURN("list", list, NULL);
609
610    ret = _ecore_list_index_goto(list, indx);
611
612    return ret;
613 }
614
615 /* This is the non-threadsafe version, use this inside internal functions that
616  * already lock the list */
617 static void        *
618 _ecore_list_index_goto(Ecore_List * list, int indx)
619 {
620    int                 i;
621
622    if (!list)
623       return NULL;
624
625    if (ecore_list_empty_is(list))
626       return NULL;
627
628    if (indx > ecore_list_count(list) || indx < 0)
629       return NULL;
630
631    _ecore_list_first_goto(list);
632
633    for (i = 0; i < indx && _ecore_list_next(list); i++)
634       ;
635
636    if (i >= list->nodes)
637       return NULL;
638
639    list->index = i;
640
641    return list->current->data;
642 }
643
644 /**
645  * Make the current item the node that contains @p data.
646  * @param   list The list.
647  * @param   data The data to find.
648  * @return  A pointer to @p data on success, @c NULL on failure.
649  * @ingroup Ecore_Data_List_Traverse_Group
650  */
651 EAPI void          *
652 ecore_list_goto(Ecore_List * list, const void *data)
653 {
654    void               *ret;
655
656    CHECK_PARAM_POINTER_RETURN("list", list, NULL);
657
658    ret = _ecore_list_goto(list, data);
659
660    return ret;
661 }
662
663 /* Set the current position to the node containing data */
664 static void        *
665 _ecore_list_goto(Ecore_List * list, const void *data)
666 {
667    int                 indx;
668    Ecore_List_Node    *node;
669
670    if (!list)
671       return NULL;
672
673    indx = 0;
674
675    node = list->first;
676    while (node && node->data)
677      {
678         Ecore_List_Node    *next;
679
680         if (node->data == data)
681            break;
682
683         next = node->next;
684
685         node = next;
686
687         indx++;
688      }
689
690    if (!node)
691       return NULL;
692
693    list->current = node;
694    list->index = indx;
695
696    return list->current->data;
697 }
698
699 /**
700  * Make the current item the first item in the list
701  * @param   list The list.
702  * @return  A pointer to the first item on success, @c NULL on failure
703  * @ingroup Ecore_Data_List_Traverse_Group
704  */
705 EAPI void          *
706 ecore_list_first_goto(Ecore_List * list)
707 {
708    void               *ret;
709
710    CHECK_PARAM_POINTER_RETURN("list", list, NULL);
711
712    ret = _ecore_list_first_goto(list);
713
714    return ret;
715 }
716
717 /* Set the current position to the start of the list */
718 static void        *
719 _ecore_list_first_goto(Ecore_List * list)
720 {
721    if (!list->first)
722       return NULL;
723
724    list->current = list->first;
725    list->index = 0;
726
727    return list->current->data;
728 }
729
730 /**
731  * Make the current item the last item in the list.
732  * @param   list The list.
733  * @return  A pointer to the last item on success, @c NULL on failure.
734  * @ingroup Ecore_Data_List_Traverse_Group
735  */
736 EAPI void          *
737 ecore_list_last_goto(Ecore_List * list)
738 {
739    void               *ret;
740
741    CHECK_PARAM_POINTER_RETURN("list", list, NULL);
742
743    ret = _ecore_list_last_goto(list);
744
745    return ret;
746 }
747
748 /* Set the current position to the end of the list */
749 static void        *
750 _ecore_list_last_goto(Ecore_List * list)
751 {
752    if (!list || !list->last)
753       return NULL;
754
755    list->current = list->last;
756    list->index = (list->nodes - 1);
757
758    return list->current->data;
759 }
760
761 /**
762  * Retrieve the data pointed to by the current item in @p list.
763  * @param  list The list.
764  * @return Returns the data at current position, can be @c NULL.
765  */
766 EAPI void          *
767 ecore_list_current(Ecore_List * list)
768 {
769    void               *ret;
770
771    ret = _ecore_list_current(list);
772
773    return ret;
774 }
775
776 /* Return the data of the current node without incrementing */
777 static void        *
778 _ecore_list_current(Ecore_List * list)
779 {
780    void               *ret;
781
782    if (!list || !list->current)
783       return NULL;
784
785    ret = list->current->data;
786
787    return ret;
788 }
789
790 /**
791  * Retrieve the data pointed to by the current item, and make the next item
792  * the current item.
793  * @param   list The list to retrieve data from.
794  * @return  The current item in the list on success, @c NULL on failure.
795  */
796 EAPI void          *
797 ecore_list_next(Ecore_List * list)
798 {
799    void               *data;
800
801    CHECK_PARAM_POINTER_RETURN("list", list, NULL);
802
803    data = _ecore_list_next(list);
804
805    return data;
806 }
807
808 /* Return the data contained in the current node and go to the next node */
809 static void        *
810 _ecore_list_next(Ecore_List * list)
811 {
812    void               *data;
813    Ecore_List_Node    *ret;
814    Ecore_List_Node    *next;
815
816    if (!list->current)
817       return NULL;
818
819    ret = list->current;
820    next = list->current->next;
821
822    list->current = next;
823    list->index++;
824
825    data = ret->data;
826
827    return data;
828 }
829
830 /**
831  * Remove all nodes from @p list.
832  * @param  list The list.
833  * @return Returns @c TRUE on success, @c FALSE on error.
834  * @note The data for each item on the list is not freed by
835  *       @c ecore_list_clear().
836  */
837 EAPI int
838 ecore_list_clear(Ecore_List * list)
839 {
840    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
841
842    while (!ecore_list_empty_is(list))
843       _ecore_list_first_remove(list);
844
845    return TRUE;
846 }
847
848 /**
849  * Execute function for each node in @p list.
850  * @param   list     The list.
851  * @param   function The function to pass each node from @p list to.
852  * @return  Returns @c TRUE on success, @c FALSE on failure.
853  * @ingroup Ecore_Data_List_Traverse_Group
854  */
855 EAPI int
856 ecore_list_for_each(Ecore_List * list, Ecore_For_Each function, void *user_data)
857 {
858    int                 ret;
859
860    CHECK_PARAM_POINTER_RETURN("list", list, FALSE);
861
862    ret = _ecore_list_for_each(list, function, user_data);
863
864    return ret;
865 }
866
867 /* The real meat of executing the function for each data node */
868 static int
869 _ecore_list_for_each(Ecore_List * list, Ecore_For_Each function,
870                      void *user_data)
871 {
872    Ecore_List_Node    *node, *next;
873
874    if (!function)
875       return FALSE;
876
877    for (node = list->first; node; node = next)
878      {
879         next = node->next;
880         function(node->data, user_data);
881      }
882
883    return TRUE;
884 }
885
886 /**
887  * Find data in @p list using the compare function @p func
888  * @param list      The list.
889  * @param function  The function to test each node of @p list with
890  * @param user_data Data to match against (used by @p function)
891  * @return the first matching data node, or NULL if none match
892  */
893 EAPI void          *
894 ecore_list_find(Ecore_List * list, Ecore_Compare_Cb function,
895                 const void *user_data)
896 {
897    CHECK_PARAM_POINTER_RETURN("list", list, NULL);
898
899    return _ecore_list_find(list, function, user_data);
900 }
901
902 /* The real meat of finding a node via a compare cb */
903 static void        *
904 _ecore_list_find(Ecore_List * list, Ecore_Compare_Cb function,
905                  const void *user_data)
906 {
907    Ecore_List_Node    *node, *next;
908
909    if (!function)
910       return NULL;
911
912    for (node = list->first; node; node = next)
913      {
914         next = node->next;
915         if (!function(node->data, user_data))
916            return node->data;
917      }
918
919    return NULL;
920 }
921
922 /* Initialize a node to starting values */
923 EAPI int
924 ecore_list_node_init(Ecore_List_Node * node)
925 {
926    CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
927
928    node->next = NULL;
929    node->data = NULL;
930
931    return TRUE;
932 }
933
934 /**
935 @defgroup Ecore_Data_List_Node_Group List Node Functions
936
937 Functions that are used in the creation, maintenance and destruction of
938 Ecore_List nodes.
939 */
940
941 /**
942  * Allocates and initializes a new list node.
943  * @return  A new Ecore_List_Node on success, @c NULL otherwise.
944  * @ingroup Ecore_Data_List_Node_Group
945  */
946 EAPI Ecore_List_Node *
947 ecore_list_node_new(void)
948 {
949    Ecore_List_Node    *new_node;
950
951    new_node = (Ecore_List_Node *) malloc(sizeof(Ecore_List_Node));
952
953    if (!ecore_list_node_init(new_node))
954      {
955         free(new_node);
956         return NULL;
957      }
958
959    return new_node;
960 }
961
962 /**
963  * Calls the function to free the data and the node.
964  * @param   node      Node to destroy.
965  * @param   free_func Function to call if @p node points to data to free.
966  * @return  @c TRUE.
967  * @ingroup Ecore_Data_List_Node_Group
968  */
969 EAPI int
970 ecore_list_node_destroy(Ecore_List_Node * node, Ecore_Free_Cb free_func)
971 {
972    CHECK_PARAM_POINTER_RETURN("node", node, FALSE);
973
974    if (free_func && node->data)
975       free_func(node->data);
976
977    free(node);
978
979    return TRUE;
980 }
981
982 #endif /* !USE_ECORE */
983
984 /*
985  * E16 additions
986  */
987
988 EAPI void          *
989 ecore_list_node_remove(Ecore_List * list, void *_data)
990 {
991    void               *data;
992
993    data = ecore_list_goto(list, _data);
994    if (data)
995       ecore_list_remove(list);
996
997    return data;
998 }
999
1000 EAPI void         **
1001 ecore_list_items_get(Ecore_List * list, int *pnum)
1002 {
1003    void              **lst, *b;
1004    int                 i, num;
1005
1006    *pnum = 0;
1007    num = ecore_list_count(list);
1008    if (num <= 0)
1009       return NULL;
1010
1011    lst = (void **)malloc(num * sizeof(void *));
1012    if (!lst)
1013       return NULL;
1014
1015    for (i = 0, ecore_list_first_goto(list);
1016         (b = ecore_list_next(list)) != NULL;)
1017       lst[i++] = b;
1018
1019    *pnum = num;
1020    return lst;
1021 }