Coverage Report

Created: 2026-04-12 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeradius-server/src/freeradius-devel/util/rb.h
Line
Count
Source
1
#pragma once
2
/*
3
 *   This program is free software; you can redistribute it and/or modify
4
 *   it under the terms of the GNU General Public License as published by
5
 *   the Free Software Foundation; either version 2 of the License, or
6
 *   (at your option) any later version.
7
 *
8
 *   This program is distributed in the hope that it will be useful,
9
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 *   GNU General Public License for more details.
12
 *
13
 *   You should have received a copy of the GNU General Public License
14
 *   along with this program; if not, write to the Free Software
15
 *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16
 */
17
18
/** Red/black tree implementation
19
 *
20
 * @file src/lib/util/rb.h
21
 *
22
 * @copyright 2016 The FreeRADIUS server project
23
 */
24
RCSIDH(fr_rb_h, "$Id: 2f5ea0ab87e701d079421a487b9a647b7d375205 $")
25
26
#ifdef __cplusplus
27
extern "C" {
28
#endif
29
30
#include <freeradius-devel/util/misc.h>
31
32
33
/* Red-Black tree description */
34
typedef enum {
35
  BLACK,
36
  RED
37
} fr_rb_colour_t;
38
39
typedef struct fr_rb_node_s fr_rb_node_t;
40
struct fr_rb_node_s {
41
  fr_rb_node_t    *left;    //!< Left child
42
  fr_rb_node_t    *right;   //!< Right child
43
  fr_rb_node_t    *parent;  //!< Parent
44
  void      *data;    //!< data stored in node
45
46
  fr_rb_colour_t    colour;   //!< Node colour (BLACK, RED)
47
  bool      being_freed;  //!< Disable frees if we're currently calling
48
            ///< a free function.
49
};
50
51
typedef struct fr_rb_tree_s fr_rb_tree_t;
52
53
/** Callback used to alloc rbnodes
54
 *
55
 * @param[in] tree  to allocate the node for.
56
 * @param[in] data  associated with node.
57
 */
58
typedef fr_rb_node_t *(* rb_node_alloc_t)(fr_rb_tree_t const *tree, void *data);
59
60
/** Callback used to free rbnodes
61
 *
62
 * @param[in] tree  that owns the node.
63
 * @param[in] node  to free.
64
 * @param[in] free_data free user data.
65
 */
66
typedef void (* rb_node_free_t)(fr_rb_tree_t const *tree, fr_rb_node_t *node, bool free_data);
67
68
/** The main red black tree structure
69
 *
70
 */
71
struct fr_rb_tree_s {
72
#ifndef NDEBUG
73
  uint32_t    magic;
74
#endif
75
76
  fr_rb_node_t    *root;    //!< Root of the rbtree.
77
78
  TALLOC_CTX    *node_ctx;  //!< Talloc ctx to allocate nodes in.
79
80
  char const    *type;    //!< Talloc type to check elements against.
81
82
  fr_cmp_t    data_cmp; //!< Callback to compare node data.
83
  fr_free_t   data_free;  //!< Callback to free node data.
84
85
  rb_node_alloc_t   node_alloc; //!< Callback to allocate a new node.
86
  rb_node_free_t    node_free;  //!< Callback to free a node.
87
88
  /*
89
   *  Try and pack these more efficiently
90
   *  by grouping them together.
91
   */
92
  uint16_t    offset;   //!< Where's the fr_rb_node_t is located in
93
            ///< the structure being inserted.
94
  bool      being_freed;  //!< Prevent double frees in talloc_destructor.
95
  uint32_t    num_elements; //!< How many elements are inside the tree.
96
};
97
98
/** Initialises a red black that verifies elements are of a specific talloc type
99
 *
100
 * This variant allocates an #fr_rb_node_t on the heap.  This allows the data
101
 * structure to be inserted into multiple trees.
102
 *
103
 * @param[out] _tree    to initialise.
104
 * @param[in] _node_ctx   to tie tree lifetime to.
105
 *        If ctx is freed, tree will free any nodes, calling the
106
 *        free function if set.
107
 * @param[in] _type   of item being stored in the tree, e.g. fr_value_box_t.
108
 * @param[in] _data_cmp   Callback to compare node data.
109
 * @param[in] _data_free  Optional function used to free data if tree nodes are
110
 *        deleted or replaced.
111
 * @return
112
 *  - A new rbtree on success.
113
 *  - NULL on failure.
114
 */
115
#define   fr_rb_talloc_init(_tree, _node_ctx, _type, _data_cmp, _data_free) \
116
    _fr_rb_init(_tree, _node_ctx, -1, #_type, _data_cmp, _data_free)
117
118
/** Initialises a red black tree
119
 *
120
 * This variant initiates an #fr_rb_node_t on the heap.  This allows the data structure
121
 * to be inserted into multiple trees.
122
 *
123
 * @param[out] _tree    to initialise.
124
 * @param[in] _node_ctx   to tie tree lifetime to.
125
 *        If ctx is freed, tree will free any nodes, calling the
126
 *        free function if set.
127
 * @param[in] _data_cmp   Callback to compare node data.
128
 * @param[in] _data_free  Optional function used to free data if tree nodes are
129
 *        deleted or replaced.
130
 * @return
131
 *  - A new rbtree on success.
132
 *  - NULL on failure.
133
 */
134
#define   fr_rb_init(_tree, _node_ctx, _data_cmp, _data_free) \
135
    _fr_rb_init(_tree, _node_ctx, -1, NULL, _data_cmp, _data_free)
136
137
/** Initialises a red black that verifies elements are of a specific talloc type
138
 *
139
 * This variant stores #fr_rb_node_t data inline with the data structure to avoid
140
 * initiating #fr_rb_node_t on the heap.
141
 *
142
 * It is suitable for use where the data structure will only be inserted into a
143
 * fixed set of trees.
144
 *
145
 * @param[out] _tree    to initialise.
146
 * @param[in] _type   of item being stored in the tree, e.g. fr_value_box_t.
147
 * @param[in] _field    Containing the #fr_rb_node_t within item being stored.
148
 * @param[in] _data_cmp   Callback to compare node data.
149
 * @param[in] _data_free  Optional function used to free data if tree nodes are
150
 *        deleted or replaced.
151
 * @return
152
 *  - A new rbtree on success.
153
 *  - NULL on failure.
154
 */
155
#define   fr_rb_inline_talloc_init(_tree, _type, _field, _data_cmp, _data_free) \
156
0
    _Generic((((_type *)0)->_field), \
157
0
      fr_rb_node_t: _fr_rb_init(_tree, NULL, offsetof(_type, _field), #_type, _data_cmp, _data_free) \
158
0
    )
159
160
/** Initialises a red black tree
161
 *
162
 * This variant stores #fr_rb_node_t data inline with the data structure to avoid
163
 * initiating #fr_rb_node_t on the heap.
164
 *
165
 * It is suitable for use where the data structure will only be inserted into a
166
 * fixed set of trees.
167
 *
168
 * @param[out] _tree    to initialise.
169
 * @param[in] _type   of item being stored in the tree, e.g. fr_value_box_t.
170
 * @param[in] _field    Containing the #fr_rb_node_t within item being stored.
171
 * @param[in] _data_cmp   Callback to compare node data.
172
 * @param[in] _data_free  Optional function used to free data if tree nodes are
173
 *        deleted or replaced.
174
 * @return
175
 *  - 0 on success.
176
 *  - -1 on failure.
177
 */
178
#define   fr_rb_inline_init(_tree, _type, _field, _data_cmp, _data_free) \
179
    _Generic((((_type *)0)->_field), \
180
      fr_rb_node_t: _fr_rb_init(_tree, NULL, offsetof(_type, _field), NULL, _data_cmp, _data_free) \
181
    )
182
183
int _fr_rb_init(fr_rb_tree_t *tree, TALLOC_CTX *node_ctx,
184
    ssize_t offset, char const *type,
185
    fr_cmp_t data_cmp, fr_free_t data_free);
186
187
/** Allocs a red black that verifies elements are of a specific talloc type
188
 *
189
 * This variant allocates an #fr_rb_node_t on the heap.  This allows the data structure
190
 * to be inserted into multiple trees.
191
 *
192
 * @param[in] _ctx    to tie tree lifetime to.
193
 *        If ctx is freed, tree will free any nodes, calling the
194
 *        free function if set.
195
 * @param[in] _type   of item being stored in the tree, e.g. fr_value_box_t.
196
 * @param[in] _data_cmp   Callback to compare node data.
197
 * @param[in] _data_free  Optional function used to free data if tree nodes are
198
 *        deleted or replaced.
199
 * @return
200
 *  - A new rbtree on success.
201
 *  - NULL on failure.
202
 */
203
#define   fr_rb_talloc_alloc(_ctx, _type, _data_cmp, _data_free) \
204
0
    _fr_rb_alloc(_ctx, -1, #_type, _data_cmp, _data_free)
205
206
/** Allocs a red black tree
207
 *
208
 * This variant allocates an #fr_rb_node_t on the heap.  This allows the data structure
209
 * to be inserted into multiple trees.
210
 *
211
 * @param[in] _ctx    to tie tree lifetime to.
212
 *        If ctx is freed, tree will free any nodes, calling the
213
 *        free function if set.
214
 * @param[in] _data_cmp   Callback to compare node data.
215
 * @param[in] _data_free  Optional function used to free data if tree nodes are
216
 *        deleted or replaced.
217
 * @return
218
 *  - A new rbtree on success.
219
 *  - NULL on failure.
220
 */
221
#define   fr_rb_alloc(_ctx, _data_cmp, _data_free) \
222
0
    _fr_rb_alloc(_ctx, -1, NULL, _data_cmp, _data_free)
223
224
/** Allocs a red black that verifies elements are of a specific talloc type
225
 *
226
 * This variant stores #fr_rb_node_t data inline with the data structure to avoid
227
 * allocating #fr_rb_node_t on the heap.
228
 *
229
 * It is suitable for use where the data structure will only be inserted into a fixed
230
 * set of trees.
231
 *
232
 * @param[in] _ctx    to tie tree lifetime to.
233
 *        If ctx is freed, tree will free any nodes, calling the
234
 *        free function if set.
235
 * @param[in] _type   of item being stored in the tree, e.g. fr_value_box_t.
236
 * @param[in] _field    Containing the #fr_rb_node_t within item being stored.
237
 * @param[in] _data_cmp   Callback to compare node data.
238
 * @param[in] _data_free  Optional function used to free data if tree nodes are
239
 *        deleted or replaced.
240
 * @return
241
 *  - A new rbtree on success.
242
 *  - NULL on failure.
243
 */
244
#define   fr_rb_inline_talloc_alloc(_ctx, _type, _field, _data_cmp, _data_free) \
245
42
    _Generic((((_type *)0)->_field), \
246
42
      fr_rb_node_t: _fr_rb_alloc(_ctx, offsetof(_type, _field), #_type, _data_cmp, _data_free) \
247
42
    )
248
249
/** Allocs a red black tree
250
 *
251
 * This variant stores #fr_rb_node_t data inline with the data structure to avoid
252
 * allocating #fr_rb_node_t on the heap.
253
 *
254
 * It is suitable for use where the data structure will only be inserted into a fixed
255
 * set of trees.
256
 *
257
 * @param[in] _ctx    to tie tree lifetime to.
258
 *        If ctx is freed, tree will free any nodes, calling the
259
 *        free function if set.
260
 * @param[in] _type   of item being stored in the tree, e.g. fr_value_box_t.
261
 * @param[in] _field    Containing the #fr_rb_node_t within item being stored.
262
 * @param[in] _data_cmp   Callback to compare node data.
263
 * @param[in] _data_free  Optional function used to free data if tree nodes are
264
 *        deleted or replaced.
265
 * @return
266
 *  - A new rbtree on success.
267
 *  - NULL on failure.
268
 */
269
#define   fr_rb_inline_alloc(_ctx, _type, _field, _data_cmp, _data_free) \
270
38
    _Generic((((_type *)0)->_field), \
271
38
      fr_rb_node_t: _fr_rb_alloc(_ctx, offsetof(_type, _field), NULL, _data_cmp, _data_free) \
272
38
    )
273
274
fr_rb_tree_t  *_fr_rb_alloc(TALLOC_CTX *ctx, ssize_t offset, char const *type,
275
            fr_cmp_t data_cmp, fr_free_t data_free) CC_HINT(warn_unused_result);
276
277
/** @hidecallergraph */
278
void    *fr_rb_find(fr_rb_tree_t const *tree, void const *data) CC_HINT(nonnull);
279
280
int   fr_rb_find_or_insert(void **found, fr_rb_tree_t *tree, void const *data) CC_HINT(nonnull(2,3));
281
282
bool    fr_rb_insert(fr_rb_tree_t *tree, void const *data) CC_HINT(nonnull);
283
284
int   fr_rb_replace(void **old, fr_rb_tree_t *tree, void const *data) CC_HINT(nonnull(2,3));
285
286
void    *fr_rb_remove(fr_rb_tree_t *tree, void const *data) CC_HINT(nonnull);
287
288
void    *fr_rb_remove_by_inline_node(fr_rb_tree_t *tree, fr_rb_node_t *node) CC_HINT(nonnull);
289
290
bool    fr_rb_delete(fr_rb_tree_t *tree, void const *data) CC_HINT(nonnull);
291
292
bool    fr_rb_delete_by_inline_node(fr_rb_tree_t *tree, fr_rb_node_t *node) CC_HINT(nonnull);
293
294
uint32_t  fr_rb_num_elements(fr_rb_tree_t *tree) CC_HINT(nonnull);
295
296
void    *fr_rb_first(fr_rb_tree_t *tree) CC_HINT(nonnull);
297
298
void    *fr_rb_last(fr_rb_tree_t *tree) CC_HINT(nonnull);
299
300
/** Check to see if an item is in a tree by examining its inline #fr_rb_node_t
301
 *
302
 * This works because we use NIL sentinels to represent the absence of a child
303
 * or parent.  When the node is initialised all these fields should be NULL
304
 * and when it's removed from the tree, the "free" function for inline nodes
305
 * also sets all of these back to NULL.
306
 *
307
 * @param[in] node  to check.
308
 * @return
309
 *  - true if node is in the tree.
310
 *  - talse if node is not in the tree.
311
 */
312
static inline bool fr_rb_node_inline_in_tree(fr_rb_node_t const *node)
313
0
{
314
0
  return (node->left && node->right && node->parent && !node->being_freed);
315
0
}
Unexecuted instantiation: fuzzer_dhcpv6.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer_util.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer_dhcpv4.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer_cbor.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer_der.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer_dns.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer_tacacs.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer_bfd.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer_radius.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer_tftp.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer_vmps.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: base32.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: base64.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: calc.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: cbor.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: decode.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dict_ext.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dict_fixup.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dict_print.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dict_test.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dict_tokenize.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dict_unknown.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dict_util.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dict_validate.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dl.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dns.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: edit.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: encode.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: event.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: timer.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: file.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: htrie.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: inet.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: log.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: packet.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: pair.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: pair_inline.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: pair_legacy.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: pair_print.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: pair_tokenize.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: print.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: proto.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: rb.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: rb_expire.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: regex.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: socket.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: stats.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: struct.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: trie.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: types.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: uri.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: value.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: fuzzer.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: base.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: raw.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: udp.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: json.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: jpath.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: cache.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: cert.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: conf.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: ctx.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: engine.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: pairs.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: session.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: strerror.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: utils.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: verify.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: version.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: virtual_server.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: list.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: tcp.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: abinary.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: auth.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: cf_file.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: cf_parse.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: cf_util.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: client.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: command.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: connection.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dependency.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: dl_module.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: exec.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: exec_legacy.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: exfile.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: global_lib.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: main_config.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: main_loop.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: map.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: map_proc.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: module.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: module_method.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: module_rlm.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: paircmp.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: pairmove.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: password.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: pool.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: request.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: request_data.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: section.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: snmp.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: state.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: tmpl_dcursor.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: tmpl_eval.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: tmpl_tokenize.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: trigger.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: trunk.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: users_file.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: util.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: virtual_servers.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: call.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: call_env.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: caller.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: catch.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: child_request.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: compile.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: condition.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: detach.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: finally.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: foreach.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: function.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: group.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: interpret.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: interpret_synchronous.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: io.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: limit.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: load_balance.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: map_builtin.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: parallel.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: return.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: subrequest.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: switch.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: timeout.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: tmpl.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: try.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: transaction.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat_alloc.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat_builtin.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat_eval.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat_expr.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat_func.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat_inst.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat_pair.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat_purify.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat_redundant.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: xlat_tokenize.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: app_io.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: channel.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: coord.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: coord_pair.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: master.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: network.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: schedule.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: thread.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: worker.c:fr_rb_node_inline_in_tree
Unexecuted instantiation: vmps.c:fr_rb_node_inline_in_tree
316
317
/** Iterator structure for in-order traversal of an rbtree
318
 */
319
typedef struct {
320
  fr_rb_node_t  *node;      ///< current node--set to NULL (not NIL) by fr_rb_iter_delete()
321
  fr_rb_node_t  *next;      ///< if non-NULL, next node cached by fr_rb_iter_delete()
322
} fr_rb_iter_inorder_t;
323
324
void    *fr_rb_iter_init_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter) CC_HINT(nonnull);
325
326
void    *fr_rb_iter_next_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter) CC_HINT(nonnull);
327
328
void    fr_rb_iter_delete_inorder(fr_rb_tree_t *tree, fr_rb_iter_inorder_t *iter) CC_HINT(nonnull);
329
330
0
#define fr_rb_inorder_foreach(_tree, _type, _iter) \
331
0
{ \
332
0
  fr_rb_iter_inorder_t _state; \
333
0
  for (_type *_iter = fr_rb_iter_init_inorder(_tree, &_state); _iter; _iter = fr_rb_iter_next_inorder(_tree, &_state))
334
335
/** Iterator structure for pre-order traversal of an rbtree
336
 */
337
typedef struct {
338
  fr_rb_node_t  *node;      ///< current node
339
} fr_rb_iter_preorder_t;
340
341
void    *fr_rb_iter_init_preorder(fr_rb_tree_t *tree, fr_rb_iter_preorder_t *iter) CC_HINT(nonnull);
342
343
void    *fr_rb_iter_next_preorder(fr_rb_tree_t *tree, fr_rb_iter_preorder_t *iter) CC_HINT(nonnull);
344
345
#define fr_rb_preorder_foreach(_tree, _type, _iter) \
346
{ \
347
  fr_rb_iter_preorder_t _state; \
348
  for (_type *_iter = fr_rb_iter_init_preorder(_tree, &_state); _iter; _iter = fr_rb_iter_next_preorder(_tree, &_state))
349
350
/** Iterator structure for post-order traversal of an rbtree
351
 */
352
typedef struct {
353
  fr_rb_node_t  *node;      ///< current node
354
} fr_rb_iter_postorder_t;
355
356
void    *fr_rb_iter_init_postorder(fr_rb_tree_t *tree, fr_rb_iter_postorder_t *iter) CC_HINT(nonnull);
357
358
void    *fr_rb_iter_next_postorder(fr_rb_tree_t *tree, fr_rb_iter_postorder_t *iter) CC_HINT(nonnull);
359
360
#define fr_rb_postorder_foreach(_tree, _type, _iter) \
361
{ \
362
  fr_rb_iter_postorder_t _state; \
363
  for (_type *_iter = fr_rb_iter_init_postorder(_tree, &_state); _iter; _iter = fr_rb_iter_next_postorder(_tree, &_state))
364
365
int   fr_rb_flatten_inorder(TALLOC_CTX *ctx, void **out[], fr_rb_tree_t *tree);
366
367
int   fr_rb_flatten_preorder(TALLOC_CTX *ctx, void **out[], fr_rb_tree_t *tree);
368
369
int   fr_rb_flatten_postorder(TALLOC_CTX *ctx, void **out[], fr_rb_tree_t *tree);
370
#ifdef __cplusplus
371
}
372
#endif