23RCSID(
"$Id: 4ca3c1edec829ae89977fdfc0c3a459cdd92d7b9 $")
25#include <freeradius-devel/util/minmax_heap.h>
26#include <freeradius-devel/util/strerror.h>
27#include <freeradius-devel/util/debug.h>
28#include <freeradius-devel/util/misc.h>
67#define INITIAL_CAPACITY 2048
74#define HEAP_PARENT(_x) ((_x) >> 1)
75#define HEAP_GRANDPARENT(_x) HEAP_PARENT(HEAP_PARENT(_x))
76#define HEAP_LEFT(_x) (2 * (_x))
77#define HEAP_RIGHT(_x) (2 * (_x) + 1 )
78#define HEAP_SWAP(_a, _b) do { void *_tmp = _a; _a = _b; _b = _tmp; } while (0)
90 return (
depth(i) & 1) == 0;
103 if (
unlikely(candidate_depth < ancestor_depth))
return false;
106 return (candidate - level_min) < level_min;
109#define is_max_level_index(_i) (!(is_min_level_index(_i)))
147 h->
p[0] = (
void *)UINTPTR_MAX;
165 if (h->
size == UINT_MAX) {
171 n_size = 2 * h->
size;
177 n_size, (n_size *
sizeof(
void *)));
208#define OFFSET_SET(_heap, _idx) index_set(_heap, _heap->p[_idx], _idx)
209#define OFFSET_RESET(_heap, _idx) index_set(_heap, _heap->p[_idx], 0)
289 c = h->
cmp(h->
p[upb], h->
p[max]);
291 if (c ==
CMP_GT) max = upb;
311 c = h->
cmp(h->
p[i], h->
p[max]);
339 c = h->
cmp(h->
p[m], h->
p[idx]);
391 c = h->
cmp(h->
p[m], h->
p[idx]);
576 c = h->
cmp(h->
p[2], h->
p[3]);
635 if (likely(ret == 0)) ret =
push_down(h, idx);
693#ifndef TALLOC_GET_TYPE_ABORT_NOOP
715 "CONSISTENCY CHECK FAILED %s[%i]: num_elements exceeds size",
file,
line);
718 "CONSISTENCY CHECK FAILED %s[%i]: zeroeth element special value overwritten",
file,
line);
721 void *
data = h->
p[i];
724 if (h->
type) (void)_talloc_get_type_abort(
data, h->
type, __location__);
726 "CONSISTENCY CHECK FAILED %s[%i]: node %u index != %u",
file,
line, i, i);
765 "CONSISTENCY CHECK FAILED %s[%i]: comparator error: %s",
768 "CONSISTENCY CHECK FAILED %s[%i]: node %u violates %s level condition",
769 file,
line, i, on_min_level ?
"min" :
"max");
static size_t min(size_t x, size_t y)
#define fr_fatal_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
static uint8_t fr_high_bit_pos(uint64_t num)
Find the highest order high bit in an unsigned 64 bit integer.
static int max_child_or_grandchild(fr_minmax_heap_index_t *out, minmax_heap_t *h, fr_minmax_heap_index_t idx)
int fr_minmax_heap_insert(fr_minmax_heap_t *hp, void *data)
static bool has_grandchildren(minmax_heap_t *h, fr_minmax_heap_index_t i)
static int min_child_or_grandchild(fr_minmax_heap_index_t *out, minmax_heap_t *h, fr_minmax_heap_index_t idx)
Find the index of the minimum child or grandchild of the entry at a given index.
static void index_set(minmax_heap_t *h, void *data, fr_minmax_heap_index_t idx)
static int push_up_max(minmax_heap_t *h, fr_minmax_heap_index_t idx)
#define OFFSET_SET(_heap, _idx)
static int push_down_min(minmax_heap_t *h, fr_minmax_heap_index_t idx)
precondition: idx is the index of an existing entry on a min level
static int minmax_heap_expand(fr_minmax_heap_t *hp)
void * fr_minmax_heap_iter_next(fr_minmax_heap_t *hp, fr_minmax_heap_iter_t *iter)
Get the next entry in a minmax heap.
int fr_minmax_heap_min_pop(void **out, fr_minmax_heap_t *hp)
void * p[]
Array of nodes.
static int push_up_min(minmax_heap_t *h, fr_minmax_heap_index_t idx)
int fr_minmax_heap_max_pop(void **out, fr_minmax_heap_t *hp)
static int push_up(minmax_heap_t *h, fr_minmax_heap_index_t idx)
static bool has_children(minmax_heap_t *h, fr_minmax_heap_index_t idx)
void * fr_minmax_heap_min_peek(fr_minmax_heap_t *hp)
static int push_down_max(minmax_heap_t *h, fr_minmax_heap_index_t idx)
precondition: idx is the index of an existing entry on a max level (Just like push_down_min() save fo...
#define OFFSET_RESET(_heap, _idx)
#define is_max_level_index(_i)
#define HEAP_GRANDPARENT(_x)
static uint8_t depth(fr_minmax_heap_index_t i)
static int push_down(minmax_heap_t *h, fr_minmax_heap_index_t idx)
fr_minmax_heap_cmp_t cmp
Comparator function.
unsigned int fr_minmax_heap_num_elements(fr_minmax_heap_t *hp)
Return the number of elements in the minmax heap.
#define HEAP_SWAP(_a, _b)
struct fr_minmax_heap_s minmax_heap_t
fr_minmax_heap_t * _fr_minmax_heap_alloc(TALLOC_CTX *ctx, fr_minmax_heap_cmp_t cmp, char const *type, size_t offset, unsigned int init)
static bool is_min_level_index(fr_minmax_heap_index_t i)
static bool is_descendant(fr_minmax_heap_index_t candidate, fr_minmax_heap_index_t ancestor)
size_t offset
Offset of heap index in element structure.
void * fr_minmax_heap_iter_init(fr_minmax_heap_t *hp, fr_minmax_heap_iter_t *iter)
Iterate over entries in a minmax heap.
int fr_minmax_heap_extract(fr_minmax_heap_t *hp, void *data)
int fr_minmax_heap_max_peek(void **out, fr_minmax_heap_t *hp)
unsigned int size
Number of nodes allocated.
char const * type
Talloc type of elements.
static fr_minmax_heap_index_t index_get(minmax_heap_t *h, void *data)
void fr_minmax_heap_verify(char const *file, int line, fr_minmax_heap_t const *hp)
unsigned int num_elements
Number of nodes used.
static bool fr_minmax_heap_entry_inserted(fr_minmax_heap_index_t heap_idx)
Check if an entry is inserted into a heap.
fr_cmp_ret_t(* fr_minmax_heap_cmp_t)(void const *a, void const *b)
Comparator to order elements.
unsigned int fr_minmax_heap_iter_t
unsigned int fr_minmax_heap_index_t
fr_cmp_ret_t
Result of an ordering comparison.
@ CMP_ERR
comparison failed
init
Enter the EAP-IDENTITY state.
fr_aka_sim_id_type_t type
char const * fr_strerror(void)
Get the last library error.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
static size_t char ** out