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