home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lifeos2.zip / LIFE-1.02 / SOURCE / LIST.C < prev    next >
C/C++ Source or Header  |  1996-06-04  |  11KB  |  454 lines

  1. /* 
  2.  * Copyright 1991 Digital Equipment Corporation.
  3.  * All Rights Reserved.
  4.  */
  5. /*     $Id: list.c,v 1.2 1994/12/08 23:28:16 duchier Exp $     */
  6.  
  7. #ifndef lint
  8. static char vcid[] = "$Id: list.c,v 1.2 1994/12/08 23:28:16 duchier Exp $";
  9. #endif /* lint */
  10.  
  11. /*
  12. ** list.c contains the functions to manage double link list
  13. ** with 2 entries (first and last element)
  14. ** Links belongs to each atom
  15. */
  16.  
  17. #include "list.h"
  18.  
  19.  
  20.  
  21. /*=============================================================================*/
  22. /*            Set functions                           */
  23. /*=============================================================================*/
  24.  
  25. void List_SetLinkProc (header, getLinks)
  26. RefListHeader header;
  27. RefListGetLinksProc getLinks;
  28. {
  29.     header->First = NULL;
  30.     header->Last = NULL;
  31.  
  32. #ifdef prlDEBUG
  33.     header->Lock = 0;
  34. #endif
  35.  
  36.     header->GetLinks = getLinks;
  37. }
  38.  
  39. /*=============================================================================*/
  40. /*            List functions                           */
  41. /*=============================================================================*/
  42.  
  43. void List_InsertAhead (header, atom) 
  44. RefListHeader header;
  45. Ref atom;
  46. {
  47.     RefListGetLinksProc  getLinks = header->GetLinks;
  48.  
  49.         /* Update links of atom to insert */
  50.  
  51.     (*getLinks)(atom)->Next = header->First;
  52.     (*getLinks)(atom)->Prev = NULL;
  53.  
  54.         /* Link to the head of list */
  55.  
  56.     if (header->First != NULL)
  57.       (*getLinks)(header->First)->Prev = atom;
  58.  
  59.     else    /* The list is empty */
  60.       header->Last  = atom;
  61.  
  62.     header->First = atom;
  63. }
  64.  
  65. /*==============================================================================*/
  66.  
  67. void List_Append (header, atom) 
  68. RefListHeader header;
  69. Ref atom;
  70. {
  71.     RefListGetLinksProc  getLinks = header->GetLinks;
  72.  
  73.             /* Link to the end of list */
  74.  
  75.     if (header->Last != NULL)
  76.       (*getLinks)(header->Last)->Next = atom;
  77.  
  78.     else    /* The list is empty */
  79.       header->First = atom;
  80.  
  81.             /* Update links of atom to insert */
  82.  
  83.     (*getLinks)(atom)->Prev = header->Last;
  84.     (*getLinks)(atom)->Next = NULL;
  85.  
  86.         /* Update last element of header */
  87.  
  88.     header->Last  = atom;
  89. }
  90.  
  91. /*==============================================================================*/
  92.  
  93. void List_InsertBefore (header, atom, mark)
  94. RefListHeader header;
  95. Ref atom;
  96. Ref mark;
  97. {
  98.     RefListGetLinksProc  getLinks = header->GetLinks;
  99.  
  100.     if (mark != NULL)
  101.     {
  102.         (*getLinks)(atom)->Next = mark;
  103.  
  104.         if (mark != header->First)
  105.         {
  106.             (*getLinks)(atom)->Prev = (*getLinks)(mark)->Prev;
  107.             (*getLinks)((*getLinks)(mark)->Prev)->Next = atom;
  108.         }
  109.         else    /* Insert ahead the list */
  110.         {
  111.             (*getLinks)(atom)->Prev = NULL;
  112.             header->First = atom;
  113.         }
  114.  
  115.         (*getLinks)(mark)->Prev = atom;
  116.     }
  117.     else        /* Append to the list */
  118.       List_Append (header, atom);
  119.  
  120. /*==============================================================================*/
  121.  
  122. void List_InsertAfter (header, atom, mark)
  123. RefListHeader header;
  124. Ref atom;
  125. Ref mark;
  126. {
  127.     RefListGetLinksProc  getLinks = header->GetLinks;
  128.  
  129. #ifdef prlDEBUG
  130.     if (header->Lock > 1)
  131.       OS_PrintMessage ("List_InsertAfter: Warning insert after on recursive List_Enum call !!\n");
  132. #endif
  133.  
  134.     if (mark != NULL)
  135.     {
  136.         (*getLinks)(atom)->Prev = mark;
  137.  
  138.         if (mark != header->Last)
  139.         {
  140.             (*getLinks)(atom)->Next = (*getLinks)(mark)->Next;
  141.             (*getLinks)((*getLinks)(mark)->Next)->Prev = atom;
  142.         }
  143.         else    /* Insert at the end of the list */
  144.         {
  145.             (*getLinks)(atom)->Next = NULL;
  146.             header->Last = atom;
  147.         }
  148.  
  149.         (*getLinks)(mark)->Next = atom;
  150.     }
  151.     else        /* Insert ahead the list */
  152.       List_InsertAhead (header, atom);
  153.  
  154. /*==============================================================================*/
  155.  
  156. void List_Swap (header, first, second)
  157. RefListHeader header;
  158. Ref first;
  159. Ref second;
  160. {
  161.     RefListGetLinksProc    getLinks = header->GetLinks;
  162.  
  163.     /* Don't swap if the input is wrong */
  164.  
  165.     if ((*getLinks)(first)->Next != second)
  166.     {
  167. #ifdef prlDEBUG
  168.     OS_PrintMessage ("List_Swap: WARNING wrong input data, swap not done..\n");
  169. #endif
  170.     return;
  171.     }
  172.  
  173.         /* Special Cases */
  174.  
  175.     if (header->First == first)
  176.       header->First = second;
  177.     else
  178.       (*getLinks)((*getLinks)(first)->Prev)->Next = second;
  179.     
  180.     if (header->Last == second)
  181.       header->Last = first;
  182.     else
  183.       (*getLinks)((*getLinks)(second)->Next)->Prev = first;
  184.  
  185.         /* Swap the atoms */
  186.  
  187.     (*getLinks)(second)->Prev = (*getLinks)(first)->Prev;
  188.     (*getLinks)(first)->Next  = (*getLinks)(second)->Next;
  189.     (*getLinks)(first)->Prev  = second;
  190.     (*getLinks)(second)->Next = first;
  191. }
  192.  
  193. /*==============================================================================*/
  194.  
  195. static long List_SwapLinks (header, atom)
  196. RefListHeader header;
  197. Ref atom;
  198. {
  199.     Ref    save;
  200.  
  201.     save = (*header->GetLinks)(atom)->Next;
  202.     (*header->GetLinks)(atom)->Next = (*header->GetLinks)(atom)->Prev;
  203.     (*header->GetLinks)(atom)->Prev = save;
  204.  
  205.     return TRUE;
  206. }
  207.  
  208. void List_Reverse (header)
  209. RefListHeader header;
  210. {
  211.     Ref            cur, next;
  212.     RefListGetLinksProc    getLinks = header->GetLinks;
  213.  
  214.     /* This traverse cannot be done with function List_Enum() */
  215.  
  216.     cur = header->First;
  217.  
  218.     /* Swap the headers */
  219.     header->First = header->Last;
  220.     header->Last  = cur;
  221.  
  222.     while (cur != NULL)
  223.     {
  224.     next = (*getLinks)(cur)->Next;
  225.     List_SwapLinks (header, cur);
  226.     cur = next;
  227.     }
  228. }
  229.  
  230. /*==============================================================================*/
  231.  
  232. void List_Remove (header, atom)
  233. RefListHeader header;
  234. Ref atom;
  235. {
  236. /*-----------------------------------------------------------------------------
  237.  
  238. WARNING
  239.     - The container is 'updated' two times if the first and last atom
  240.       of list is the only one to remove.
  241.  
  242. -----------------------------------------------------------------------------*/
  243.  
  244.     RefListGetLinksProc  getLinks = header->GetLinks;
  245.  
  246. #ifdef prlDEBUG
  247.     if (header->Lock > 1)
  248.       OS_PrintMessage ("List_Remove: Warning remove on recursive List_Enum call !!\n");
  249. #endif
  250.  
  251.         /* Update the DownStream links */
  252.  
  253.     if ((*getLinks)(atom)->Prev != NULL)
  254.     {
  255.         (*getLinks)((*getLinks)(atom)->Prev)->Next = 
  256.             (*getLinks)(atom)->Next;
  257.     }
  258.     else            /* Atom is the first of list */
  259.       header->First = (*getLinks)(atom)->Next;
  260.  
  261.         /* Update the UpStream links */
  262.  
  263.     if ((*getLinks)(atom)->Next != NULL)
  264.     {
  265.         (*getLinks)((*getLinks)(atom)->Next)->Prev = 
  266.             (*getLinks)(atom)->Prev;
  267.     }
  268.     else            /* Atom is the last of list */
  269.       header->Last = (*getLinks)(atom)->Prev;
  270.  
  271.         /* Reset the atom links */
  272.  
  273.     (*getLinks)(atom)->Prev = NULL;
  274.     (*getLinks)(atom)->Next = NULL;
  275.  
  276. /*==============================================================================*/
  277.  
  278. void List_Concat (header1, header2)
  279. RefListHeader header1;
  280. RefListHeader header2;
  281. {
  282.     RefListGetLinksProc  getLinks = header1->GetLinks;
  283.  
  284.     if (header1->GetLinks == header2->GetLinks)
  285.     {
  286. #ifdef prlDEBUG
  287.     OS_PrintMessage ("List_Concat: ERROR concat different lists\n");
  288. #endif
  289.     return;
  290.     }
  291.  
  292.     /* Concatenate only if the second list is not empty */
  293.  
  294.     if (header2->First != NULL)
  295.     {
  296.     /* Obvious concatenate when the first list is empty */
  297.  
  298.         if (header1->First == NULL)
  299.             header1->First = header2->First;
  300.  
  301.         else    /* Concatenate the two non empty lists */
  302.         {
  303.             (*getLinks)(header1->Last)->Next  = header2->First;
  304.             (*getLinks)(header2->First)->Prev = header1->Last;
  305.         }
  306.         header1->Last = header2->Last;
  307.     }
  308.  
  309. /*==============================================================================*/
  310.  
  311. long List_EnumFrom (header, atom, proc, closure)
  312. RefListHeader    header;
  313. Ref atom;
  314. RefListEnumProc    proc;
  315. Ref closure;
  316. {
  317.     Ref    cur, next;
  318.     int    notInterrupted = TRUE;
  319.  
  320. #ifdef prlDEBUG
  321.     header->Lock += 1;
  322. #endif
  323.  
  324.     cur = atom;
  325.     while (cur != NULL && notInterrupted)
  326.     {
  327.     next = List_Next (header, cur);
  328.     notInterrupted = (*proc)(cur, closure);
  329.     cur = next;
  330.     }
  331.  
  332. #ifdef prlDEBUG
  333.     header->Lock -=1;
  334. #endif
  335.     
  336.     return (notInterrupted);
  337. }
  338.  
  339. /*==============================================================================*/
  340.  
  341. long List_Enum (header, proc, closure)
  342. RefListHeader    header;
  343. RefListEnumProc    proc;
  344. Ref closure;
  345. /*-----------------------------------------------------------------------------
  346.  
  347. (NO) SIDE EFFECTS
  348.     The current atom can be modified by the function RemoveAtom () during
  349.     the traversing of the list. This is the reason why the current pointer
  350.     is managed on the header.
  351.  
  352. -----------------------------------------------------------------------------*/
  353. {
  354.     return (List_EnumFrom (header, header->First, proc, closure));
  355. }
  356.  
  357. /*==============================================================================*/
  358.  
  359. long List_EnumBackFrom (header, atom, proc, closure)
  360. RefListHeader    header;
  361. Ref        atom;
  362. RefListEnumProc    proc;
  363. Ref        closure;
  364. {
  365.     Ref    cur, prev;
  366.     int    notInterrupted = TRUE;
  367.  
  368. #ifdef prlDEBUG
  369.     header->Lock += 1;
  370. #endif
  371.  
  372.     cur = atom;
  373.     while (cur != NULL && notInterrupted)
  374.     {
  375.     prev = List_Prev (header, cur);
  376.     notInterrupted = (*proc)(cur, closure);
  377.     cur = prev;
  378.     }
  379.  
  380. #ifdef prlDEBUG
  381.     header->Lock -=1;
  382. #endif
  383.     
  384.     return (notInterrupted);
  385. }
  386.  
  387. /*==============================================================================*/
  388.  
  389. long List_EnumBack (header, proc, closure)
  390. RefListHeader    header;
  391. RefListEnumProc    proc;
  392. Ref            closure;
  393. {
  394.     return (List_EnumBackFrom (header, header->Last, proc, closure));
  395. }
  396.  
  397. /*==============================================================================*/
  398.  
  399. /*ARGSUSED*/
  400. static long List_CountAtom (p, nbR)
  401. Ref p; 
  402. Ref nbR;
  403. {
  404.     long *nb = (long *)nbR;
  405.     
  406.     ++*nb;
  407.     return TRUE;
  408. }
  409.  
  410. long List_Card (header)
  411. RefListHeader header;
  412. {
  413.     long n = 0;
  414.     
  415.     List_Enum (header, List_CountAtom, &n);
  416.     return n;
  417. }
  418.  
  419. /*==============================================================================*/
  420.  
  421. long List_IsUnlink (links)
  422. RefListLinks links;
  423. {
  424.     return (links->Next == NULL && links->Prev == NULL);
  425. }
  426.  
  427. /*==============================================================================*/
  428.  
  429. void List_Cut (header, atom, newHeader)
  430. RefListHeader    header;
  431. Ref            atom;
  432. RefListHeader    newHeader;
  433. {
  434.     RefListGetLinksProc  getLinks = header->GetLinks;
  435.  
  436.     if (atom != List_Last (header))
  437.     {
  438.     newHeader->First = List_Next (header, atom);
  439.     newHeader->Last  = header->Last;
  440.  
  441.     header->Last = atom;
  442.  
  443.     /* Update the links */
  444.     (*getLinks)(atom)->Next = NULL;
  445.     (*getLinks)(newHeader->First)->Prev = NULL;
  446.     }
  447. }
  448.  
  449. /*==============================================================================*/
  450.