1 /**********************************************************************
2   linkedlist.c
3  **********************************************************************
4 
5   linkedlist - Linked list implementation (singly- and doubly- linked).
6   Copyright ©2000-2004, Stewart Adcock <stewart@linux-domain.com>
7   All rights reserved.
8 
9   The latest version of this program should be available at:
10   http://gaul.sourceforge.net/
11 
12   This program is free software; you can redistribute it and/or modify
13   it under the terms of the GNU General Public License as published by
14   the Free Software Foundation; either version 2 of the License, or
15   (at your option) any later version.  Alternatively, if your project
16   is incompatible with the GPL, I will probably agree to requests
17   for permission to use the terms of any other license.
18 
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY WHATSOEVER.
21 
22   A full copy of the GNU General Public License should be in the file
23   "COPYING" provided with this distribution; if not, see:
24   http://www.gnu.org/
25 
26  **********************************************************************
27 
28   Synopsis:	Linked list implementations.
29 
30 		Single-linked list functions are named slink_*().
31 		Double-linked list functions are named dlink_*().
32 
33 		MP-safe.
34 
35 		For OpenMP code, USE_OPENMP must be defined and
36 		linkedlist_init_openmp() must be called prior to any
37 		other function.
38 
39   To do:        Add sorting functions.
40                 Functions for inserting/appending lists etc. (i.e. slink_append_list() )
41                 Converting slists to dlists, and visa versa.
42                 Equivalent of avltree_destroy().
43                 ?link_unlink_data() etc like delete functions, except without freeing the element(s).
44 
45   To compile:	gcc linkedlist.c -DLINKEDLIST_COMPILE_MAIN -g -L . -lstuff
46 
47  **********************************************************************/
48 
49 #include "gaul/linkedlist.h"
50 
51 #ifdef LINKEDLIST_COMPILE_MAIN
52 #include <stdio.h>
53 #include <string.h>
54 #endif
55 
56 
57 THREAD_LOCK_DEFINE_STATIC(slist_chunk_lock);
58 THREAD_LOCK_DEFINE_STATIC(dlist_chunk_lock);
59 static MemChunk *slist_chunk = NULL;
60 static MemChunk *dlist_chunk = NULL;
61 
62 #if USE_OPENMP == 1
63 static boolean linkedlist_openmp_initialised = FALSE;
64 #endif
65 
66 /*
67  * This function must be called before any other functions is OpenMP
68  * code is to be used.  Can be safely called when OpenMP code is not
69  * being used, and can be safely called more than once.
70  */
linkedlist_init_openmp(void)71 void linkedlist_init_openmp(void)
72   {
73 
74 #if USE_OPENMP == 1
75   if (linkedlist_openmp_initialised == FALSE)
76     {
77     omp_init_lock(&slist_chunk_lock);
78     omp_init_lock(&dlist_chunk_lock);
79     linkedlist_openmp_initialised = TRUE;
80     }
81 #endif
82 
83   return;
84   }
85 
86 
slink_new(void)87 SLList *slink_new(void)
88   {
89   SLList *element;
90 
91   THREAD_LOCK(slist_chunk_lock);
92   if (!slist_chunk)
93     slist_chunk = mem_chunk_new(sizeof(SLList), 512);
94 
95   element = (SLList *)mem_chunk_alloc(slist_chunk);
96   THREAD_UNLOCK(slist_chunk_lock);
97 
98   element->next = NULL;
99   element->data = NULL;
100 
101   return element;
102   }
103 
104 
slink_free_all(SLList * list)105 void slink_free_all(SLList *list)
106   {
107   SLList	*element;
108 
109   THREAD_LOCK(slist_chunk_lock);
110   while (list)
111     {
112     element = list->next;
113     mem_chunk_free(slist_chunk, list);
114     list = element;
115     }
116 
117   if (mem_chunk_isempty(slist_chunk))
118     {
119     mem_chunk_destroy(slist_chunk);
120     slist_chunk = NULL;
121     }
122   THREAD_UNLOCK(slist_chunk_lock);
123 
124   return;
125   }
126 
127 
slink_free(SLList * list)128 void slink_free(SLList *list)
129   {
130   if (!list) return;
131 
132   THREAD_LOCK(slist_chunk_lock);
133   mem_chunk_free(slist_chunk, list);
134 
135   if (mem_chunk_isempty(slist_chunk))
136     {
137     mem_chunk_destroy(slist_chunk);
138     slist_chunk = NULL;
139     }
140   THREAD_UNLOCK(slist_chunk_lock);
141 
142   return;
143   }
144 
145 
slink_append(SLList * list,vpointer data)146 SLList *slink_append(SLList *list, vpointer data)
147   {
148   SLList *new_element;
149   SLList *last;
150 
151   new_element = slink_new();
152   new_element->data = data;
153 
154   if (!list) return new_element;
155 
156   last = slink_last(list);
157   last->next = new_element;
158 
159   return list;
160   }
161 
162 
slink_prepend(SLList * list,vpointer data)163 SLList *slink_prepend(SLList *list, vpointer data)
164   {
165   SLList *new_element;
166 
167   new_element = slink_new();
168   new_element->data = data;
169   new_element->next = list;
170 
171   return new_element;
172   }
173 
174 
slink_insert_next(SLList * list,vpointer data)175 SLList *slink_insert_next(SLList *list, vpointer data)
176   {
177   SLList *new_element;
178   SLList *next;
179 
180   new_element = slink_new();
181   new_element->data = data;
182 
183   if (!list) return new_element;
184 
185   next = list->next;
186   list->next = new_element;
187   new_element->next = next;
188 
189   return list;
190   }
191 
192 
slink_insert_index(SLList * list,vpointer data,int index)193 SLList *slink_insert_index(SLList *list, vpointer data, int index)
194   {
195   SLList *prev_list;
196   SLList *this_list;
197   SLList *new_element;
198 
199   new_element = slink_new();
200   new_element->data = data;
201 
202   if (!list) return new_element;
203 
204   prev_list = NULL;
205   this_list = list;
206 
207   while ((index-- > 0) && this_list)
208     {
209     prev_list = this_list;
210     this_list = this_list->next;
211     }
212 
213   if (!prev_list)
214     {
215     new_element->next = list;
216     return new_element;
217     }
218 
219   new_element->next = prev_list->next;
220   prev_list->next = new_element;
221 
222   return list;
223   }
224 
225 
slink_delete_data(SLList * list,vpointer data)226 SLList *slink_delete_data(SLList *list, vpointer data)
227   {
228   SLList *tmp = list;
229   SLList *prev = NULL;
230 
231   while (tmp)
232     {
233     if (tmp->data == data)
234       {
235       if (prev) prev->next = tmp->next;
236       if (list == tmp) list = list->next;
237 
238       slink_free(tmp);
239 
240       return list;
241       }
242 
243     prev = tmp;
244     tmp = tmp->next;
245     }
246 
247   return list;
248   }
249 
250 
slink_delete_all_data(SLList * list,vpointer data)251 SLList *slink_delete_all_data(SLList *list, vpointer data)
252   {
253   SLList *tmp = list;
254   SLList *prev = NULL;
255 
256   while (tmp)
257     {
258     if (tmp->data == data)
259       {
260       if (prev) prev->next = tmp->next;
261       if (list == tmp) list = list->next;
262 
263       slink_free(tmp);
264       }
265     else
266       {
267       prev = tmp;
268       tmp = tmp->next;
269       }
270     }
271 
272   return list;
273   }
274 
275 
slink_delete_link(SLList * list,SLList * link)276 SLList *slink_delete_link(SLList *list, SLList *link)
277   {
278   SLList *tmp = list;
279   SLList *prev = NULL;
280 
281   while (tmp)
282     {
283     if (tmp == link)
284       {
285       if (prev) prev->next = tmp->next;
286       if (list == tmp) list = list->next;
287 
288       slink_free(tmp);
289 
290       return list;
291       }
292 
293     prev = tmp;
294     tmp = tmp->next;
295     }
296 
297   return list;
298   }
299 
300 
slink_clone(SLList * list)301 SLList *slink_clone(SLList *list)
302   {
303   SLList *new_element = NULL;
304   SLList *last;
305 
306   if (!list) return NULL;
307 
308   new_element = slink_new();
309   new_element->data = list->data;
310   last = new_element;
311   list = list->next;
312   while (list)
313     {
314     last->next = slink_new();
315     last = last->next;
316     last->data = list->data;
317     list = list->next;
318     }
319 
320   return new_element;
321   }
322 
323 
slink_reverse(SLList * list)324 SLList *slink_reverse(SLList *list)
325   {
326   SLList *element;
327   SLList *prev = NULL;
328   SLList *last = NULL;
329 
330   while (list)
331     {
332     last = list;
333     element = list->next;
334     list->next = prev;
335     prev = list;
336     list = element;
337     }
338 
339   return last;
340   }
341 
342 
slink_nth(SLList * list,const int index)343 SLList *slink_nth(SLList *list, const int index)
344   {
345   int	i=index;
346 
347   while (i > 0 && list)
348     {
349     list = list->next;
350     i--;
351     }
352 
353   return list;
354   }
355 
356 
slink_nth_data(SLList * list,const int index)357 vpointer slink_nth_data(SLList *list, const int index)
358   {
359   list = slink_nth(list, index);
360 
361   return list?list->data:NULL;
362   }
363 
364 
slink_find(SLList * list,vpointer data)365 SLList *slink_find(SLList *list, vpointer data)
366   {
367   while (list && list->data != data) list = list->next;
368 
369   return list;
370   }
371 
372 
slink_find_custom(SLList * list,vpointer data,LLCompareFunc func)373 SLList *slink_find_custom(SLList *list, vpointer data, LLCompareFunc func)
374   {
375   if (!func) die("Null pointer to LLCompareFunc passed.");
376 
377   while (list && func(list->data, data)==FALSE)
378     list = list->next;
379 
380   return list;
381   }
382 
383 
slink_index_link(SLList * list,SLList * link)384 int slink_index_link(SLList *list, SLList *link)
385   {
386   int i=0;
387 
388   while (list)
389     {
390     if (list == link) return i;
391     i++;
392     list = list->next;
393     }
394 
395   return -1;
396   }
397 
398 
slink_index_data(SLList * list,vpointer data)399 int slink_index_data(SLList *list, vpointer data)
400   {
401   int i=0;
402 
403   while (list)
404     {
405     if (list->data == data) return i;
406     i++;
407     list = list->next;
408     }
409 
410   return -1;
411   }
412 
413 
slink_last(SLList * list)414 SLList *slink_last(SLList *list)
415   {
416   if (!list) return NULL;
417 
418   while (list->next) list = list->next;
419 
420   return list;
421   }
422 
423 
slink_size(SLList * list)424 int slink_size(SLList *list)
425   {
426   int	size=0;
427 
428   while (list)
429     {
430     size++;
431     list = list->next;
432     }
433 
434   return size;
435   }
436 
437 
slink_foreach(SLList * list,LLForeachFunc func,vpointer userdata)438 boolean slink_foreach(SLList *list, LLForeachFunc func, vpointer userdata)
439   {
440 
441   if (!func) die("Null pointer to LLForeachFunc passed.");
442 
443   while (list)
444     {
445     if ((*func)(list->data, userdata)) return TRUE;
446     list = list->next;
447     }
448 
449   return FALSE;
450   }
451 
452 
slink_insert_sorted(SLList * list,vpointer data,LLCompareFunc func)453 SLList *slink_insert_sorted(SLList *list, vpointer data, LLCompareFunc func)
454   {
455   SLList *prev_list;
456   SLList *this_list;
457   SLList *new_element;
458 
459   if (!func) die("Null pointer to LLCompareFunc passed.");
460 
461   new_element = slink_new();
462   new_element->data = data;
463 
464   if (!list) return new_element;
465 
466   prev_list = NULL;
467   this_list = list;
468 
469   while (this_list && func(this_list->data, data)<0)
470     {
471     prev_list = this_list;
472     this_list = this_list->next;
473     }
474 
475   if (!prev_list)
476     {
477     new_element->next = list;
478     return new_element;
479     }
480 
481   new_element->next = prev_list->next;
482   prev_list->next = new_element;
483 
484   return list;
485   }
486 
487 
dlink_new(void)488 DLList *dlink_new(void)
489   {
490   DLList *element;
491 
492   THREAD_LOCK(dlist_chunk_lock);
493   if (!dlist_chunk)
494     dlist_chunk = mem_chunk_new(sizeof(DLList), 512);
495 
496   element = (DLList *)mem_chunk_alloc(dlist_chunk);
497   THREAD_UNLOCK(dlist_chunk_lock);
498 
499   element->prev = NULL;
500   element->next = NULL;
501   element->data = NULL;
502 
503   return element;
504   }
505 
506 
dlink_free_all(DLList * list)507 void dlink_free_all(DLList *list)
508   {
509   DLList        *list2;
510   DLList        *element;
511 
512   if (!list) return;
513 
514   list2 = list->prev;
515 
516   THREAD_LOCK(dlist_chunk_lock);
517   while (list)
518     {
519     element = list->next;
520     mem_chunk_free(dlist_chunk, list);
521     list = element;
522     }
523 
524   while (list2)
525     {
526     element = list2->prev;
527     mem_chunk_free(dlist_chunk, list2);
528     list2 = element;
529     }
530 
531   if (mem_chunk_isempty(dlist_chunk))
532     {
533     mem_chunk_destroy(dlist_chunk);
534     dlist_chunk = NULL;
535     }
536   THREAD_UNLOCK(dlist_chunk_lock);
537 
538   return;
539   }
540 
541 
dlink_free(DLList * list)542 void dlink_free(DLList *list)
543   {
544   if (!list) return;
545 
546   THREAD_LOCK(dlist_chunk_lock);
547   mem_chunk_free(dlist_chunk, list);
548 
549   if (mem_chunk_isempty(dlist_chunk))
550     {
551     mem_chunk_destroy(dlist_chunk);
552     dlist_chunk = NULL;
553     }
554   THREAD_UNLOCK(dlist_chunk_lock);
555 
556   return;
557   }
558 
559 
dlink_append(DLList * list,vpointer data)560 DLList *dlink_append(DLList *list, vpointer data)
561   {
562   DLList *new_element;
563   DLList *last;
564 
565   new_element = dlink_new();
566   new_element->data = data;
567 
568   if (!list) return new_element;
569 
570   last = dlink_last(list);
571   last->next = new_element;
572   new_element->prev = last;
573 
574   return list;
575   }
576 
577 
dlink_prepend(DLList * list,vpointer data)578 DLList *dlink_prepend(DLList *list, vpointer data)
579   {
580   DLList *new_element;
581 
582   new_element = dlink_new();
583   new_element->data = data;
584 
585   if (!list) return new_element;
586 
587   if (list->prev)
588     {
589     list->prev->next = new_element;
590     new_element->prev = list->prev;
591     }
592 
593   list->prev = new_element;
594   new_element->next = list;
595 
596   return new_element;
597   }
598 
599 
dlink_insert_next(DLList * list,vpointer data)600 DLList *dlink_insert_next(DLList *list, vpointer data)
601   {
602   DLList *new_element;
603   DLList *next;
604 
605   new_element = dlink_new();
606   new_element->data = data;
607 
608   if (!list) return new_element;
609 
610   next = list->next;
611   if (next)
612     {
613     new_element->next = next;
614     next->prev = new_element;
615     }
616   list->next = new_element;
617   new_element->prev = list;
618 
619   return list;
620   }
621 
622 
dlink_insert_prev(DLList * list,vpointer data)623 DLList *dlink_insert_prev(DLList *list, vpointer data)
624   {
625   DLList *new_element;
626   DLList *prev;
627 
628   new_element = dlink_new();
629   new_element->data = data;
630 
631   if (!list) return new_element;
632 
633   prev = list->prev;
634   if (prev)
635     {
636     new_element->prev = prev;
637     prev->next = new_element;
638     }
639   list->prev = new_element;
640   new_element->next = list;
641 
642   return new_element;
643   }
644 
645 
dlink_insert_index(DLList * list,vpointer data,int index)646 DLList *dlink_insert_index(DLList *list, vpointer data, int index)
647   {
648   DLList *new_element;
649   DLList *this_list;
650 
651   if (index < 0)
652     {
653 /* FIXME: Prehaps I should insert from end of list instead? */
654     return dlink_append(list, data);
655     }
656   else if (index == 0)
657     {
658     return dlink_prepend(list, data);
659     }
660 
661   this_list = dlink_nth(list, index);
662   if (!this_list)
663     return dlink_append(list, data);
664 
665   new_element = dlink_new();
666   new_element->data = data;
667 
668   if (this_list->prev)
669     {
670     this_list->prev->next = new_element;
671     new_element->prev = this_list->prev;
672     }
673   new_element->next = this_list;
674   this_list->prev = new_element;
675 
676   if (this_list == list)
677     return new_element;
678   else
679     return list;
680   }
681 
682 
dlink_delete_all_data(DLList * list,vpointer data)683 DLList *dlink_delete_all_data(DLList *list, vpointer data)
684   {
685   DLList *tmp=list;
686 
687   while (tmp)
688     {
689     if (tmp->data == data)
690       {
691       if (tmp->prev) tmp->prev->next = tmp->next;
692       if (tmp->next) tmp->next->prev = tmp->prev;
693 
694       if (list == tmp) list = list->next;
695 
696       dlink_free(tmp);
697       }
698 
699     tmp = tmp->next;
700     }
701 
702   return list;
703   }
704 
705 
dlink_delete_data(DLList * list,vpointer data)706 DLList *dlink_delete_data(DLList *list, vpointer data)
707   {
708   DLList *tmp=list;
709 
710   while (tmp)
711     {
712     if (tmp->data == data)
713       {
714       if (tmp->prev) tmp->prev->next = tmp->next;
715       if (tmp->next) tmp->next->prev = tmp->prev;
716 
717       if (list == tmp) list = list->next;
718 
719       dlink_free(tmp);
720 
721       return list;
722       }
723 
724     tmp = tmp->next;
725     }
726 
727   return list;
728   }
729 
730 
dlink_delete_link(DLList * list,DLList * link)731 DLList *dlink_delete_link(DLList *list, DLList *link)
732   {
733   if (!link) return NULL;
734 
735   if (link->prev) link->prev->next = link->next;
736   if (link->next) link->next->prev = link->prev;
737 
738   if (link == list) list = list->next;
739 
740   link->prev = NULL;
741   link->next = NULL;
742 
743   return list;
744   }
745 
746 
dlink_clone(DLList * list)747 DLList *dlink_clone(DLList *list)
748   {
749   DLList *new_element = NULL;
750   DLList *last;
751 
752   if (!list) return NULL;
753 
754   new_element = dlink_new();
755   new_element->data = list->data;
756   last = new_element;
757   list = list->next;
758   while (list)
759     {
760     last->next = dlink_new();
761     last->next->prev = last;
762     last = last->next;
763     last->data = list->data;
764     list = list->next;
765     }
766 
767   return new_element;
768   }
769 
770 
dlink_reverse(DLList * list)771 DLList *dlink_reverse(DLList *list)
772   {
773   DLList *last=NULL;
774 
775   while (list)
776     {
777     last = list;
778     list = last->next;
779     last->next = last->prev;
780     last->prev = list;
781     }
782 
783   return last;
784   }
785 
786 
dlink_nth(DLList * list,const int index)787 DLList *dlink_nth(DLList *list, const int index)
788   {
789   int	i=index;
790 
791   while (i > 0 && list)
792     {
793     list = list->next;
794     i--;
795     }
796 
797   return list;
798   }
799 
800 
dlink_pth(DLList * list,const int index)801 DLList *dlink_pth(DLList *list, const int index)
802   {
803   int	i=index;
804 
805   while (i > 0 && list)
806     {
807     list = list->prev;
808     i--;
809     }
810 
811   return list;
812   }
813 
814 
dlink_nth_data(DLList * list,const int index)815 vpointer dlink_nth_data(DLList *list, const int index)
816   {
817   list = dlink_nth(list, index);
818 
819   return list?list->data:NULL;
820   }
821 
822 
dlink_pth_data(DLList * list,const int index)823 vpointer dlink_pth_data(DLList *list, const int index)
824   {
825   list = dlink_pth(list, index);
826 
827   return list?list->data:NULL;
828   }
829 
830 
dlink_find(DLList * list,vpointer data)831 DLList *dlink_find(DLList *list, vpointer data)
832   {
833   while (list && list->data != data)
834     list = list->next;
835 
836   return list;
837   }
838 
839 
dlink_find_custom(DLList * list,vpointer data,LLCompareFunc func)840 DLList *dlink_find_custom(DLList *list, vpointer data, LLCompareFunc func)
841   {
842   if (!func) die("Null pointer to LLCompareFunc passed.");
843 
844   while (list && func(list->data, data)==FALSE)
845     list = list->next;
846 
847   return list;
848   }
849 
850 
dlink_index_link(DLList * list,DLList * link)851 int dlink_index_link(DLList *list, DLList *link)
852   {
853   int i=0;
854 
855   while (list)
856     {
857     if (list == link) return i;
858     i++;
859     list = list->next;
860     }
861 
862   return -1;
863   }
864 
865 
dlink_index_data(DLList * list,vpointer data)866 int dlink_index_data(DLList *list, vpointer data)
867   {
868   int i=0;
869 
870   while (list)
871     {
872     if (list->data == data) return i;
873     i++;
874     list = list->next;
875     }
876 
877   return -1;
878   }
879 
880 
dlink_last(DLList * list)881 DLList *dlink_last(DLList *list)
882   {
883   if (!list) return NULL;
884 
885   while (list->next)
886     list = list->next;
887 
888   return list;
889   }
890 
891 
dlink_first(DLList * list)892 DLList *dlink_first(DLList *list)
893   {
894   if (!list) return NULL;
895 
896   while (list->prev) list = list->prev;
897 
898   return list;
899   }
900 
901 
dlink_size(DLList * list)902 int dlink_size(DLList *list)
903   {
904   int	size=0;
905 
906   while (list)
907     {
908     size++;
909     list = list->next;
910     }
911 
912   return size;
913   }
914 
915 
dlink_foreach(DLList * list,LLForeachFunc func,vpointer userdata)916 boolean dlink_foreach(DLList *list, LLForeachFunc func, vpointer userdata)
917   {
918 
919   if (!func) die("Null pointer to LLForeachFunc passed.");
920 
921   while (list)
922     {
923     if ((*func)(list->data, userdata)) return TRUE;
924     list = list->next;
925     }
926 
927   return FALSE;
928   }
929 
930 
dlink_foreach_reverse(DLList * list,LLForeachFunc func,vpointer userdata)931 boolean dlink_foreach_reverse(DLList *list, LLForeachFunc func, vpointer userdata)
932   {
933 
934   if (!func) die("Null pointer to LLForeachFunc passed.");
935 
936   while (list)
937     {
938     if ((*func)(list->data, userdata)) return TRUE;
939     list = list->prev;
940     }
941 
942   return FALSE;
943   }
944 
945 
dlink_insert_sorted(DLList * list,vpointer data,LLCompareFunc func)946 DLList *dlink_insert_sorted(DLList *list, vpointer data, LLCompareFunc func)
947   {
948   DLList *this_list;
949   DLList *prev_list;
950   DLList *new_element;
951 
952   if (!func) die("Null pointer to LLCompareFunc passed.");
953 
954   new_element = dlink_new();
955   new_element->data = data;
956 
957   if (!list) return new_element;
958 
959   this_list = list;
960   prev_list = NULL;
961 
962   while (this_list && func(this_list->data, data)<0)
963     {
964     prev_list = this_list;
965     this_list = this_list->next;
966     }
967 
968   new_element->prev = prev_list;
969   new_element->next = this_list;
970 
971   if (this_list)
972     {
973     this_list->prev = new_element;
974     if (!prev_list) return new_element;
975     }
976 
977   prev_list->next = new_element;
978 
979   return list;
980   }
981 
982 
983 /*
984  * Testing:
985  */
986 
linkedlist_diagnostics(void)987 void linkedlist_diagnostics(void)
988   {
989   printf("=== Linked list diagnostics ==================================\n");
990   printf("Version:                   %s\n", GA_VERSION_STRING);
991   printf("Build date:                %s\n", GA_BUILD_DATE_STRING);
992   printf("Compilation machine characteristics:\n%s\n", GA_UNAME_STRING);
993 
994   printf("--------------------------------------------------------------\n");
995   printf("structure          sizeof\n");
996   printf("SLList             %lu\n", (unsigned long) sizeof(SLList));
997   printf("DLList             %lu\n", (unsigned long) sizeof(DLList));
998   printf("==============================================================\n");
999 
1000   return;
1001   }
1002 
1003 
1004 
test_list_print(vpointer a,vpointer b)1005 static boolean test_list_print(vpointer a, vpointer b)
1006   {
1007   int val = *((int*)a);
1008   printf("%d ", val);
1009   return FALSE;
1010   }
1011 
1012 
test_list_compare_one(constvpointer a,constvpointer b)1013 static int test_list_compare_one(constvpointer a, constvpointer b)
1014   {
1015   int one = *((const int*)a);
1016   int two = *((const int*)b);
1017   return one-two;
1018   }
1019 
1020 
test_list_compare_two(constvpointer a,constvpointer b)1021 static int test_list_compare_two(constvpointer a, constvpointer b)
1022   {
1023   int one = *((const int*)a);
1024   int two = *((const int*)b);
1025   return two-one;
1026   }
1027 
1028 
1029 /*
1030  * This function is 'borrowed' from glib.
1031  * This shows that the glib-emulation works.
1032  */
1033 #ifdef LINKEDLIST_COMPILE_MAIN
main(int argc,char ** argv)1034 int main(int argc, char **argv)
1035 #else
1036 boolean linkedlist_test(void)
1037 #endif
1038 
1039 #ifdef LINKEDLIST_EMULATE_GLIST
1040   {
1041   DLList *list, *t;
1042   SLList *slist, *st;
1043   int sorteddata[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
1044   int data[10] = { 8, 9, 7, 0, 3, 2, 5, 1, 4, 6 };
1045   int i;
1046 
1047   printf("Checking doubly linked lists...\n");
1048 
1049   list = NULL;
1050   for (i = 0; i < 10; i++)
1051     list = g_list_append(list, &sorteddata[i]);
1052   list = g_list_reverse(list);
1053 
1054   for (i = 0; i < 10; i++)
1055     {
1056       t = g_list_nth (list, i);
1057       if (*((int*) t->data) != (9 - i))
1058 	printf("Regular insert failed\n");
1059     }
1060 
1061   for (i = 0; i < 10; i++)
1062     if(g_list_position(list, g_list_nth (list, i)) != i)
1063       printf("g_list_position does not seem to be the inverse of g_list_nth\n");
1064 
1065   g_list_free(list);
1066   list = NULL;
1067 
1068   for (i = 0; i < 10; i++)
1069     list = g_list_insert_sorted(list, &data[i], test_list_compare_one);
1070 
1071   g_list_foreach(list, test_list_print, NULL);
1072   printf("\n");
1073 
1074   for (i = 0; i < 10; i++)
1075     {
1076       t = g_list_nth(list, i);
1077       if (*((int*) t->data) != i)
1078          printf("Sorted insert failed\n");
1079     }
1080 
1081   g_list_free(list);
1082   list = NULL;
1083 
1084   for (i = 0; i < 10; i++)
1085     list = g_list_insert_sorted(list, &data[i], test_list_compare_two);
1086 
1087   g_list_foreach(list, test_list_print, NULL);
1088   printf("\n");
1089 
1090   for (i = 0; i < 10; i++)
1091     {
1092       t = g_list_nth(list, i);
1093       if (*((int*) t->data) != (9 - i))
1094          printf("Sorted insert failed\n");
1095     }
1096 
1097   g_list_free(list);
1098 
1099   printf ("ok\n");
1100 
1101   printf ("Checking singly linked lists...\n");
1102 
1103   slist = NULL;
1104   for (i = 0; i < 10; i++)
1105     slist = g_slist_append(slist, &sorteddata[i]);
1106   slist = g_slist_reverse(slist);
1107 
1108   for (i = 0; i < 10; i++)
1109     {
1110       st = g_slist_nth(slist, i);
1111       if (*((int*) st->data) != (9 - i))
1112 	printf ("failed\n");
1113     }
1114 
1115   g_slist_free(slist);
1116   slist = NULL;
1117 
1118   for (i = 0; i < 10; i++)
1119     slist = g_slist_insert_sorted(slist, &data[i], test_list_compare_one);
1120 
1121   g_slist_foreach(slist, test_list_print, NULL);
1122   printf("\n");
1123 
1124   for (i = 0; i < 10; i++)
1125     {
1126       st = g_slist_nth (slist, i);
1127       if (*((int*) st->data) != i)
1128          printf ("Sorted insert failed\n");
1129     }
1130 
1131   g_slist_free(slist);
1132   slist = NULL;
1133 
1134   for (i = 0; i < 10; i++)
1135     slist = g_slist_insert_sorted(slist, &data[i], test_list_compare_two);
1136 
1137   g_slist_foreach(slist, test_list_print, NULL);
1138   printf("\n");
1139 
1140   for (i = 0; i < 10; i++)
1141     {
1142       st = g_slist_nth(slist, i);
1143       if (*((int*) st->data) != (9 - i))
1144          printf("Sorted insert failed\n");
1145     }
1146 
1147   g_slist_free(slist);
1148 
1149   printf("ok\n");
1150 
1151 #else
1152   {
1153   DLList *list, *t;
1154   SLList *slist, *st;
1155   int sorteddata[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
1156   int data[10] = { 8, 9, 7, 0, 3, 2, 5, 1, 4, 6 };
1157   int i;
1158 
1159   printf("Checking doubly linked lists...\n");
1160 
1161   list = NULL;
1162   for (i = 0; i < 10; i++)
1163     list = dlink_append(list, &sorteddata[i]);
1164   list = dlink_reverse(list);
1165 
1166   for (i = 0; i < 10; i++)
1167     {
1168       t = dlink_nth(list, i);
1169       if (*((int*) t->data) != (9 - i))
1170 	printf("Regular insert failed\n");
1171     }
1172 
1173   for (i = 0; i < 10; i++)
1174     if(dlink_index_link(list, dlink_nth(list, i)) != (int) i)
1175       printf("dlink_index_link does not seem to be the inverse of dlink_nth_data\n");
1176 
1177   dlink_free_all(list);
1178   list = NULL;
1179 
1180   for (i = 0; i < 10; i++)
1181     list = dlink_insert_sorted(list, &data[i], test_list_compare_one);
1182 
1183   dlink_foreach(list, test_list_print, NULL);
1184   printf("\n");
1185 
1186   for (i = 0; i < 10; i++)
1187     {
1188       t = dlink_nth(list, i);
1189       if (*((int*) t->data) != i)
1190          printf("Sorted insert failed\n");
1191     }
1192 
1193   dlink_free_all(list);
1194   list = NULL;
1195 
1196   for (i = 0; i < 10; i++)
1197     list = dlink_insert_sorted(list, &data[i], test_list_compare_two);
1198 
1199   dlink_foreach(list, test_list_print, NULL);
1200   printf("\n");
1201 
1202   for (i = 0; i < 10; i++)
1203     {
1204       t = dlink_nth(list, i);
1205       if (*((int*) t->data) != (9 - i))
1206          printf("Sorted insert failed\n");
1207     }
1208 
1209   dlink_free_all(list);
1210 
1211   printf ("ok\n");
1212 
1213   printf ("Checking singly linked lists...\n");
1214 
1215   slist = NULL;
1216   for (i = 0; i < 10; i++)
1217     slist = slink_append(slist, &sorteddata[i]);
1218   slist = slink_reverse(slist);
1219 
1220   for (i = 0; i < 10; i++)
1221     {
1222       st = slink_nth(slist, i);
1223       if (*((int*) st->data) != (9 - i))
1224 	printf ("failed\n");
1225     }
1226 
1227   slink_free_all(slist);
1228   slist = NULL;
1229 
1230   for (i = 0; i < 10; i++)
1231     slist = slink_insert_sorted(slist, &data[i], test_list_compare_one);
1232 
1233   slink_foreach(slist, test_list_print, NULL);
1234   printf("\n");
1235 
1236   for (i = 0; i < 10; i++)
1237     {
1238       st = slink_nth(slist, i);
1239       if (*((int*) st->data) != (int) i)
1240          printf ("Sorted insert failed\n");
1241     }
1242 
1243   slink_free_all(slist);
1244   slist = NULL;
1245 
1246   for (i = 0; i < 10; i++)
1247     slist = slink_insert_sorted(slist, &data[i], test_list_compare_two);
1248 
1249   slink_foreach(slist, test_list_print, NULL);
1250   printf("\n");
1251 
1252   for (i = 0; i < 10; i++)
1253     {
1254       st = slink_nth(slist, i);
1255       if (*((int*) st->data) != (9 - i))
1256          printf("Sorted insert failed\n");
1257     }
1258 
1259   slink_free_all(slist);
1260 
1261   printf("ok\n");
1262 #endif
1263 
1264 #ifdef LINKEDLIST_COMPILE_MAIN
1265   exit(EXIT_SUCCESS);
1266 #else
1267   return TRUE;
1268 #endif
1269   }
1270 
1271