xref: /minix3/crypto/external/bsd/heimdal/dist/lib/roken/tsearch.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: tsearch.c,v 1.1.1.2 2014/04/24 12:45:52 pettai Exp $	*/
2ebfedea0SLionel Sambuc 
3ebfedea0SLionel Sambuc /*
4ebfedea0SLionel Sambuc  * Tree search generalized from Knuth (6.2.2) Algorithm T just like
5ebfedea0SLionel Sambuc  * the AT&T man page says.
6ebfedea0SLionel Sambuc  *
7ebfedea0SLionel Sambuc  * The node_t structure is for internal use only, lint doesn't grok it.
8ebfedea0SLionel Sambuc  *
9ebfedea0SLionel Sambuc  * Written by reading the System V Interface Definition, not the code.
10ebfedea0SLionel Sambuc  *
11ebfedea0SLionel Sambuc  * Totally public domain.
12ebfedea0SLionel Sambuc  *
13ebfedea0SLionel Sambuc  * NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp
14ebfedea0SLionel Sambuc  * NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp
15ebfedea0SLionel Sambuc  * NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp
16ebfedea0SLionel Sambuc  * NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp
17ebfedea0SLionel Sambuc  */
18ebfedea0SLionel Sambuc 
19ebfedea0SLionel Sambuc #include <config.h>
20ebfedea0SLionel Sambuc #include <krb5/roken.h>
21ebfedea0SLionel Sambuc #include "search.h"
22ebfedea0SLionel Sambuc #include <stdlib.h>
23ebfedea0SLionel Sambuc 
24ebfedea0SLionel Sambuc typedef struct node {
25ebfedea0SLionel Sambuc   char         *key;
26ebfedea0SLionel Sambuc   struct node  *llink, *rlink;
27ebfedea0SLionel Sambuc } node_t;
28ebfedea0SLionel Sambuc 
29ebfedea0SLionel Sambuc #ifndef __DECONST
30ebfedea0SLionel Sambuc #define __DECONST(type, var)    ((type)(uintptr_t)(const void *)(var))
31ebfedea0SLionel Sambuc #endif
32ebfedea0SLionel Sambuc 
33ebfedea0SLionel Sambuc /*
34ebfedea0SLionel Sambuc  * find or insert datum into search tree
35ebfedea0SLionel Sambuc  *
36ebfedea0SLionel Sambuc  * Parameters:
37ebfedea0SLionel Sambuc  *	vkey:	key to be located
38ebfedea0SLionel Sambuc  *	vrootp:	address of tree root
39ebfedea0SLionel Sambuc  */
40ebfedea0SLionel Sambuc 
41ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION void *
rk_tsearch(const void * vkey,void ** vrootp,int (* compar)(const void *,const void *))42ebfedea0SLionel Sambuc rk_tsearch(const void *vkey, void **vrootp,
43ebfedea0SLionel Sambuc 	int (*compar)(const void *, const void *))
44ebfedea0SLionel Sambuc {
45ebfedea0SLionel Sambuc 	node_t *q;
46ebfedea0SLionel Sambuc 	node_t **rootp = (node_t **)vrootp;
47ebfedea0SLionel Sambuc 
48ebfedea0SLionel Sambuc 	if (rootp == NULL)
49ebfedea0SLionel Sambuc 		return NULL;
50ebfedea0SLionel Sambuc 
51ebfedea0SLionel Sambuc 	while (*rootp != NULL) {	/* Knuth's T1: */
52ebfedea0SLionel Sambuc 		int r;
53ebfedea0SLionel Sambuc 
54ebfedea0SLionel Sambuc 		if ((r = (*compar)(vkey, (*rootp)->key)) == 0)	/* T2: */
55ebfedea0SLionel Sambuc 			return *rootp;		/* we found it! */
56ebfedea0SLionel Sambuc 
57ebfedea0SLionel Sambuc 		rootp = (r < 0) ?
58ebfedea0SLionel Sambuc 		    &(*rootp)->llink :		/* T3: follow left branch */
59ebfedea0SLionel Sambuc 		    &(*rootp)->rlink;		/* T4: follow right branch */
60ebfedea0SLionel Sambuc 	}
61ebfedea0SLionel Sambuc 
62ebfedea0SLionel Sambuc 	q = malloc(sizeof(node_t));		/* T5: key not found */
63ebfedea0SLionel Sambuc 	if (q != 0) {				/* make new node */
64ebfedea0SLionel Sambuc 		*rootp = q;			/* link new node to old */
65ebfedea0SLionel Sambuc 		/* LINTED const castaway ok */
66ebfedea0SLionel Sambuc 		q->key = __DECONST(void *, vkey); /* initialize new node */
67ebfedea0SLionel Sambuc 		q->llink = q->rlink = NULL;
68ebfedea0SLionel Sambuc 	}
69ebfedea0SLionel Sambuc 	return q;
70ebfedea0SLionel Sambuc }
71ebfedea0SLionel Sambuc 
72ebfedea0SLionel Sambuc /*
73ebfedea0SLionel Sambuc  * Walk the nodes of a tree
74ebfedea0SLionel Sambuc  *
75ebfedea0SLionel Sambuc  * Parameters:
76ebfedea0SLionel Sambuc  *	root:	Root of the tree to be walked
77ebfedea0SLionel Sambuc  */
78ebfedea0SLionel Sambuc static void
trecurse(const node_t * root,void (* action)(const void *,VISIT,int),int level)79ebfedea0SLionel Sambuc trecurse(const node_t *root, void (*action)(const void *, VISIT, int),
80ebfedea0SLionel Sambuc 	 int level)
81ebfedea0SLionel Sambuc {
82ebfedea0SLionel Sambuc 
83ebfedea0SLionel Sambuc 	if (root->llink == NULL && root->rlink == NULL)
84ebfedea0SLionel Sambuc 		(*action)(root, leaf, level);
85ebfedea0SLionel Sambuc 	else {
86ebfedea0SLionel Sambuc 		(*action)(root, preorder, level);
87ebfedea0SLionel Sambuc 		if (root->llink != NULL)
88ebfedea0SLionel Sambuc 			trecurse(root->llink, action, level + 1);
89ebfedea0SLionel Sambuc 		(*action)(root, postorder, level);
90ebfedea0SLionel Sambuc 		if (root->rlink != NULL)
91ebfedea0SLionel Sambuc 			trecurse(root->rlink, action, level + 1);
92ebfedea0SLionel Sambuc 		(*action)(root, endorder, level);
93ebfedea0SLionel Sambuc 	}
94ebfedea0SLionel Sambuc }
95ebfedea0SLionel Sambuc 
96ebfedea0SLionel Sambuc /*
97ebfedea0SLionel Sambuc  * Walk the nodes of a tree
98ebfedea0SLionel Sambuc  *
99ebfedea0SLionel Sambuc  * Parameters:
100ebfedea0SLionel Sambuc  *	vroot:	Root of the tree to be walked
101ebfedea0SLionel Sambuc  */
102ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION void
rk_twalk(const void * vroot,void (* action)(const void *,VISIT,int))103ebfedea0SLionel Sambuc rk_twalk(const void *vroot,
104ebfedea0SLionel Sambuc       void (*action)(const void *, VISIT, int))
105ebfedea0SLionel Sambuc {
106ebfedea0SLionel Sambuc 	if (vroot != NULL && action != NULL)
107ebfedea0SLionel Sambuc 		trecurse(vroot, action, 0);
108ebfedea0SLionel Sambuc }
109ebfedea0SLionel Sambuc 
110ebfedea0SLionel Sambuc /*
111ebfedea0SLionel Sambuc  * delete node with given key
112ebfedea0SLionel Sambuc  *
113ebfedea0SLionel Sambuc  * vkey:   key to be deleted
114ebfedea0SLionel Sambuc  * vrootp: address of the root of the tree
115ebfedea0SLionel Sambuc  * compar: function to carry out node comparisons
116ebfedea0SLionel Sambuc  */
117ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION void *
rk_tdelete(const void * vkey,void ** vrootp,int (* compar)(const void *,const void *))118*0a6a1f1dSLionel Sambuc rk_tdelete(const void * vkey, void ** vrootp,
119ebfedea0SLionel Sambuc 	int (*compar)(const void *, const void *))
120ebfedea0SLionel Sambuc {
121ebfedea0SLionel Sambuc 	node_t **rootp = (node_t **)vrootp;
122ebfedea0SLionel Sambuc 	node_t *p, *q, *r;
123ebfedea0SLionel Sambuc 	int cmp;
124ebfedea0SLionel Sambuc 
125ebfedea0SLionel Sambuc 	if (rootp == NULL || (p = *rootp) == NULL)
126ebfedea0SLionel Sambuc 		return NULL;
127ebfedea0SLionel Sambuc 
128ebfedea0SLionel Sambuc 	while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) {
129ebfedea0SLionel Sambuc 		p = *rootp;
130ebfedea0SLionel Sambuc 		rootp = (cmp < 0) ?
131ebfedea0SLionel Sambuc 		    &(*rootp)->llink :		/* follow llink branch */
132ebfedea0SLionel Sambuc 		    &(*rootp)->rlink;		/* follow rlink branch */
133ebfedea0SLionel Sambuc 		if (*rootp == NULL)
134ebfedea0SLionel Sambuc 			return NULL;		/* key not found */
135ebfedea0SLionel Sambuc 	}
136ebfedea0SLionel Sambuc 	r = (*rootp)->rlink;			/* D1: */
137ebfedea0SLionel Sambuc 	if ((q = (*rootp)->llink) == NULL)	/* Left NULL? */
138ebfedea0SLionel Sambuc 		q = r;
139ebfedea0SLionel Sambuc 	else if (r != NULL) {			/* Right link is NULL? */
140ebfedea0SLionel Sambuc 		if (r->llink == NULL) {		/* D2: Find successor */
141ebfedea0SLionel Sambuc 			r->llink = q;
142ebfedea0SLionel Sambuc 			q = r;
143ebfedea0SLionel Sambuc 		} else {			/* D3: Find NULL link */
144ebfedea0SLionel Sambuc 			for (q = r->llink; q->llink != NULL; q = r->llink)
145ebfedea0SLionel Sambuc 				r = q;
146ebfedea0SLionel Sambuc 			r->llink = q->rlink;
147ebfedea0SLionel Sambuc 			q->llink = (*rootp)->llink;
148ebfedea0SLionel Sambuc 			q->rlink = (*rootp)->rlink;
149ebfedea0SLionel Sambuc 		}
150ebfedea0SLionel Sambuc 	}
151ebfedea0SLionel Sambuc 	free(*rootp);				/* D4: Free node */
152ebfedea0SLionel Sambuc 	*rootp = q;				/* link parent to new node */
153ebfedea0SLionel Sambuc 	return p;
154ebfedea0SLionel Sambuc }
155ebfedea0SLionel Sambuc 
156ebfedea0SLionel Sambuc /*
157ebfedea0SLionel Sambuc  * find a node, or return 0
158ebfedea0SLionel Sambuc  *
159ebfedea0SLionel Sambuc  * Parameters:
160ebfedea0SLionel Sambuc  *	vkey:	key to be found
161ebfedea0SLionel Sambuc  *	vrootp:	address of the tree root
162ebfedea0SLionel Sambuc  */
163ebfedea0SLionel Sambuc ROKEN_LIB_FUNCTION void *
rk_tfind(const void * vkey,void * const * vrootp,int (* compar)(const void *,const void *))164ebfedea0SLionel Sambuc rk_tfind(const void *vkey, void * const *vrootp,
165ebfedea0SLionel Sambuc       int (*compar)(const void *, const void *))
166ebfedea0SLionel Sambuc {
167ebfedea0SLionel Sambuc 	node_t **rootp = (node_t **)vrootp;
168ebfedea0SLionel Sambuc 
169ebfedea0SLionel Sambuc 	if (rootp == NULL)
170ebfedea0SLionel Sambuc 		return NULL;
171ebfedea0SLionel Sambuc 
172ebfedea0SLionel Sambuc 	while (*rootp != NULL) {		/* T1: */
173ebfedea0SLionel Sambuc 		int r;
174ebfedea0SLionel Sambuc 
175ebfedea0SLionel Sambuc 		if ((r = (*compar)(vkey, (*rootp)->key)) == 0)	/* T2: */
176ebfedea0SLionel Sambuc 			return *rootp;		/* key found */
177ebfedea0SLionel Sambuc 		rootp = (r < 0) ?
178ebfedea0SLionel Sambuc 		    &(*rootp)->llink :		/* T3: follow left branch */
179ebfedea0SLionel Sambuc 		    &(*rootp)->rlink;		/* T4: follow right branch */
180ebfedea0SLionel Sambuc 	}
181ebfedea0SLionel Sambuc 	return NULL;
182ebfedea0SLionel Sambuc }
183