Tesseract  3.02
tesseract-ocr/cutil/oldlist.cpp
Go to the documentation of this file.
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 }