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