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