xref: /src/lib/libc/stdlib/tdestroy.c (revision 988555e329d00a47c42e5e849e78c1b8e4ce2e17)
1b8c99e7dSKonstantin Belousov /*
2b8c99e7dSKonstantin Belousov  * Copyright 2025 The FreeBSD Foundation
3b8c99e7dSKonstantin Belousov  *
4b8c99e7dSKonstantin Belousov  * SPDX-License-Identifier: BSD-2-Clause
5b8c99e7dSKonstantin Belousov  *
6b8c99e7dSKonstantin Belousov  * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
7b8c99e7dSKonstantin Belousov  * under sponsorship from the FreeBSD Foundation.
8b8c99e7dSKonstantin Belousov  */
9b8c99e7dSKonstantin Belousov 
10b8c99e7dSKonstantin Belousov #define	_SEARCH_PRIVATE
11b8c99e7dSKonstantin Belousov #include <search.h>
12b8c99e7dSKonstantin Belousov #include <stdlib.h>
13b8c99e7dSKonstantin Belousov 
14b8c99e7dSKonstantin Belousov static void
nul_node_free(void * node __unused)15b8c99e7dSKonstantin Belousov nul_node_free(void *node __unused)
16b8c99e7dSKonstantin Belousov {
17b8c99e7dSKonstantin Belousov }
18b8c99e7dSKonstantin Belousov 
19b8c99e7dSKonstantin Belousov void
tdestroy(void * rootp,void (* node_free)(void *))20b8c99e7dSKonstantin Belousov tdestroy(void *rootp, void (*node_free)(void *))
21b8c99e7dSKonstantin Belousov {
22988555e3SDoug Moore 	posix_tnode *back, *curr, **front;
23b8c99e7dSKonstantin Belousov 
24988555e3SDoug Moore 	if (rootp == NULL)
25b8c99e7dSKonstantin Belousov 		return;
26b8c99e7dSKonstantin Belousov 	if (node_free == NULL)
27b8c99e7dSKonstantin Belousov 		node_free = nul_node_free;
28b8c99e7dSKonstantin Belousov 
29988555e3SDoug Moore 	back = rootp;
30988555e3SDoug Moore 	front = &back;
31988555e3SDoug Moore 
32988555e3SDoug Moore 	for (;;) {
33b8c99e7dSKonstantin Belousov 		/*
34988555e3SDoug Moore 		 * The sequence of nodes from back to just before *front linked
35988555e3SDoug Moore 		 * by llink have been found to have non-NULL rlink.
36988555e3SDoug Moore 		 *
37988555e3SDoug Moore 		 * Extend *front to (*front)->llink, deleting *front from the
38988555e3SDoug Moore 		 * sequence if it has a NULL rlink.
39b8c99e7dSKonstantin Belousov 		 */
40988555e3SDoug Moore 		curr = *front;
41988555e3SDoug Moore 		if (curr->rlink != NULL)
42988555e3SDoug Moore 			front = &curr->llink;
43988555e3SDoug Moore 		else {
44988555e3SDoug Moore 			*front = curr->llink;
45988555e3SDoug Moore 			node_free(curr->key);
46988555e3SDoug Moore 			free(curr);
47b8c99e7dSKonstantin Belousov 		}
48988555e3SDoug Moore 		if (*front != NULL)
49988555e3SDoug Moore 			continue;
50988555e3SDoug Moore 		if (back == NULL)
51988555e3SDoug Moore 			break;
52b8c99e7dSKonstantin Belousov 
53b8c99e7dSKonstantin Belousov 		/*
54988555e3SDoug Moore 		 * The sequence cannot be extended because *front is NULL.  Make
55988555e3SDoug Moore 		 * the rlink of the back node the new *front, the llink of the
56988555e3SDoug Moore 		 * back node the new back, and free the old back node.
57b8c99e7dSKonstantin Belousov 		 */
58988555e3SDoug Moore 		curr = back;
59988555e3SDoug Moore 		back = curr->llink;
60988555e3SDoug Moore 		if (back == NULL)
61988555e3SDoug Moore 			front = &back;
62988555e3SDoug Moore 		*front = curr->rlink;
63988555e3SDoug Moore 		node_free(curr->key);
64988555e3SDoug Moore 		free(curr);
65b8c99e7dSKonstantin Belousov 	}
66b8c99e7dSKonstantin Belousov }
67