Leptonica 1.68
C Image Processing Library

list.c

Go to the documentation of this file.
00001 /*====================================================================*
00002  -  Copyright (C) 2001 Leptonica.  All rights reserved.
00003  -  This software is distributed in the hope that it will be
00004  -  useful, but with NO WARRANTY OF ANY KIND.
00005  -  No author or distributor accepts responsibility to anyone for the
00006  -  consequences of using this software, or for whether it serves any
00007  -  particular purpose or works at all, unless he or she says so in
00008  -  writing.  Everyone is granted permission to copy, modify and
00009  -  redistribute this source code, for commercial or non-commercial
00010  -  purposes, with the following restrictions: (1) the origin of this
00011  -  source code must not be misrepresented; (2) modified versions must
00012  -  be plainly marked as such; and (3) this notice may not be removed
00013  -  or altered from any source or modified source distribution.
00014  *====================================================================*/
00015 
00016 /*
00017  *   list.c
00018  *
00019  *      Inserting and removing elements
00020  *
00021  *           void      listDestroy()
00022  *           DLLIST   *listAddToHead()
00023  *           l_int32   listAddToTail()
00024  *           l_int32   listInsertBefore()
00025  *           l_int32   listInsertAfter()
00026  *           void     *listRemoveElement()
00027  *           void     *listRemoveFromHead()
00028  *           void     *listRemoveFromTail()
00029  *
00030  *      Other list operations
00031  *
00032  *           DLLIST   *listFindElement()
00033  *           DLLIST   *listFindTail()
00034  *           l_int32   listGetCount()
00035  *           l_int32   listReverse()
00036  *           DLLIST   *listJoin()
00037  *
00038  *      Lists are much harder to handle than arrays.  There is
00039  *      more overhead for the programmer, both cognitive and
00040  *      codewise, and more likelihood that an error can be made.
00041  *      For that reason, lists should only be used when it is
00042  *      inefficient to use arrays, such as when elements are
00043  *      routinely inserted or deleted from inside arrays whose
00044  *      average size is greater than about 10.
00045  *
00046  *      A list of data structures can be implemented in a number
00047  *      of ways.  The two most popular are:
00048  *
00049  *         (1) The list can be composed of a linked list of
00050  *             pointer cells ("cons cells"), where the data structures
00051  *             are hung off the cells.  This is more difficult
00052  *             to use because you have to keep track of both
00053  *             your hanging data and the cell structures.
00054  *             It requires 3 pointers for every data structure
00055  *             that is put in a list.  There is no problem
00056  *             cloning (using reference counts) for structures that
00057  *             are put in such a list.  We implement lists by this
00058  *             method here.
00059  *
00060  *         (2) The list pointers can be inserted directly into
00061  *             the data structures.  This is easy to implement
00062  *             and easier to use, but it adds 2 ptrs of overhead
00063  *             to every data structure in which the ptrs are embedded.
00064  *             It also requires special care not to put the ptrs
00065  *             in any data that is cloned with a reference count;
00066  *             else your lists will break.
00067  *
00068  *      Writing C code that uses list pointers explicitly to make
00069  *      and alter lists is difficult and prone to error.
00070  *      Consequently, a generic list utility that handles lists
00071  *      of arbitrary objects and doesn't force the programmer to
00072  *      touch the "next" and "prev" pointers, is quite useful.
00073  *      Such functions are provided here.   However, the usual
00074  *      situation requires traversing a list and applying some
00075  *      function to one or more of the list elements.  Macros
00076  *      for traversing the list are, in general, necessary, to
00077  *      achieve the goal of invisibly handling all "next" and "prev"
00078  *      pointers in generic lists.  We provide macros for
00079  *      traversing a list in both forward and reverse directions.
00080  *
00081  *      Because of the typing in C, implementation of a general
00082  *      list utility requires casting.  If macros are used, the
00083  *      casting can be done implicitly; otherwise, using functions,
00084  *      some of the casts must be explicit.  Fortunately, this
00085  *      can be implemented with void* so the programmer using
00086  *      the library will not have to make any casts!  (Unless you
00087  *      compile with g++, in which case the rules on implicit
00088  *      conversion are more strict.)
00089  *
00090  *      For example, to add an arbitrary data structure foo to the
00091  *      tail of a list, use
00092  *             listAddToTail(&head, &tail, pfoo);
00093  *      where head and tail are list cell ptrs and pfoo is
00094  *      a pointer to the foo object.
00095  *      And to remove an arbitrary data structure foo from a
00096  *      list, when you know the list cell element it is hanging from,
00097  *      use
00098  *             pfoo = listRemoveElement(&head, elem)
00099  *      where head and elem are list cell ptrs and pfoo is a pointer
00100  *      to the foo object.  No casts are required for foo in
00101  *      either direction in ANSI C.  (However, casts are
00102  *      required for ANSI C++).
00103  *      
00104  *      We use lists that are composed of doubly-linked
00105  *      cells with data structures hanging off the cells.
00106  *      We use doubly-linked cells to simplify insertion
00107  *      and deletion, and to allow operations to proceed in either
00108  *      direction along the list.  With doubly-linked lists,
00109  *      it is tempting to make them circular, by setting head->prev
00110  *      to the tail of the list and tail->next to the head.
00111  *      The circular list costs nothing extra in storage, and
00112  *      allows operations to proceed from either end of the list
00113  *      with equal speed.  However, the circular link adds 
00114  *      cognitive overhead for the application programmer in 
00115  *      general, and it greatly complicates list traversal when
00116  *      arbitrary list elements can be added or removed as you
00117  *      move through.  It can be done, but in the spirit of
00118  *      simplicity, we avoid the temptation.  The price to be paid
00119  *      is the extra cost to find the tail of a list -- a full
00120  *      traversal -- before the tail can be used.  This is a
00121  *      cheap price to pay to avoid major headaches and buggy code.
00122  *
00123  *      When you are only applying some function to each element
00124  *      in a list, you can go either forwards or backwards.
00125  *      To run through a list forwards, use:
00126  *
00127  *          for (elem = head; elem; elem = nextelem) {
00128  *              nextelem = elem->next;   (in case we destroy elem)
00129  *              <do something with elem->data>
00130  *          }
00131  *
00132  *      To run through a list backwards, find the tail and use:
00133  *
00134  *          for (elem = tail; elem; elem = prevelem) {
00135  #              prevelem = elem->prev;  (in case we destroy elem)
00136  *              <do something with elem->data>
00137  *          }
00138  *
00139  *      Even though these patterns are very simple, they are so common
00140  *      that we've provided macros for them in list.h.  Using the
00141  *      macros, this becomes:
00142  *
00143  *          L_BEGIN_LIST_FORWARD(head, elem)
00144  *              <do something with elem->data>
00145  *          L_END_LIST
00146  *
00147  *          L_BEGIN_LIST_REVERSE(tail, elem)
00148  *              <do something with elem->data>
00149  *          L_END_LIST
00150  *
00151  *      Note again that with macros, the application programmer does
00152  *      not need to refer explicitly to next and prev fields.  Also,
00153  *      in the reverse case, note that we do not explicitly
00154  *      show the head of the list.  However, the head of the list
00155  *      is always in scope, and functions can be called within the
00156  *      iterator that change the head.
00157  *
00158  *      Some special cases are simpler.  For example, when
00159  *      removing all items from the head of the list, you can use
00160  *
00161  *          while (head) {
00162  *              obj = listRemoveFromHead(&head);
00163  *              <do something with obj>
00164  *          }
00165  *
00166  *      Removing successive elements from the tail is equally simple:
00167  *
00168  *          while (tail) {
00169  *              obj = listRemoveFromTail(&head, &tail);
00170  *              <do something with obj>
00171  *          }
00172  *
00173  *      When removing an arbitrary element from a list, use
00174  *
00175  *              obj = listRemoveElement(&head, elem);
00176  *  
00177  *      All the listRemove*() functions hand you the object,
00178  *      destroy the list cell to which it was attached, and
00179  *      reset the list pointers if necessary.
00180  *
00181  *      Several other list operations, that do not involve
00182  *      inserting or removing objects, are also provided.
00183  *      The function listFindElement() locates a list pointer
00184  *      by matching the object hanging on it to a given
00185  *      object.  The function listFindTail() gets a handle
00186  *      to the tail list ptr, allowing backwards traversals of
00187  *      the list.  listGetCount() gives the number of elements
00188  *      in a list.  Functions that reverse a list and concatenate
00189  *      two lists are also provided.
00190  *
00191  *      These functions can be modified for efficiency in the
00192  *      situation where there is a large amount of creation and
00193  *      destruction of list cells.  If millions of cells are
00194  *      made and destroyed, but a relatively small number are
00195  *      around at any time, the list cells can be stored for
00196  *      later re-use in a stack (see the generic stack functions
00197  *      in stack.c).
00198  */
00199 
00200 #include <stdio.h>
00201 #include <stdlib.h>
00202 #include <string.h>
00203 #include "allheaders.h"
00204 
00205 
00206 /*---------------------------------------------------------------------*
00207  *                    Inserting and removing elements                  *
00208  *---------------------------------------------------------------------*/
00209 /*!
00210  *  listDestroy()
00211  *
00212  *      Input:  &head   (<to be nulled> head of list)
00213  *      Return: void
00214  *
00215  *  Notes:
00216  *      (1) This only destroys the cons cells.  Before destroying
00217  *          the list, it is necessary to remove all data and set the
00218  *          data pointers in each cons cell to NULL.
00219  *      (2) listDestroy() will give a warning message for each data
00220  *          ptr that is not NULL.
00221  */
00222 void
00223 listDestroy(DLLIST  **phead)
00224 {
00225 DLLIST  *elem, *next, *head;
00226 
00227     PROCNAME("listDestroy");
00228 
00229     if (phead == NULL) {
00230         L_WARNING("ptr address is null!", procName);
00231         return;
00232     }
00233 
00234     if ((head = *phead) == NULL)
00235         return;
00236 
00237     for (elem = head; elem; elem = next) {
00238         if (elem->data)
00239             L_WARNING("list data ptr is not null", procName);
00240         next = elem->next;
00241         FREE(elem);
00242     }
00243     *phead = NULL;
00244     return;
00245 }
00246 
00247 
00248 /*!
00249  *  listAddToHead()
00250  *
00251  *      Input:  &head  (<optional> input head)
00252  *              data  (void* ptr, to be added)
00253  *      Return: 0 if OK; 1 on error
00254  *
00255  *  Notes:
00256  *      (1) This makes a new cell, attaches the data, and adds the
00257  *          cell to the head of the list.
00258  *      (2) When consing from NULL, be sure to initialize head to NULL
00259  *          before calling this function.  
00260  */
00261 l_int32
00262 listAddToHead(DLLIST  **phead,
00263               void     *data)
00264 {
00265 DLLIST  *cell, *head;
00266 
00267     PROCNAME("listAddToHead");
00268 
00269     if (!phead)
00270         return ERROR_INT("&head not defined", procName, 1);
00271     head = *phead;
00272     if (!data)
00273         return ERROR_INT("data not defined", procName, 1);
00274 
00275     if ((cell = (DLLIST *)CALLOC(1, sizeof(DLLIST))) == NULL)
00276         return ERROR_INT("cell not made", procName, 1);
00277     cell->data = data;
00278 
00279     if (!head) {  /* start the list; initialize the ptrs */
00280         cell->prev = NULL;
00281         cell->next = NULL;
00282     }
00283     else {
00284         cell->prev = NULL;
00285         cell->next = head;
00286         head->prev = cell;
00287     }
00288     *phead = cell;
00289     return 0;
00290 }
00291 
00292 
00293 /*!
00294  *  listAddToTail()
00295  *
00296  *      Input:  &head  (<may be updated>, head can be null)
00297  *              &tail  (<updated>, tail can be null)
00298  *              data  (void* ptr, to be hung on tail cons cell)
00299  *      Return: 0 if OK; 1 on error
00300  *
00301  *  Notes:
00302  *      (1) This makes a new cell, attaches the data, and adds the
00303  *          cell to the tail of the list.
00304  *      (2) &head is input to allow the list to be "cons'd" up from NULL.
00305  *      (3) &tail is input to allow the tail to be updated
00306  *          for efficient sequential operation with this function.
00307  *      (4) We assume that if *phead and/or *ptail are not NULL,
00308  *          then they are valid addresses.  Therefore:
00309  *           (a) when consing from NULL, be sure to initialize both
00310  *               head and tail to NULL.
00311  *           (b) when tail == NULL for an existing list, the tail
00312  *               will be found and updated.
00313  */
00314 l_int32
00315 listAddToTail(DLLIST  **phead,
00316               DLLIST  **ptail,
00317               void     *data)
00318 {
00319 DLLIST  *cell, *head, *tail;
00320 
00321     PROCNAME("listAddToTail");
00322 
00323     if (!phead)
00324         return ERROR_INT("&head not defined", procName, 1);
00325     head = *phead;
00326     if (!ptail)
00327         return ERROR_INT("&tail not defined", procName, 1);
00328     if (!data)
00329         return ERROR_INT("data not defined", procName, 1);
00330 
00331     if ((cell = (DLLIST *)CALLOC(1, sizeof(DLLIST))) == NULL)
00332         return ERROR_INT("cell not made", procName, 1);
00333     cell->data = data;
00334 
00335     if (!head) {  /*   Start the list and initialize the ptrs.  *ptail
00336                    *   should also have been initialized to NULL */
00337         cell->prev = NULL;
00338         cell->next = NULL;
00339         *phead = cell;
00340         *ptail = cell;
00341     }
00342     else {
00343         if ((tail = *ptail) == NULL) 
00344             tail = listFindTail(head);
00345         cell->prev = tail;
00346         cell->next = NULL;
00347         tail->next = cell;
00348         *ptail = cell;
00349     }
00350 
00351     return 0;
00352 }
00353 
00354 
00355 /*!
00356  *  listInsertBefore()
00357  *
00358  *      Input:  &head  (<optional> input head)
00359  *               elem  (list element to be inserted in front of;
00360  *                      must be null if head is null)
00361  *               data  (void*  address, to be added)
00362  *      Return: 0 if OK; 1 on error
00363  *
00364  *  Notes: 
00365  *      (1) This can be called on a null list, in which case both
00366  *          head and elem must be null.
00367  *      (2) If you are searching through a list, looking for a condition
00368  *          to add an element, you can do something like this:
00369  *            L_BEGIN_LIST_FORWARD(head, elem)
00370  *                <identify an elem to insert before>
00371  *                listInsertBefore(&head, elem, data);
00372  *            L_END_LIST
00373  *                  
00374  */
00375 l_int32
00376 listInsertBefore(DLLIST  **phead,
00377                  DLLIST   *elem,
00378                  void     *data)
00379 {
00380 DLLIST  *cell, *head;
00381 
00382     PROCNAME("listInsertBefore");
00383 
00384     if (!phead)
00385         return ERROR_INT("&head not defined", procName, 1);
00386     head = *phead;
00387     if (!data)
00388         return ERROR_INT("data not defined", procName, 1);
00389     if ((!head && elem) || (head && !elem))
00390         return ERROR_INT("head and elem not consistent", procName, 1);
00391 
00392         /* New cell to insert */
00393     if ((cell = (DLLIST *)CALLOC(1, sizeof(DLLIST))) == NULL)
00394         return ERROR_INT("cell not made", procName, 1);
00395     cell->data = data;
00396 
00397     if (!head) {  /* start the list; initialize the ptrs */
00398         cell->prev = NULL;
00399         cell->next = NULL;
00400         *phead = cell;
00401     }
00402     else if (head == elem) {  /* insert before head of list */
00403         cell->prev = NULL;
00404         cell->next = head;
00405         head->prev = cell;
00406         *phead = cell;
00407     }
00408     else  {   /* insert before elem and after head of list */
00409         cell->prev = elem->prev;
00410         cell->next = elem;
00411         elem->prev->next = cell;
00412         elem->prev = cell;
00413     }
00414     return 0;
00415 }
00416 
00417 
00418 /*!
00419  *  listInsertAfter()
00420  *
00421  *      Input:  &head  (<optional> input head)
00422  *               elem  (list element to be inserted after;
00423  *                      must be null if head is null)
00424  *               data  (void*  ptr, to be added)
00425  *      Return: 0 if OK; 1 on error
00426  *
00427  *  Notes:
00428  *      (1) This can be called on a null list, in which case both
00429  *          head and elem must be null.  The head is included
00430  *          in the call to allow "consing" up from NULL.
00431  *      (2) If you are searching through a list, looking for a condition
00432  *          to add an element, you can do something like this:
00433  *            L_BEGIN_LIST_FORWARD(head, elem)
00434  *                <identify an elem to insert after>
00435  *                listInsertAfter(&head, elem, data);
00436  *            L_END_LIST
00437  */
00438 l_int32
00439 listInsertAfter(DLLIST  **phead,
00440                 DLLIST   *elem,
00441                 void     *data)
00442 {
00443 DLLIST  *cell, *head;
00444 
00445     PROCNAME("listInsertAfter");
00446 
00447     if (!phead)
00448         return ERROR_INT("&head not defined", procName, 1);
00449     head = *phead;
00450     if (!data)
00451         return ERROR_INT("data not defined", procName, 1);
00452     if ((!head && elem) || (head && !elem))
00453         return ERROR_INT("head and elem not consistent", procName, 1);
00454 
00455         /* New cell to insert */
00456     if ((cell = (DLLIST *)CALLOC(1, sizeof(DLLIST))) == NULL)
00457         return ERROR_INT("cell not made", procName, 1);
00458     cell->data = data;
00459 
00460     if (!head) {  /* start the list; initialize the ptrs */
00461         cell->prev = NULL;
00462         cell->next = NULL;
00463         *phead = cell;
00464     }
00465     else if (elem->next == NULL) {  /* insert after last */
00466         cell->prev = elem;
00467         cell->next = NULL;
00468         elem->next = cell;
00469     }
00470     else  {  /* insert after elem and before the end */
00471         cell->prev = elem;
00472         cell->next = elem->next;
00473         elem->next->prev = cell;
00474         elem->next = cell;
00475     }
00476     return 0;
00477 }
00478 
00479 
00480 /*!
00481  *  listRemoveElement()
00482  *
00483  *      Input:  &head (<can be changed> input head)
00484  *              elem (list element to be removed)
00485  *      Return: data  (void* struct on cell)
00486  *
00487  *  Notes:
00488  *      (1) in ANSI C, it is not necessary to cast return to actual type; e.g.,
00489  *             pix = listRemoveElement(&head, elem);
00490  *          but in ANSI C++, it is necessary to do the cast:
00491  *             pix = (Pix *)listRemoveElement(&head, elem);
00492  */
00493 void *
00494 listRemoveElement(DLLIST  **phead,
00495                   DLLIST   *elem)
00496 {
00497 void    *data;
00498 DLLIST  *head;
00499 
00500     PROCNAME("listRemoveElement");
00501 
00502     if (!phead)
00503         return (void *)ERROR_PTR("&head not defined", procName, NULL);
00504     head = *phead;
00505     if (!head)
00506         return (void *)ERROR_PTR("head not defined", procName, NULL);
00507     if (!elem)
00508         return (void *)ERROR_PTR("elem not defined", procName, NULL);
00509 
00510     data = elem->data;
00511 
00512     if (head->next == NULL) {  /* only one */
00513         if (elem != head)
00514             return (void *)ERROR_PTR("elem must be head", procName, NULL);
00515         *phead = NULL;
00516     }
00517     else if (head == elem) {   /* first one */
00518         elem->next->prev = NULL;
00519         *phead = elem->next;
00520     }
00521     else if (elem->next == NULL) {   /* last one */
00522         elem->prev->next = NULL;
00523     }
00524     else {  /* neither the first nor the last one */
00525         elem->next->prev = elem->prev;
00526         elem->prev->next = elem->next;
00527     }
00528 
00529     FREE(elem);
00530     return data;
00531 }
00532 
00533 
00534 /*!
00535  *  listRemoveFromHead()
00536  *
00537  *      Input:  &head (<to be updated> head of list)
00538  *      Return: data  (void* struct on cell), or null on error
00539  *
00540  *  Notes:
00541  *      (1) in ANSI C, it is not necessary to cast return to actual type; e.g.,
00542  *            pix = listRemoveFromHead(&head);
00543  *          but in ANSI C++, it is necessary to do the cast; e.g.,
00544  *            pix = (Pix *)listRemoveFromHead(&head);
00545  */
00546 void *
00547 listRemoveFromHead(DLLIST  **phead)
00548 {
00549 DLLIST  *head;
00550 void    *data;
00551 
00552     PROCNAME("listRemoveFromHead");
00553 
00554     if (!phead)
00555         return (void *)ERROR_PTR("&head not defined", procName, NULL);
00556     if ((head = *phead) == NULL)
00557         return (void *)ERROR_PTR("head not defined", procName, NULL);
00558 
00559     if (head->next == NULL)  /* only one */
00560         *phead = NULL;
00561     else {
00562         head->next->prev = NULL;
00563         *phead = head->next;
00564     }
00565 
00566     data = head->data;
00567     FREE(head);
00568     return data;
00569 }
00570 
00571 
00572 /*!
00573  *  listRemoveFromTail()
00574  *
00575  *      Input:  &head (<may be changed>, head must NOT be null)
00576  *              &tail (<always updated>, tail may be null)
00577  *      Return: data  (void* struct on cell) or null on error
00578  *
00579  *  Notes:
00580  *      (1) We include &head so that it can be set to NULL if 
00581  *          if the only element in the list is removed.
00582  *      (2) The function is relying on the fact that if tail is
00583  *          not NULL, then is is a valid address.  You can use
00584  *          this function with tail == NULL for an existing list, in
00585  *          which case  the tail is found and updated, and the
00586  *          removed element is returned.
00587  *      (3) In ANSI C, it is not necessary to cast return to actual type; e.g.,
00588  *            pix = listRemoveFromTail(&head, &tail);
00589  *          but in ANSI C++, it is necessary to do the cast; e.g.,
00590  *            pix = (Pix *)listRemoveFromTail(&head, &tail);
00591  */
00592 void *
00593 listRemoveFromTail(DLLIST  **phead,
00594                    DLLIST  **ptail)
00595 {
00596 DLLIST  *head, *tail;
00597 void    *data;
00598 
00599     PROCNAME("listRemoveFromTail");
00600 
00601     if (!phead)
00602         return (void *)ERROR_PTR("&head not defined", procName, NULL);
00603     if ((head = *phead) == NULL)
00604         return (void *)ERROR_PTR("head not defined", procName, NULL);
00605     if (!ptail)
00606         return (void *)ERROR_PTR("&tail not defined", procName, NULL);
00607     if ((tail = *ptail) == NULL)
00608         tail = listFindTail(head);
00609 
00610     if (head->next == NULL) { /* only one */
00611         *phead = NULL;
00612         *ptail = NULL;
00613     }
00614     else {
00615         tail->prev->next = NULL;
00616         *ptail = tail->prev;
00617     }
00618 
00619     data = tail->data;
00620     FREE(tail);
00621     return data;
00622 }
00623 
00624 
00625 
00626 /*---------------------------------------------------------------------*
00627  *                         Other list operations                       *
00628  *---------------------------------------------------------------------*/
00629 /*!
00630  *  listFindElement()
00631  *
00632  *      Input:  head  (list head)
00633  *              data  (void*  address, to be searched for)
00634  *      Return: cell  (the containing cell, or null if not found or on error)
00635  *
00636  *  Notes:
00637  *      (1) This returns a ptr to the cell, which is still embedded in
00638  *          the list.
00639  *      (2) This handle and the attached data have not been copied or
00640  *          reference counted, so they must not be destroyed.  This
00641  *          violates our basic rule that every handle returned from a
00642  *          function is owned by that function and must be destroyed,
00643  *          but if rules aren't there to be broken, why have them?
00644  */
00645 DLLIST *
00646 listFindElement(DLLIST  *head,
00647                 void    *data)
00648 {
00649 DLLIST  *cell;
00650 
00651     PROCNAME("listFindElement");
00652 
00653     if (!head)
00654         return (DLLIST *)ERROR_PTR("head not defined", procName, NULL);
00655     if (!data)
00656         return (DLLIST *)ERROR_PTR("data not defined", procName, NULL);
00657 
00658     for (cell = head; cell; cell = cell->next) {
00659         if (cell->data == data)
00660             return cell;
00661     }
00662 
00663     return NULL;
00664 }
00665 
00666 
00667 /*!
00668  *  listFindTail()
00669  *
00670  *      Input:  head
00671  *      Return: tail, or null on error
00672  */
00673 DLLIST *
00674 listFindTail(DLLIST  *head)
00675 {
00676 DLLIST  *cell;
00677 
00678     PROCNAME("listFindTail");
00679 
00680     if (!head)
00681         return (DLLIST *)ERROR_PTR("head not defined", procName, NULL);
00682 
00683     for (cell = head; cell; cell = cell->next) {
00684         if (cell->next == NULL)
00685             return cell;
00686     }
00687 
00688     return (DLLIST *)ERROR_PTR("tail not found !!", procName, NULL);
00689 }
00690 
00691 
00692 /*!
00693  *  listGetCount()
00694  *
00695  *      Input:  head  (of list)
00696  *      Return: number of elements; 0 if no list or on error
00697  */
00698 l_int32
00699 listGetCount(DLLIST  *head)
00700 {
00701 l_int32  count;
00702 DLLIST  *elem;
00703 
00704     PROCNAME("listGetCount");
00705 
00706     if (!head)
00707         return ERROR_INT("head not defined", procName, 0);
00708 
00709     count = 0;
00710     for (elem = head; elem; elem = elem->next)
00711         count++;
00712     
00713     return count;
00714 }
00715 
00716 
00717 /*!
00718  *  listReverse()
00719  *
00720  *      Input:  &head  (<may be changed> list head)
00721  *      Return: 0 if OK, 1 on error
00722  *
00723  *  Notes:
00724  *      (1) This reverses the list in-place.
00725  */
00726 l_int32
00727 listReverse(DLLIST  **phead)
00728 {
00729 void    *obj;  /* whatever */
00730 DLLIST  *head, *rhead;
00731 
00732     PROCNAME("listReverse");
00733 
00734     if (!phead)
00735         return ERROR_INT("&head not defined", procName, 1);
00736     if ((head = *phead) == NULL)
00737         return ERROR_INT("head not defined", procName, 1);
00738 
00739     rhead = NULL;
00740     while (head) {
00741         obj = listRemoveFromHead(&head);
00742         listAddToHead(&rhead, obj);
00743     }
00744 
00745     *phead = rhead;
00746     return 0;
00747 }
00748 
00749 
00750 /*!
00751  *  listJoin()
00752  *
00753  *      Input:  &head1  (<may be changed> head of first list)
00754  *              &head2  (<to be nulled> head of second list)
00755  *      Return: 0 if OK, 1 on error
00756  *
00757  *  Notes:
00758  *      (1) The concatenated list is returned with head1 as the new head.
00759  *      (2) Both input ptrs must exist, though either can have the value NULL.
00760  */
00761 l_int32
00762 listJoin(DLLIST  **phead1,
00763          DLLIST  **phead2)
00764 {
00765 void    *obj;
00766 DLLIST  *head1, *head2, *tail1;
00767 
00768     PROCNAME("listJoin");
00769 
00770     if (!phead1)
00771         return ERROR_INT("&head1 not defined", procName, 1);
00772     if (!phead2)
00773         return ERROR_INT("&head2 not defined", procName, 1);
00774 
00775         /* If no list2, just return list1 unchanged */
00776     if ((head2 = *phead2) == NULL)
00777         return 0;
00778 
00779         /* If no list1, just return list2 */
00780     if ((head1 = *phead1) == NULL) {
00781         *phead1 = head2;
00782         *phead2 = NULL;
00783         return 0;
00784     }
00785 
00786         /* General case for concatenation into list 1 */
00787     tail1 = listFindTail(head1);
00788     while (head2) {
00789         obj = listRemoveFromHead(&head2);
00790         listAddToTail(&head1, &tail1, obj);
00791     }
00792     *phead2 = NULL;
00793     return 0;
00794 }
00795 
00796 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines