source: npl/mediabox/lcdproc_edwin/src/shared/LL.c @ c5c522c

gcc484ntopperl-5.22
Last change on this file since c5c522c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 15.9 KB
Line 
1#include <stdlib.h>
2#include <stdio.h>
3#include "LL.h"
4
5#ifdef DEBUG
6#undef DEBUG
7#endif
8
9//TODO: Comment everything
10//TODO: Test everything?
11
12//////////////////////////////////////////////////////////////////////
13// Creates a new list...
14LL * LL_new()
15{
16  LL *list;
17 
18  list = malloc(sizeof(LL));
19  if(!list) return NULL;
20 
21  list->head.data=NULL;
22  list->head.prev=NULL;
23  list->head.next=&list->tail;
24  list->tail.data=NULL;
25  list->tail.prev=&list->head;
26  list->tail.next=NULL;
27  list->current = &list->head;
28
29  return list;
30}
31
32//////////////////////////////////////////////////////////////////////
33// TODO: test this function
34// Destroys the entire list
35// Warning!  Does not free the list data! (only the list itself)
36int LL_Destroy(LL *list)
37{
38  LL_node *node, *next;
39 
40  if(!list) return -1;
41
42  node = &list->head;
43 
44  for(node = node->next;  node  &&  node->next;  node = next)
45  {
46     // Avoid accessing "node" after it's freed..  :)
47     next = node->next;
48     if(LL_node_Destroy(node) < 0) return -1;
49  }
50 
51  free(list);
52 
53  return 0;
54}
55
56//////////////////////////////////////////////////////////////////////
57// TODO: test this function
58// Warning!  This does not assert that the node data is free!
59int LL_node_Destroy(LL_node *node)
60{
61  if(!node) return -1;
62
63  if(LL_node_Unlink(node) < 0) return -1;
64
65  free(node);
66 
67  return 0;
68}
69
70//////////////////////////////////////////////////////////////////////
71int LL_node_Unlink(LL_node *node)
72{
73  LL_node *next, *prev;
74
75  if(!node) return -1;
76
77  next = node->next;
78  prev = node->prev;
79 
80  if(next)
81    next->prev = prev;
82  if(prev)
83    prev->next = next;
84 
85  node->next = NULL;
86  node->prev = NULL;
87
88  return 0;
89}
90
91//////////////////////////////////////////////////////////////////////
92// Frees the data in a list node, if not NULL...
93int LL_node_DestroyData(LL_node *node)
94{
95  if(!node) return -1;
96
97  if(node->data) free(node->data);
98  else return -1;
99  return 0;
100}
101
102
103//////////////////////////////////////////////////////////////////////
104// Returns to the beginning of the list...
105int LL_Rewind(LL *list)
106{
107  if(!list) return -1;
108/*
109  printf("LL_Rewind:  list=%8x\n", list);
110  printf("LL_Rewind:  list.head=%8x\n", &list->head);
111  printf("LL_Rewind:  list.tail=%8x\n", &list->tail);
112*/
113 
114  if(list->head.next != &list->tail)
115    list->current = list->head.next;
116  else
117    list->current = &list->head;
118
119  return 0;
120}
121
122//////////////////////////////////////////////////////////////////////
123// Goes to the end of the list...
124int LL_End(LL *list)
125{
126  if(!list) return -1;
127
128  if(list->tail.prev != &list->head)
129    list->current = list->tail.prev;
130  else
131    list->current = &list->tail;
132
133  return 0;
134}
135
136//////////////////////////////////////////////////////////////////////
137// Go to the next node
138int LL_Next(LL *list)
139{
140  if(!list) return -1;
141  if(!list->current) return -1;
142 
143  if(list->current->next != &list->tail)
144  {
145    list->current = list->current->next;
146    return 0;
147  }
148  else
149  {
150    return -1;
151  }
152}
153
154//////////////////////////////////////////////////////////////////////
155// Go to the previous node
156int LL_Prev(LL *list)
157{
158  if(!list) return -1;
159  if(!list->current) return -1;
160 
161  if(list->current->prev != &list->head)
162  {
163    list->current = list->current->prev;
164    return 0;
165  }
166  else
167  {
168    return -1;
169  }
170}
171
172
173//////////////////////////////////////////////////////////////////////
174// Data manipulation
175void * LL_Get(LL *list)
176{
177  if(!list) return NULL;
178  if(!list->current) return NULL;
179 
180  return list->current->data;
181}
182
183//////////////////////////////////////////////////////////////////////
184int LL_Put(LL *list, void *data)
185{
186  if(!list) return -1;
187  if(!list->current) return -1;
188 
189  list->current->data = data;
190
191  return 0;
192}
193
194
195//////////////////////////////////////////////////////////////////////
196LL_node * LL_GetNode(LL *list)
197{
198  if(!list) return NULL;
199
200  return list->current;
201}
202
203//////////////////////////////////////////////////////////////////////
204// Don't use this unless you know what you're doing.
205int LL_PutNode(LL *list, LL_node *node)
206{
207  if(!list) return -1;
208  if(!node) return -1;
209
210  list->current = node;
211 
212  return 0;
213}
214
215
216//////////////////////////////////////////////////////////////////////
217void * LL_GetFirst(LL *list)    // gets data from first node
218{
219  if(!list) return NULL;
220
221  if(0> LL_Rewind(list)) return NULL;
222
223  return LL_Get(list);
224}
225
226//////////////////////////////////////////////////////////////////////
227//
228void * LL_GetNext (LL *list)    //            ... next node
229{
230  if(!list) return NULL;
231
232  if(0 > LL_Next(list)) return NULL;
233 
234  return LL_Get(list);
235}
236
237//////////////////////////////////////////////////////////////////////
238void * LL_GetPrev (LL *list)    //            ... prev node
239{
240  if(!list) return NULL;
241
242  if(0 > LL_Prev(list)) return NULL;
243 
244  return LL_Get(list);
245}
246
247//////////////////////////////////////////////////////////////////////
248void * LL_GetLast (LL *list)    //            ... last node
249{
250  if(!list) return NULL;
251
252  if(0 > LL_End(list)) return NULL;
253 
254  return LL_Get(list);
255}
256
257//////////////////////////////////////////////////////////////////////
258int LL_AddNode(LL *list, void * add)    // Adds node AFTER current one
259{
260  LL_node *node;
261
262  if(!list) return -1;
263  //if(!add) return -1;  // Nevermind..  NULL entries can be good...
264  if(!list->current) return -1;
265
266  //LL_dprint(list);
267 
268 
269  node = malloc(sizeof(LL_node));
270  if(!node) return -1;
271  //printf("Allocated node\n");
272
273/*   printf("Current: prev: %8x\tnode: %8x\tnext: %8x\n", */
274/*       (int)list->current->prev, */
275/*       (int)list->current, */
276/*       (int)list->current->next); */
277  if(list->current == &list->tail)
278  {
279     list->current = list->current->prev;
280/*      printf("Was at end of list...\n"); */
281/*      printf("Current: prev: %8x\tnode: %8x\tnext: %8x\n", */
282/*          (int)list->current->prev, */
283/*          (int)list->current, */
284/*          (int)list->current->next); */
285  }
286 
287//  printf("Setting node data\n");
288  node->next = list->current->next;
289  node->prev = list->current;
290  node->data = add;
291//  printf("...done\n");
292/*      printf("NewNode: prev: %8x\tnode: %8x\tnext: %8x\n", */
293/*          (int)node->prev, */
294/*          (int)node, */
295/*          (int)node->next); */
296 
297//  printf("Relinking...\n");
298  if(node->next)
299    node->next->prev = node;
300//  printf("...\n");
301  list->current->next = node;
302//  printf("...done\n");
303 
304  list->current = node;
305
306//  printf("Added node\n");
307//  LL_dprint(list);
308 
309  return 0;
310}
311
312//////////////////////////////////////////////////////////////////////
313int LL_InsertNode(LL *list, void * add)// Adds node BEFORE current one
314{
315  LL_node *node;
316
317  if(!list) return -1;
318  if(!add) return -1;
319  if(!list->current) return -1;
320
321  node = malloc(sizeof(LL_node));
322  if(!node) return -1;
323
324  if(list->current == &list->head)  list->current = list->current->next;
325 
326  node->next = list->current;
327  node->prev = list->current->prev;
328  node->data = add;
329 
330  if(list->current->prev)
331    list->current->prev->next = node;
332 
333  list->current->prev = node;
334
335  list->current = node;
336 
337  return 0;
338}
339
340////////////////////////////////////////////////////////////////////////
341// Removes a node from the link
342// ... and advances one node forward
343void * LL_DeleteNode(LL *list)
344{
345  LL_node *next, *prev;
346  void *data;
347
348  if(!list) return NULL;
349  if(!list->current) return NULL;
350  if(list->current == &list->head) return NULL;
351  if(list->current == &list->tail) return NULL;
352
353  #ifdef DEBUG
354  printf("LL_DeleteNode: Before...\n");
355  LL_dprint(list);
356  #endif
357 
358 
359  next = list->current->next;
360  prev = list->current->prev;
361  data = list->current->data;
362
363  if(prev)
364    prev->next = next;
365 
366  if(next)
367    next->prev = prev;
368
369  list->current->prev = NULL;
370  list->current->next = NULL;
371  // This should not free things; the user should do it explicitly.
372  //if(list->current->data) free(list->current->data);
373  list->current->data = NULL;
374 
375  free(list->current);
376
377  list->current = next;
378
379  #ifdef DEBUG
380  printf("LL_DeleteNode: After...\n");
381  LL_dprint(list);
382  #endif
383 
384  return data;
385}
386//////////////////////////////////////////////////////////////////////
387// Removes a specific node...
388void * LL_Remove(LL *list, void * data)
389{
390   void *find;
391   
392   if(!list) return NULL;
393
394   LL_Rewind(list);
395   do {
396      find = LL_Get(list);
397      if(find == data) return LL_DeleteNode(list);
398   } while (LL_Next(list) == 0);
399
400   return NULL;
401}
402
403
404//////////////////////////////////////////////////////////////////////
405// Stack operations
406int LL_Push(LL *list, void *add)    // Add node to end of list
407{
408  if(!list) return -1;
409  if(!add) return -1;
410 
411//  printf("Going to end of list...\n");
412  LL_End(list);
413
414//  printf("Adding node...\n");
415  return LL_AddNode(list, add);
416}
417
418//////////////////////////////////////////////////////////////////////
419void * LL_Pop(LL *list)      // Remove node from end of list
420{
421  if(!list) return NULL;
422 
423  if(0 > LL_End(list)) return NULL;
424 
425  return LL_DeleteNode(list);
426}
427
428//////////////////////////////////////////////////////////////////////
429void * LL_Top(LL *list)      // Peek at end node
430{
431  return LL_GetLast(list);
432}
433
434//////////////////////////////////////////////////////////////////////
435void * LL_Shift(LL *list)            // Remove node from start of list
436{
437  if(!list) return NULL;
438
439  if(0 > LL_Rewind(list)) return NULL;
440 
441  return LL_DeleteNode(list);
442}
443
444//////////////////////////////////////////////////////////////////////
445void * LL_Look(LL *list)            // Peek at first node
446{
447  return LL_GetFirst(list);
448}
449
450//////////////////////////////////////////////////////////////////////
451int LL_Unshift(LL *list, void *add) // Add node to beginning of list
452{
453  if(!list) return -1;
454  if(!add) return -1;
455 
456  LL_Rewind(list);
457
458  return LL_InsertNode(list, add);
459}
460
461//////////////////////////////////////////////////////////////////////
462int LL_Roll(LL *list)  // Make last node first
463{
464  LL_node *node, *next;
465 
466  if(!list) return -1;
467  //if(!list->current) return -1;
468
469  if(0 > LL_End(list)) return -1;
470
471  // Avoid rolling an empty list, or unlinking the head/tail...
472  if(list->current == &list->head) list->current = list->current->next;
473  if(list->current == &list->tail) list->current = list->current->prev;
474  // List is empty
475  if(list->current == &list->head) return 0;
476  // List has one item
477  if(list->current->prev == &list->head) return 0;
478
479  node = list->current;
480 
481  LL_node_Unlink(node);
482
483  if(0 > LL_Rewind(list)) return -1;
484
485  next = list->head.next;
486
487  list->head.next = node;
488  next->prev = node;
489  node->prev = &list->head;
490  node->next = next;
491 
492  return 0;
493}
494
495//////////////////////////////////////////////////////////////////////
496int LL_UnRoll(LL *list)// Roll the other way...
497{
498  LL_node *node, *prev;
499 
500  if(!list) return -1;
501  //if(!list->current) return -1;
502
503  if(0 > LL_Rewind(list)) return -1;
504
505  // Avoid rolling an empty list, or unlinking the head/tail...
506  if(list->current == &list->tail) list->current = list->current->prev;
507  if(list->current == &list->head) list->current = list->current->next;
508  // List is empty
509  if(list->current == &list->tail) return 0;
510  // List has one item
511  if(list->current->next == &list->tail) return 0;
512
513  node = list->current;
514 
515  LL_node_Unlink(node);
516
517  if(0 > LL_End(list)) return -1;
518
519  prev = list->tail.prev;
520
521  list->tail.prev = node;
522  prev->next = node;
523  node->next = &list->tail;
524  node->prev = prev;
525 
526  return 0;
527}
528
529
530
531//////////////////////////////////////////////////////////////////////
532// Add an item to the end of its "priority group"
533// The list is assumed to be sorted already...
534int LL_PriorityEnqueue(LL *list, void *add, int compare(void *, void *))
535{
536   void *data;
537   int i;
538   
539   if(!list) return -1;
540   if(!add) return -1;
541   if(!compare) return -1;
542
543   // From the end of the list, keep searching while we're "less than"
544   // the given nodes...
545   LL_End(list);
546   do {
547      data = LL_Get(list);
548      if(data)
549      {
550         i = compare(add, data);
551         if(i >= 0) // If we're in the right place, add it and exit
552         {
553            LL_AddNode(list, add);
554            return 0;
555         }
556      }
557   } while(LL_Prev(list) == 0);
558
559   // If we're less than *everything*, put it at the beginning
560   LL_Unshift(list, add);
561
562   return 0;
563}
564
565
566
567//////////////////////////////////////////////////////////////////////
568int LL_SwapNodes(LL_node *one, LL_node *two)   // Switch two nodes positions...
569{
570  LL_node *firstprev, *firstnext;
571  LL_node *secondprev, *secondnext;
572
573  if(!one  ||  !two) return -1;
574  if(one == two) return 0;    // Do nothing
575
576  firstprev  = one->prev;    // Look up the nodes neighbors...
577  firstnext  = one->next;
578  secondprev = two->prev;
579  secondnext = two->next;
580
581  if(firstprev  != NULL)  firstprev->next  = two;  // Swap the neighboring
582  if(firstnext  != NULL)  firstnext->prev  = two;  // nodes pointers...
583  if(secondprev != NULL)  secondprev->next = one;
584  if(secondprev != NULL)  secondnext->prev = one;
585
586  one->next = secondnext;      // Swap the nodes pointers
587  one->prev = secondprev;
588  two->next = firstnext;
589  two->prev = firstprev;
590
591  if(firstnext  == two)  one->prev = two;  // Fix things in case
592  if(firstprev  == two)  one->next = two;  // they were next to
593  if(secondprev == one)  two->next = one;  // each other...
594  if(secondnext == one)  two->prev = one;
595 
596 
597  return 0;
598 
599}
600//////////////////////////////////////////////////////////////////////
601int LL_nSwapNodes(int one, int two)   // Switch two nodes positions...
602{
603  return -1;
604}
605
606//////////////////////////////////////////////////////////////////////
607int LL_Length(LL *list) // Returns # of nodes in entire list
608{
609  LL_node *node;
610  int num = 0;
611 
612  if(!list) return -1;
613 
614  node = &list->head;
615
616  for(num = -1; 
617      node != &list->tail; 
618      num++)
619    node = node->next;
620
621  return num;
622}
623
624//////////////////////////////////////////////////////////////////////
625// Searching...
626// Goes to the list item which matches "value", and returns the
627// data found there.
628//
629// The "compare" function should return 0 for a "match"
630//
631// Note that this does *not* rewind the list first!  You should do
632// it yourself if you want to start from the beginning!
633void * LL_Find(LL *list, int compare(void *, void *), void *value)
634{
635  void *data;
636
637  if(!list) return NULL;
638  if(!compare) return NULL;
639  if(!value) return NULL;
640
641  do{
642    data = LL_Get(list);
643    if( 0 == compare(data, value) ) return data;
644   
645  } while(LL_Next(list) == 0);
646 
647  return NULL;
648}
649
650
651//////////////////////////////////////////////////////////////////////
652// Sorts the list, then rewinds it...
653//
654int LL_Sort(LL *list, int compare(void *, void *))
655{
656  int i,j;              // Junk / loop variables
657  int numnodes;         // number of nodes in list
658  LL_node *best, *last; // best match and last node in the list
659  LL_node *current;
660 
661 
662  if(!list) return -1;
663  if(!compare) return -1;
664
665  numnodes = LL_Length(list);   // get the number of nodes...
666  if(0 > LL_End(list)) return -1;       // Find the last node.
667  last = LL_GetNode(list);
668 
669  if(numnodes < 2) return 0;
670 
671
672  for(i=numnodes-1; i>0; i--)
673  {
674    LL_Rewind(list);    // get the first node again
675    best = last;                        // reset our "best" node
676   
677    for(j=0; j<i; j++)
678    {
679      current = LL_GetNode(list);
680      // If we found a better match...
681      if(compare(current->data, best->data) > 0)
682      {
683        best = current;                 // keep track of the "best" match
684      }
685      LL_Next(list);    // Go to the next node.
686    }
687
688    LL_SwapNodes(last, best);           // Switch two nodes...
689    if(best) last = best->prev;
690    else return -1;
691   
692    //last = LL_FindPrev(best);         // And go backwards by one node.
693  }
694 
695  //return LLFindFirst(current);        // return pointer to the first node.
696  LL_Rewind(list);
697 
698  return 0;
699 
700}
701
702void LL_dprint(LL *list)
703{
704   LL_node *current;
705
706   current = &list->head;
707
708   printf("Head:  prev:\t0x%8x\taddr:\t0x%8x\tnext:\t0x%8x\n",
709          (int)list->head.prev,
710          (int)&list->head,
711          (int)list->head.next);
712
713   for(current = current->next;
714       current != &list->tail;
715       current = current->next)
716   {
717      printf("node:  prev:\t0x%8x\taddr:\t0x%8x\tnext:\t0x%8x\n",
718             (int)current->prev,
719             (int)current,
720             (int)current->next);
721     
722   }
723
724   printf("Tail:  prev:\t0x%8x\taddr:\t0x%8x\tnext:\t0x%8x\n",
725          (int)list->tail.prev,
726          (int)&list->tail,
727          (int)list->tail.next);
728}
Note: See TracBrowser for help on using the repository browser.