home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk1.iso / altsrc / articles / 10680 < prev    next >
Text File  |  1994-06-19  |  24KB  |  605 lines

  1. Newsgroups: alt.sources
  2. Path: wupost!cs.utexas.edu!swrinde!ihnp4.ucsd.edu!sdd.hp.com!spool.mu.edu!torn!watserv2.uwaterloo.ca!watdragon.uwaterloo.ca!kppomaki
  3. From: kppomaki@jeeves.uwaterloo.ca (Keith Pomakis)
  4. Subject: Generic List Library for C  --  documentation
  5. Message-ID: <CrHwz3.1LI@watdragon.uwaterloo.ca>
  6. Sender: news@watdragon.uwaterloo.ca (USENET News System)
  7. Organization: University of Waterloo
  8. Date: Thu, 16 Jun 1994 15:13:50 GMT
  9. Lines: 594
  10.  
  11.  
  12.    *************************************************************************
  13.    *************************************************************************
  14.    **                                                                     **
  15.    **                        Generic List Library                         **
  16.    **                                                                     **
  17.    **                          by Keith Pomakis                           **
  18.    **                     kppomaki@jeeves.uwaterloo.ca                    **
  19.    **                                                                     **
  20.    **                            Spring, 1994                             **
  21.    **                                                                     **
  22.    *************************************************************************
  23.    *************************************************************************
  24.  
  25.                            ****  Documentation  ****
  26.  
  27.  
  28. ****************************************************************************
  29. PURPOSE AND HISTORY
  30. ****************************************************************************
  31.  
  32. The basic data structures of lists, stacks and queues are fundamental to
  33. programming at almost every level.  However, because of the nature of the C
  34. programming language, it is difficult to program a set of generic list
  35. functions without sacrificing simplicity.  Therefore, C programmers often
  36. find themselves programming specialized list functions over and over again.
  37. This is not only a large waste of effort, but can also be the source of many
  38. errors since each individual implementation is often tested only
  39. haphazardly.
  40.  
  41. After countless assignments and projects (both academic and personal) in
  42. which I found myself constantly rewriting the same list manipulation
  43. functions in slightly different contexts, I figured it was about time to
  44. take the effort and program an efficient, flexible, and easy-to-use library
  45. of generic list functions.  And that is exactly what I did!
  46.  
  47. It is my hope that, in distributing this library, others will be able to use
  48. what I've put together to increase their own programming productivity.
  49.  
  50.  
  51. ****************************************************************************
  52. DISCLAIMER
  53. ****************************************************************************
  54.  
  55. I am releasing this library to the public domain.  Therefore, people can use
  56. it, copy it, distribute it, modify it, and do whatever they want with it.
  57.  
  58. Although this library has been well thought out, tested, and used in real
  59. applications, it is not guaranteed to be bug-free.  Therefore, I am not
  60. responsible for anything that happens, either directly or indirectly, due to
  61. the usage of this library.
  62.  
  63. If you modify or add to this library in any way, I'd appreciate it if you
  64. dropped me a line (or Internet packet, whatever) telling me what you did.
  65. I'm always interested in potential improvements to my work!
  66.  
  67. Also, if you find any bugs (gasp!) or have any questions or comments about
  68. the library, you can contact me as well.  My e-mail address is
  69. "kppomaki@jeeves.uwaterloo.ca".  I'd be interested in hearing what you
  70. think!
  71.  
  72. Oh, one other thing... I've put a lot of work into this library, so I'd
  73. appreciate it if you kept my name attached to it when distributing or
  74. modifying it.
  75.  
  76.  
  77. ****************************************************************************
  78. REQUIREMENTS
  79. ****************************************************************************
  80.  
  81. The only requirements for the usage of this library are an ANSI C compiler,
  82. a machine to run it on, and a project that is in need of generic list
  83. functions!  This library has been tested with gcc on a Sun 4 and with Think
  84. C on a Macintosh.  The code is ANSI-compliant, and should present no problem
  85. with any other setup.
  86.  
  87.  
  88. ****************************************************************************
  89. PHILOSOPHY
  90. ****************************************************************************
  91.  
  92. My goal when designing this library was to make it as flexible and complete
  93. as possible, while still keeping it efficient and easy to use.  I have seen
  94. and have tried to use other generic list libraries (and yes, I realize they
  95. are numerous), but often they have failed me on one or more of the above
  96. points.  I also realize that such a library would be a trivial piece of work
  97. in C++.  However, as much of a proponent of the object-oriented paradigm as
  98. I am, I tend to dislike C++ because of the hideous syntactic nightmares I
  99. get when tackling the language.  Therefore, I have decided to write the
  100. library in C.
  101.  
  102. A set of basic generic doubly-linked list functions were designed and
  103. programmed first (along with a suitable efficient data structure), and then
  104. some higher-level functions were added to increase ease of use.  The
  105. functionality of stacks, queues and sorted lists were then added.  In
  106. actuality, these functions (with the exception of one of the sorted-list
  107. functions) are nothing more than aliases for the appropriate generic list
  108. operations.  This aliasing is behind the scenes, however, and the user of
  109. this library may treat the operation of lists, stacks and queues in this
  110. library as completely separate functionality.
  111.  
  112. In order to make the library completely generic, it was designed to
  113. manipulate pointers of type void *.  Therefore, it is assumed that the
  114. programmer is statically or dynamically creating the objects of interest,
  115. and using the generic list functions to manipulate them.  It is up to the
  116. programmer to handle the allocation and deallocation of the memory for the
  117. objects themselves.
  118.  
  119. A pointer to the same object may be stored in a list multiple times.  The
  120. only restriction imposed is that a NULL pointer may not be stored.
  121.  
  122.  
  123. ****************************************************************************
  124. USAGE
  125. ****************************************************************************
  126.  
  127. The use of this library is simple and straight-forward.  In every source
  128. file that requires the use of generic list functions, the line:
  129.  
  130. #include "generic_list.h"
  131.  
  132. must be included at the top of the file.  For those who hand-craft their own
  133. makefiles, "generic_list.h" should become a prerequisite for each of these
  134. files, as well as for "generic_list.c" itself.
  135.  
  136. The library defines three data types:
  137.  
  138.     Generic_list
  139.     Generic_stack
  140.     Generic_queue
  141.  
  142. The usage of these functions is best illustrated with an example:
  143.  
  144. foo() {
  145.     Generic_stack stack;
  146.     My_object *obj;
  147.  
  148.     initialize_stack(&stack);
  149.  
  150.     obj = new_object();
  151.     push(stack, obj);
  152.     ...
  153.     obj = pop(stack);
  154.     free(obj);
  155.     ...
  156.     destroy_stack(&stack);
  157. }
  158.  
  159. Each list must be initialized before use and should be destroyed after it is
  160. no longer needed.  The programmer must handle the allocation and
  161. deallocation of the memory for the objects being stored.  Explicit memory
  162. management for the lists is not necessary.
  163.  
  164.  
  165. ****************************************************************************
  166. LIST OF FUNCTIONS
  167. ****************************************************************************
  168.  
  169. The following are the headers of the functions provided in the generic list
  170. library.  They are described in more detail later.
  171.  
  172. Generic Lists
  173. -------------
  174.  
  175. void initialize_list(Generic_list *list);
  176. void destroy_list(Generic_list *list);
  177. void add_to_beginning(Generic_list list, void *pointer);
  178. void add_to_end(Generic_list list, void *pointer);
  179. void add_to_list(Generic_list list, void *pointer);
  180. void *remove_from_beginning(Generic_list list);
  181. void *remove_from_end(Generic_list list);
  182. void *remove_from_list(Generic_list list, void *pointer);
  183. void remove_all(Generic_list list);
  184. void *peek_at_beginning(Generic_list list);
  185. void *peek_at_end(Generic_list list);
  186.  
  187. void *first_in_list(Generic_list list);
  188. void *next_in_list(Generic_list list);
  189. void *current_in_list(Generic_list list);
  190. void *remove_current(Generic_list list);
  191. void *previous_in_list(Generic_list list);
  192. void *last_in_list(Generic_list list);
  193. void reset_to_beginning(Generic_list list);
  194. void reset_to_end(Generic_list list);
  195.  
  196. int num_of_objects(Generic_list list);
  197. int is_empty(Generic_list list);
  198. int is_in_list(Generic_list list, void *pointer);
  199. Generic_list copy_list(Generic_list list);
  200.  
  201. void perform_on_list
  202.      (Generic_list list, void (*fn)(void *pointer, void *args), void *args);
  203. void *first_that
  204.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  205. void *next_that
  206.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  207. void *previous_that
  208.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  209. void *last_that
  210.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  211. Generic_list all_such_that
  212.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  213. void remove_all_such_that
  214.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  215.  
  216.  
  217. Generic Sorted Lists
  218. --------------------
  219.  
  220. void initialize_sorted_list(Generic_list *list, int (*lt)(void *a, void *b));
  221.  
  222. ...and all Generic_list functions except:
  223.  
  224. void add_to_beginning(Generic_list list, void *pointer);
  225. void add_to_end(Generic_list list, void *pointer);
  226. void *remove_from_beginning(Generic_list list);
  227. void *remove_from_end(Generic_list list);
  228.  
  229.  
  230. Generic Stacks
  231. --------------
  232.  
  233. void initialize_stack(Generic_stack *stack);
  234. void destroy_stack(Generic_stack *stack);
  235. void push(Generic_stack stack, void *pointer);
  236. void *pop(Generic_stack stack);
  237. void pop_all(Generic_stack stack);
  238. void *peek_at_top(Generic_stack stack);
  239. Generic_stack copy_stack(Generic_stack stack);
  240. int is_empty(Generic_stack stack);
  241.  
  242.  
  243. Generic Queues
  244. --------------
  245.  
  246. void initialize_queue(Generic_queue *queue);
  247. void destroy_queue(Generic_queue *queue);
  248. void enqueue(Generic_queue queue, void *pointer);
  249. void *dequeue(Generic_queue queue);
  250. void dequeue_all(Generic_queue queue);
  251. void *peek_at_head(Generic_queue queue);
  252. void *peek_at_tail(Generic_queue queue);
  253. Generic_queue copy_queue(Generic_queue queue);
  254. int is_empty(Generic_queue queue);
  255.  
  256.  
  257. ****************************************************************************
  258. DETAILED DESCRIPTION OF FUNCTIONS
  259. ****************************************************************************
  260.  
  261. Generic Lists
  262. -------------
  263.  
  264. void initialize_list(Generic_list *list);
  265.  
  266.     Every list must be initialized before it is used.  The only time it is
  267.     valid to re-initialize a list is after it has been destroyed.
  268.  
  269. void destroy_list(Generic_list *list);
  270.  
  271.     When a list is no longer needed, it should be destroyed.  This process
  272.     will automatically remove all remaining objects from the list.  However,
  273.     the memory for these objects will not be reclaimed, so if the objects
  274.     have no other references, care should be taken to purge the list and
  275.     free all objects before destroying the list.
  276.  
  277.     It is an error to destroy a list more than once (unless it has been
  278.     re-initialized in the meantime).
  279.  
  280. void add_to_beginning(Generic_list list, void *pointer);
  281.  
  282.     This function will add the specified object to the beginning of the
  283.     list.  The pointer must not be NULL.
  284.  
  285. void add_to_end(Generic_list list, void *pointer);
  286.  
  287.     This function will add the specified object to the end of the
  288.     list.  The pointer must not be NULL.
  289.  
  290. void add_to_list(Generic_list list, void *pointer);
  291.  
  292.     This function will add the specified object to the list.  The pointer
  293.     must not be NULL.
  294.  
  295. void *remove_from_beginning(Generic_list list);
  296.  
  297.     This function will remove the first object from the beginning of the
  298.     list and return it.  If the list is empty, NULL is returned.
  299.  
  300. void *remove_from_end(Generic_list list);
  301.  
  302.     This function will remove the last object from the end of the list and
  303.     return it.  If the list is empty, NULL is returned.
  304.  
  305. void *remove_from_list(Generic_list list, void *pointer);
  306.  
  307.     This function will remove the specified object from the list and return
  308.     it.  If the specified object does not exist in the list, NULL is
  309.     returned.  If the specified object exists in the list more than once,
  310.     only the last reference to it is removed.
  311.  
  312. void remove_all(Generic_list list);
  313.  
  314.     This function will remove all objects from the list.  Note that the
  315.     memory for these objects will not be reclaimed, so if the objects have
  316.     no other references, it is best to avoid this function and remove the
  317.     objects one by one, freeing them when necessary.
  318.  
  319. void *peek_at_beginning(Generic_list list);
  320.  
  321.     This function will return the first object in the list.  If the list is
  322.     empty, NULL is returned.
  323.  
  324. void *peek_at_end(Generic_list list);
  325.  
  326.     This function will return the last object in the list.  If the list is
  327.     empty, NULL is returned.
  328.  
  329. void *first_in_list(Generic_list list);
  330.  
  331.     This function will return the first object in the list and mark it as
  332.     the current object.  If the list is empty, NULL is returned.
  333.  
  334. void *next_in_list(Generic_list list);
  335.  
  336.     This function will return the next object in the list and mark it as
  337.     the current object.  If the end of the list is reached, or if the list
  338.     is empty, NULL is returned.
  339.  
  340. void *current_in_list(Generic_list list);
  341.  
  342.     This function will return the object in the list that is considered
  343.     the current object (as defined by the surrounding functions).  If the
  344.     current object has just been removed, if current points to the
  345.     beginning or end of the list, or if the list is empty, NULL is
  346.     returned.
  347.  
  348. void *remove_current(Generic_list list);
  349.  
  350.     This function will remove the current object from the list and return
  351.     it.  If the current object has already been removed, if current points
  352.     to the beginning or end of the list, or if the list is empty, NULL is
  353.     returned.
  354.  
  355. void *previous_in_list(Generic_list list);
  356.  
  357.     This function will return the previous object in the list and mark it
  358.     as the current object.  If the beginning of the list is reached, or if
  359.     the list is empty, NULL is returned.
  360.  
  361. void *last_in_list(Generic_list list);
  362.  
  363.     This function will return the last object in the list and mark it as
  364.     the current object.  If the list is empty, NULL is returned.
  365.  
  366. void reset_to_beginning(Generic_list list);
  367.  
  368.     This function will reset the list to the beginning.  Therefore, current
  369.     points to the beginning of the list, and the next object in the list is
  370.     the first object.
  371.  
  372. void reset_to_end(Generic_list list);
  373.  
  374.     This function will reset the list to the end.  Therefore, current
  375.     points to the end of the list, and the previous object in the list is
  376.     the last object.
  377.  
  378. int num_of_objects(Generic_list list);
  379.  
  380.     This function will return the number of objects in the list.
  381.  
  382. int is_empty(Generic_list list);
  383.  
  384.     This function will return TRUE (1) if the list is empty, and FALSE (0)
  385.     otherwise.
  386.  
  387. int is_in_list(Generic_list list, void *pointer);
  388.  
  389.     This function will return TRUE (1) if the specified object is a member
  390.     of the list, and FALSE (0) otherwise.
  391.  
  392. Generic_list copy_list(Generic_list list);
  393.  
  394.     This function will return a copy of the list.  The objects themselves
  395.     are not copied; only new references to them are made.  The new list
  396.     loses its concept of the current object.
  397.  
  398. void perform_on_list
  399.      (Generic_list list, void (*fn)(void *pointer, void *args), void *args);
  400.  
  401.     This function will perform the specified function on each object in the
  402.     list.  Any optional arguments required can be passed through args.
  403.  
  404. void *first_that
  405.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  406.  
  407.      This function will find and return the first object in the list which
  408.      causes the specified function to return a TRUE (non-zero) value.  Any
  409.      optional arguments required can be passed through args.  The found
  410.      object is then marked as the current object.  If no objects in the list
  411.      meet the criteria of the specified function, NULL is returned.
  412.  
  413. void *next_that
  414.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  415.  
  416.      This function will find and return the next object in the list which
  417.      causes the specified function to return a TRUE (non-zero) value.  Any
  418.      optional arguments required can be passed through args.  The found
  419.      object is then marked as the current object.  If there are no objects
  420.      left in the list that meet the criteria of the specified function,
  421.      NULL is returned.
  422.  
  423. void *previous_that
  424.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  425.  
  426.      This function will find and return the previous object in the list
  427.      which causes the specified function to return a TRUE (non-zero) value.
  428.      Any optional arguments required can be passed through args.  The found
  429.      object is then marked as the current object.  If there are no objects
  430.      left in the list that meet the criteria of the specified function,
  431.      NULL is returned.
  432.  
  433. void *last_that
  434.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  435.  
  436.      This function will find and return the last object in the list which
  437.      causes the specified function to return a TRUE (non-zero) value.  Any
  438.      optional arguments required can be passed through args.  The found
  439.      object is then marked as the current object.  If no objects in the
  440.      list meet the criteria of the specified function, NULL is returned.
  441.  
  442. Generic_list all_such_that
  443.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  444.  
  445.     This function will return a new list containing all of the objects in
  446.     the specified list which cause the specified function to return a TRUE
  447.     (non-zero) value.  Any optional arguments required can be passed
  448.     through args. The objects themselves are not copied; only new
  449.     references to them are made.
  450.  
  451. void remove_all_such_that
  452.      (Generic_list list, int (*fn)(void *pointer, void *args), void *args);
  453.  
  454.     This function will remove all objects in the list which cause the
  455.     specified function to return a TRUE (non-zero) value.  Any optional
  456.     arguments required can be passed through args.  Note that the memory
  457.     for these objects will not be reclaimed, so if the objects have
  458.     no other references, it is best to avoid this function and remove the
  459.     objects one by one, freeing them when necessary.
  460.  
  461.  
  462. Generic Sorted Lists
  463. --------------------
  464.  
  465. void initialize_sorted_list(Generic_list *list, int (*lt)(void *a, void *b));
  466.  
  467.     This function initializes a sorted list.  A less-than function must be
  468.     specified which accepts two pointers, a and b, and returns TRUE
  469.     (non-zero) if a is less than b, FALSE otherwise.
  470.  
  471.     Once a list is initialized in this way, all of the generic list
  472.     functions described above can be used, except for:
  473.  
  474.         void add_to_beginning(Generic_list list, void *pointer);
  475.         void add_to_end(Generic_list list, void *pointer);
  476.         void *remove_from_beginning(Generic_list list);
  477.         void *remove_from_end(Generic_list list);
  478.  
  479.     and the list will remain sorted by the criteria specified by the
  480.     less-than function.  The only time it is valid to re-initialize a list
  481.     is after it has been destroyed.
  482.  
  483.  
  484. Generic Stacks
  485. --------------
  486.  
  487. void initialize_stack(Generic_stack *stack);
  488.  
  489.     Every stack must be initialized before it is used.  The only time it is
  490.     valid to re-initialize a stack is after it has been destroyed.
  491.  
  492. void destroy_stack(Generic_stack *stack);
  493.  
  494.     When a stack is no longer needed, it should be destroyed.  This process
  495.     will automatically remove all remaining objects from the stack.
  496.     However, the memory for these objects will not be reclaimed, so if the
  497.     objects have no other references, care should be taken to purge the
  498.     stack and free all objects before destroying the stack.
  499.  
  500.     It is an error to destroy a stack more than once (unless it has been
  501.     re-initialized in the meantime).
  502.  
  503. void push(Generic_stack stack, void *pointer);
  504.  
  505.     This function will push the specified object onto the stack.  The
  506.     pointer must not be NULL.
  507.  
  508. void *pop(Generic_stack stack);
  509.  
  510.     This function will pop the first object from the top of the stack and
  511.     return it.  If the stack is empty, NULL is returned.
  512.  
  513. void pop_all(Generic_stack stack);
  514.  
  515.     This function will pop all objects from the stack.  Note that the
  516.     memory for these objects will not be reclaimed, so if the objects have
  517.     no other references, it is best to avoid this function and pop the
  518.     objects one by one, freeing them when necessary.
  519.  
  520. void *peek_at_top(Generic_stack stack);
  521.  
  522.     This function will return the object on the top of the stack.  If the
  523.     stack is empty, NULL is returned.
  524.  
  525. Generic_stack copy_stack(Generic_stack stack);
  526.  
  527.     This function will return a copy of the stack.  The objects themselves
  528.     are not copied; only new references to them are made.
  529.  
  530. int is_empty(Generic_stack stack);
  531.  
  532.     This function will return TRUE (1) if the stack is empty, and FALSE (0)
  533.     otherwise.
  534.  
  535.  
  536. Generic Queues
  537. --------------
  538.  
  539. void initialize_queue(Generic_queue *queue);
  540.  
  541.     Every queue must be initialized before it is used.  The only time it is
  542.     valid to re-initialize a queue is after it has been destroyed.
  543.  
  544. void destroy_queue(Generic_queue *queue);
  545.  
  546.     When a queue is no longer needed, it should be destroyed.  This process
  547.     will automatically remove all remaining objects from the queue.
  548.     However, the memory for these objects will not be reclaimed, so if the
  549.     objects have no other references, care should be taken to purge the
  550.     queue and free all objects before destroying the queue.
  551.  
  552.     It is an error to destroy a queue more than once (unless it has been
  553.     re-initialized in the meantime).
  554.  
  555. void enqueue(Generic_queue queue, void *pointer);
  556.  
  557.     This function will add the specified object to the tail of the queue.
  558.     The pointer must not be NULL.
  559.  
  560. void *dequeue(Generic_queue queue);
  561.  
  562.     This function will remove the first object from the head of the queue
  563.     and return it.  If the queue is empty, NULL is returned.
  564.  
  565. void dequeue_all(Generic_queue queue);
  566.  
  567.     This function will remove all objects from the queue.  Note that the
  568.     memory for these objects will not be reclaimed, so if the objects have
  569.     no other references, it is best to avoid this function and dequeue the
  570.     objects one by one, freeing them when necessary.
  571.  
  572. void *peek_at_head(Generic_queue queue);
  573.  
  574.     This function will return the object at the head of the queue.  If the
  575.     queue is empty, NULL is returned.
  576.  
  577. void *peek_at_tail(Generic_queue queue);
  578.  
  579.     This function will return the object at the tail of the queue.  If the
  580.     queue is empty, NULL is returned.
  581.  
  582. Generic_queue copy_queue(Generic_queue queue);
  583.  
  584.     This function will return a copy of the queue.  The objects themselves
  585.     are not copied; only new references to them are made.
  586.  
  587. int is_empty(Generic_queue queue);
  588.  
  589.     This function will return TRUE (1) if the queue is empty, and FALSE (0)
  590.     otherwise.
  591.  
  592.  
  593. ****************************************************************************
  594. HINTS
  595. ****************************************************************************
  596.  
  597. Technically, any of the above functions can be used with any of the three
  598. data types.  For example, one can use perform_on_list() to perform a
  599. specified function on every object in a queue, or is_in_list() to determine
  600. whether or not a particular object is a member of a stack.  One can even
  601. pop from a queue and dequeue from a stack.  However, such usage is not
  602. recommended, as it is contrary to the logical usage of such data
  603. structures.
  604.  
  605.