Tesseract
3.02
|
00001 /* -*-C-*- 00002 ############################################################################### 00003 # 00004 # File: list.c 00005 # Description: List processing procedures. 00006 # Author: Mark Seaman, Software Productivity 00007 # Created: Thu Jul 23 13:24:09 1987 00008 # Modified: Thu Dec 22 10:59:52 1988 (Mark Seaman) marks@hpgrlt 00009 # Language: C 00010 # Package: N/A 00011 # Status: Reusable Software Component 00012 # 00013 # (c) Copyright 1987, Hewlett-Packard Company. 00014 ** Licensed under the Apache License, Version 2.0 (the "License"); 00015 ** you may not use this file except in compliance with the License. 00016 ** You may obtain a copy of the License at 00017 ** http://www.apache.org/licenses/LICENSE-2.0 00018 ** Unless required by applicable law or agreed to in writing, software 00019 ** distributed under the License is distributed on an "AS IS" BASIS, 00020 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00021 ** See the License for the specific language governing permissions and 00022 ** limitations under the License. 00023 # 00024 ################################################################################ 00025 00026 * Revision 1.13 90/03/06 15:37:54 15:37:54 marks (Mark Seaman) 00027 * Look for correct file of <malloc.h> or <stdlib.h> 00028 * 00029 * Revision 1.12 90/02/26 17:37:36 17:37:36 marks (Mark Seaman) 00030 * Added pop_off and join_on 00031 * 00032 00033 This file contains a set of general purpose list manipulation routines. 00034 These routines can be used in a wide variety of ways to provide several 00035 different popular data structures. A new list can be created by declaring 00036 a variable of type 'LIST', and can be initialized with the value 'NIL_LIST'. 00037 All of these routines check for the NIL_LIST condition before dereferencing 00038 pointers. NOTE: There is a users' manual available in printed form from 00039 Mark Seaman at (303) 350-4492 at Greeley Hard Copy. 00040 00041 To implement a STACK use: 00042 00043 push to add to the Stack l = push (l, (LIST) "jim"); 00044 pop to remove items from the Stack l = pop (l); 00045 first_node to access the head name = (char *) first_node (l); 00046 00047 To implement a QUEUE use: 00048 00049 push_last to add to the Queue l = push_last (l, (LIST) "jim"); 00050 pop remove items from the Queue l = pop (l); 00051 first_node to access the head name = (char *) first_node (l); 00052 00053 To implement LISP like functions use: 00054 00055 first_node CAR x = (int) first_node (l); 00056 rest CDR l = list_rest (l); 00057 push CONS l = push (l, (LIST) this); 00058 last LAST x = last (l); 00059 concat APPEND l = concat (r, s); 00060 count LENGTH x = count (l); 00061 search MEMBER if (search (l, x, NULL)) 00062 00063 To implement SETS use: 00064 00065 adjoin l = adjoin (l, x); 00066 set_union l = set_union (r, s); 00067 intersection l = intersection (r, s); 00068 set_difference l = set_difference (r, s); 00069 delete l = delete (s, x, NULL); 00070 search if (search (l, x, NULL)) 00071 00072 To Implement Associated LISTS use: 00073 00074 lpush l = lpush (l, p); 00075 assoc s = assoc (l, x); 00076 adelete l = adelete (l, x); 00077 00078 The following rules of closure exist for the functions provided. 00079 a = first_node (push (a, b)) 00080 b = list_rest (push (a, b)) 00081 a = push (pop (a), a)) For all a <> NIL_LIST 00082 a = reverse (reverse (a)) 00083 00084 ******************************************************************************/ 00085 #include "oldlist.h" 00086 #include "structures.h" 00087 #include <stdio.h> 00088 #if MAC_OR_DOS 00089 #include <stdlib.h> 00090 #else 00091 #include "freelist.h" 00092 #endif 00093 00094 /*---------------------------------------------------------------------- 00095 M a c r o s 00096 ----------------------------------------------------------------------*/ 00097 #define add_on(l,x) l = push (l,first_node (x)) 00098 #define next_one(l) l = list_rest (l) 00099 00100 /*---------------------------------------------------------------------- 00101 F u n c t i o n s 00102 ----------------------------------------------------------------------*/ 00103 /********************************************************************** 00104 * c o u n t 00105 * 00106 * Recursively count the elements in a list. Return the count. 00107 **********************************************************************/ 00108 int count(LIST var_list) { 00109 int temp = 0; 00110 00111 iterate (var_list) temp += 1; 00112 return (temp); 00113 } 00114 00115 00116 /********************************************************************** 00117 * d e l e t e d 00118 * 00119 * Delete all the elements out of the current list that match the key. 00120 * This operation destroys the original list. The caller will supply a 00121 * routine that will compare each node to the 00122 * key, and return a non-zero value when they match. If the value 00123 * NULL is supplied for is_equal, the is_key routine will be used. 00124 **********************************************************************/ 00125 LIST delete_d(LIST list, void *key, int_compare is_equal) { 00126 LIST result = NIL_LIST; 00127 LIST last_one = NIL_LIST; 00128 00129 if (is_equal == NULL) 00130 is_equal = is_same; 00131 00132 while (list != NIL_LIST) { 00133 if (!(*is_equal) (first_node (list), key)) { 00134 if (last_one == NIL_LIST) { 00135 last_one = list; 00136 list = list_rest (list); 00137 result = last_one; 00138 set_rest(last_one, NIL_LIST); 00139 } 00140 else { 00141 set_rest(last_one, list); 00142 last_one = list; 00143 list = list_rest (list); 00144 set_rest(last_one, NIL_LIST); 00145 } 00146 } 00147 else { 00148 list = pop (list); 00149 } 00150 } 00151 return (result); 00152 } 00153 00154 LIST delete_d(LIST list, void *key, 00155 TessResultCallback2<int, void*, void*>* is_equal) { 00156 LIST result = NIL_LIST; 00157 LIST last_one = NIL_LIST; 00158 00159 while (list != NIL_LIST) { 00160 if (!(*is_equal).Run (first_node (list), key)) { 00161 if (last_one == NIL_LIST) { 00162 last_one = list; 00163 list = list_rest (list); 00164 result = last_one; 00165 set_rest(last_one, NIL_LIST); 00166 } 00167 else { 00168 set_rest(last_one, list); 00169 last_one = list; 00170 list = list_rest (list); 00171 set_rest(last_one, NIL_LIST); 00172 } 00173 } 00174 else { 00175 list = pop (list); 00176 } 00177 } 00178 return (result); 00179 } 00180 00181 00182 /********************************************************************** 00183 * d e s t r o y 00184 * 00185 * Return the space taken by a list to the heap. 00186 **********************************************************************/ 00187 LIST destroy(LIST list) { 00188 LIST next; 00189 00190 while (list != NIL_LIST) { 00191 next = list_rest (list); 00192 free_cell(list); 00193 list = next; 00194 } 00195 return (NIL_LIST); 00196 } 00197 00198 00199 /********************************************************************** 00200 * d e s t r o y n o d e s 00201 * 00202 * Return the space taken by the LISTs of a list to the heap. 00203 **********************************************************************/ 00204 void destroy_nodes(LIST list, void_dest destructor) { 00205 if (destructor == NULL) 00206 destructor = memfree; 00207 00208 while (list != NIL_LIST) { 00209 (*destructor) (first_node (list)); 00210 list = pop (list); 00211 } 00212 } 00213 00214 00215 /********************************************************************** 00216 * i n s e r t 00217 * 00218 * Create a list element and rearange the pointers so that the first 00219 * element in the list is the second aurgment. 00220 **********************************************************************/ 00221 void insert(LIST list, void *node) { 00222 LIST element; 00223 00224 if (list != NIL_LIST) { 00225 element = push (NIL_LIST, node); 00226 set_rest (element, list_rest (list)); 00227 set_rest(list, element); 00228 node = first_node (list); 00229 list->node = first_node (list_rest (list)); 00230 list->next->node = (LIST) node; 00231 } 00232 } 00233 00234 00235 /********************************************************************** 00236 * i s s a m e n o d e 00237 * 00238 * Compare the list node with the key value return TRUE (non-zero) 00239 * if they are equivalent strings. (Return FALSE if not) 00240 **********************************************************************/ 00241 int is_same_node(void *item1, void *item2) { 00242 return (item1 == item2); 00243 } 00244 00245 00246 /********************************************************************** 00247 * i s s a m e 00248 * 00249 * Compare the list node with the key value return TRUE (non-zero) 00250 * if they are equivalent strings. (Return FALSE if not) 00251 **********************************************************************/ 00252 int is_same(void *item1, void *item2) { 00253 return (!strcmp ((char *) item1, (char *) item2)); 00254 } 00255 00256 00257 /********************************************************************** 00258 * j o i n 00259 * 00260 * Join the two lists together. This function is similar to concat 00261 * except that concat creates a new list. This function returns the 00262 * first list updated. 00263 **********************************************************************/ 00264 LIST join(LIST list1, LIST list2) { 00265 if (list1 == NIL_LIST) 00266 return (list2); 00267 set_rest (last (list1), list2); 00268 return (list1); 00269 } 00270 00271 00272 /********************************************************************** 00273 * l a s t 00274 * 00275 * Return the last list item (this is list type). 00276 **********************************************************************/ 00277 LIST last(LIST var_list) { 00278 while (list_rest (var_list) != NIL_LIST) 00279 var_list = list_rest (var_list); 00280 return (var_list); 00281 } 00282 00283 00284 /********************************************************************** 00285 * n t h c e l l 00286 * 00287 * Return nth list cell in the list. 00288 **********************************************************************/ 00289 void *nth_cell(LIST var_list, int item_num) { 00290 int x = 0; 00291 iterate(var_list) { 00292 if (x++ == item_num) 00293 return (var_list); 00294 } 00295 return (var_list); 00296 } 00297 00298 00299 /********************************************************************** 00300 * p o p 00301 * 00302 * Return the list with the first element removed. Destroy the space 00303 * that it occupied in the list. 00304 **********************************************************************/ 00305 LIST pop(LIST list) { 00306 LIST temp; 00307 00308 temp = list_rest (list); 00309 00310 if (list != NIL_LIST) { 00311 free_cell(list); 00312 } 00313 return (temp); 00314 } 00315 00316 00317 /********************************************************************** 00318 * p u s h 00319 * 00320 * Create a list element. Push the second parameter (the node) onto 00321 * the first parameter (the list). Return the new list to the caller. 00322 **********************************************************************/ 00323 LIST push(LIST list, void *element) { 00324 LIST t; 00325 00326 t = new_cell (); 00327 t->node = (LIST) element; 00328 set_rest(t, list); 00329 return (t); 00330 } 00331 00332 00333 /********************************************************************** 00334 * p u s h l a s t 00335 * 00336 * Create a list element. Add the element onto the end of the list. 00337 **********************************************************************/ 00338 LIST push_last(LIST list, void *item) { 00339 LIST t; 00340 00341 if (list != NIL_LIST) { 00342 t = last (list); 00343 t->next = push (NIL_LIST, item); 00344 return (list); 00345 } 00346 else 00347 return (push (NIL_LIST, item)); 00348 } 00349 00350 00351 /********************************************************************** 00352 * r e v e r s e 00353 * 00354 * Create a new list with the elements reversed. The old list is not 00355 * destroyed. 00356 **********************************************************************/ 00357 LIST reverse(LIST list) { 00358 LIST newlist = NIL_LIST; 00359 00360 iterate (list) copy_first (list, newlist); 00361 return (newlist); 00362 } 00363 00364 00365 /********************************************************************** 00366 * r e v e r s e d 00367 * 00368 * Create a new list with the elements reversed. The old list is 00369 * destroyed. 00370 **********************************************************************/ 00371 LIST reverse_d(LIST list) { 00372 LIST result = reverse (list); 00373 destroy(list); 00374 return (result); 00375 } 00376 00377 00378 /********************************************************************** 00379 * s a d j o i n 00380 * 00381 * Adjoin an element to an assorted list. The original list is 00382 * modified. Returns the modified list. 00383 **********************************************************************/ 00384 LIST s_adjoin(LIST var_list, void *variable, int_compare compare) { 00385 LIST l; 00386 int result; 00387 00388 if (compare == NULL) 00389 compare = (int_compare) strcmp; 00390 00391 l = var_list; 00392 iterate(l) { 00393 result = (*compare) (variable, first_node (l)); 00394 if (result == 0) 00395 return (var_list); 00396 else if (result < 0) { 00397 insert(l, variable); 00398 return (var_list); 00399 } 00400 } 00401 return (push_last (var_list, variable)); 00402 } 00403 00404 00405 /********************************************************************** 00406 * s e a r c h 00407 * 00408 * Search list, return NIL_LIST if not found. Return the list starting from 00409 * the item if found. The compare routine "is_equal" is passed in as 00410 * the third paramter to this routine. If the value NULL is supplied 00411 * for is_equal, the is_key routine will be used. 00412 **********************************************************************/ 00413 LIST search(LIST list, void *key, int_compare is_equal) { 00414 if (is_equal == NULL) 00415 is_equal = is_same; 00416 00417 iterate (list) if ((*is_equal) (first_node (list), key)) 00418 return (list); 00419 return (NIL_LIST); 00420 } 00421 00422 LIST search(LIST list, void *key, TessResultCallback2<int, void*, void*>* is_equal) { 00423 iterate (list) if ((*is_equal).Run(first_node (list), key)) 00424 return (list); 00425 return (NIL_LIST); 00426 }