1 /*
2  * Copyright (C) 2003-2009 the oxine project
3  *
4  * xine is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * xine is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  * doubly linked lists with builtin iterator,
19  * based upon xine_list functions of the xine project
20  */
21 
22 #include "config.h"
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/types.h>
27 #include <inttypes.h>
28 
29 #ifdef DEBUG
30 #include <string.h>
31 #endif
32 
33 #include "list.h"
34 #include "utils.h"
35 
36 /*
37  * private data structures
38  */
39 
40 typedef struct node_s {
41 
42   struct node_s    *next, *prev;
43   void             *content;
44   int              priority;
45 
46 } node_t;
47 
48 
49 struct list_s {
50 
51   node_t    *first, *last, *cur;
52 
53 #ifdef DEBUG
54 #define TAG_SIZE 256
55   char tag[TAG_SIZE];
56 #endif
57 };
58 
59 
60 /*
61  * create a new, empty list
62  */
63 
64 #ifdef DEBUG
_list_new_tagged(const char * file,int line)65 list_t *_list_new_tagged(const char *file, int line) {
66 
67   char tag[TAG_SIZE];
68   list_t *list;
69 
70   snprintf(tag, TAG_SIZE, "list @ %s:%i", file, line);
71   list = ho_new_tagged(list_t, tag);
72   strcpy(list->tag, tag);
73 
74   list->first=NULL;
75   list->last =NULL;
76   list->cur  =NULL;
77 
78   return list;
79 }
80 #else
list_new(void)81 list_t *list_new (void) {
82   list_t *list;
83 
84   list = ho_new(list_t);
85 
86   list->first=NULL;
87   list->last =NULL;
88   list->cur  =NULL;
89 
90   return list;
91 }
92 #endif
93 
94 /*
95  * dispose a list (and only the list, contents have to be managed separately)
96  */
97 
list_free(list_t * l)98 void list_free(list_t *l) {
99   node_t *node;
100 
101   if (!l) {
102     printf ("list: tried to free empty list\n");
103     abort();
104   }
105 
106   if (!l->first) {
107 
108     ho_free(l);
109 
110     return;
111   }
112 
113   node = l->first;
114 
115   while(node) {
116     node_t *n = node;
117 
118     node = n->next;
119     ho_free(n);
120   }
121 
122   ho_free(l);
123 }
124 
list_first_content(list_t * l)125 void *list_first_content (list_t *l) {
126 
127   l->cur = l->first;
128 
129   if (l->first)
130     return l->first->content;
131   else
132     return NULL;
133 }
134 
list_next_content(list_t * l)135 void *list_next_content (list_t *l) {
136   if (l->cur) {
137 
138     if (l->cur->next) {
139       l->cur = l->cur->next;
140       return l->cur->content;
141     }
142     else
143       return NULL;
144 
145   } else {
146     printf ("list: next_content - passed end of list\n");
147     abort ();
148   }
149 }
150 
list_current_content(list_t * l)151 void *list_current_content (list_t *l) {
152   if (l->cur) {
153 
154     return l->cur->content;
155 
156   } else {
157     printf ("list: next_content - passed end of list\n");
158     abort ();
159   }
160 }
161 
list_is_empty(list_t * l)162 int list_is_empty (list_t *l) {
163 
164   if (l == NULL){
165     printf ("list: list_is_empty : list is NULL\n");
166     abort();
167   }
168   return (l->first != NULL);
169 }
170 
list_last_content(list_t * l)171 void *list_last_content (list_t *l) {
172 
173   if (l->last) {
174     l->cur = l->last;
175     return l->last->content;
176   } else
177     return NULL;
178 }
179 
list_prev_content(list_t * l)180 void *list_prev_content (list_t *l) {
181 
182   if (l->cur) {
183     if (l->cur->prev) {
184       l->cur = l->cur->prev;
185       return l->cur->content;
186     }
187     else
188       return NULL;
189   } else {
190     printf ("list: passed begin of list\n");
191     abort ();
192   }
193 }
194 
list_append_priority_content(list_t * l,void * content,int priority)195 void list_append_priority_content (list_t *l, void *content, int priority) {
196   node_t *node;
197 
198 #ifdef DEBUG
199   char tag[TAG_SIZE];
200 
201   snprintf(tag, TAG_SIZE, "pri node in %s", l->tag);
202   node = ho_new_tagged(node_t, tag);
203 #else
204   node = ho_new(node_t);
205 #endif
206 
207   node->content = content;
208   node->priority = priority;
209 
210   if (l->first) {
211     node_t *cur;
212 
213     cur = l->first;
214 
215     while(1) {
216       if( priority >= cur->priority ) {
217         node->next = cur;
218         node->prev = cur->prev;
219 
220         if( node->prev )
221           node->prev->next = node;
222         else
223           l->first = node;
224         cur->prev = node;
225 
226         l->cur = node;
227         break;
228       }
229 
230       if( !cur->next ) {
231         node->next = NULL;
232         node->prev = cur;
233         cur->next = node;
234 
235         l->cur = node;
236         l->last = node;
237         break;
238       }
239 
240       cur = cur->next;
241     }
242   }
243   else {
244     l->first = l->last = l->cur = node;
245     node->prev = node->next = NULL;
246   }
247 }
248 
249 #ifdef DEBUG
_list_append_content(list_t * l,void * content,const char * file,int line)250 void _list_append_content(list_t *l, void *content, const char *file, int line) {
251   node_t *node;
252   char tag[TAG_SIZE];
253 
254   snprintf(tag, TAG_SIZE, "app node @ %s:%i", file, line);
255   node = ho_new_tagged(node_t, tag);
256 
257 #else
258 void list_append_content (list_t *l, void *content) {
259   node_t *node;
260 
261   node = ho_new(node_t);
262 #endif
263   node->content = content;
264 
265   if (l->last) {
266     node->next = NULL;
267     node->prev = l->last;
268     l->last->next = node;
269     l->last = node;
270     l->cur = node;
271   }
272   else {
273     l->first = l->last = l->cur = node;
274     node->prev = node->next = NULL;
275   }
276 }
277 
278 void list_insert_content (list_t *l, void *content) {
279   node_t *nodecur, *nodenew, *nodeprev;
280 
281 #ifdef DEBUG
282   char tag[TAG_SIZE];
283 
284   snprintf(tag, TAG_SIZE, "ins node in %s", l->tag);
285   nodenew = ho_new_tagged(node_t, tag);
286 #else
287   nodenew = ho_new(node_t);
288 #endif
289   nodenew->content = content;
290   nodecur = l->cur;
291 
292   if(!nodecur) {
293     list_append_content(l, content);
294     return;
295   }
296 
297   nodeprev = nodecur->prev;
298   nodecur->prev = nodenew;
299   nodenew->next = nodecur;
300   nodenew->prev = nodeprev;
301   if(nodecur != l->first) {
302     nodeprev->next = nodenew;
303   } else {
304     l->first = nodenew;
305   }
306   l->cur = nodenew;
307 }
308 
309 void list_delete_current (list_t *l) {
310   node_t *node_cur;
311 
312   node_cur = l->cur;
313 
314   if(node_cur->prev) {
315     node_cur->prev->next = node_cur->next;
316   }
317   else { /* First entry */
318     l->first = node_cur->next;
319   }
320 
321   if(node_cur->next) {
322     node_cur->next->prev = node_cur->prev;
323     l->cur = node_cur->next;
324   }
325   else { /* last entry in the list */
326     l->last = node_cur->prev;
327     l->cur = node_cur->prev;
328   }
329   ho_free(node_cur);
330 }
331 
332 /*
333  * glib's implementation of lists
334  */
335 
336 #define _g_list_new g_list_new
337 g_list_t* g_list_new (void) {
338   g_list_t *list;
339 
340   list = ho_new(g_list_t);
341 
342   return list;
343 }
344 
345 void g_list_free (g_list_t *list) {
346   g_list_t *last;
347 
348   while (list)
349   {
350     last = list;
351     list = list->next;
352     ho_free (last);
353   }
354 }
355 
356 #define _g_list_free_1 g_list_free_1
357 void g_list_free_1 (g_list_t *list) {
358   ho_free (list);
359 }
360 
361 g_list_t* g_list_append (g_list_t *list, void* data) {
362   g_list_t *new_list;
363   g_list_t *last;
364 
365   new_list = _g_list_new ();
366   new_list->data = data;
367 
368   if (list)
369   {
370     last = g_list_last (list);
371     last->next = new_list;
372     new_list->prev = last;
373 
374     return list;
375   }
376   else
377     return new_list;
378 }
379 
380 g_list_t* g_list_prepend (g_list_t *list, void* data) {
381   g_list_t *new_list;
382 
383   new_list = _g_list_new ();
384   new_list->data = data;
385 
386   if (list)
387   {
388     if (list->prev)
389     {
390       list->prev->next = new_list;
391       new_list->prev = list->prev;
392     }
393     list->prev = new_list;
394     new_list->next = list;
395   }
396 
397   return new_list;
398 }
399 
400 g_list_t* g_list_insert (g_list_t *list, void* data, int position) {
401   g_list_t *new_list;
402   g_list_t *tmp_list;
403 
404   if (position < 0)
405     return g_list_append (list, data);
406   else if (position == 0)
407     return g_list_prepend (list, data);
408 
409   tmp_list = g_list_nth (list, position);
410   if (!tmp_list)
411     return g_list_append (list, data);
412 
413   new_list = _g_list_new ();
414   new_list->data = data;
415 
416   if (tmp_list->prev)
417   {
418     tmp_list->prev->next = new_list;
419     new_list->prev = tmp_list->prev;
420   }
421   new_list->next = tmp_list;
422   tmp_list->prev = new_list;
423 
424   if (tmp_list == list)
425     return new_list;
426   else
427     return list;
428 }
429 
430 g_list_t* g_list_insert_before (g_list_t *list, g_list_t *sibling, void* data) {
431   if (!list)
432   {
433     list = g_list_new ();
434     list->data = data;
435     return list;
436   }
437   else if (sibling)
438   {
439     g_list_t *node;
440 
441     node = g_list_new ();
442     node->data = data;
443     if (sibling->prev)
444     {
445       node->prev = sibling->prev;
446       node->prev->next = node;
447       node->next = sibling;
448       sibling->prev = node;
449       return list;
450     }
451     else
452     {
453       node->next = sibling;
454       sibling->prev = node;
455       return node;
456     }
457   }
458   else
459   {
460     g_list_t *last;
461 
462     last = list;
463     while (last->next)
464       last = last->next;
465 
466     last->next = g_list_new ();
467     last->next->data = data;
468     last->next->prev = last;
469 
470     return list;
471   }
472 }
473 
474 g_list_t * g_list_concat (g_list_t *list1, g_list_t *list2) {
475   g_list_t *tmp_list;
476 
477   if (list2)
478   {
479     tmp_list = g_list_last (list1);
480     if (tmp_list)
481       tmp_list->next = list2;
482     else
483       list1 = list2;
484     list2->prev = tmp_list;
485   }
486 
487   return list1;
488 }
489 
490 g_list_t* g_list_remove (g_list_t *list, const void *data) {
491   g_list_t *tmp;
492 
493   tmp = list;
494   while (tmp)
495   {
496     if (tmp->data != data)
497       tmp = tmp->next;
498     else
499     {
500       if (tmp->prev)
501 	tmp->prev->next = tmp->next;
502       if (tmp->next)
503 	tmp->next->prev = tmp->prev;
504 
505       if (list == tmp)
506 	list = list->next;
507 
508       _g_list_free_1 (tmp);
509 
510       break;
511     }
512   }
513   return list;
514 }
515 
516 g_list_t* g_list_remove_all (g_list_t *list, const void *data) {
517   g_list_t *tmp = list;
518 
519   while (tmp)
520   {
521     if (tmp->data != data)
522       tmp = tmp->next;
523     else
524     {
525       g_list_t *next = tmp->next;
526 
527       if (tmp->prev)
528 	tmp->prev->next = next;
529       else
530 	list = next;
531       if (next)
532 	next->prev = tmp->prev;
533 
534       _g_list_free_1 (tmp);
535       tmp = next;
536     }
537   }
538   return list;
539 }
540 
541 static inline g_list_t* _g_list_remove_link (g_list_t *list, g_list_t *link) {
542   if (link)
543   {
544     if (link->prev)
545       link->prev->next = link->next;
546     if (link->next)
547       link->next->prev = link->prev;
548 
549     if (link == list)
550       list = list->next;
551 
552     link->next = NULL;
553     link->prev = NULL;
554   }
555 
556   return list;
557 }
558 
559 g_list_t* g_list_remove_link (g_list_t *list, g_list_t *link) {
560   return _g_list_remove_link (list, link);
561 }
562 
563 g_list_t* g_list_delete_link (g_list_t *list, g_list_t *link) {
564   list = _g_list_remove_link (list, link);
565   _g_list_free_1 (link);
566 
567   return list;
568 }
569 
570 g_list_t* g_list_copy (g_list_t *list) {
571   g_list_t *new_list = NULL;
572 
573   if (list)
574   {
575     g_list_t *last;
576 
577     new_list = _g_list_new ();
578     new_list->data = list->data;
579     last = new_list;
580     list = list->next;
581     while (list)
582     {
583       last->next = _g_list_new ();
584       last->next->prev = last;
585       last = last->next;
586       last->data = list->data;
587       list = list->next;
588     }
589   }
590 
591   return new_list;
592 }
593 
594 g_list_t* g_list_reverse (g_list_t *list) {
595   g_list_t *last;
596 
597   last = NULL;
598   while (list)
599     {
600       last = list;
601       list = last->next;
602       last->next = last->prev;
603       last->prev = list;
604     }
605 
606   return last;
607 }
608 
609 g_list_t* g_list_nth (g_list_t *list, unsigned int  n) {
610   while ((n-- > 0) && list)
611     list = list->next;
612 
613   return list;
614 }
615 
616 g_list_t* g_list_nth_prev (g_list_t *list, unsigned int n) {
617   while ((n-- > 0) && list)
618     list = list->prev;
619 
620   return list;
621 }
622 
623 void* g_list_nth_data (g_list_t *list, unsigned int n) {
624   while ((n-- > 0) && list)
625     list = list->next;
626 
627   return list ? list->data : NULL;
628 }
629 
630 g_list_t* g_list_find (g_list_t *list, const void *data) {
631   while (list)
632   {
633     if (list->data == data)
634       break;
635     list = list->next;
636   }
637 
638   return list;
639 }
640 
641 g_list_t* g_list_find_custom (g_list_t *list, const void *data, list_compare func) {
642 
643   while (list)
644   {
645     if (! func (list->data, data))
646       return list;
647     list = list->next;
648   }
649 
650   return NULL;
651 }
652 
653 
654 int g_list_position (g_list_t *list, g_list_t *link) {
655   int i;
656 
657   i = 0;
658   while (list)
659   {
660     if (list == link)
661       return i;
662     i++;
663     list = list->next;
664   }
665 
666   return -1;
667 }
668 
669 int g_list_index (g_list_t *list, const void *data) {
670   int i;
671 
672   i = 0;
673   while (list)
674   {
675     if (list->data == data)
676       return i;
677     i++;
678     list = list->next;
679   }
680 
681   return -1;
682 }
683 
684 g_list_t* g_list_last (g_list_t *list) {
685   if (list)
686   {
687     while (list->next)
688       list = list->next;
689   }
690 
691   return list;
692 }
693 
694 g_list_t* g_list_first (g_list_t *list) {
695   if (list)
696   {
697     while (list->prev)
698       list = list->prev;
699   }
700 
701   return list;
702 }
703 
704 unsigned int g_list_length (g_list_t *list) {
705   unsigned int length;
706 
707   length = 0;
708   while (list)
709   {
710     length++;
711     list = list->next;
712   }
713 
714   return length;
715 }
716 
717 void g_list_foreach (g_list_t *list, list_func func, void *user_data) {
718   while (list)
719   {
720     g_list_t *next = list->next;
721     (*func) (list->data, user_data);
722     list = next;
723   }
724 }
725 
726 
727 g_list_t* g_list_insert_sorted (g_list_t *list, void *data, list_compare func) {
728   g_list_t *tmp_list = list;
729   g_list_t *new_list;
730   int cmp;
731 
732   if (!func) return list;
733 
734   if (!list)
735   {
736     new_list = _g_list_new ();
737     new_list->data = data;
738     return new_list;
739   }
740 
741   cmp = (*func) (data, tmp_list->data);
742 
743   while ((tmp_list->next) && (cmp > 0))
744   {
745     tmp_list = tmp_list->next;
746     cmp = (*func) (data, tmp_list->data);
747   }
748 
749   new_list = _g_list_new ();
750   new_list->data = data;
751 
752   if ((!tmp_list->next) && (cmp > 0))
753   {
754     tmp_list->next = new_list;
755     new_list->prev = tmp_list;
756     return list;
757   }
758 
759   if (tmp_list->prev)
760   {
761     tmp_list->prev->next = new_list;
762     new_list->prev = tmp_list->prev;
763   }
764   new_list->next = tmp_list;
765   tmp_list->prev = new_list;
766 
767   if (tmp_list == list)
768     return new_list;
769   else
770     return list;
771 }
772 
773 static g_list_t *g_list_sort_merge (g_list_t *l1, g_list_t *l2, list_func compare_func,
774     int use_data, void *user_data) {
775 
776   g_list_t list, *l, *lprev;
777   int cmp;
778 
779   l = &list;
780   lprev = NULL;
781 
782   while (l1 && l2)
783   {
784     if (use_data)
785       cmp = ((list_compare_data) compare_func) (l1->data, l2->data, user_data);
786     else
787       cmp = ((list_compare) compare_func) (l1->data, l2->data);
788 
789     if (cmp <= 0)
790     {
791       l->next = l1;
792       l = l->next;
793       l->prev = lprev;
794       lprev = l;
795       l1 = l1->next;
796     }
797     else
798     {
799       l->next = l2;
800       l = l->next;
801       l->prev = lprev;
802       lprev = l;
803       l2 = l2->next;
804     }
805   }
806   l->next = l1 ? l1 : l2;
807   l->next->prev = l;
808 
809   return list.next;
810 }
811 
812 static g_list_t* g_list_sort_real (g_list_t *list, list_func compare_func,
813     int use_data, void *user_data) {
814 
815   g_list_t *l1, *l2;
816 
817   if (!list)
818     return NULL;
819   if (!list->next)
820     return list;
821 
822   l1 = list;
823   l2 = list->next;
824 
825   while ((l2 = l2->next) != NULL)
826   {
827     if ((l2 = l2->next) == NULL)
828       break;
829     l1 = l1->next;
830   }
831   l2 = l1->next;
832   l1->next = NULL;
833 
834   return g_list_sort_merge (g_list_sort_real (list, compare_func, use_data, user_data),
835 			    g_list_sort_real (l2, compare_func, use_data, user_data),
836 			    compare_func,
837 			    use_data,
838 			    user_data);
839 }
840 
841 g_list_t *g_list_sort (g_list_t *list, list_compare compare_func) {
842   return g_list_sort_real (list, (list_func) compare_func, 0, NULL);
843 }
844 
845 g_list_t * g_list_sort_with_data (g_list_t *list, list_compare compare_func, void *user_data) {
846   return g_list_sort_real (list, (list_func) compare_func, 1, user_data);
847 }
848 
849 #if 0
850 static g_list_t* g_list_sort2 (g_list_t *list, list_compare compare_func) {
851   g_list_t *runs = NULL;
852   g_list_t *tmp;
853 
854   /* Degenerate case.  */
855   if (!list) return NULL;
856 
857   /* Assume: list = [12,2,4,11,2,4,6,1,1,12].  */
858   for (tmp = list; tmp; )
859   {
860     g_list_t *tmp2;
861     for (tmp2 = tmp;
862 	 tmp2->next && compare_func (tmp2->data, tmp2->next->data) <= 0;
863 	 tmp2 = tmp2->next)
864       /* Nothing */;
865     runs = g_list_append (runs, tmp);
866     tmp = tmp2->next;
867     tmp2->next = NULL;
868   }
869   /* Now: runs = [[12],[2,4,11],[2,4,6],[1,1,12]].  */
870 
871   while (runs->next)
872   {
873     /* We have more than one run.  Merge pairwise.  */
874     g_list_t *dst, *src, *dstprev = NULL;
875     dst = src = runs;
876     while (src && src->next)
877     {
878       dst->data = g_list_sort_merge (src->data,
879 				     src->next->data,
880 				     (list_func) compare_func,
881 				     0, NULL);
882       dstprev = dst;
883       dst = dst->next;
884       src = src->next->next;
885     }
886 
887     /* If number of runs was odd, just keep the last.  */
888     if (src)
889     {
890       dst->data = src->data;
891       dstprev = dst;
892       dst = dst->next;
893     }
894 
895     dstprev->next = NULL;
896     g_list_free (dst);
897   }
898 
899   /* After 1st loop: runs = [[2,4,11,12],[1,1,2,4,6,12]].  */
900   /* After 2nd loop: runs = [[1,1,2,2,4,4,6,11,12,12]].  */
901 
902   list = runs->data;
903   g_list_free (runs);
904   return list;
905 }
906 #endif
907