24RCSIDH(tlist_h,
"$Id: b24c438809dc9c8cc822619ddf41f0921a1a6637 $")
30#include <freeradius-devel/util/dlist.h>
41#define tlist_type(_list) ((_list)->dlist_head.type)
138#define fr_tlist_init(_head, _type, _field) \
139 _Generic((((_type *)0)->_field), fr_tlist_t: _fr_tlist_init(_head, offsetof(_type, _field), NULL))
153#define fr_tlist_talloc_init(_head, _type, _field) \
154 _Generic((((_type *)0)->_field), fr_tlist_t: _fr_tlist_init(_head, offsetof(_type, _field), #_type))
179#define fr_tlist_foreach_entry(_list_head, _iter) \
180 for (void *_iter = fr_dlist_head(&_list_head->dlist_head); _iter; _iter = fr_dlist_next(&_list_head->dlist_head, _iter))
319 if (!list_head)
return true;
488#ifndef TALLOC_GET_TYPE_ABORT_NOOP
503 fr_assert_msg(entry->
list_head == list_head,
"CONSISTENCY CHECK FAILED %s[%i]: tlist entry %p has wrong parent",
513 "CONSISTENCY CHECK FAILED %s[%i]: tlist entry %p has different child type from parent",
520# define FR_TLIST_VERIFY(_head) fr_tlist_verify(__FILE__, __LINE__, _head)
521#elif !defined(NDEBUG)
522# define FR_TLIST_VERIFY(_head) fr_assert(_head)
524# define FR_TLIST_VERIFY(_head)
538#ifdef WITH_VERIFY_PTR
576#ifdef WITH_VERIFY_PTR
772#define FR_TLIST_ENTRY(_name) _name ## _entry_t
779#define FR_TLIST_HEAD(_name) _name ## _head_t
786#define FR_TLIST_TYPES(_name) \
787 typedef struct { fr_tlist_t entry; } FR_TLIST_ENTRY(_name); \
788 typedef struct { fr_tlist_head_t head; } FR_TLIST_HEAD(_name); \
800#define FR_TLIST_FUNCS(_name, _element_type, _element_entry) \
801DIAG_OFF(unused-function) \
802 _Static_assert(IS_FIELD_COMPATIBLE(_element_type, _element_entry, FR_TLIST_ENTRY(_name)) == 1, "Bad tlist entry field type");\
803 static inline fr_tlist_head_t *_name ## _list_head(FR_TLIST_HEAD(_name) const *list) \
804 { return UNCONST(fr_tlist_head_t *, &list->head); } \
806 static inline fr_dlist_head_t *_name ## _dlist_head(FR_TLIST_HEAD(_name) const *list) \
807 { return UNCONST(fr_dlist_head_t *, &list->head.dlist_head); } \
809 static inline void _name ## _entry_init(_element_type *entry) \
811 _Generic((&entry->_element_entry), \
812 FR_TLIST_ENTRY(_name) *: fr_tlist_entry_init(UNCONST(fr_tlist_t *, &entry->_element_entry.entry)), \
813 FR_TLIST_ENTRY(_name) const *: fr_tlist_noop()\
817 static inline void _name ## _init(FR_TLIST_HEAD(_name) *list) \
818 { _fr_tlist_init(&list->head, offsetof(_element_type, _element_entry), NULL); } \
820 static inline void _name ## _talloc_init(FR_TLIST_HEAD(_name) *list) \
821 { _fr_tlist_init(&list->head, offsetof(_element_type, _element_entry), #_element_type); } \
823 static inline void _name ## _clear(FR_TLIST_HEAD(_name) *list) \
824 { fr_tlist_clear(&list->head); } \
826 static inline bool _name ## _in_list(FR_TLIST_HEAD(_name) *list, _element_type *ptr) \
827 { return fr_tlist_in_list(&list->head, ptr); } \
829 static inline bool _name ## _in_a_list(_element_type *ptr) \
830 { return fr_tlist_entry_in_a_list(&ptr->_element_entry.entry); } \
832 static inline int _name ## _insert_head(FR_TLIST_HEAD(_name) *list, _element_type *ptr) \
833 { return fr_tlist_insert_head(&list->head, ptr); } \
835 static inline int _name ## _insert_tail(FR_TLIST_HEAD(_name) *list, _element_type *ptr) \
836 { return fr_tlist_insert_tail(&list->head, ptr); } \
838 static inline int _name ## _insert_after(FR_TLIST_HEAD(_name) *list, _element_type *pos, _element_type *ptr) \
839 { return fr_tlist_insert_after(&list->head, pos, ptr); } \
841 static inline int _name ## _insert_before(FR_TLIST_HEAD(_name) *list, _element_type *pos, _element_type *ptr) \
842 { return fr_tlist_insert_before(&list->head, pos, ptr); } \
844 static inline _element_type *_name ## _head(FR_TLIST_HEAD(_name) const *list) \
845 { return fr_tlist_head(&list->head); } \
847 static inline bool _name ## _empty(FR_TLIST_HEAD(_name) const *list) \
848 { return fr_tlist_empty(&list->head); } \
850 static inline bool _name ## _initialised(FR_TLIST_HEAD(_name) const *list) \
851 { return fr_tlist_initialised(&list->head); } \
853 static inline _element_type *_name ## _tail(FR_TLIST_HEAD(_name) const *list) \
854 { return fr_tlist_tail(&list->head); } \
856 static inline _element_type *_name ## _next(FR_TLIST_HEAD(_name) const *list, _element_type const *ptr) \
857 { return fr_tlist_next(&list->head, ptr); } \
859 static inline _element_type *_name ## _prev(FR_TLIST_HEAD(_name) const *list, _element_type const *ptr) \
860 { return fr_tlist_prev(&list->head, ptr); } \
862 static inline _element_type *_name ## _remove(FR_TLIST_HEAD(_name) *list, _element_type *ptr) \
863 { return fr_tlist_remove(&list->head, ptr); } \
865 static inline _element_type *_name ## _pop_head(FR_TLIST_HEAD(_name) *list) \
866 { return fr_tlist_pop_head(&list->head); } \
868 static inline _element_type *_name ## _pop_tail(FR_TLIST_HEAD(_name) *list) \
869 { return fr_tlist_pop_tail(&list->head); } \
871 static inline _element_type *_name ## _replace(FR_TLIST_HEAD(_name) *list, _element_type *item, _element_type *ptr) \
872 { return fr_tlist_replace(&list->head, item, ptr); } \
874 static inline int _name ## _move(FR_TLIST_HEAD(_name) *dst, FR_TLIST_HEAD(_name) *src) \
875 { return fr_tlist_move(&dst->head, &src->head); } \
877 static inline int _name ## _move_head(FR_TLIST_HEAD(_name) *dst, FR_TLIST_HEAD(_name) *src) \
878 { return fr_tlist_move_head(&dst->head, &src->head); } \
880 static inline void _name ## _talloc_free_head(FR_TLIST_HEAD(_name) *list) \
881 { fr_tlist_talloc_free_head(&list->head); } \
883 static inline void _name ## _talloc_free_tail(FR_TLIST_HEAD(_name) *list) \
884 { fr_tlist_talloc_free_tail(&list->head); } \
886 static inline void _name ## _talloc_free_item(FR_TLIST_HEAD(_name) *list, _element_type *ptr) \
887 { fr_tlist_talloc_free_item(&list->head, ptr); } \
889 static inline void _name ## _talloc_free(FR_TLIST_HEAD(_name) *list) \
890 { fr_tlist_talloc_free(&list->head); } \
892 static inline void _name ## _talloc_free_to_tail(FR_TLIST_HEAD(_name) *list, _element_type *ptr) \
893 { fr_tlist_talloc_free_to_tail(&list->head, ptr); } \
895 static inline void _name ## _talloc_reverse_free(FR_TLIST_HEAD(_name) *list) \
896 { fr_tlist_talloc_reverse_free(&list->head); } \
898 static inline unsigned int _name ## _num_elements(FR_TLIST_HEAD(_name) const *list) \
899 { return fr_tlist_num_elements(&list->head); } \
901 static inline int _name ## _sort(FR_TLIST_HEAD(_name) *list, fr_cmp_t cmp) \
902 { return fr_tlist_sort(&list->head, cmp); } \
904 static inline FR_TLIST_HEAD(_name) *_name ## _parent(const _element_type *ptr) \
905 { return (FR_TLIST_HEAD(_name) *) (ptr->_element_entry.entry.list_head); } \
907 static inline FR_TLIST_HEAD(_name) *_name ## _children(_element_type *ptr) \
908 { return (FR_TLIST_HEAD(_name) *) (ptr->_element_entry.entry.children); } \
910 static inline void _name ## _talloc_init_children(_element_type *ptr, FR_TLIST_HEAD(_name) *children) \
911 { _name ## _talloc_init(children); ptr->_element_entry.entry.children = &children->head; } \
913 static inline void _name ## _add_children(_element_type *ptr, FR_TLIST_HEAD(_name) *children) \
914 { fr_tlist_add_children(&ptr->_element_entry.entry, &children->head); } \
916 static inline FR_TLIST_HEAD(_name) * _name ## _remove_children(_element_type *ptr) \
917 { return (FR_TLIST_HEAD(_name) *) fr_tlist_remove_children(&ptr->_element_entry.entry); } \
919 static inline void _name ## _set_head(fr_tlist_head_t *list, _element_type *ptr) \
920 { ptr->_element_entry.entry.list_head = list; }
927 if (!ptr || !list_head)
return NULL;
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_assert_msg(_x, _msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
static int fr_dlist_sort_merge(void **merged, fr_dlist_head_t *head, void **a, void **b, fr_cmp_t cmp)
Merge phase of a merge sort of a dlist.
static int fr_dlist_sort(fr_dlist_head_t *list, fr_cmp_t cmp)
Sort a dlist using merge sort.
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
static int fr_dlist_move_head(fr_dlist_head_t *list_dst, fr_dlist_head_t *list_src)
Merge two lists, inserting the source at the head of the destination.
unsigned int offset
Positive offset from start of structure to fr_dlist_t.
static void * fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr)
Remove an item from the list.
static void fr_dlist_sort_split(fr_dlist_head_t *head, void **source, void **front, void **back)
Split phase of a merge sort of a dlist.
static int fr_dlist_insert_before(fr_dlist_head_t *list_head, void *pos, void *ptr)
Insert an item before an item already in the list.
static void fr_dlist_entry_unlink(fr_dlist_t *entry)
Remove an item from the dlist when we don't have access to the head.
char const * type
of items contained within the list.
static void * fr_dlist_prev(fr_dlist_head_t const *list_head, void const *ptr)
Get the previous item in a list.
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
static bool fr_dlist_empty(fr_dlist_head_t const *list_head)
Check whether a list has any items.
static void * fr_dlist_tail(fr_dlist_head_t const *list_head)
Return the TAIL item of a list or NULL if the list is empty.
static void * fr_dlist_replace(fr_dlist_head_t *list_head, void *item, void *ptr)
Replace an item in a dlist.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
static int fr_dlist_move(fr_dlist_head_t *list_dst, fr_dlist_head_t *list_src)
Merge two lists, inserting the source at the tail of the destination.
static int fr_dlist_insert_head(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the head of a list.
static void fr_dlist_entry_init(fr_dlist_t *entry)
Initialise a linked list without metadata.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
static int fr_dlist_insert_after(fr_dlist_head_t *list_head, void *pos, void *ptr)
Insert an item after an item already in the list.
static bool fr_dlist_initialised(fr_dlist_head_t const *list_head)
Check if the list head is initialised.
static int fr_dlist_recursive_sort(fr_dlist_head_t *head, void **ptr, fr_cmp_t cmp)
Recursive sort routine for dlist.
static void fr_dlist_clear(fr_dlist_head_t *list_head)
Efficiently remove all elements in a dlist.
Head of a doubly linked list.
Entry in a doubly linked list.
static void * item(fr_lst_t const *lst, fr_lst_index_t idx)
fr_cmp_ret_t(* fr_cmp_t)(void const *a, void const *b)
fr_aka_sim_id_type_t type
static void fr_tlist_entry_init(fr_tlist_t *entry)
Initialise a linked list without metadata.
static void * fr_tlist_head(fr_tlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
static void fr_tlist_talloc_free(fr_tlist_head_t *head)
Free all items in a doubly linked list (with talloc)
static void fr_tlist_talloc_free_to_tail(fr_tlist_head_t *head, void *ptr)
Free items in a doubly linked list (with talloc)
fr_tlist_t * parent
the parent entry which holds this list. May be NULL.
static void fr_tlist_sort_split(fr_tlist_head_t *head, void **source, void **front, void **back)
Split phase of a merge sort of a dlist.
static void * fr_tlist_pop_tail(fr_tlist_head_t *list_head)
Remove the tail item in a list.
static int fr_tlist_sort_merge(void **merged, fr_tlist_head_t *head, void **a, void **b, fr_cmp_t cmp)
Merge phase of a merge sort of a dlist.
static int fr_tlist_recursive_sort(fr_tlist_head_t *head, void **ptr, fr_cmp_t cmp)
Recursive sort routine for tlist.
static bool fr_tlist_empty(fr_tlist_head_t const *list_head)
Check whether a list has any items.
static void fr_tlist_talloc_free_tail(fr_tlist_head_t *list_head)
Free the last item in the list.
static void fr_tlist_talloc_free_head(fr_tlist_head_t *list_head)
Free the first item in the list.
static int fr_tlist_insert_tail(fr_tlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
fr_tlist_head_t * list_head
the list which holds this entry
static void fr_tlist_noop(void)
static void fr_tlist_verify(char const *file, int line, fr_tlist_head_t const *list_head)
Check all items in the list are valid.
static void * fr_tlist_talloc_free_item(fr_tlist_head_t *list_head, void *ptr)
Free the item specified.
static int fr_tlist_sort(fr_tlist_head_t *list, fr_cmp_t cmp)
Sort a tlist using merge sort.
#define fr_tlist_foreach_entry(_list_head, _iter)
Iterate over the contents of a list, only one level.
static int fr_tlist_insert_before(fr_tlist_head_t *list_head, void *pos, void *ptr)
Insert an item after an item already in the list.
static void * fr_tlist_entry_to_item(fr_tlist_head_t const *list_head, fr_tlist_t const *entry)
Get the item from a fr_tlist_t.
static void * fr_tlist_pop_head(fr_tlist_head_t *list_head)
Remove the head item in a list.
static int fr_tlist_insert_head(fr_tlist_head_t *list_head, void *ptr)
Insert an item into the head of a list.
static void * fr_tlist_parent(fr_tlist_head_t *list_head, void const *ptr)
static void * fr_tlist_prev(fr_tlist_head_t const *list_head, void const *ptr)
Get the previous item in a list.
static int fr_tlist_add_children(fr_tlist_t *entry, fr_tlist_head_t *children)
Add a pre-initialized child tlist to a parent entry.
static fr_tlist_t * fr_tlist_item_to_entry(fr_tlist_head_t const *list_head, void const *item)
Find the tlist pointers within a list item.
fr_dlist_head_t dlist_head
static void * fr_tlist_next(fr_tlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
static int fr_tlist_move(fr_tlist_head_t *list_dst, fr_tlist_head_t *list_src)
Merge two lists, inserting the source at the tail of the destination.
static void * fr_tlist_remove(fr_tlist_head_t *list_head, void *ptr)
Remove an item from the list.
static unsigned int fr_tlist_num_elements(fr_tlist_head_t const *list_head)
Return the number of elements in the tlist.
static bool fr_tlist_entry_in_a_list(fr_tlist_t const *entry)
Check if a list entry is part of a list.
static void * fr_tlist_replace(fr_tlist_head_t *list_head, void *item, void *ptr)
Replace an item in a dlist.
static void fr_tlist_init_children(fr_tlist_t *entry, fr_tlist_head_t *children)
Initialize a child tlist based on a parent entry.
static int fr_tlist_insert_after(fr_tlist_head_t *list_head, void *pos, void *ptr)
Insert an item after an item already in the list.
static int fr_tlist_move_head(fr_tlist_head_t *list_dst, fr_tlist_head_t *list_src)
Merge two lists, inserting the source at the head of the destination.
static void fr_tlist_entry_unlink(fr_tlist_t *entry)
static void fr_tlist_clear(fr_tlist_head_t *list_head)
Remove all elements in a tlist.
static void fr_tlist_talloc_reverse_free(fr_tlist_head_t *head)
Free all items in a doubly linked list from the tail backwards.
static void _fr_tlist_init(fr_tlist_head_t *list_head, size_t offset, char const *type)
Initialise common fields in a tlist.
#define tlist_type(_list)
static fr_tlist_head_t * fr_tlist_remove_children(fr_tlist_t *entry)
Remove a child tlist from a parent entry.
fr_tlist_head_t * children
any child list
static void * fr_tlist_tail(fr_tlist_head_t const *list_head)
Return the TAIL item of a list or NULL if the list is empty.
static bool fr_tlist_in_list(fr_tlist_head_t *list_head, void *ptr)
Check if a list entry is part of a tlist.
static fr_tlist_head_t * fr_tlist_head_from_dlist(fr_dlist_head_t *dlist_head)
Get a fr_tlist_head_t from a fr_dlist_head_t.
fr_dlist_t dlist_entry
the doubly linked list of entries.
static bool fr_tlist_initialised(fr_tlist_head_t const *list_head)
Check if the list head is initialised.