/src/freeradius-server/src/freeradius-devel/util/minmax_heap.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 | | /** Structures and prototypes for binary min-max heaps |
19 | | * |
20 | | * @file src/lib/util/minmax_heap.h |
21 | | * |
22 | | * @copyright 2021 Network RADIUS SAS (legal@networkradius.com) |
23 | | */ |
24 | | RCSIDH(minmax_heap_h, "$Id: 4f0fcd55c6a25890c9b7e24c67eea81d19c3f611 $") |
25 | | |
26 | | #ifdef __cplusplus |
27 | | extern "C" { |
28 | | #endif |
29 | | |
30 | | #include <freeradius-devel/build.h> |
31 | | #include <freeradius-devel/missing.h> |
32 | | #include <freeradius-devel/util/talloc.h> |
33 | | |
34 | | #include <stdint.h> |
35 | | #include <sys/types.h> |
36 | | |
37 | | typedef unsigned int fr_minmax_heap_index_t; |
38 | | typedef unsigned int fr_minmax_heap_iter_t; |
39 | | |
40 | | /** How many talloc headers need to be pre-allocated for a minmax heap |
41 | | */ |
42 | | #define FR_MINMAX_HEAP_TALLOC_HEADERS 2 |
43 | | |
44 | | /** Comparator to order elements |
45 | | * |
46 | | * Return a negative number if 'a' precedes 'b'. |
47 | | * Return zero if the ordering of 'a' and 'b' doesn't matter. |
48 | | * Return a positive number if 'b' precedes 'a'. |
49 | | */ |
50 | | typedef int8_t (*fr_minmax_heap_cmp_t)(void const *a, void const *b); |
51 | | |
52 | | /** The main minmax heap structure |
53 | | * Note that fr_minmax_heap_t is a pointer to fr_minmax_heap_s. This added level of indirection |
54 | | * lets one allocate/reallocate the heap structure and the array of pointers to items in the |
55 | | * minmax heap as a unit without affecting the caller. |
56 | | */ |
57 | | typedef struct fr_minmax_heap_s * fr_minmax_heap_t; |
58 | | |
59 | | size_t fr_minmax_heap_pre_alloc_size(unsigned int count); |
60 | | |
61 | | /** Creates a minmax heap that can be used with non-talloced elements |
62 | | * |
63 | | * @param[in] _ctx Talloc ctx to allocate heap in. |
64 | | * @param[in] _cmp Comparator used to compare elements. |
65 | | * @param[in] _type Of elements. |
66 | | * @param[in] _field to store heap indexes in. |
67 | | * @param[in] _init the initial number of elements to allocate. |
68 | | * Pass 0 to use the default. |
69 | | */ |
70 | | #define fr_minmax_heap_alloc(_ctx, _cmp, _type, _field, _init) \ |
71 | | _fr_minmax_heap_alloc(_ctx, _cmp, NULL, (size_t)offsetof(_type, _field), _init) |
72 | | |
73 | | /** Creates a minmax heap that verifies elements are of a specific talloc type |
74 | | * |
75 | | * @param[in] _ctx Talloc ctx to allocate heap in. |
76 | | * @param[in] _cmp Comparator used to compare elements. |
77 | | * @param[in] _talloc_type of elements. |
78 | | * @param[in] _field to store heap indexes in. |
79 | | * @param[in] _init the initial number of elements to allocate. |
80 | | * Pass 0 to use the default. |
81 | | * @return |
82 | | * - A new minmax heap. |
83 | | * - NULL on error. |
84 | | */ |
85 | | #define fr_minmax_heap_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init) \ |
86 | | _fr_minmax_heap_alloc(_ctx, _cmp, #_talloc_type, (size_t)offsetof(_talloc_type, _field), _init) |
87 | | |
88 | | fr_minmax_heap_t *_fr_minmax_heap_alloc(TALLOC_CTX *ctx, fr_minmax_heap_cmp_t cmp, char const *talloc_type, size_t offset, unsigned int init) CC_HINT(nonnull(2)); |
89 | | |
90 | | /** Check if an entry is inserted into a heap |
91 | | * |
92 | | */ |
93 | | static inline bool fr_minmax_heap_entry_inserted(fr_minmax_heap_index_t heap_idx) |
94 | 0 | { |
95 | 0 | return (heap_idx > 0); |
96 | 0 | } |
97 | | |
98 | | int fr_minmax_heap_insert(fr_minmax_heap_t *hp, void *data) CC_HINT(nonnull); |
99 | | int fr_minmax_heap_extract(fr_minmax_heap_t *hp, void *data) CC_HINT(nonnull); |
100 | | void *fr_minmax_heap_min_pop(fr_minmax_heap_t *hp) CC_HINT(nonnull); |
101 | | void *fr_minmax_heap_min_peek(fr_minmax_heap_t *hp) CC_HINT(nonnull); |
102 | | void *fr_minmax_heap_max_pop(fr_minmax_heap_t *hp) CC_HINT(nonnull); |
103 | | void *fr_minmax_heap_max_peek(fr_minmax_heap_t *hp) CC_HINT(nonnull); |
104 | | |
105 | | uint32_t fr_minmax_heap_num_elements(fr_minmax_heap_t *hp) CC_HINT(nonnull); |
106 | | |
107 | | void *fr_minmax_heap_iter_init(fr_minmax_heap_t *hp, fr_minmax_heap_iter_t *iter) CC_HINT(nonnull); |
108 | | void *fr_minmax_heap_iter_next(fr_minmax_heap_t *hp, fr_minmax_heap_iter_t *iter) CC_HINT(nonnull); |
109 | | |
110 | | /** Iterate over the contents of a minmax_heap |
111 | | * |
112 | | * @note The initializer section of a for loop can't declare variables with distinct |
113 | | * base types, so we require a containing block, and can't follow the standard |
114 | | * do {...} while(0) dodge. The code to be run for each item in the heap should |
115 | | * therefore start with 1 open braces and end with 2 close braces, and shouldn't |
116 | | * be followed with a semicolon. |
117 | | * This may fake out code formatting programs, including editors. |
118 | | * |
119 | | * @param[in] _hp to iterate over. |
120 | | * @param[in] _type of item the heap contains. |
121 | | * @param[in] _data Name of variable holding a pointer to the heap element. |
122 | | * Will be declared in the scope of the loop. |
123 | | */ |
124 | | #define fr_minmax_heap_foreach(_hp, _type, _data) \ |
125 | | { \ |
126 | | fr_minmax_heap_iter_t _iter; \ |
127 | | for (_type *_data = fr_minmax_heap_iter_init(_hp, &_iter); _data; _data = fr_minmax_heap_iter_next(_hp, &_iter)) |
128 | | |
129 | | #ifndef TALLOC_GET_TYPE_ABORT_NOOP |
130 | | CC_HINT(nonnull(1)) void fr_minmax_heap_verify(char const *file, int line, fr_minmax_heap_t const *hp); |
131 | | # define FR_MINMAX_HEAP_VERIFY(_hp) fr_minmax_heap_verify(__FILE__, __LINE__, _hp) |
132 | | #elif !defined(NDEBUG) |
133 | | # define FR_MINMAX_HEAP_VERIFY(_hp) fr_assert(_hp) |
134 | | #else |
135 | | # define FR_MINMAX_HEAP_VERIFY(_hp) |
136 | | #endif |
137 | | |
138 | | |
139 | | #ifdef __cplusplus |
140 | | } |
141 | | #endif |
142 | | |