xref: /freebsd/crypto/openssl/include/internal/ossl_rbtree.h (revision f9bc005b8ef3b507a5ecbc2d7fe4411ef70eff38)
1*f9bc005bSEnji Cooper /*
2*f9bc005bSEnji Cooper  * Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
3*f9bc005bSEnji Cooper  * Copyright (c) 2016 David Gwynne <david@gwynne.id.au>
4*f9bc005bSEnji Cooper  *
5*f9bc005bSEnji Cooper  * Licensed under the Apache License 2.0 (the "License").  You may not use
6*f9bc005bSEnji Cooper  * this file except in compliance with the License.  You can obtain a copy
7*f9bc005bSEnji Cooper  * in the file LICENSE in the source distribution or at
8*f9bc005bSEnji Cooper  * https://www.openssl.org/source/license.html
9*f9bc005bSEnji Cooper  */
10*f9bc005bSEnji Cooper 
11*f9bc005bSEnji Cooper /*
12*f9bc005bSEnji Cooper  * The code here comes from David Gwynne <david@gwynne.id.au>. The original
13*f9bc005bSEnji Cooper  * version can be found:
14*f9bc005bSEnji Cooper  *    https://github.com/dgwynne/data-structures/
15*f9bc005bSEnji Cooper  * file bst.h. The same code is also part of OpenBSD OS where it is shipped
16*f9bc005bSEnji Cooper  * under BSD license.
17*f9bc005bSEnji Cooper  *
18*f9bc005bSEnji Cooper  * David Gwynne agrees to include modified version to OpenSSL and ship it
19*f9bc005bSEnji Cooper  * under OpenSSL Apache 2.0 license.
20*f9bc005bSEnji Cooper  */
21*f9bc005bSEnji Cooper #ifndef _OSSL_INTERNAL_RBTREE_H_
22*f9bc005bSEnji Cooper #define _OSSL_INTERNAL_RBTREE_H_
23*f9bc005bSEnji Cooper 
24*f9bc005bSEnji Cooper #include "internal/e_os.h"
25*f9bc005bSEnji Cooper 
26*f9bc005bSEnji Cooper /*
27*f9bc005bSEnji Cooper  * List of changes against upstream version:
28*f9bc005bSEnji Cooper  *   augmentation mechanism is removed in OpenSSL as there is no demand for it
29*f9bc005bSEnji Cooper  *
30*f9bc005bSEnji Cooper  *   prefix changed from rb/rbt to ossl_rbt
31*f9bc005bSEnji Cooper  *
32*f9bc005bSEnji Cooper  *   debug version of OSSL_RBT_REMOVE() sets parent, left, right members
33*f9bc005bSEnji Cooper  *   to NULL
34*f9bc005bSEnji Cooper  *
35*f9bc005bSEnji Cooper  *   cstyle is changed to match OpenSSL.
36*f9bc005bSEnji Cooper  */
37*f9bc005bSEnji Cooper struct ossl_rbt_type {
38*f9bc005bSEnji Cooper     int (*t_compare)(const void *, const void *);
39*f9bc005bSEnji Cooper     uintptr_t t_offset; /* offset of ossl_rbt_entry in type */
40*f9bc005bSEnji Cooper };
41*f9bc005bSEnji Cooper 
42*f9bc005bSEnji Cooper struct ossl_rbt_tree {
43*f9bc005bSEnji Cooper     struct ossl_rbt_entry *rb_root;
44*f9bc005bSEnji Cooper };
45*f9bc005bSEnji Cooper 
46*f9bc005bSEnji Cooper struct ossl_rbt_entry {
47*f9bc005bSEnji Cooper     struct ossl_rbt_entry *rb_parent;
48*f9bc005bSEnji Cooper     struct ossl_rbt_entry *rb_left;
49*f9bc005bSEnji Cooper     struct ossl_rbt_entry *rb_right;
50*f9bc005bSEnji Cooper     unsigned int rb_color;
51*f9bc005bSEnji Cooper };
52*f9bc005bSEnji Cooper 
53*f9bc005bSEnji Cooper #define OSSL_RBT_HEAD(_name, _type)    \
54*f9bc005bSEnji Cooper     struct _name {                     \
55*f9bc005bSEnji Cooper         struct ossl_rbt_tree rbh_root; \
56*f9bc005bSEnji Cooper     }
57*f9bc005bSEnji Cooper 
58*f9bc005bSEnji Cooper #define OSSL_RBT_ENTRY(_type) struct ossl_rbt_entry
59*f9bc005bSEnji Cooper 
60*f9bc005bSEnji Cooper static ossl_inline void
61*f9bc005bSEnji Cooper ossl_rbt_init(struct ossl_rbt_tree *rb)
62*f9bc005bSEnji Cooper {
63*f9bc005bSEnji Cooper     rb->rb_root = NULL;
64*f9bc005bSEnji Cooper }
65*f9bc005bSEnji Cooper 
66*f9bc005bSEnji Cooper static ossl_inline int
67*f9bc005bSEnji Cooper ossl_rbt_empty(struct ossl_rbt_tree *rb)
68*f9bc005bSEnji Cooper {
69*f9bc005bSEnji Cooper     return rb->rb_root == NULL;
70*f9bc005bSEnji Cooper }
71*f9bc005bSEnji Cooper 
72*f9bc005bSEnji Cooper void *ossl_rbt_insert(const struct ossl_rbt_type *, struct ossl_rbt_tree *, void *);
73*f9bc005bSEnji Cooper void *ossl_rbt_remove(const struct ossl_rbt_type *, struct ossl_rbt_tree *, void *);
74*f9bc005bSEnji Cooper void *ossl_rbt_find(const struct ossl_rbt_type *, struct ossl_rbt_tree *, const void *);
75*f9bc005bSEnji Cooper void *ossl_rbt_nfind(const struct ossl_rbt_type *, struct ossl_rbt_tree *, const void *);
76*f9bc005bSEnji Cooper void *ossl_rbt_root(const struct ossl_rbt_type *, struct ossl_rbt_tree *);
77*f9bc005bSEnji Cooper void *ossl_rbt_min(const struct ossl_rbt_type *, struct ossl_rbt_tree *);
78*f9bc005bSEnji Cooper void *ossl_rbt_max(const struct ossl_rbt_type *, struct ossl_rbt_tree *);
79*f9bc005bSEnji Cooper void *ossl_rbt_next(const struct ossl_rbt_type *, void *);
80*f9bc005bSEnji Cooper void *ossl_rbt_prev(const struct ossl_rbt_type *, void *);
81*f9bc005bSEnji Cooper void *ossl_rbt_left(const struct ossl_rbt_type *, void *);
82*f9bc005bSEnji Cooper void *ossl_rbt_right(const struct ossl_rbt_type *, void *);
83*f9bc005bSEnji Cooper void *ossl_rbt_parent(const struct ossl_rbt_type *, void *);
84*f9bc005bSEnji Cooper void ossl_rbt_set_left(const struct ossl_rbt_type *, void *, void *);
85*f9bc005bSEnji Cooper void ossl_rbt_set_right(const struct ossl_rbt_type *, void *, void *);
86*f9bc005bSEnji Cooper void ossl_rbt_set_parent(const struct ossl_rbt_type *, void *, void *);
87*f9bc005bSEnji Cooper void ossl_rbt_init_rbe(const struct ossl_rbt_type *, void *);
88*f9bc005bSEnji Cooper 
89*f9bc005bSEnji Cooper #define OSSL_RBT_INITIALIZER(_head) \
90*f9bc005bSEnji Cooper     {                               \
91*f9bc005bSEnji Cooper         {                           \
92*f9bc005bSEnji Cooper             NULL                    \
93*f9bc005bSEnji Cooper         }                           \
94*f9bc005bSEnji Cooper     }
95*f9bc005bSEnji Cooper 
96*f9bc005bSEnji Cooper #define OSSL_RBT_PROTOTYPE(_name, _type, _field, _cmp)                       \
97*f9bc005bSEnji Cooper     extern const struct ossl_rbt_type *const _name##_OSSL_RBT_TYPE;          \
98*f9bc005bSEnji Cooper                                                                              \
99*f9bc005bSEnji Cooper     ossl_unused static ossl_inline void                                      \
100*f9bc005bSEnji Cooper     _name##_OSSL_RBT_INIT(struct _name *head)                                \
101*f9bc005bSEnji Cooper     {                                                                        \
102*f9bc005bSEnji Cooper         ossl_rbt_init(&head->rbh_root);                                      \
103*f9bc005bSEnji Cooper     }                                                                        \
104*f9bc005bSEnji Cooper                                                                              \
105*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
106*f9bc005bSEnji Cooper     _name##_OSSL_RBT_INSERT(struct _name *head, struct _type *elm)           \
107*f9bc005bSEnji Cooper     {                                                                        \
108*f9bc005bSEnji Cooper         return ossl_rbt_insert(_name##_OSSL_RBT_TYPE, &head->rbh_root, elm); \
109*f9bc005bSEnji Cooper     }                                                                        \
110*f9bc005bSEnji Cooper                                                                              \
111*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
112*f9bc005bSEnji Cooper     _name##_OSSL_RBT_REMOVE(struct _name *head, struct _type *elm)           \
113*f9bc005bSEnji Cooper     {                                                                        \
114*f9bc005bSEnji Cooper         return ossl_rbt_remove(_name##_OSSL_RBT_TYPE, &head->rbh_root, elm); \
115*f9bc005bSEnji Cooper     }                                                                        \
116*f9bc005bSEnji Cooper                                                                              \
117*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
118*f9bc005bSEnji Cooper     _name##_OSSL_RBT_FIND(struct _name *head, const struct _type *key)       \
119*f9bc005bSEnji Cooper     {                                                                        \
120*f9bc005bSEnji Cooper         return ossl_rbt_find(_name##_OSSL_RBT_TYPE, &head->rbh_root, key);   \
121*f9bc005bSEnji Cooper     }                                                                        \
122*f9bc005bSEnji Cooper                                                                              \
123*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
124*f9bc005bSEnji Cooper     _name##_OSSL_RBT_NFIND(struct _name *head, const struct _type *key)      \
125*f9bc005bSEnji Cooper     {                                                                        \
126*f9bc005bSEnji Cooper         return ossl_rbt_nfind(_name##_OSSL_RBT_TYPE, &head->rbh_root, key);  \
127*f9bc005bSEnji Cooper     }                                                                        \
128*f9bc005bSEnji Cooper                                                                              \
129*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
130*f9bc005bSEnji Cooper     _name##_OSSL_RBT_ROOT(struct _name *head)                                \
131*f9bc005bSEnji Cooper     {                                                                        \
132*f9bc005bSEnji Cooper         return ossl_rbt_root(_name##_OSSL_RBT_TYPE, &head->rbh_root);        \
133*f9bc005bSEnji Cooper     }                                                                        \
134*f9bc005bSEnji Cooper                                                                              \
135*f9bc005bSEnji Cooper     ossl_unused static ossl_inline int                                       \
136*f9bc005bSEnji Cooper     _name##_OSSL_RBT_EMPTY(struct _name *head)                               \
137*f9bc005bSEnji Cooper     {                                                                        \
138*f9bc005bSEnji Cooper         return ossl_rbt_empty(&head->rbh_root);                              \
139*f9bc005bSEnji Cooper     }                                                                        \
140*f9bc005bSEnji Cooper                                                                              \
141*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
142*f9bc005bSEnji Cooper     _name##_OSSL_RBT_MIN(struct _name *head)                                 \
143*f9bc005bSEnji Cooper     {                                                                        \
144*f9bc005bSEnji Cooper         return ossl_rbt_min(_name##_OSSL_RBT_TYPE, &head->rbh_root);         \
145*f9bc005bSEnji Cooper     }                                                                        \
146*f9bc005bSEnji Cooper                                                                              \
147*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
148*f9bc005bSEnji Cooper     _name##_OSSL_RBT_MAX(struct _name *head)                                 \
149*f9bc005bSEnji Cooper     {                                                                        \
150*f9bc005bSEnji Cooper         return ossl_rbt_max(_name##_OSSL_RBT_TYPE, &head->rbh_root);         \
151*f9bc005bSEnji Cooper     }                                                                        \
152*f9bc005bSEnji Cooper                                                                              \
153*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
154*f9bc005bSEnji Cooper     _name##_OSSL_RBT_NEXT(struct _type *elm)                                 \
155*f9bc005bSEnji Cooper     {                                                                        \
156*f9bc005bSEnji Cooper         return ossl_rbt_next(_name##_OSSL_RBT_TYPE, elm);                    \
157*f9bc005bSEnji Cooper     }                                                                        \
158*f9bc005bSEnji Cooper                                                                              \
159*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
160*f9bc005bSEnji Cooper     _name##_OSSL_RBT_PREV(struct _type *elm)                                 \
161*f9bc005bSEnji Cooper     {                                                                        \
162*f9bc005bSEnji Cooper         return ossl_rbt_prev(_name##_OSSL_RBT_TYPE, elm);                    \
163*f9bc005bSEnji Cooper     }                                                                        \
164*f9bc005bSEnji Cooper                                                                              \
165*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
166*f9bc005bSEnji Cooper     _name##_OSSL_RBT_LEFT(struct _type *elm)                                 \
167*f9bc005bSEnji Cooper     {                                                                        \
168*f9bc005bSEnji Cooper         return ossl_rbt_left(_name##_OSSL_RBT_TYPE, elm);                    \
169*f9bc005bSEnji Cooper     }                                                                        \
170*f9bc005bSEnji Cooper                                                                              \
171*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
172*f9bc005bSEnji Cooper     _name##_OSSL_RBT_RIGHT(struct _type *elm)                                \
173*f9bc005bSEnji Cooper     {                                                                        \
174*f9bc005bSEnji Cooper         return ossl_rbt_right(_name##_OSSL_RBT_TYPE, elm);                   \
175*f9bc005bSEnji Cooper     }                                                                        \
176*f9bc005bSEnji Cooper                                                                              \
177*f9bc005bSEnji Cooper     ossl_unused static ossl_inline struct _type *                            \
178*f9bc005bSEnji Cooper     _name##_OSSL_RBT_PARENT(struct _type *elm)                               \
179*f9bc005bSEnji Cooper     {                                                                        \
180*f9bc005bSEnji Cooper         return ossl_rbt_parent(_name##_OSSL_RBT_TYPE, elm);                  \
181*f9bc005bSEnji Cooper     }                                                                        \
182*f9bc005bSEnji Cooper                                                                              \
183*f9bc005bSEnji Cooper     ossl_unused static ossl_inline void                                      \
184*f9bc005bSEnji Cooper     _name##_OSSL_RBT_SET_LEFT(struct _type *elm, struct _type *left)         \
185*f9bc005bSEnji Cooper     {                                                                        \
186*f9bc005bSEnji Cooper         ossl_rbt_set_left(_name##_OSSL_RBT_TYPE, elm, left);                 \
187*f9bc005bSEnji Cooper     }                                                                        \
188*f9bc005bSEnji Cooper                                                                              \
189*f9bc005bSEnji Cooper     ossl_unused static ossl_inline void                                      \
190*f9bc005bSEnji Cooper     _name##_OSSL_RBT_SET_RIGHT(struct _type *elm, struct _type *right)       \
191*f9bc005bSEnji Cooper     {                                                                        \
192*f9bc005bSEnji Cooper         ossl_rbt_set_right(_name##_OSSL_RBT_TYPE, elm, right);               \
193*f9bc005bSEnji Cooper     }                                                                        \
194*f9bc005bSEnji Cooper                                                                              \
195*f9bc005bSEnji Cooper     ossl_unused static ossl_inline void                                      \
196*f9bc005bSEnji Cooper     _name##_OSSL_RBT_SET_PARENT(struct _type *elm, struct _type *parent)     \
197*f9bc005bSEnji Cooper     {                                                                        \
198*f9bc005bSEnji Cooper         ossl_rbt_set_parent(_name##_OSSL_RBT_TYPE, elm, parent);             \
199*f9bc005bSEnji Cooper     }                                                                        \
200*f9bc005bSEnji Cooper     ossl_unused static ossl_inline void                                      \
201*f9bc005bSEnji Cooper     _name##_OSSL_RBT_INIT_RBE(struct _type *elm)                             \
202*f9bc005bSEnji Cooper     {                                                                        \
203*f9bc005bSEnji Cooper         ossl_rbt_init_rbe(_name##_OSSL_RBT_TYPE, elm);                       \
204*f9bc005bSEnji Cooper     }
205*f9bc005bSEnji Cooper 
206*f9bc005bSEnji Cooper #define OSSL_RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp)   \
207*f9bc005bSEnji Cooper     static int                                                   \
208*f9bc005bSEnji Cooper     _name##_OSSL_RBT_COMPARE(const void *lptr, const void *rptr) \
209*f9bc005bSEnji Cooper     {                                                            \
210*f9bc005bSEnji Cooper         const struct _type *l = lptr, *r = rptr;                 \
211*f9bc005bSEnji Cooper         return _cmp(l, r);                                       \
212*f9bc005bSEnji Cooper     }                                                            \
213*f9bc005bSEnji Cooper     static const struct ossl_rbt_type _name##_OSSL_RBT_INFO = {  \
214*f9bc005bSEnji Cooper         _name##_OSSL_RBT_COMPARE,                                \
215*f9bc005bSEnji Cooper         offsetof(struct _type, _field),                          \
216*f9bc005bSEnji Cooper     };                                                           \
217*f9bc005bSEnji Cooper     const struct ossl_rbt_type *const _name##_OSSL_RBT_TYPE = &_name##_OSSL_RBT_INFO
218*f9bc005bSEnji Cooper 
219*f9bc005bSEnji Cooper #define OSSL_RBT_GENERATE(_name, _type, _field, _cmp) \
220*f9bc005bSEnji Cooper     OSSL_RBT_GENERATE_INTERNAL(_name, _type, _field, _cmp)
221*f9bc005bSEnji Cooper 
222*f9bc005bSEnji Cooper #define OSSL_RBT_INIT(_name, _head) _name##_OSSL_RBT_INIT(_head)
223*f9bc005bSEnji Cooper #define OSSL_RBT_INSERT(_name, _head, _elm) _name##_OSSL_RBT_INSERT(_head, _elm)
224*f9bc005bSEnji Cooper #define OSSL_RBT_REMOVE(_name, _head, _elm) _name##_OSSL_RBT_REMOVE(_head, _elm)
225*f9bc005bSEnji Cooper #define OSSL_RBT_FIND(_name, _head, _key) _name##_OSSL_RBT_FIND(_head, _key)
226*f9bc005bSEnji Cooper #define OSSL_RBT_NFIND(_name, _head, _key) _name##_OSSL_RBT_NFIND(_head, _key)
227*f9bc005bSEnji Cooper #define OSSL_RBT_ROOT(_name, _head) _name##_OSSL_RBT_ROOT(_head)
228*f9bc005bSEnji Cooper #define OSSL_RBT_EMPTY(_name, _head) _name##_OSSL_RBT_EMPTY(_head)
229*f9bc005bSEnji Cooper #define OSSL_RBT_MIN(_name, _head) _name##_OSSL_RBT_MIN(_head)
230*f9bc005bSEnji Cooper #define OSSL_RBT_MAX(_name, _head) _name##_OSSL_RBT_MAX(_head)
231*f9bc005bSEnji Cooper #define OSSL_RBT_NEXT(_name, _elm) _name##_OSSL_RBT_NEXT(_elm)
232*f9bc005bSEnji Cooper #define OSSL_RBT_PREV(_name, _elm) _name##_OSSL_RBT_PREV(_elm)
233*f9bc005bSEnji Cooper #define OSSL_RBT_LEFT(_name, _elm) _name##_OSSL_RBT_LEFT(_elm)
234*f9bc005bSEnji Cooper #define OSSL_RBT_RIGHT(_name, _elm) _name##_OSSL_RBT_RIGHT(_elm)
235*f9bc005bSEnji Cooper #define OSSL_RBT_PARENT(_name, _elm) _name##_OSSL_RBT_PARENT(_elm)
236*f9bc005bSEnji Cooper #define OSSL_RBT_SET_LEFT(_name, _elm, _l) _name##_OSSL_RBT_SET_LEFT(_elm, _l)
237*f9bc005bSEnji Cooper #define OSSL_RBT_SET_RIGHT(_name, _elm, _r) _name##_OSSL_RBT_SET_RIGHT(_elm, _r)
238*f9bc005bSEnji Cooper #define OSSL_RBT_SET_PARENT(_name, _elm, _p) _name##_OSSL_RBT_SET_PARENT(_elm, _p)
239*f9bc005bSEnji Cooper #ifndef NDEBUG
240*f9bc005bSEnji Cooper #define OSSL_RBT_INIT_RBE(_name, _elm) _name##_OSSL_RBT_INIT_RBE(_elm)
241*f9bc005bSEnji Cooper #else
242*f9bc005bSEnji Cooper #define OSSL_RBT_INIT_RBE(_name, _elm) (void)(0)
243*f9bc005bSEnji Cooper #endif
244*f9bc005bSEnji Cooper 
245*f9bc005bSEnji Cooper #define OSSL_RBT_FOREACH(_e, _name, _head)    \
246*f9bc005bSEnji Cooper     for ((_e) = OSSL_RBT_MIN(_name, (_head)); \
247*f9bc005bSEnji Cooper         (_e) != NULL;                         \
248*f9bc005bSEnji Cooper         (_e) = OSSL_RBT_NEXT(_name, (_e)))
249*f9bc005bSEnji Cooper 
250*f9bc005bSEnji Cooper #define OSSL_RBT_FOREACH_SAFE(_e, _name, _head, _n)             \
251*f9bc005bSEnji Cooper     for ((_e) = OSSL_RBT_MIN(_name, (_head));                   \
252*f9bc005bSEnji Cooper         (_e) != NULL && ((_n) = OSSL_RBT_NEXT(_name, (_e)), 1); \
253*f9bc005bSEnji Cooper         (_e) = (_n))
254*f9bc005bSEnji Cooper 
255*f9bc005bSEnji Cooper #define OSSL_RBT_FOREACH_REVERSE(_e, _name, _head) \
256*f9bc005bSEnji Cooper     for ((_e) = OSSL_RBT_MAX(_name, (_head));      \
257*f9bc005bSEnji Cooper         (_e) != NULL;                              \
258*f9bc005bSEnji Cooper         (_e) = OSSL_RBT_PREV(_name, (_e)))
259*f9bc005bSEnji Cooper 
260*f9bc005bSEnji Cooper #define OSSL_RBT_FOREACH_REVERSE_SAFE(_e, _name, _head, _n)     \
261*f9bc005bSEnji Cooper     for ((_e) = OSSL_RBT_MAX(_name, (_head));                   \
262*f9bc005bSEnji Cooper         (_e) != NULL && ((_n) = OSSL_RBT_PREV(_name, (_e)), 1); \
263*f9bc005bSEnji Cooper         (_e) = (_n))
264*f9bc005bSEnji Cooper 
265*f9bc005bSEnji Cooper #endif /* _OSSL_INTERNAL_RBTREE_H_ */
266