comparison mupdf-source/thirdparty/leptonica/src/list.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
27 /*!
28 * \file list.c
29 * <pre>
30 *
31 * Inserting and removing elements
32 *
33 * void listDestroy()
34 * DLLIST *listAddToHead()
35 * l_int32 listAddToTail()
36 * l_int32 listInsertBefore()
37 * l_int32 listInsertAfter()
38 * void *listRemoveElement()
39 * void *listRemoveFromHead()
40 * void *listRemoveFromTail()
41 *
42 * Other list operations
43 *
44 * DLLIST *listFindElement()
45 * DLLIST *listFindTail()
46 * l_int32 listGetCount()
47 * l_int32 listReverse()
48 * DLLIST *listJoin()
49 *
50 * Lists are much harder to handle than arrays. There is
51 * more overhead for the programmer, both cognitive and
52 * codewise, and more likelihood that an error can be made.
53 * For that reason, lists should only be used when it is
54 * inefficient to use arrays, such as when elements are
55 * routinely inserted or deleted from inside arrays whose
56 * average size is greater than about 10.
57 *
58 * A list of data structures can be implemented in a number
59 * of ways. The two most popular are:
60 *
61 * (1) The list can be composed of a linked list of
62 * pointer cells ("cons cells"), where the data structures
63 * are hung off the cells. This is more difficult
64 * to use because you have to keep track of both
65 * your hanging data and the cell structures.
66 * It requires 3 pointers for every data structure
67 * that is put in a list. There is no problem
68 * cloning (using reference counts) for structures that
69 * are put in such a list. We implement lists by this
70 * method here.
71 *
72 * (2) The list pointers can be inserted directly into
73 * the data structures. This is easy to implement
74 * and easier to use, but it adds 2 ptrs of overhead
75 * to every data structure in which the ptrs are embedded.
76 * It also requires special care not to put the ptrs
77 * in any data that is cloned with a reference count;
78 * else your lists will break.
79 *
80 * Writing C code that uses list pointers explicitly to make
81 * and alter lists is difficult and prone to error.
82 * Consequently, a generic list utility that handles lists
83 * of arbitrary objects and doesn't force the programmer to
84 * touch the "next" and "prev" pointers, is quite useful.
85 * Such functions are provided here. However, the usual
86 * situation requires traversing a list and applying some
87 * function to one or more of the list elements. Macros
88 * for traversing the list are, in general, necessary, to
89 * achieve the goal of invisibly handling all "next" and "prev"
90 * pointers in generic lists. We provide macros for
91 * traversing a list in both forward and reverse directions.
92 *
93 * Because of the typing in C, implementation of a general
94 * list utility requires casting. If macros are used, the
95 * casting can be done implicitly; otherwise, using functions,
96 * some of the casts must be explicit. Fortunately, this
97 * can be implemented with void* so the programmer using
98 * the library will not have to make any casts! (Unless you
99 * compile with g++, in which case the rules on implicit
100 * conversion are more strict.)
101 *
102 * For example, to add an arbitrary data structure foo to the
103 * tail of a list, use
104 * listAddToTail(&head, &tail, pfoo);
105 * where head and tail are list cell ptrs and pfoo is
106 * a pointer to the foo object.
107 * And to remove an arbitrary data structure foo from a
108 * list, when you know the list cell element it is hanging from,
109 * use
110 * pfoo = listRemoveElement(&head, elem)
111 * where head and elem are list cell ptrs and pfoo is a pointer
112 * to the foo object. No casts are required for foo in
113 * either direction in ANSI C. (However, casts are
114 * required for ANSI C++).
115 *
116 * We use lists that are composed of doubly-linked
117 * cells with data structures hanging off the cells.
118 * We use doubly-linked cells to simplify insertion
119 * and deletion, and to allow operations to proceed in either
120 * direction along the list. With doubly-linked lists,
121 * it is tempting to make them circular, by setting head->prev
122 * to the tail of the list and tail->next to the head.
123 * The circular list costs nothing extra in storage, and
124 * allows operations to proceed from either end of the list
125 * with equal speed. However, the circular link adds
126 * cognitive overhead for the application programmer in
127 * general, and it greatly complicates list traversal when
128 * arbitrary list elements can be added or removed as you
129 * move through. It can be done, but in the spirit of
130 * simplicity, we avoid the temptation. The price to be paid
131 * is the extra cost to find the tail of a list -- a full
132 * traversal -- before the tail can be used. This is a
133 * cheap price to pay to avoid major headaches and buggy code.
134 *
135 * When you are only applying some function to each element
136 * in a list, you can go either forwards or backwards.
137 * To run through a list forwards, use:
138 * \code
139 * for (elem = head; elem; elem = nextelem) {
140 * nextelem = elem->next; (in case we destroy elem)
141 * <do something with elem->data>
142 * }
143 * \endcode
144 * To run through a list backwards, find the tail and use:
145 *
146 * for (elem = tail; elem; elem = prevelem) {
147 # prevelem = elem->prev; (in case we destroy elem)
148 * <do something with elem->data>
149 * }
150 *
151 * Even though these patterns are very simple, they are so common
152 * that we've provided macros for them in list.h. Using the
153 * macros, this becomes:
154 * \code
155 * L_BEGIN_LIST_FORWARD(head, elem)
156 * <do something with elem->data>
157 * L_END_LIST
158 *
159 * L_BEGIN_LIST_REVERSE(tail, elem)
160 * <do something with elem->data>
161 * L_END_LIST
162 * \endcode
163 * Note again that with macros, the application programmer does
164 * not need to refer explicitly to next and prev fields. Also,
165 * in the reverse case, note that we do not explicitly
166 * show the head of the list. However, the head of the list
167 * is always in scope, and functions can be called within the
168 * iterator that change the head.
169 *
170 * Some special cases are simpler. For example, when
171 * removing all items from the head of the list, you can use
172 * \code
173 * while (head) {
174 * obj = listRemoveFromHead(&head);
175 * <do something with obj>
176 * }
177 * \endcode
178 * Removing successive elements from the tail is equally simple:
179 * \code
180 * while (tail) {
181 * obj = listRemoveFromTail(&head, &tail);
182 * <do something with obj>
183 * }
184 * \endcode
185 * When removing an arbitrary element from a list, use
186 * \code
187 * obj = listRemoveElement(&head, elem);
188 * \endcode
189 * All the listRemove*() functions hand you the object,
190 * destroy the list cell to which it was attached, and
191 * reset the list pointers if necessary.
192 *
193 * Several other list operations, that do not involve
194 * inserting or removing objects, are also provided.
195 * The function listFindElement() locates a list pointer
196 * by matching the object hanging on it to a given
197 * object. The function listFindTail() gets a handle
198 * to the tail list ptr, allowing backwards traversals of
199 * the list. listGetCount() gives the number of elements
200 * in a list. Functions that reverse a list and concatenate
201 * two lists are also provided.
202 *
203 * These functions can be modified for efficiency in the
204 * situation where there is a large amount of creation and
205 * destruction of list cells. If millions of cells are
206 * made and destroyed, but a relatively small number are
207 * around at any time, the list cells can be stored for
208 * later re-use in a stack (see the generic stack functions
209 * in stack.c).
210 * </pre>
211 */
212
213 #ifdef HAVE_CONFIG_H
214 #include <config_auto.h>
215 #endif /* HAVE_CONFIG_H */
216
217 #include <string.h>
218 #include "allheaders.h"
219
220 /*---------------------------------------------------------------------*
221 * Inserting and removing elements *
222 *---------------------------------------------------------------------*/
223 /*!
224 * \brief listDestroy()
225 *
226 * \param[in,out] phead head of list; will be set to null before returning
227 * \return void
228 *
229 * <pre>
230 * Notes:
231 * (1) This only destroys the cons cells. Before destroying
232 * the list, it is necessary to remove all data and set the
233 * data pointers in each cons cell to NULL.
234 * (2) listDestroy() will give a warning message for each data
235 * ptr that is not NULL.
236 * </pre>
237 */
238 void
239 listDestroy(DLLIST **phead)
240 {
241 DLLIST *elem, *next, *head;
242
243 if (phead == NULL) {
244 L_WARNING("ptr address is null!\n", __func__);
245 return;
246 }
247
248 if ((head = *phead) == NULL)
249 return;
250
251 for (elem = head; elem; elem = next) {
252 if (elem->data)
253 L_WARNING("list data ptr is not null\n", __func__);
254 next = elem->next;
255 LEPT_FREE(elem);
256 }
257 *phead = NULL;
258 }
259
260
261 /*!
262 * \brief listAddToHead()
263 *
264 * \param[in,out] phead [optional] input head
265 * \param[in] data void* ptr, to be added
266 * \return 0 if OK; 1 on error
267 *
268 * <pre>
269 * Notes:
270 * (1) This makes a new cell, attaches %data, and adds the
271 * cell to the head of the list.
272 * (2) When consing from NULL, be sure to initialize head to NULL
273 * before calling this function.
274 * </pre>
275 */
276 l_ok
277 listAddToHead(DLLIST **phead,
278 void *data)
279 {
280 DLLIST *cell, *head;
281
282 if (!phead)
283 return ERROR_INT("&head not defined", __func__, 1);
284 head = *phead;
285 if (!data)
286 return ERROR_INT("data not defined", __func__, 1);
287
288 cell = (DLLIST *)LEPT_CALLOC(1, sizeof(DLLIST));
289 cell->data = data;
290 if (!head) { /* start the list; initialize the ptrs */
291 cell->prev = NULL;
292 cell->next = NULL;
293 } else {
294 cell->prev = NULL;
295 cell->next = head;
296 head->prev = cell;
297 }
298 *phead = cell;
299 return 0;
300 }
301
302
303 /*!
304 * \brief listAddToTail()
305 *
306 * \param[in,out] phead [may be updated], can be NULL
307 * \param[in,out] ptail [updated], can be NULL
308 * \param[in] data void* ptr, to be hung on tail cons cell
309 * \return 0 if OK; 1 on error
310 *
311 * <pre>
312 * Notes:
313 * (1) This makes a new cell, attaches %data, and adds the
314 * cell to the tail of the list.
315 * (2) &head is input to allow the list to be "cons'd" up from NULL.
316 * (3) &tail is input to allow the tail to be updated
317 * for efficient sequential operation with this function.
318 * (4) We assume that if *phead and/or *ptail are not NULL,
319 * then they are valid addresses. Therefore:
320 * (a) when consing from NULL, be sure to initialize both
321 * head and tail to NULL.
322 * (b) when tail == NULL for an existing list, the tail
323 * will be found and updated.
324 * </pre>
325 */
326 l_ok
327 listAddToTail(DLLIST **phead,
328 DLLIST **ptail,
329 void *data)
330 {
331 DLLIST *cell, *head, *tail;
332
333 if (!phead)
334 return ERROR_INT("&head not defined", __func__, 1);
335 head = *phead;
336 if (!ptail)
337 return ERROR_INT("&tail not defined", __func__, 1);
338 if (!data)
339 return ERROR_INT("data not defined", __func__, 1);
340
341 cell = (DLLIST *)LEPT_CALLOC(1, sizeof(DLLIST));
342 cell->data = data;
343 if (!head) { /* Start the list and initialize the ptrs. *ptail
344 * should also have been initialized to NULL */
345 cell->prev = NULL;
346 cell->next = NULL;
347 *phead = cell;
348 *ptail = cell;
349 } else {
350 if ((tail = *ptail) == NULL)
351 tail = listFindTail(head);
352 cell->prev = tail;
353 cell->next = NULL;
354 tail->next = cell;
355 *ptail = cell;
356 }
357
358 return 0;
359 }
360
361
362 /*!
363 * \brief listInsertBefore()
364 *
365 * \param[in,out] phead [optional] input head
366 * \param[in] elem list element to be inserted in front of;
367 * must be NULL if head is NULL
368 * \param[in] data void* address, to be added
369 * \return 0 if OK; 1 on error
370 *
371 * <pre>
372 * Notes:
373 * (1) This can be called on a null list, in which case both
374 * head and elem must be null.
375 * (2) If you are searching through a list, looking for a condition
376 * to add an element, you can do something like this:
377 * \code
378 * L_BEGIN_LIST_FORWARD(head, elem)
379 * <identify an elem to insert before>
380 * listInsertBefore(&head, elem, data);
381 * L_END_LIST
382 * \endcode
383 * </pre>
384 */
385 l_ok
386 listInsertBefore(DLLIST **phead,
387 DLLIST *elem,
388 void *data)
389 {
390 DLLIST *cell, *head;
391
392 if (!phead)
393 return ERROR_INT("&head not defined", __func__, 1);
394 head = *phead;
395 if (!data)
396 return ERROR_INT("data not defined", __func__, 1);
397 if ((!head && elem) || (head && !elem))
398 return ERROR_INT("head and elem not consistent", __func__, 1);
399
400 /* New cell to insert */
401 cell = (DLLIST *)LEPT_CALLOC(1, sizeof(DLLIST));
402 cell->data = data;
403 if (!head) { /* start the list; initialize the ptrs */
404 cell->prev = NULL;
405 cell->next = NULL;
406 *phead = cell;
407 } else if (head == elem) { /* insert before head of list */
408 cell->prev = NULL;
409 cell->next = head;
410 head->prev = cell;
411 *phead = cell;
412 } else { /* insert before elem and after head of list */
413 cell->prev = elem->prev;
414 cell->next = elem;
415 elem->prev->next = cell;
416 elem->prev = cell;
417 }
418 return 0;
419 }
420
421
422 /*!
423 * \brief listInsertAfter()
424 *
425 * \param[in,out] phead [optional] input head
426 * \param[in] elem list element to be inserted after;
427 * must be NULL if head is NULL
428 * \param[in] data void* ptr, to be added
429 * \return 0 if OK; 1 on error
430 *
431 * <pre>
432 * Notes:
433 * (1) This can be called on a null list, in which case both
434 * head and elem must be null. The head is included
435 * in the call to allow "consing" up from NULL.
436 * (2) If you are searching through a list, looking for a condition
437 * to add an element, you can do something like this:
438 * \code
439 * L_BEGIN_LIST_FORWARD(head, elem)
440 * <identify an elem to insert after>
441 * listInsertAfter(&head, elem, data);
442 * L_END_LIST
443 * \endcode
444 * </pre>
445 */
446 l_ok
447 listInsertAfter(DLLIST **phead,
448 DLLIST *elem,
449 void *data)
450 {
451 DLLIST *cell, *head;
452
453 if (!phead)
454 return ERROR_INT("&head not defined", __func__, 1);
455 head = *phead;
456 if (!data)
457 return ERROR_INT("data not defined", __func__, 1);
458 if ((!head && elem) || (head && !elem))
459 return ERROR_INT("head and elem not consistent", __func__, 1);
460
461 /* New cell to insert */
462 cell = (DLLIST *)LEPT_CALLOC(1, sizeof(DLLIST));
463 cell->data = data;
464 if (!head) { /* start the list; initialize the ptrs */
465 cell->prev = NULL;
466 cell->next = NULL;
467 *phead = cell;
468 } else if (elem->next == NULL) { /* insert after last */
469 cell->prev = elem;
470 cell->next = NULL;
471 elem->next = cell;
472 } else { /* insert after elem and before the end */
473 cell->prev = elem;
474 cell->next = elem->next;
475 elem->next->prev = cell;
476 elem->next = cell;
477 }
478 return 0;
479 }
480
481
482 /*!
483 * \brief listRemoveElement()
484 *
485 * \param[in,out] phead input head; can be changed
486 * \param[in] elem list element to be removed
487 * \return data void* struct on cell
488 *
489 * <pre>
490 * Notes:
491 * (1) in ANSI C, it is not necessary to cast return to actual type; e.g.,
492 * pix = listRemoveElement(&head, elem);
493 * but in ANSI C++, it is necessary to do the cast:
494 * pix = (Pix *)listRemoveElement(&head, elem);
495 * </pre>
496 */
497 void *
498 listRemoveElement(DLLIST **phead,
499 DLLIST *elem)
500 {
501 void *data;
502 DLLIST *head;
503
504 if (!phead)
505 return (void *)ERROR_PTR("&head not defined", __func__, NULL);
506 head = *phead;
507 if (!head)
508 return (void *)ERROR_PTR("head not defined", __func__, NULL);
509 if (!elem)
510 return (void *)ERROR_PTR("elem not defined", __func__, NULL);
511
512 data = elem->data;
513
514 if (head->next == NULL) { /* only one */
515 if (elem != head)
516 return (void *)ERROR_PTR("elem must be head", __func__, NULL);
517 *phead = NULL;
518 } else if (head == elem) { /* first one */
519 elem->next->prev = NULL;
520 *phead = elem->next;
521 } else if (elem->next == NULL) { /* last one */
522 elem->prev->next = NULL;
523 } else { /* neither the first nor the last one */
524 elem->next->prev = elem->prev;
525 elem->prev->next = elem->next;
526 }
527
528 LEPT_FREE(elem);
529 return data;
530 }
531
532
533 /*!
534 * \brief listRemoveFromHead()
535 *
536 * \param[in,out] phead head of list; updated
537 * \return data void* struct on cell, or NULL on error
538 *
539 * <pre>
540 * Notes:
541 * (1) in ANSI C, it is not necessary to cast return to actual type; e.g.,
542 * pix = listRemoveFromHead(&head);
543 * but in ANSI C++, it is necessary to do the cast; e.g.,
544 * pix = (Pix *)listRemoveFromHead(&head);
545 * </pre>
546 */
547 void *
548 listRemoveFromHead(DLLIST **phead)
549 {
550 DLLIST *head;
551 void *data;
552
553 if (!phead)
554 return (void *)ERROR_PTR("&head not defined", __func__, NULL);
555 if ((head = *phead) == NULL)
556 return (void *)ERROR_PTR("head not defined", __func__, NULL);
557
558 if (head->next == NULL) { /* only one */
559 *phead = NULL;
560 } else {
561 head->next->prev = NULL;
562 *phead = head->next;
563 }
564
565 data = head->data;
566 LEPT_FREE(head);
567 return data;
568 }
569
570
571 /*!
572 * \brief listRemoveFromTail()
573 *
574 * \param[in,out] phead list head must NOT be NULL; may be changed
575 * \param[in,out] ptail list tail may be NULL; always updated
576 * \return data void* struct on cell or NULL on error
577 *
578 * <pre>
579 * Notes:
580 * (1) We include &head so that it can be set to NULL if
581 * if the only element in the list is removed.
582 * (2) The function is relying on the fact that if tail is
583 * not NULL, then is is a valid address. You can use
584 * this function with tail == NULL for an existing list, in
585 * which case the tail is found and updated, and the
586 * removed element is returned.
587 * (3) In ANSI C, it is not necessary to cast return to actual type; e.g.,
588 * pix = listRemoveFromTail(&head, &tail);
589 * but in ANSI C++, it is necessary to do the cast; e.g.,
590 * pix = (Pix *)listRemoveFromTail(&head, &tail);
591 * </pre>
592 */
593 void *
594 listRemoveFromTail(DLLIST **phead,
595 DLLIST **ptail)
596 {
597 DLLIST *head, *tail;
598 void *data;
599
600 if (!phead)
601 return (void *)ERROR_PTR("&head not defined", __func__, NULL);
602 if ((head = *phead) == NULL)
603 return (void *)ERROR_PTR("head not defined", __func__, NULL);
604 if (!ptail)
605 return (void *)ERROR_PTR("&tail not defined", __func__, NULL);
606 if ((tail = *ptail) == NULL)
607 tail = listFindTail(head);
608
609 if (head->next == NULL) { /* only one */
610 *phead = NULL;
611 *ptail = NULL;
612 } else {
613 tail->prev->next = NULL;
614 *ptail = tail->prev;
615 }
616
617 data = tail->data;
618 LEPT_FREE(tail);
619 return data;
620 }
621
622
623
624 /*---------------------------------------------------------------------*
625 * Other list operations *
626 *---------------------------------------------------------------------*/
627 /*!
628 * \brief listFindElement()
629 *
630 * \param[in] head list head
631 * \param[in] data void* address, to be searched for
632 * \return cell the containing cell, or NULL if not found or on error
633 *
634 * <pre>
635 * Notes:
636 * (1) This returns a ptr to the cell, which is still embedded in
637 * the list.
638 * (2) This handle and the attached data have not been copied or
639 * reference counted, so they must not be destroyed. This
640 * violates our basic rule that every handle returned from a
641 * function is owned by that function and must be destroyed,
642 * but if rules aren't there to be broken, why have them?
643 * </pre>
644 */
645 DLLIST *
646 listFindElement(DLLIST *head,
647 void *data)
648 {
649 DLLIST *cell;
650
651 if (!head)
652 return (DLLIST *)ERROR_PTR("head not defined", __func__, NULL);
653 if (!data)
654 return (DLLIST *)ERROR_PTR("data not defined", __func__, NULL);
655
656 for (cell = head; cell; cell = cell->next) {
657 if (cell->data == data)
658 return cell;
659 }
660
661 return NULL;
662 }
663
664
665 /*!
666 * \brief listFindTail()
667 *
668 * \param[in] head
669 * \return tail, or NULL on error
670 */
671 DLLIST *
672 listFindTail(DLLIST *head)
673 {
674 DLLIST *cell;
675
676 if (!head)
677 return (DLLIST *)ERROR_PTR("head not defined", __func__, NULL);
678
679 for (cell = head; cell; cell = cell->next) {
680 if (cell->next == NULL)
681 return cell;
682 }
683
684 return (DLLIST *)ERROR_PTR("tail not found !!", __func__, NULL);
685 }
686
687
688 /*!
689 * \brief listGetCount()
690 *
691 * \param[in] head of list
692 * \return number of elements; 0 if no list or on error
693 */
694 l_int32
695 listGetCount(DLLIST *head)
696 {
697 l_int32 count;
698 DLLIST *elem;
699
700 if (!head)
701 return ERROR_INT("head not defined", __func__, 0);
702
703 count = 0;
704 for (elem = head; elem; elem = elem->next)
705 count++;
706
707 return count;
708 }
709
710
711 /*!
712 * \brief listReverse()
713 *
714 * \param[in,out] phead list head; may be changed
715 * \return 0 if OK, 1 on error
716 *
717 * <pre>
718 * Notes:
719 * (1) This reverses the list in-place.
720 * </pre>
721 */
722 l_ok
723 listReverse(DLLIST **phead)
724 {
725 void *obj; /* whatever */
726 DLLIST *head, *rhead;
727
728 if (!phead)
729 return ERROR_INT("&head not defined", __func__, 1);
730 if ((head = *phead) == NULL)
731 return ERROR_INT("head not defined", __func__, 1);
732
733 rhead = NULL;
734 while (head) {
735 obj = listRemoveFromHead(&head);
736 listAddToHead(&rhead, obj);
737 }
738
739 *phead = rhead;
740 return 0;
741 }
742
743
744 /*!
745 * \brief listJoin()
746 *
747 * \param[in,out] phead1 head of first list; may be changed
748 * \param[in,out] phead2 head of second list; to be nulled
749 * \return 0 if OK, 1 on error
750 *
751 * <pre>
752 * Notes:
753 * (1) The concatenated list is returned with head1 as the new head.
754 * (2) Both input ptrs must exist, though either can have the value NULL.
755 * </pre>
756 */
757 l_ok
758 listJoin(DLLIST **phead1,
759 DLLIST **phead2)
760 {
761 void *obj;
762 DLLIST *head1, *head2, *tail1;
763
764 if (!phead1)
765 return ERROR_INT("&head1 not defined", __func__, 1);
766 if (!phead2)
767 return ERROR_INT("&head2 not defined", __func__, 1);
768
769 /* If no list2, just return list1 unchanged */
770 if ((head2 = *phead2) == NULL)
771 return 0;
772
773 /* If no list1, just return list2 */
774 if ((head1 = *phead1) == NULL) {
775 *phead1 = head2;
776 *phead2 = NULL;
777 return 0;
778 }
779
780 /* General case for concatenation into list 1 */
781 tail1 = listFindTail(head1);
782 while (head2) {
783 obj = listRemoveFromHead(&head2);
784 listAddToTail(&head1, &tail1, obj);
785 }
786 *phead2 = NULL;
787 return 0;
788 }