Leptonica 1.68
C Image Processing Library
|
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