Coverage Report

Created: 2024-08-28 06:17

/src/freeradius-server/src/freeradius-devel/util/heap.h
Line
Count
Source (jump to first uncovered line)
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 heaps
19
 *
20
 * @file src/lib/util/heap.h
21
 *
22
 * @copyright 2007 Alan DeKok
23
 */
24
RCSIDH(heap_h, "$Id: 5c615f0e4fee73795140048ce5b2eac2f3fd941f $")
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
/*
38
 *  Allow public and private versions of the same structures
39
 */
40
#ifdef _CONST
41
#  error _CONST can only be defined in the local header
42
#endif
43
#ifndef _HEAP_PRIVATE
44
#  define _CONST const
45
#else
46
#  define _CONST
47
#endif
48
49
/** Comparator to order heap elements
50
 *
51
 *  Return negative numbers to put 'a' at the top of the heap.
52
 *  Return positive numbers to put 'b' at the top of the heap.
53
 */
54
typedef int8_t (*fr_heap_cmp_t)(void const *a, void const *b);
55
56
/** The main heap structure
57
 *
58
 * A heap entry is made of a pointer to the object, which
59
 * contains the key.  The heap itself is an array of pointers.
60
 *
61
 * Heaps normally support only ordered insert, and extraction
62
 * of the minimum element.  The heap entry can contain an "int"
63
 * field that holds the entries position in the heap.  The offset
64
 * of the field is held inside of the heap structure.
65
 */
66
typedef struct {
67
  unsigned int  _CONST size;    //!< Number of nodes allocated.
68
  unsigned int  _CONST min;   //!< Minimum number of elements we allow
69
            ///< the heap to reduce down to.
70
  size_t    _CONST offset;    //!< Offset of heap index in element structure.
71
72
  unsigned int  _CONST num_elements;  //!< Number of nodes used.
73
74
  char const  * _CONST type;    //!< Talloc type of elements.
75
  fr_heap_cmp_t _CONST cmp;   //!< Comparator function.
76
77
  void    * _CONST p[];   //!< Array of nodes.
78
} fr_heap_t;
79
80
typedef unsigned int fr_heap_index_t;
81
typedef unsigned int fr_heap_iter_t;
82
83
0
#define FR_HEAP_INDEX_INVALID (0)
84
85
/** How many talloc headers need to be pre-allocated for a heap
86
 */
87
#define FR_HEAP_TALLOC_HEADERS 2
88
89
size_t fr_heap_pre_alloc_size(unsigned int count);
90
91
/** Creates a heap that can be used with non-talloced elements
92
 *
93
 * @param[in] _ctx    Talloc ctx to allocate heap in.
94
 * @param[in] _cmp    Comparator used to compare elements.
95
 * @param[in] _type   Of elements.
96
 * @param[in] _field    to store heap indexes in.
97
 * @param[in] _init   the initial number of elements to allocate.
98
 *        Pass 0 to use the default.
99
 */
100
#define fr_heap_alloc(_ctx, _cmp, _type, _field, _init) \
101
  _fr_heap_alloc(_ctx, _cmp, NULL, (size_t)offsetof(_type, _field), _init)
102
103
/** Creates a heap that verifies elements are of a specific talloc type
104
 *
105
 * @param[in] _ctx    Talloc ctx to allocate heap in.
106
 * @param[in] _cmp    Comparator used to compare elements.
107
 * @param[in] _talloc_type  of elements.
108
 * @param[in] _field    to store heap indexes in.
109
 * @param[in] _init   the initial number of elements to allocate.
110
 *        Pass 0 to use the default.
111
 * @return
112
 *  - A new heap.
113
 *  - NULL on error.
114
 */
115
#define fr_heap_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init) \
116
  _fr_heap_alloc(_ctx, _cmp, #_talloc_type, (size_t)offsetof(_talloc_type, _field), _init)
117
fr_heap_t *_fr_heap_alloc(TALLOC_CTX *ctx, fr_heap_cmp_t cmp, char const *talloc_type,
118
        size_t offset, unsigned int init) CC_HINT(nonnull(2));
119
120
/** Check if an entry is inserted into a heap
121
 *
122
 * @param[in] heap_idx from object to check.
123
 */
124
static inline bool fr_heap_entry_inserted(fr_heap_index_t heap_idx)
125
0
{
126
0
  return (heap_idx != FR_HEAP_INDEX_INVALID);
127
0
}
Unexecuted instantiation: fuzzer_tacacs.c:fr_heap_entry_inserted
Unexecuted instantiation: fuzzer_vmps.c:fr_heap_entry_inserted
Unexecuted instantiation: fuzzer_tftp.c:fr_heap_entry_inserted
Unexecuted instantiation: fuzzer_dns.c:fr_heap_entry_inserted
Unexecuted instantiation: fuzzer_dhcpv6.c:fr_heap_entry_inserted
Unexecuted instantiation: fuzzer_radius.c:fr_heap_entry_inserted
Unexecuted instantiation: fuzzer_util.c:fr_heap_entry_inserted
Unexecuted instantiation: fuzzer_dhcpv4.c:fr_heap_entry_inserted
Unexecuted instantiation: fuzzer_bfd.c:fr_heap_entry_inserted
Unexecuted instantiation: decode.c:fr_heap_entry_inserted
Unexecuted instantiation: dl.c:fr_heap_entry_inserted
Unexecuted instantiation: encode.c:fr_heap_entry_inserted
Unexecuted instantiation: heap.c:fr_heap_entry_inserted
Unexecuted instantiation: struct.c:fr_heap_entry_inserted
Unexecuted instantiation: fuzzer.c:fr_heap_entry_inserted
Unexecuted instantiation: vmps.c:fr_heap_entry_inserted
Unexecuted instantiation: base.c:fr_heap_entry_inserted
128
129
/** Return the item from the top of the heap but don't pop it
130
 *
131
 * @param[in] h   to return element from.
132
 * @return
133
 *  - Element at the top of the heap.
134
 *  - NULL if no elements remain in the heap.
135
 */
136
static inline void *fr_heap_peek(fr_heap_t *h)
137
0
{
138
0
  if (h->num_elements == 0) return NULL;
139
0
140
0
  return h->p[1];
141
0
}
Unexecuted instantiation: fuzzer_tacacs.c:fr_heap_peek
Unexecuted instantiation: fuzzer_vmps.c:fr_heap_peek
Unexecuted instantiation: fuzzer_tftp.c:fr_heap_peek
Unexecuted instantiation: fuzzer_dns.c:fr_heap_peek
Unexecuted instantiation: fuzzer_dhcpv6.c:fr_heap_peek
Unexecuted instantiation: fuzzer_radius.c:fr_heap_peek
Unexecuted instantiation: fuzzer_util.c:fr_heap_peek
Unexecuted instantiation: fuzzer_dhcpv4.c:fr_heap_peek
Unexecuted instantiation: fuzzer_bfd.c:fr_heap_peek
Unexecuted instantiation: decode.c:fr_heap_peek
Unexecuted instantiation: dl.c:fr_heap_peek
Unexecuted instantiation: encode.c:fr_heap_peek
Unexecuted instantiation: heap.c:fr_heap_peek
Unexecuted instantiation: struct.c:fr_heap_peek
Unexecuted instantiation: fuzzer.c:fr_heap_peek
Unexecuted instantiation: vmps.c:fr_heap_peek
Unexecuted instantiation: base.c:fr_heap_peek
142
143
/** Peek at a specific index in the heap
144
 *
145
 * @param[in] h   to return element from.
146
 * @param[in] idx to lookup
147
 * @return
148
 *  - Element at the top of the heap.
149
 *  - NULL if index outside of the range of the heap.
150
 */
151
static inline void *fr_heap_peek_at(fr_heap_t *h, fr_heap_index_t idx)
152
0
{
153
0
  if (unlikely(idx > h->num_elements)) return NULL;
154
0
155
0
  return h->p[idx];
156
0
}
Unexecuted instantiation: fuzzer_tacacs.c:fr_heap_peek_at
Unexecuted instantiation: fuzzer_vmps.c:fr_heap_peek_at
Unexecuted instantiation: fuzzer_tftp.c:fr_heap_peek_at
Unexecuted instantiation: fuzzer_dns.c:fr_heap_peek_at
Unexecuted instantiation: fuzzer_dhcpv6.c:fr_heap_peek_at
Unexecuted instantiation: fuzzer_radius.c:fr_heap_peek_at
Unexecuted instantiation: fuzzer_util.c:fr_heap_peek_at
Unexecuted instantiation: fuzzer_dhcpv4.c:fr_heap_peek_at
Unexecuted instantiation: fuzzer_bfd.c:fr_heap_peek_at
Unexecuted instantiation: decode.c:fr_heap_peek_at
Unexecuted instantiation: dl.c:fr_heap_peek_at
Unexecuted instantiation: encode.c:fr_heap_peek_at
Unexecuted instantiation: heap.c:fr_heap_peek_at
Unexecuted instantiation: struct.c:fr_heap_peek_at
Unexecuted instantiation: fuzzer.c:fr_heap_peek_at
Unexecuted instantiation: vmps.c:fr_heap_peek_at
Unexecuted instantiation: base.c:fr_heap_peek_at
157
158
/** Peek at the last element in the heap (not necessarily the bottom)
159
 *
160
 * @param[in] h   to return element from.
161
 * @return
162
 *  - Last element in the heap.
163
 *  - NULL if no elements remain in the heap.
164
 */
165
static inline void *fr_heap_peek_tail(fr_heap_t *h)
166
0
{
167
0
  if (h->num_elements == 0) return NULL;
168
0
169
0
  /*
170
0
   *  If this is NULL, we have a problem.
171
0
   */
172
0
  return h->p[h->num_elements];
173
0
}
Unexecuted instantiation: fuzzer_tacacs.c:fr_heap_peek_tail
Unexecuted instantiation: fuzzer_vmps.c:fr_heap_peek_tail
Unexecuted instantiation: fuzzer_tftp.c:fr_heap_peek_tail
Unexecuted instantiation: fuzzer_dns.c:fr_heap_peek_tail
Unexecuted instantiation: fuzzer_dhcpv6.c:fr_heap_peek_tail
Unexecuted instantiation: fuzzer_radius.c:fr_heap_peek_tail
Unexecuted instantiation: fuzzer_util.c:fr_heap_peek_tail
Unexecuted instantiation: fuzzer_dhcpv4.c:fr_heap_peek_tail
Unexecuted instantiation: fuzzer_bfd.c:fr_heap_peek_tail
Unexecuted instantiation: decode.c:fr_heap_peek_tail
Unexecuted instantiation: dl.c:fr_heap_peek_tail
Unexecuted instantiation: encode.c:fr_heap_peek_tail
Unexecuted instantiation: heap.c:fr_heap_peek_tail
Unexecuted instantiation: struct.c:fr_heap_peek_tail
Unexecuted instantiation: fuzzer.c:fr_heap_peek_tail
Unexecuted instantiation: vmps.c:fr_heap_peek_tail
Unexecuted instantiation: base.c:fr_heap_peek_tail
174
175
/** Return the number of elements in the heap
176
 *
177
 * @param[in] h   to return the number of elements from.
178
 */
179
static inline unsigned int fr_heap_num_elements(fr_heap_t *h)
180
0
{
181
0
  return h->num_elements;
182
0
}
Unexecuted instantiation: fuzzer_tacacs.c:fr_heap_num_elements
Unexecuted instantiation: fuzzer_vmps.c:fr_heap_num_elements
Unexecuted instantiation: fuzzer_tftp.c:fr_heap_num_elements
Unexecuted instantiation: fuzzer_dns.c:fr_heap_num_elements
Unexecuted instantiation: fuzzer_dhcpv6.c:fr_heap_num_elements
Unexecuted instantiation: fuzzer_radius.c:fr_heap_num_elements
Unexecuted instantiation: fuzzer_util.c:fr_heap_num_elements
Unexecuted instantiation: fuzzer_dhcpv4.c:fr_heap_num_elements
Unexecuted instantiation: fuzzer_bfd.c:fr_heap_num_elements
Unexecuted instantiation: decode.c:fr_heap_num_elements
Unexecuted instantiation: dl.c:fr_heap_num_elements
Unexecuted instantiation: encode.c:fr_heap_num_elements
Unexecuted instantiation: heap.c:fr_heap_num_elements
Unexecuted instantiation: struct.c:fr_heap_num_elements
Unexecuted instantiation: fuzzer.c:fr_heap_num_elements
Unexecuted instantiation: vmps.c:fr_heap_num_elements
Unexecuted instantiation: base.c:fr_heap_num_elements
183
184
int   fr_heap_insert(fr_heap_t **hp, void *data) CC_HINT(nonnull);
185
int   fr_heap_extract(fr_heap_t **hp, void *data) CC_HINT(nonnull);
186
void    *fr_heap_pop(fr_heap_t **hp) CC_HINT(nonnull);
187
188
void    *fr_heap_iter_init(fr_heap_t *hp, fr_heap_iter_t *iter) CC_HINT(nonnull);
189
void    *fr_heap_iter_next(fr_heap_t *hp, fr_heap_iter_t *iter) CC_HINT(nonnull);
190
191
/** Iterate over the contents of a heap
192
 *
193
 * @note The initializer section of a for loop can't declare variables with distinct
194
 *   base types, so we require a containing block, and can't follow the standard
195
 *   do {...} while(0) dodge. The code to be run for each item in the heap should
196
 *   thus start with one open brace and end with two close braces, and shouldn't
197
 *   be followed with a semicolon.
198
 *   This may fake out code formatting programs and code-aware editors.
199
 *
200
 * @param[in] _heap   to iterate over.
201
 * @param[in] _type   of item the heap contains.
202
 * @param[in] _data   Name of variable holding a pointer to the heap element.
203
 *        Will be declared in the scope of the loop.
204
 */
205
#define fr_heap_foreach(_heap, _type, _data) \
206
{ \
207
  fr_heap_iter_t _iter; \
208
  for (_type *_data = fr_heap_iter_init(_heap, &_iter); _data; _data = fr_heap_iter_next(_heap, &_iter))
209
210
#ifndef TALLOC_GET_TYPE_ABORT_NOOP
211
void fr_heap_verify(char const *file, int line, fr_heap_t *hp);
212
#  define FR_HEAP_VERIFY(_heap) fr_heap_verify(__FILE__, __LINE__, _heap)
213
#elif !defined(NDEBUG)
214
#  define FR_HEAP_VERIFY(_heap) fr_assert(_heap)
215
#else
216
#  define FR_HEAP_VERIFY(_heap)
217
#endif
218
219
#undef _CONST
220
#ifdef __cplusplus
221
}
222
#endif