tesseract  4.00.00dev
oldlist.cpp
Go to the documentation of this file.
1 /* -*-C-*-
2 ###############################################################################
3 #
4 # File: oldlist.cpp
5 # Description: List processing procedures.
6 # Author: Mark Seaman, Software Productivity
7 # Created: Thu Jul 23 13:24:09 1987
8 # Modified: Thu Dec 22 10:59:52 1988 (Mark Seaman) marks@hpgrlt
9 # Language: C
10 # Package: N/A
11 # Status: Reusable Software Component
12 #
13 # (c) Copyright 1987, Hewlett-Packard Company.
14 ** Licensed under the Apache License, Version 2.0 (the "License");
15 ** you may not use this file except in compliance with the License.
16 ** You may obtain a copy of the License at
17 ** http://www.apache.org/licenses/LICENSE-2.0
18 ** Unless required by applicable law or agreed to in writing, software
19 ** distributed under the License is distributed on an "AS IS" BASIS,
20 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 ** See the License for the specific language governing permissions and
22 ** limitations under the License.
23 #
24 ################################################################################
25 
26 * Revision 1.13 90/03/06 15:37:54 15:37:54 marks (Mark Seaman)
27 * Look for correct file of <malloc.h> or <stdlib.h>
28 *
29 * Revision 1.12 90/02/26 17:37:36 17:37:36 marks (Mark Seaman)
30 * Added pop_off and join_on
31 *
32 
33  This file contains a set of general purpose list manipulation routines.
34  These routines can be used in a wide variety of ways to provide several
35  different popular data structures. A new list can be created by declaring
36  a variable of type 'LIST', and can be initialized with the value 'NIL_LIST'.
37  All of these routines check for the NIL_LIST condition before dereferencing
38  pointers. NOTE: There is a users' manual available in printed form from
39  Mark Seaman at (303) 350-4492 at Greeley Hard Copy.
40 
41  To implement a STACK use:
42 
43  push to add to the Stack l = push(l, (LIST)"jim");
44  pop to remove items from the Stack l = pop(l);
45  first_node to access the head name = (char *)first_node(l);
46 
47  To implement a QUEUE use:
48 
49  push_last to add to the Queue l = push_last(l, (LIST)"x");
50  pop remove items from the Queue l = pop(l);
51  first_node to access the head name = (char *)first_node (l);
52 
53  To implement LISP like functions use:
54 
55  first_node CAR x = (int)first_node(l);
56  rest CDR l = list_rest (l);
57  push CONS l = push(l, (LIST)this);
58  last LAST x = last(l);
59  concat APPEND l = concat(r, s);
60  count LENGTH x = count(l);
61  search MEMBER if (search(l, x, NULL))
62 
63  To implement SETS use:
64 
65  adjoin l = adjoin(l, x);
66  set_union l = set_union(r, s);
67  intersection l = intersection(r, s);
68  set_difference l = set_difference(r, s);
69  delete l = delete(s, x, NULL);
70  search if (search(l, x, NULL))
71 
72  To Implement Associated LISTS use:
73 
74  lpush l = lpush(l, p);
75  assoc s = assoc(l, x);
76  adelete l = adelete(l, x);
77 
78  The following rules of closure exist for the functions provided.
79  a = first_node (push (a, b))
80  b = list_rest (push (a, b))
81  a = push (pop (a), a)) For all a <> NIL_LIST
82  a = reverse (reverse (a))
83 
84 ******************************************************************************/
85 #include "oldlist.h"
86 #include <stdio.h>
87 #include "structures.h"
88 
89 /*----------------------------------------------------------------------
90  M a c r o s
91 ----------------------------------------------------------------------*/
92 #define add_on(l, x) l = push(l, first_node(x))
93 #define next_one(l) l = list_rest(l)
94 
95 /*----------------------------------------------------------------------
96  F u n c t i o n s
97 ----------------------------------------------------------------------*/
98 /**********************************************************************
99  * c o u n t
100  *
101  * Recursively count the elements in a list. Return the count.
102  **********************************************************************/
103 int count(LIST var_list) {
104  int temp = 0;
105 
106  iterate(var_list) temp += 1;
107  return (temp);
108 }
109 
110 /**********************************************************************
111  * d e l e t e d
112  *
113  * Delete all the elements out of the current list that match the key.
114  * This operation destroys the original list. The caller will supply a
115  * routine that will compare each node to the
116  * key, and return a non-zero value when they match. If the value
117  * NULL is supplied for is_equal, the is_key routine will be used.
118  **********************************************************************/
119 LIST delete_d(LIST list, void *key, int_compare is_equal) {
120  LIST result = NIL_LIST;
121  LIST last_one = NIL_LIST;
122 
123  if (is_equal == NULL) is_equal = is_same;
124 
125  while (list != NIL_LIST) {
126  if (!(*is_equal)(first_node(list), key)) {
127  if (last_one == NIL_LIST) {
128  last_one = list;
129  list = list_rest(list);
130  result = last_one;
131  set_rest(last_one, NIL_LIST);
132  } else {
133  set_rest(last_one, list);
134  last_one = list;
135  list = list_rest(list);
136  set_rest(last_one, NIL_LIST);
137  }
138  } else {
139  list = pop(list);
140  }
141  }
142  return (result);
143 }
144 
145 LIST delete_d(LIST list, void *key,
147  LIST result = NIL_LIST;
148  LIST last_one = NIL_LIST;
149 
150  while (list != NIL_LIST) {
151  if (!(*is_equal).Run(first_node(list), key)) {
152  if (last_one == NIL_LIST) {
153  last_one = list;
154  list = list_rest(list);
155  result = last_one;
156  set_rest(last_one, NIL_LIST);
157  } else {
158  set_rest(last_one, list);
159  last_one = list;
160  list = list_rest(list);
161  set_rest(last_one, NIL_LIST);
162  }
163  } else {
164  list = pop(list);
165  }
166  }
167  return (result);
168 }
169 
170 /**********************************************************************
171  * d e s t r o y
172  *
173  * Return the space taken by a list to the heap.
174  **********************************************************************/
176  LIST next;
177 
178  while (list != NIL_LIST) {
179  next = list_rest(list);
180  free_cell(list);
181  list = next;
182  }
183  return (NIL_LIST);
184 }
185 
186 /**********************************************************************
187  * d e s t r o y n o d e s
188  *
189  * Return the space taken by the LISTs of a list to the heap.
190  **********************************************************************/
191 void destroy_nodes(LIST list, void_dest destructor) {
192  ASSERT_HOST(destructor != nullptr);
193 
194  while (list != NIL_LIST) {
195  if (first_node(list) != NULL) (*destructor)(first_node(list));
196  list = pop(list);
197  }
198 }
199 
200 /**********************************************************************
201  * i n s e r t
202  *
203  * Create a list element and rearange the pointers so that the first
204  * element in the list is the second aurgment.
205  **********************************************************************/
206 void insert(LIST list, void *node) {
207  LIST element;
208 
209  if (list != NIL_LIST) {
210  element = push(NIL_LIST, node);
211  set_rest(element, list_rest(list));
212  set_rest(list, element);
213  node = first_node(list);
214  list->node = first_node(list_rest(list));
215  list->next->node = (LIST)node;
216  }
217 }
218 
219 /**********************************************************************
220  * i s s a m e
221  *
222  * Compare the list node with the key value return TRUE (non-zero)
223  * if they are equivalent strings. (Return FALSE if not)
224  **********************************************************************/
225 int is_same(void *item1, void *item2) {
226  return strcmp((char *)item1, (char *)item2) == 0 ? 1 : 0;
227 }
228 
229 /**********************************************************************
230  * j o i n
231  *
232  * Join the two lists together. This function is similar to concat
233  * except that concat creates a new list. This function returns the
234  * first list updated.
235  **********************************************************************/
236 LIST join(LIST list1, LIST list2) {
237  if (list1 == NIL_LIST) return (list2);
238  set_rest(last(list1), list2);
239  return (list1);
240 }
241 
242 /**********************************************************************
243  * l a s t
244  *
245  * Return the last list item (this is list type).
246  **********************************************************************/
247 LIST last(LIST var_list) {
248  while (list_rest(var_list) != NIL_LIST) var_list = list_rest(var_list);
249  return (var_list);
250 }
251 
252 /**********************************************************************
253  * n t h c e l l
254  *
255  * Return nth list cell in the list.
256  **********************************************************************/
257 void *nth_cell(LIST var_list, int item_num) {
258  int x = 0;
259  iterate(var_list) {
260  if (x++ == item_num) return (var_list);
261  }
262  return (var_list);
263 }
264 
265 /**********************************************************************
266  * p o p
267  *
268  * Return the list with the first element removed. Destroy the space
269  * that it occupied in the list.
270  **********************************************************************/
271 LIST pop(LIST list) {
272  LIST temp;
273 
274  temp = list_rest(list);
275 
276  if (list != NIL_LIST) {
277  free_cell(list);
278  }
279  return (temp);
280 }
281 
282 /**********************************************************************
283  * p u s h
284  *
285  * Create a list element. Push the second parameter (the node) onto
286  * the first parameter (the list). Return the new list to the caller.
287  **********************************************************************/
288 LIST push(LIST list, void *element) {
289  LIST t;
290 
291  t = new_cell();
292  t->node = (LIST)element;
293  set_rest(t, list);
294  return (t);
295 }
296 
297 /**********************************************************************
298  * p u s h l a s t
299  *
300  * Create a list element. Add the element onto the end of the list.
301  **********************************************************************/
302 LIST push_last(LIST list, void *item) {
303  LIST t;
304 
305  if (list != NIL_LIST) {
306  t = last(list);
307  t->next = push(NIL_LIST, item);
308  return (list);
309  } else
310  return (push(NIL_LIST, item));
311 }
312 
313 /**********************************************************************
314  * r e v e r s e
315  *
316  * Create a new list with the elements reversed. The old list is not
317  * destroyed.
318  **********************************************************************/
320  LIST newlist = NIL_LIST;
321 
322  iterate(list) copy_first(list, newlist);
323  return (newlist);
324 }
325 
326 /**********************************************************************
327  * r e v e r s e d
328  *
329  * Create a new list with the elements reversed. The old list is
330  * destroyed.
331  **********************************************************************/
333  LIST result = reverse(list);
334  destroy(list);
335  return (result);
336 }
337 
338 /**********************************************************************
339  * s a d j o i n
340  *
341  * Adjoin an element to an assorted list. The original list is
342  * modified. Returns the modified list.
343  **********************************************************************/
344 LIST s_adjoin(LIST var_list, void *variable, int_compare compare) {
345  LIST l;
346  int result;
347 
348  if (compare == NULL) compare = (int_compare)strcmp;
349 
350  l = var_list;
351  iterate(l) {
352  result = (*compare)(variable, first_node(l));
353  if (result == 0)
354  return (var_list);
355  else if (result < 0) {
356  insert(l, variable);
357  return (var_list);
358  }
359  }
360  return (push_last(var_list, variable));
361 }
362 
363 /**********************************************************************
364  * s e a r c h
365  *
366  * Search list, return NIL_LIST if not found. Return the list starting from
367  * the item if found. The compare routine "is_equal" is passed in as
368  * the third parameter to this routine. If the value NULL is supplied
369  * for is_equal, the is_key routine will be used.
370  **********************************************************************/
371 LIST search(LIST list, void *key, int_compare is_equal) {
372  if (is_equal == NULL) is_equal = is_same;
373 
374  iterate(list) if ((*is_equal)(first_node(list), key)) return (list);
375  return (NIL_LIST);
376 }
377 
378 LIST search(LIST list, void *key,
380  iterate(list) if ((*is_equal).Run(first_node(list), key)) return (list);
381  return (NIL_LIST);
382 }
LIST new_cell()
LIST pop(LIST list)
Definition: oldlist.cpp:271
void(* void_dest)(void *)
Definition: cutil.h:72
void * nth_cell(LIST var_list, int item_num)
Definition: oldlist.cpp:257
LIST push(LIST list, void *element)
Definition: oldlist.cpp:288
#define copy_first(l1, l2)
Definition: oldlist.h:149
LIST last(LIST var_list)
Definition: oldlist.cpp:247
LIST destroy(LIST list)
Definition: oldlist.cpp:175
int count(LIST var_list)
Definition: oldlist.cpp:103
int is_same(void *item1, void *item2)
Definition: oldlist.cpp:225
#define list_rest(l)
Definition: oldlist.h:138
list_rec * LIST
Definition: oldlist.h:132
LIST reverse(LIST list)
Definition: oldlist.cpp:319
void free_cell(LIST)
LIST search(LIST list, void *key, int_compare is_equal)
Definition: oldlist.cpp:371
#define is_equal(p1, p2)
Definition: outlines.h:109
int(* int_compare)(void *, void *)
Definition: cutil.h:71
LIST push_last(LIST list, void *item)
Definition: oldlist.cpp:302
#define set_rest(l, cell)
Definition: oldlist.h:222
#define NIL_LIST
Definition: oldlist.h:126
#define ASSERT_HOST(x)
Definition: errcode.h:84
void insert(LIST list, void *node)
Definition: oldlist.cpp:206
#define first_node(l)
Definition: oldlist.h:139
LIST s_adjoin(LIST var_list, void *variable, int_compare compare)
Definition: oldlist.cpp:344
struct list_rec * next
Definition: oldlist.h:130
#define iterate(l)
Definition: oldlist.h:159
LIST reverse_d(LIST list)
Definition: oldlist.cpp:332
LIST join(LIST list1, LIST list2)
Definition: oldlist.cpp:236
void destroy_nodes(LIST list, void_dest destructor)
Definition: oldlist.cpp:191
LIST delete_d(LIST list, void *key, int_compare is_equal)
Definition: oldlist.cpp:119
struct list_rec * node
Definition: oldlist.h:129