23 RCSID(
"$Id: 0d1afa2f48e13d67958aa272eea1d49c20178b2a $")
25 #include <freeradius-devel/util/lst.h>
26 #include <freeradius-devel/util/misc.h>
27 #include <freeradius-devel/util/rand.h>
28 #include <freeradius-devel/util/strerror.h>
48 #define INITIAL_CAPACITY 2048
50 #define is_power_of_2(_n) ((_n) && (((_n) & ((_n) - 1)) == 0))
108 return idx & ((lst)->capacity - 1);
111 static inline CC_HINT(always_inline,
nonnull)
168 if (s->
size == UINT_MAX) {
176 n_size = s->
size * 2;
216 static inline CC_HINT(always_inline,
nonnull)
219 s->data[idx] = new_value;
226 unsigned int initial_stack_capacity;
234 for (initial_stack_capacity = 1; (1U << initial_stack_capacity) <
init; initial_stack_capacity++) ;
252 lst->
p = talloc_array(lst,
void *, lst->
capacity);
266 s->
size = initial_stack_capacity;
304 if (reduced_idx <= reduced_right)
return reduced_right - reduced_idx;
306 return (lst->
capacity - reduced_idx) + reduced_right;
347 for (ridx = 0; ridx < stack_index; ridx++) {
352 empty_bucket = (new_space - prev_pivot_index) == 1;
355 if (!empty_bucket)
lst_move(lst, new_space,
item(lst, prev_pivot_index + 1));
358 lst_move(lst, prev_pivot_index + 1,
item(lst, prev_pivot_index));
368 stack_set(&lst->
s, stack_index, new_space + 1);
384 lst->
idx = reduced_idx;
405 unsigned int old_capacity = lst->
capacity, n_capacity;
408 if (
unlikely(old_capacity > (UINT_MAX - old_capacity))) {
409 if (old_capacity == UINT_MAX) {
413 n_capacity = UINT_MAX;
416 n_capacity = old_capacity * 2;
419 n = talloc_realloc(lst, lst->
p,
void *, n_capacity);
422 n_capacity, n_capacity *
sizeof(
void *));
431 for (i = 0; i < lst->
idx; i++) {
432 void *to_be_moved =
item(lst, i);
435 lst_move(lst, new_index, to_be_moved);
479 pivot =
item(lst, pivot_index);
481 if (pivot_index != low) {
493 while (lst->
cmp(
item(lst, --h), pivot) > 0) ;
494 while (lst->
cmp(
item(lst, ++l), pivot) < 0) ;
507 pivot_index = low + pivot_index -
index_reduce(lst, low);
509 pivot_index = high - (
index_reduce(lst, high) - pivot_index);
515 if (pivot_index < h) {
519 if (pivot_index > h) {
544 if (stack_index == 0)
break;
586 if (
lst_size(lst, stack_index) == 0) {
640 }
else if (cmp > 0) {
665 #ifndef TALLOC_GET_TYPE_ABORT_NOOP
666 if (lst->
type) (void)_talloc_get_type_abort(
data, lst->
type, __location__);
793 #ifndef TALLOC_GET_TYPE_ABORT_NOOP
796 fr_lst_index_t fake_pivot_index, reduced_fake_pivot_index, reduced_end;
799 bool pivots_in_order =
true;
800 bool pivot_indices_in_order =
true;
803 talloc_get_type_abort(lst,
fr_lst_t);
815 reduced_fake_pivot_index =
index_reduce(lst, fake_pivot_index);
818 "CONSISTENCY CHECK FAILED %s[%i]: fictitious pivot doesn't point past last element",
830 "CONSISTENCY CHECK FAILED %s[%i]: bucket %u size %u is invalid",
831 file,
line, stack_index, bucket_size);
832 bucket_size_sum += bucket_size;
836 "CONSISTENCY CHECK FAILED %s[%i]: buckets inconsistent with number of elements",
846 void *element =
item(lst, lst->
idx + i);
848 fr_fatal_assert_msg(element,
"CONSISTENCY CHECK FAILED %s[%i]: null element pointer at %u",
851 "CONSISTENCY CHECK FAILED %s[%i]: element %u index mismatch",
file,
line, i);
852 if (lst->
type) (void) _talloc_get_type_abort(element, lst->
type, __location__);
865 void *current_pivot =
pivot_item(lst, stack_index);
866 void *next_pivot =
pivot_item(lst, stack_index + 1);
868 if (current_pivot && next_pivot && lst->
cmp(current_pivot, next_pivot) < 0) pivots_in_order =
false;
870 fr_fatal_assert_msg(pivots_in_order,
"CONSISTENCY CHECK FAILED %s[%i]: pivots not in ascending order",
882 if (previous_pivot_index >= current_pivot_index) pivot_indices_in_order =
false;
884 fr_fatal_assert_msg(pivot_indices_in_order,
"CONSISTENCY CHECK FAILED %s[%i]: pivots indices not in order",
896 if (stack_index > 0) {
898 pivot_index = upb =
stack_item(&(lst->
s), stack_index);
901 element =
item(lst, index);
903 "CONSISTENCY CHECK FAILED %s[%i]: element at %u > pivot at %u",
907 if (stack_index + 1 <
depth) {
909 lwb = pivot_index =
stack_item(&(lst->
s), stack_index + 1);
912 element =
item(lst, index);
914 "CONSISTENCY CHECK FAILED %s[%i]: element at %u < pivot at %u",
#define fr_fatal_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
int fr_lst_extract(fr_lst_t *lst, void *data)
Remove an element from an LST.
stack_index_t depth
The current stack depth.
static void * _fr_lst_pop(fr_lst_t *lst, stack_index_t stack_index)
static fr_lst_index_t stack_item(pivot_stack_t const *s, stack_index_t idx)
static void lst_indices_reduce(fr_lst_t *lst)
Reduce pivot stack indices based on their difference from lst->idx, and then reduce lst->idx.
static stack_index_t stack_depth(pivot_stack_t const *s)
void fr_lst_verify(char const *file, int line, fr_lst_t const *lst)
static void lst_flatten(fr_lst_t *lst, stack_index_t stack_index)
Flatten an LST, i.e.
#define is_power_of_2(_n)
static void item_set(fr_lst_t *lst, fr_lst_index_t idx, void *data)
void * fr_lst_pop(fr_lst_t *lst)
static fr_lst_index_t lst_size(fr_lst_t *lst, stack_index_t stack_index)
The size function for LSTs (number of items a (sub)tree contains)
static void partition(fr_lst_t *lst, stack_index_t stack_index)
unsigned int capacity
Number of elements that will fit.
static bool is_equivalent(fr_lst_t const *lst, fr_lst_index_t idx1, fr_lst_index_t idx2)
static void * pivot_item(fr_lst_t const *lst, stack_index_t idx)
char const * type
Type of elements.
void * fr_lst_iter_next(fr_lst_t *lst, fr_lst_iter_t *iter)
Get the next entry in an LST.
pivot_stack_t s
Stack of pivots, always with depth >= 1.
static fr_lst_index_t index_reduce(fr_lst_t const *lst, fr_lst_index_t idx)
static bool lst_expand(fr_lst_t *lst)
Make more space available in an LST.
static stack_index_t lst_length(fr_lst_t const *lst, stack_index_t stack_index)
The length function for LSTs (how many buckets it contains)
static void bucket_delete(fr_lst_t *lst, stack_index_t stack_index, void *data)
static void stack_set(pivot_stack_t *s, stack_index_t idx, fr_lst_index_t new_value)
fr_lst_index_t idx
Starting index, initially zero.
int fr_lst_insert(fr_lst_t *lst, void *data)
static void * index_addr(fr_lst_t const *lst, void *data)
unsigned int fr_lst_num_elements(fr_lst_t *lst)
static void stack_pop(pivot_stack_t *s, unsigned int n)
fr_lst_t * _fr_lst_alloc(TALLOC_CTX *ctx, fr_lst_cmp_t cmp, char const *type, size_t offset, fr_lst_index_t init)
static void bucket_add(fr_lst_t *lst, stack_index_t stack_index, void *data)
Add data to the bucket of a specified (sub)tree.
static void _fr_lst_extract(fr_lst_t *lst, stack_index_t stack_index, void *data)
static fr_lst_index_t raw_item_index(fr_lst_t const *lst, void *data)
void * fr_lst_peek(fr_lst_t *lst)
unsigned int size
The current stack size (number of frames)
fr_lst_cmp_t cmp
Comparator function.
static void _fr_lst_insert(fr_lst_t *lst, stack_index_t stack_index, void *data)
unsigned int stack_index_t
fr_fast_rand_t rand_ctx
Seed for random choices.
unsigned int num_elements
Number of elements in the LST.
static void lst_move(fr_lst_t *lst, fr_lst_index_t location, void *data)
Move data to a specific location in an LST's array.
fr_lst_index_t * data
Array of indices of the pivots (sometimes called roots)
static fr_lst_index_t item_index(fr_lst_t const *lst, void *data)
static bool is_bucket(fr_lst_t const *lst, stack_index_t idx)
static void item_index_set(fr_lst_t *lst, void *data, fr_lst_index_t idx)
static fr_lst_index_t bucket_upb(fr_lst_t const *lst, stack_index_t stack_index)
static int stack_push(fr_lst_t *lst, pivot_stack_t *s, fr_lst_index_t pivot)
static fr_lst_index_t bucket_lwb(fr_lst_t const *lst, stack_index_t stack_index)
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
void * fr_lst_iter_init(fr_lst_t *lst, fr_lst_iter_t *iter)
Iterate over entries in LST.
size_t offset
Offset of heap index in element structure.
static void * _fr_lst_peek(fr_lst_t *lst, stack_index_t stack_index)
static bool stack_expand(fr_lst_t *lst, pivot_stack_t *s)
void ** p
Array of elements.
fr_lst_index_t fr_lst_iter_t
int8_t(* fr_lst_cmp_t)(void const *a, void const *b)
unsigned int fr_lst_index_t
static uint8_t fr_high_bit_pos(uint64_t num)
Find the highest order high bit in an unsigned 64 bit integer.
static uint8_t depth(fr_minmax_heap_index_t i)
uint32_t fr_fast_rand(fr_fast_rand_t *ctx)
uint32_t fr_rand(void)
Return a 32-bit random number.
Smaller fast random number generator.
static size_t min(size_t x, size_t y)
init
Enter the EAP-IDENTITY state.
fr_aka_sim_id_type_t type
#define talloc_zero_pooled_object(_ctx, _type, _num_subobjects, _total_subobjects_size)
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)