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