xref: /openbsd-src/usr.sbin/nsd/radtree.h (revision ee5153b76e0db0e530220bd4ec0e249a51365081)
1d3fecca9Ssthen /*
2d3fecca9Ssthen  * radtree -- generic radix tree for binary strings.
3d3fecca9Ssthen  *
4d3fecca9Ssthen  * Copyright (c) 2010, NLnet Labs.  See LICENSE for license.
5d3fecca9Ssthen  */
6d3fecca9Ssthen #ifndef RADTREE_H
7d3fecca9Ssthen #define RADTREE_H
8d3fecca9Ssthen 
9d3fecca9Ssthen struct radnode;
10d3fecca9Ssthen struct region;
11d3fecca9Ssthen 
12d3fecca9Ssthen /** length of the binary string */
13fe5fe5f6Sflorian typedef uint16_t radstrlen_type;
14d3fecca9Ssthen 
15d3fecca9Ssthen /**
16d3fecca9Ssthen  * The radix tree
17d3fecca9Ssthen  *
18d3fecca9Ssthen  * The elements are stored based on binary strings(0-255) of a given length.
19d3fecca9Ssthen  * They are sorted, a prefix is sorted before its suffixes.
20d3fecca9Ssthen  * If you want to know the key string, you should store it yourself, the
21d3fecca9Ssthen  * tree stores it in the parts necessary for lookup.
22d3fecca9Ssthen  * For binary strings for domain names see the radname routines.
23d3fecca9Ssthen  */
24d3fecca9Ssthen struct radtree {
25d3fecca9Ssthen 	/** root node in tree */
26d3fecca9Ssthen 	struct radnode* root;
27d3fecca9Ssthen 	/** count of number of elements */
28d3fecca9Ssthen 	size_t count;
29d3fecca9Ssthen 	/** region for allocation */
30d3fecca9Ssthen 	struct region* region;
31d3fecca9Ssthen };
32d3fecca9Ssthen 
33d3fecca9Ssthen /**
34d3fecca9Ssthen  * A radix tree lookup node.
35d3fecca9Ssthen  * The array is malloced separately from the radnode.
36d3fecca9Ssthen  */
37d3fecca9Ssthen struct radnode {
38d3fecca9Ssthen 	/** data element associated with the binary string up to this node */
39d3fecca9Ssthen 	void* elem;
40d3fecca9Ssthen 	/** parent node (NULL for the root) */
41d3fecca9Ssthen 	struct radnode* parent;
42d3fecca9Ssthen 	/** index in the parent lookup array */
43d3fecca9Ssthen 	uint8_t pidx;
44d3fecca9Ssthen 	/** offset of the lookup array, add to [i] for lookups */
45d3fecca9Ssthen 	uint8_t offset;
46d3fecca9Ssthen 	/** length of the lookup array */
47d3fecca9Ssthen 	uint16_t len;
48d3fecca9Ssthen 	/** capacity of the lookup array (can be larger than length) */
49d3fecca9Ssthen 	uint16_t capacity;
50d3fecca9Ssthen 	/** the lookup array by [byte-offset] */
51d3fecca9Ssthen 	struct radsel* array;
52*ee5153b7Sflorian } ATTR_PACKED;
53d3fecca9Ssthen 
54d3fecca9Ssthen /**
55d3fecca9Ssthen  * radix select edge in array
56d3fecca9Ssthen  */
57d3fecca9Ssthen struct radsel {
58d3fecca9Ssthen 	/** additional string after the selection-byte for this edge. */
59d3fecca9Ssthen 	uint8_t* str;
60d3fecca9Ssthen 	/** length of the additional string for this edge */
61fe5fe5f6Sflorian 	radstrlen_type len;
62d3fecca9Ssthen 	/** node that deals with byte+str */
63d3fecca9Ssthen 	struct radnode* node;
64*ee5153b7Sflorian } ATTR_PACKED;
65d3fecca9Ssthen 
66d3fecca9Ssthen /**
67d3fecca9Ssthen  * Create new radix tree
68d3fecca9Ssthen  * @param region: where to allocate the tree.
69d3fecca9Ssthen  * @return new tree or NULL on alloc failure.
70d3fecca9Ssthen  */
71d3fecca9Ssthen struct radtree* radix_tree_create(struct region* region);
72d3fecca9Ssthen 
73d3fecca9Ssthen /**
74d3fecca9Ssthen  * Init new radix tree.
75d3fecca9Ssthen  * @param rt: radix tree to be initialized.
76d3fecca9Ssthen  */
77d3fecca9Ssthen void radix_tree_init(struct radtree* rt);
78d3fecca9Ssthen 
79d3fecca9Ssthen /**
80d3fecca9Ssthen  * Delete intermediate nodes from radix tree
81d3fecca9Ssthen  * @param rt: radix tree to be initialized.
82d3fecca9Ssthen  */
83d3fecca9Ssthen void radix_tree_clear(struct radtree* rt);
84d3fecca9Ssthen 
85d3fecca9Ssthen /**
86d3fecca9Ssthen  * Delete radix tree.
87d3fecca9Ssthen  * @param rt: radix tree to be deleted.
88d3fecca9Ssthen  */
89d3fecca9Ssthen void radix_tree_delete(struct radtree* rt);
90d3fecca9Ssthen 
91d3fecca9Ssthen 
92d3fecca9Ssthen /**
93d3fecca9Ssthen  * Insert element into radix tree.
94d3fecca9Ssthen  * @param rt: the radix tree.
95d3fecca9Ssthen  * @param key: key string.
96d3fecca9Ssthen  * @param len: length of key.
97d3fecca9Ssthen  * @param elem: pointer to element data.
98d3fecca9Ssthen  * @return NULL on failure - out of memory.
99d3fecca9Ssthen  * 	NULL on failure - duplicate entry.
100d3fecca9Ssthen  * 	On success the new radix node for this element.
101d3fecca9Ssthen  */
102fe5fe5f6Sflorian struct radnode* radix_insert(struct radtree* rt, uint8_t* k,
103fe5fe5f6Sflorian 	radstrlen_type len, void* elem);
104d3fecca9Ssthen 
105d3fecca9Ssthen /**
106d3fecca9Ssthen  * Delete element from radix tree.
107d3fecca9Ssthen  * @param rt: the radix tree.
108d3fecca9Ssthen  * @param n: radix node for that element.
109d3fecca9Ssthen  * 	if NULL, nothing is deleted.
110d3fecca9Ssthen  */
111d3fecca9Ssthen void radix_delete(struct radtree* rt, struct radnode* n);
112d3fecca9Ssthen 
113d3fecca9Ssthen /**
114d3fecca9Ssthen  * Find radix element in tree.
115d3fecca9Ssthen  * @param rt: the radix tree.
116d3fecca9Ssthen  * @param key: key string.
117d3fecca9Ssthen  * @param len: length of key.
118d3fecca9Ssthen  * @return the radix node or NULL if not found.
119d3fecca9Ssthen  */
120fe5fe5f6Sflorian struct radnode* radix_search(struct radtree* rt, uint8_t* k,
121fe5fe5f6Sflorian 	radstrlen_type len);
122d3fecca9Ssthen 
123d3fecca9Ssthen /**
124d3fecca9Ssthen  * Find radix element in tree, and if not found, find the closest smaller or
125d3fecca9Ssthen  * equal element in the tree.
126d3fecca9Ssthen  * @param rt: the radix tree.
127d3fecca9Ssthen  * @param key: key string.
128d3fecca9Ssthen  * @param len: length of key.
129d3fecca9Ssthen  * @param result: returns the radix node or closest match (NULL if key is
130d3fecca9Ssthen  * 	smaller than the smallest key in the tree).
131d3fecca9Ssthen  * @return true if exact match, false if no match.
132d3fecca9Ssthen  */
133fe5fe5f6Sflorian int radix_find_less_equal(struct radtree* rt, uint8_t* k, radstrlen_type len,
134d3fecca9Ssthen 	struct radnode** result);
135d3fecca9Ssthen 
136d3fecca9Ssthen /**
137d3fecca9Ssthen  * Return the first (smallest) element in the tree.
138d3fecca9Ssthen  * @param rt: the radix tree.
139d3fecca9Ssthen  * @return: first node or NULL if none.
140d3fecca9Ssthen  */
141d3fecca9Ssthen struct radnode* radix_first(struct radtree* rt);
142d3fecca9Ssthen 
143d3fecca9Ssthen /**
144d3fecca9Ssthen  * Return the last (largest) element in the tree.
145d3fecca9Ssthen  * @param rt: the radix tree.
146d3fecca9Ssthen  * @return: last node or NULL if none.
147d3fecca9Ssthen  */
148d3fecca9Ssthen struct radnode* radix_last(struct radtree* rt);
149d3fecca9Ssthen 
150d3fecca9Ssthen /**
151d3fecca9Ssthen  * Return the next element.
152d3fecca9Ssthen  * @param n: the element to go from.
153d3fecca9Ssthen  * @return: next node or NULL if none.
154d3fecca9Ssthen  */
155d3fecca9Ssthen struct radnode* radix_next(struct radnode* n);
156d3fecca9Ssthen 
157d3fecca9Ssthen /**
158d3fecca9Ssthen  * Return the previous element.
159d3fecca9Ssthen  * @param n: the element to go from.
160d3fecca9Ssthen  * @return: prev node or NULL if none.
161d3fecca9Ssthen  */
162d3fecca9Ssthen struct radnode* radix_prev(struct radnode* n);
163d3fecca9Ssthen 
164d3fecca9Ssthen /*
165d3fecca9Ssthen  * Perform a walk through all elements of the tree.
166d3fecca9Ssthen  * node: variable of type struct radnode*.
167d3fecca9Ssthen  * tree: pointer to the tree.
168d3fecca9Ssthen  *	for(node=radix_first(tree); node; node=radix_next(node))
169d3fecca9Ssthen */
170d3fecca9Ssthen 
171d3fecca9Ssthen /**
172d3fecca9Ssthen  * Create a binary string to represent a domain name
173d3fecca9Ssthen  * @param k: string buffer to store into
174d3fecca9Ssthen  * @param len: output length, initially, the max, output the result.
175d3fecca9Ssthen  * @param dname: the domain name to convert, in wireformat.
176d3fecca9Ssthen  * @param dlen: length of space for dname.
177d3fecca9Ssthen  */
178fe5fe5f6Sflorian void radname_d2r(uint8_t* k, radstrlen_type* len, const uint8_t* dname,
179d3fecca9Ssthen 	size_t dlen);
180d3fecca9Ssthen 
181d3fecca9Ssthen /**
182d3fecca9Ssthen  * Convert a binary string back to a domain name.
183d3fecca9Ssthen  * @param k: the binary string.
184d3fecca9Ssthen  * @param len: length of k.
185d3fecca9Ssthen  * @param dname: buffer to store domain name into.
186d3fecca9Ssthen  * @param dlen: length of dname (including root label).
187d3fecca9Ssthen  */
188fe5fe5f6Sflorian void radname_r2d(uint8_t* k, radstrlen_type len, uint8_t* dname, size_t* dlen);
189d3fecca9Ssthen 
190d3fecca9Ssthen /**
191d3fecca9Ssthen  * Search the radix tree using a domain name.
192d3fecca9Ssthen  * The name is internally converted to a radname.
193d3fecca9Ssthen  * @param rt: tree
194d3fecca9Ssthen  * @param d: domain name, no compression pointers allowed.
195d3fecca9Ssthen  * @param max: max length to go from d.
196d3fecca9Ssthen  * @return NULL on parse error or if not found.
197d3fecca9Ssthen  */
198d3fecca9Ssthen struct radnode* radname_search(struct radtree* rt, const uint8_t* d,
199d3fecca9Ssthen 	size_t max);
200d3fecca9Ssthen 
201d3fecca9Ssthen /**
202d3fecca9Ssthen  * Find radix element in tree by domain name, and if not found,
203d3fecca9Ssthen  * find the closest smaller or equal element in the tree.
204d3fecca9Ssthen  * The name is internally converted to a radname (same sorting order).
205d3fecca9Ssthen  * @param rt: the radix tree.
206d3fecca9Ssthen  * @param d: domain name, no compression pointers allowed.
207d3fecca9Ssthen  * @param max: max length to go from d.
208d3fecca9Ssthen  * @param result: returns the radix node or closest match (NULL if key is
209d3fecca9Ssthen  * 	smaller than the smallest key in the tree).
210d3fecca9Ssthen  * 	could result in NULL on a parse error as well (with return false).
211d3fecca9Ssthen  * @return true if exact match, false if no match.
212d3fecca9Ssthen  */
213d3fecca9Ssthen int radname_find_less_equal(struct radtree* rt, const uint8_t* d, size_t max,
214d3fecca9Ssthen 	struct radnode** result);
215d3fecca9Ssthen 
216d3fecca9Ssthen /**
217d3fecca9Ssthen  * Insert radix element by domain name.
218d3fecca9Ssthen  * @param rt: the radix tree
219d3fecca9Ssthen  * @param d: domain name, no compression pointers.
220d3fecca9Ssthen  * @param max: max length from d.
221d3fecca9Ssthen  * @param elem: the element pointer to insert.
222d3fecca9Ssthen  * @return NULL on failure - out of memory.
223d3fecca9Ssthen  * 	NULL on failure - duplicate entry.
224d3fecca9Ssthen  * 	NULL on failure - parse error.
225d3fecca9Ssthen  * 	On success the radix node for this element.
226d3fecca9Ssthen  */
227d3fecca9Ssthen struct radnode* radname_insert(struct radtree* rt, const uint8_t* d,
228d3fecca9Ssthen 	size_t max, void* elem);
229d3fecca9Ssthen 
230d3fecca9Ssthen /**
231d3fecca9Ssthen  * Delete element by domain name from radix tree.
232d3fecca9Ssthen  * @param rt: the radix tree.
233d3fecca9Ssthen  * @param d: the domain name.  If it is not in the tree nothing happens.
234d3fecca9Ssthen  * @param max: max length.
235d3fecca9Ssthen  */
236d3fecca9Ssthen void radname_delete(struct radtree* rt, const uint8_t* d, size_t max);
237d3fecca9Ssthen 
238d3fecca9Ssthen /** number of bytes in common in strings */
239fe5fe5f6Sflorian radstrlen_type bstr_common_ext(uint8_t* x, radstrlen_type xlen, uint8_t* y,
240fe5fe5f6Sflorian 	radstrlen_type ylen);
241d3fecca9Ssthen /** true if one is prefix of the other */
242fe5fe5f6Sflorian int bstr_is_prefix_ext(uint8_t* p, radstrlen_type plen, uint8_t* x,
243fe5fe5f6Sflorian 	radstrlen_type xlen);
244d3fecca9Ssthen 
245d3fecca9Ssthen #endif /* RADTREE_H */
246