home *** CD-ROM | disk | FTP | other *** search
/ Programmer's ROM - The Computer Language Library / programmersrom.iso / ada / misc / list.ada < prev    next >
Encoding:
Text File  |  1988-05-03  |  17.1 KB  |  499 lines

  1.  
  2. -------- SIMTEL20 Ada Software Repository Prologue ------------
  3. --                                                           -*
  4. -- Unit name    : generic package LINKED_LIST
  5. -- Version      : 1.0
  6. -- Author       : Richard Conn
  7. --              : Texas Instruments
  8. --              : PO Box 801, Mail Stop 8007
  9. --              : McKinney, TX  75069
  10. -- DDN Address  : RCONN@SIMTEL20
  11. -- Copyright    : (c) 1984 Richard Conn
  12. -- Date created :  OCTOBER 2, 1984
  13. -- Release date :  NOVEMBER 29, 1984
  14. -- Last update  :  CONN NOVEMBER 29, 1984
  15. --                                                           -*
  16. ---------------------------------------------------------------
  17. --                                                           -*
  18. -- Keywords     :  DOUBLY-LINKED LIST
  19. ----------------:  LIST MANIPULATION
  20. --
  21. -- Abstract     :  This package provides a number of routines
  22. ----------------:  which can be used to manipulate a doubly-
  23. ----------------:  linked list.  See the visible section for
  24. ----------------:  a rather complete set of documentation on
  25. ----------------:  the routines.
  26. ----------------:  
  27. ----------------:  Each element of the list is of the following
  28. ----------------:  structure:
  29. ----------------:     RECORD
  30. ----------------:      contents: element_object;  -- data
  31. ----------------:      next:     element_pointer; -- ptr
  32. ----------------:    previous: element_pointer; -- ptr
  33. ----------------:     END RECORD;
  34. ----------------:
  35. --                                                           -*
  36. ------------------ Revision history ---------------------------
  37. --                                                           -*
  38. -- DATE         VERSION    AUTHOR                  HISTORY
  39. -- 11/29/84       1.0    Richard Conn        Initial Release
  40. --                                                           -*
  41. ------------------ Distribution and Copyright -----------------
  42. --                                                           -*
  43. -- This prologue must be included in all copies of this software.
  44. --
  45. -- This software is copyright by the author.
  46. --
  47. -- This software is released to the Ada community.
  48. -- This software is released to the Public Domain (note:
  49. --   software released to the Public Domain is not subject
  50. --   to copyright protection).
  51. -- Restrictions on use or distribution:  NONE
  52. --                                                           -*
  53. ------------------ Disclaimer ---------------------------------
  54. --                                                           -*
  55. -- This software and its documentation are provided "AS IS" and
  56. -- without any expressed or implied warranties whatsoever.
  57. -- No warranties as to performance, merchantability, or fitness
  58. -- for a particular purpose exist.
  59. --
  60. -- Because of the diversity of conditions and hardware under
  61. -- which this software may be used, no warranty of fitness for
  62. -- a particular purpose is offered.  The user is advised to
  63. -- test the software thoroughly before relying on it.  The user
  64. -- must assume the entire risk and liability of using this
  65. -- software.
  66. --
  67. -- In no event shall any person or organization of people be
  68. -- held responsible for any direct, indirect, consequential
  69. -- or inconsequential damages or lost profits.
  70. --                                                           -*
  71. -------------------END-PROLOGUE--------------------------------
  72.  
  73. -- 
  74. -- Generic Package to Handle Doubly-Linked Lists
  75. --    by Richard Conn, TI Ada Technology Branch
  76. -- 
  77. -- The purpose of this package is to provide a software component
  78. -- which can be generically instantiated to handle any type of
  79. -- doubly-linked list.  The set of routines provided in this package
  80. -- are general-purpose in nature and manipulate the elements of a
  81. -- doubly-linked list without regard to their contents.  Each element
  82. -- of the list is of the following structure:
  83. -- 
  84. --    record
  85. --      content  : element_object;  -- the data in the list element
  86. --      next     : element_pointer; -- pointer to the next element
  87. --      previous : element_pointer; -- pointer to the previous element
  88. --    end record;
  89. -- 
  90.  
  91. generic
  92.     type element_object is private;
  93.  
  94.  
  95. package generic_list is
  96.  
  97. -- 
  98. -- The following type declarations are used throughout is package
  99. -- and are needed by the programs which WITH this package.
  100. -- 
  101.  
  102.     type list_element;
  103.     type element_pointer is access list_element;
  104.     type list_element is
  105.         record
  106.             content  : element_object; -- the generic object
  107.             next     : element_pointer;
  108.             previous : element_pointer;
  109.         end record;
  110.  
  111.  
  112. -- 
  113. -- The following procedures and functions initialize the list and
  114. -- return pointers to the three list elements which are continuously
  115. -- tracked by the routines in this package.  These list elements
  116. -- are:
  117. -- 
  118. --    first_element       the first element in the list
  119. --    last_element        the last element in the list
  120. --    current_element     the current element in the list
  121. -- 
  122.  
  123.     procedure initialize_list;
  124.     function  return_first_element   return element_pointer;
  125.     function  return_last_element    return element_pointer;
  126.     function  return_current_element return element_pointer;
  127.     function  return_first_element   return element_object;
  128.     function  return_last_element    return element_object;
  129.     function  return_current_element return element_object;
  130.  
  131. -- 
  132. -- The following procedures and functions manipulate the current
  133. -- element pointer.  The following table outlines their functions:
  134. -- 
  135. --    set_first           the first element becomes the current element
  136. --    set_last            the last element becomes the current element
  137. --    current_index       return the number of the current element
  138. --                          (ordinal); 0 returned if list is empty
  139. --    current_next        set current element to next element in the
  140. --                          list; return TRUE if done or FALSE if
  141. --                          already at end of list
  142. --    current_previous    set current element to previous element in the
  143. --                          list; return TRUE if done or FALSE if
  144. --                          already at front of list
  145. --    set_current_index   set the Nth element as the current element;
  146. --                          return TRUE if done or FALSE if end of list
  147. --                          encountered, in which case the last element
  148. --                          becomes the current element
  149. -- 
  150.  
  151.     procedure set_first;
  152.     procedure set_last;
  153.     function  current_index     return natural;
  154.     function  current_next      return boolean;
  155.     function  current_previous  return boolean;
  156.     function  set_current_index (index : natural) return boolean;
  157.  
  158. -- 
  159. -- The following functions return the index of the last element in
  160. -- the list and indicate if the list is empty or not.
  161. -- 
  162. --    last_index          return the number of the last element
  163. --                          (ordinal); 0 returned if list is empty
  164. --    list_empty          return TRUE if the list is empty; FALSE if
  165. --                          the list is not empty
  166. --    at_end_of_list      return TRUE if the current_element is also
  167. --                          the last_element; return FALSE if not
  168. --    at_front_of_list    return TRUE if the current_element is also
  169. --                          the first_element; return FALSE if not
  170. -- 
  171.  
  172.     function last_index       return natural;
  173.     function list_empty       return boolean;
  174.     function at_end_of_list   return boolean;
  175.     function at_front_of_list return boolean;
  176.  
  177. -- 
  178. -- The following procedures and functions are used to manipulate
  179. -- the elements in the list.
  180. -- 
  181. --    append_element       append the indicated element after the
  182. --                           current_element in the list; the
  183. --                           current_element is set to the new
  184. --                           element
  185. --    insert_element       insert the indicated element before the
  186. --                           current_element in the list; the
  187. --                           current_element is unchanged
  188. --    delete_element       delete the current_element from the list;
  189. --                           the next element is the new current_element
  190. --                           unless there is no next element, in which
  191. --                           case the previous element is the new
  192. --                           current_element
  193. -- 
  194.  
  195.     procedure append_element (element : element_pointer);
  196.     procedure append_element (element : element_object);
  197.     procedure insert_element (element : element_pointer);
  198.     procedure insert_element (element : element_object);
  199.     procedure delete_element;
  200.  
  201. -- 
  202. -- The following function and procedure are used to dynamically
  203. -- create new elements and to free the space occupied by unneeded
  204. -- elements.
  205. -- 
  206. --    new_element        returns a pointer to a new list_element
  207. --    free_element       frees the indicated list_element
  208. -- 
  209.  
  210.     function  new_element  return element_pointer;
  211.     procedure free_element (element : element_pointer);
  212.  
  213. end generic_list;
  214.  
  215.  
  216. -- 
  217. -- BODY of generic_list
  218. -- 
  219. package body generic_list is
  220.  
  221. -- 
  222. -- Definition of the three element pointers
  223. -- 
  224.     first_element, last_element, current_element : element_pointer;
  225.  
  226. -- 
  227. -- Procedure to initialize the list
  228. --    All element pointers are initialized to null
  229. -- 
  230.     procedure initialize_list is
  231.     begin
  232.         first_element := null;
  233.         last_element := null;
  234.         current_element := null;
  235.     end initialize_list;
  236.  
  237. -- 
  238. -- Functions to return element pointers
  239. -- 
  240.     function return_first_element return element_pointer is
  241.     begin
  242.         return first_element;
  243.     end return_first_element;
  244.  
  245.     function return_first_element return element_object is
  246.     begin
  247.         return first_element.content;
  248.     end return_first_element;
  249.  
  250.     function return_last_element return element_pointer is
  251.     begin
  252.         return last_element;
  253.     end return_last_element;
  254.  
  255.     function return_last_element return element_object is
  256.     begin
  257.         return last_element.content;
  258.     end return_last_element;
  259.  
  260.     function return_current_element return element_pointer is
  261.     begin
  262.         return current_element;
  263.     end return_current_element;
  264.  
  265.     function return_current_element return element_object is
  266.     begin
  267.         return current_element.content;
  268.     end return_current_element;
  269.  
  270. -- 
  271. -- Current element pointer manipulation
  272. -- 
  273.     procedure set_first is
  274.     begin
  275.         current_element := first_element;
  276.     end set_first;
  277.  
  278.     procedure set_last is
  279.     begin
  280.         current_element := last_element;
  281.     end set_last;
  282.  
  283.     function current_index return natural is
  284.         local_element : element_pointer;
  285.         index         : natural;
  286.     begin
  287.         index := 0; -- initialize counter and set empty list return
  288.         if current_element /= null then
  289.             local_element := first_element; -- point to first element
  290.             index := 1;
  291.             while local_element /= current_element loop
  292.                 exit when local_element = null; -- error trap
  293.                 local_element := local_element.next;
  294.                 index := index + 1;
  295.             end loop;
  296.         end if;
  297.         return index;
  298.     end current_index;
  299.  
  300.     function current_next return boolean is
  301.     begin
  302.         if current_element = last_element then
  303.             return FALSE;
  304.         else
  305.             current_element := current_element.next;
  306.             return TRUE;
  307.         end if;
  308.     end current_next;
  309.  
  310.     function current_previous return boolean is
  311.     begin
  312.         if current_element = first_element then
  313.             return FALSE;
  314.         else
  315.             current_element := current_element.previous;
  316.             return TRUE;
  317.         end if;
  318.     end current_previous;
  319.  
  320.     function set_current_index (index : natural) return boolean is
  321.         counter : natural;
  322.     begin
  323.         current_element := first_element; -- start at first element
  324.         if index <= 1 then
  325.             return TRUE;
  326.         else
  327.             for counter in 1 .. index - 1 loop
  328.                 if current_element = last_element then
  329.                     return FALSE;
  330.                     exit;      -- this exit may not be necessary
  331.                 else
  332.                     current_element := current_element.next;
  333.                 end if;
  334.             end loop;
  335.             return TRUE;
  336.         end if;
  337.     end set_current_index;
  338.  
  339. -- 
  340. -- Return the index of the last element in the list
  341. -- 
  342.     function last_index return natural is
  343.         current_save : element_pointer;
  344.         index        : natural;
  345.     begin
  346.         current_save := current_element;
  347.         current_element := last_element;
  348.         index := current_index;
  349.         current_element := current_save;
  350.         return index;
  351.     end last_index;
  352.  
  353. -- 
  354. -- Determine if the list is empty; return TRUE if so, FALSE if not
  355. -- 
  356.     function list_empty return boolean is
  357.     begin
  358.         if first_element = null then
  359.             return TRUE; -- list is empty
  360.         else
  361.             return FALSE; -- list is not empty
  362.         end if;
  363.     end list_empty;
  364.  
  365. -- 
  366. -- Determine if at first element in list; return TRUE if so
  367. -- 
  368.     function at_front_of_list return boolean is
  369.     begin
  370.         if current_element = first_element then
  371.             return TRUE;
  372.         else
  373.             return FALSE;
  374.         end if;
  375.     end at_front_of_list;
  376.  
  377. -- 
  378. -- Determine if at last element in list; return TRUE if so
  379. -- 
  380.     function at_end_of_list return boolean is
  381.     begin
  382.         if current_element = last_element then
  383.             return TRUE;
  384.         else
  385.             return FALSE;
  386.         end if;
  387.     end at_end_of_list;
  388.  
  389. -- 
  390. -- Procedures to manipulate elements in list
  391. --  These procedures insert elements into the list and
  392. --  delete elements from the list
  393. -- 
  394.     procedure append_element (element : element_pointer) is
  395.     begin
  396.         if list_empty then
  397.             first_element := element;
  398.             last_element := element;
  399.             current_element := element;
  400.             element.next := null;
  401.             element.previous := null;
  402.         else
  403.             element.next := current_element.next;
  404.             current_element.next := element;
  405.             element.previous := current_element;
  406.             if element.next /= null then
  407.                 element.next.previous := element;
  408.             else
  409.                 last_element := element;
  410.             end if;
  411.         end if;
  412.         current_element := element;
  413.     end append_element;
  414.  
  415.     procedure append_element (element : element_object) is
  416.         loc_element : element_pointer;
  417.     begin
  418.         loc_element := new_element;
  419.         loc_element.content := element;
  420.         append_element (loc_element);
  421.     end append_element;
  422.  
  423.     procedure insert_element (element : element_pointer) is
  424.     begin
  425.         if list_empty then
  426.             first_element := element;
  427.             last_element := element;
  428.             current_element := element;
  429.             element.next := null;
  430.             element.previous := null;
  431.         else
  432.             element.previous := current_element.previous;
  433.             current_element.previous := element;
  434.             element.next := current_element;
  435.             if element.previous /= null then
  436.                 element.previous.next := element;
  437.             else
  438.                 first_element := element;
  439.             end if;
  440.         end if;
  441.     end insert_element;
  442.  
  443.     procedure insert_element (element : element_object) is
  444.         loc_element : element_pointer;
  445.     begin
  446.         loc_element := new_element;
  447.         loc_element.content := element;
  448.         insert_element (loc_element);
  449.     end insert_element;
  450.  
  451.     procedure delete_element is
  452.         temp_element : element_pointer;
  453.     begin
  454.         if not list_empty then
  455.  
  456.             if current_element = first_element then
  457.                 first_element := current_element.next;
  458.             else
  459.                 current_element.previous.next := current_element.next;
  460.             end if;
  461.  
  462.             if current_element = last_element then
  463.                 last_element := current_element.previous;
  464.                 temp_element := last_element;
  465.             else
  466.                 current_element.next.previous := current_element.previous;
  467.                 temp_element := current_element.next;
  468.             end if;
  469.  
  470.             free_element (current_element);
  471.             current_element := temp_element;
  472.         end if;
  473.     end delete_element;
  474.  
  475. -- 
  476. -- Memory management routines
  477. --   Obtain a new list element and free old, unneeded list elements
  478. -- 
  479.     function new_element return element_pointer is
  480.     begin
  481.         return (new list_element);
  482.     end new_element;
  483.  
  484.     procedure free_element (element : element_pointer) is
  485. -- 
  486. -- This procedure is a dummy for now; the following generic
  487. -- instantiation is what it should be, but there is a bug in my
  488. -- Ada compiler which prevents this instatiation from working
  489. -- 
  490. -- procedure free_element is new unchecked_deallocation
  491. --    (list_element, element_pointer);
  492. -- 
  493.     begin
  494.         null;
  495.     end free_element;
  496.  
  497. end generic_list;
  498.  
  499.