mirror of
https://git.freebsd.org/src.git
synced 2026-01-11 19:57:22 +00:00
libc: add glibc-compatible tdestroy(3)
The function clears the whole tree. Relnotes: yes Reviewed by: alc, emaste Discussed with: dougm Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D54365
This commit is contained in:
parent
04a664d876
commit
b8c99e7d91
4 changed files with 71 additions and 0 deletions
|
|
@ -77,6 +77,7 @@ void twalk(const posix_tnode *, void (*)(const posix_tnode *, VISIT, int));
|
|||
int hcreate_r(size_t, struct hsearch_data *);
|
||||
void hdestroy_r(struct hsearch_data *);
|
||||
int hsearch_r(ENTRY, ACTION, ENTRY **, struct hsearch_data *);
|
||||
void tdestroy(void *, void (*)(void *));
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ MISRCS+= \
|
|||
strtouq.c \
|
||||
system.c \
|
||||
tdelete.c \
|
||||
tdestroy.c \
|
||||
tfind.c \
|
||||
tsearch.c \
|
||||
twalk.c
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ FBSD_1.8 {
|
|||
FBSD_1.9 {
|
||||
memalignment;
|
||||
recallocarray;
|
||||
tdestroy;
|
||||
};
|
||||
|
||||
FBSDprivate_1.0 {
|
||||
|
|
|
|||
68
lib/libc/stdlib/tdestroy.c
Normal file
68
lib/libc/stdlib/tdestroy.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2025 The FreeBSD Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* This software was developed by Konstantin Belousov <kib@FreeBSD.org>
|
||||
* under sponsorship from the FreeBSD Foundation.
|
||||
*/
|
||||
|
||||
#define _SEARCH_PRIVATE
|
||||
#include <search.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static void
|
||||
nul_node_free(void *node __unused)
|
||||
{
|
||||
}
|
||||
|
||||
/* Find the leftmost node. */
|
||||
static posix_tnode *
|
||||
tdestroy_find_leftmost(posix_tnode *tn)
|
||||
{
|
||||
while (tn->llink != NULL)
|
||||
tn = tn->llink;
|
||||
return (tn);
|
||||
}
|
||||
|
||||
/*
|
||||
* This algorithm for non-recursive non-allocating destruction of the tree
|
||||
* is described in
|
||||
* https://codegolf.stackexchange.com/questions/478/free-a-binary-tree/489#489P
|
||||
* and in https://devblogs.microsoft.com/oldnewthing/20251107-00/?p=111774.
|
||||
*/
|
||||
void
|
||||
tdestroy(void *rootp, void (*node_free)(void *))
|
||||
{
|
||||
posix_tnode *tn, *tn_leftmost, *xtn;
|
||||
|
||||
tn = rootp;
|
||||
if (tn == NULL)
|
||||
return;
|
||||
if (node_free == NULL)
|
||||
node_free = nul_node_free;
|
||||
tn_leftmost = tn;
|
||||
|
||||
while (tn != NULL) {
|
||||
/*
|
||||
* Make the right subtree the left subtree of the
|
||||
* leftmost node, and recalculate the leftmost.
|
||||
*/
|
||||
tn_leftmost = tdestroy_find_leftmost(tn_leftmost);
|
||||
if (tn->rlink != NULL) {
|
||||
tn_leftmost->llink = tn->rlink;
|
||||
tn_leftmost = tn_leftmost->llink;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point, all children of tn have been
|
||||
* arranged to be reachable via tn->left. We can
|
||||
* safely delete the current node and advance to its
|
||||
* left child as the new root.
|
||||
*/
|
||||
xtn = tn->llink;
|
||||
node_free(tn->key);
|
||||
free(tn);
|
||||
tn = xtn;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue