diff options
| author | Michael Biebl <biebl@debian.org> | 2018-06-04 00:07:45 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-06-04 00:07:45 +0200 |
| commit | 04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (patch) | |
| tree | d10c354b1b980ca8a7b9e48ec9019e8ed88bde2b /shared/nm-utils/c-list.h | |
| parent | ee9c73a923909e23a649407be77e25235d769e25 (diff) | |
New upstream version 1.11.4 upstream/1.11.4
Diffstat (limited to 'shared/nm-utils/c-list.h')
| -rw-r--r-- | shared/nm-utils/c-list.h | 397 |
1 files changed, 0 insertions, 397 deletions
diff --git a/shared/nm-utils/c-list.h b/shared/nm-utils/c-list.h deleted file mode 100644 index a3c4053b..00000000 --- a/shared/nm-utils/c-list.h +++ /dev/null @@ -1,397 +0,0 @@ -#pragma once - -/* - * Circular Double Linked List Implementation in Standard ISO-C11 - * - * This implements a generic circular double linked list. List entries must - * embed the CList object, which provides pointers to the next and previous - * element. Insertion and removal can be done in O(1) due to the double links. - * Furthermore, the list is circular, thus allows access to front/tail in O(1) - * as well, even if you only have a single head pointer (which is not how the - * list is usually operated, though). - * - * Note that you are free to use the list implementation without a head - * pointer. However, usual operation uses a single CList object as head, which - * is itself linked in the list and as such must be identified as list head. - * This allows very simply list operations and avoids a lot of special cases. - * Most importantly, you can unlink entries without requiring a head pointer. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stddef.h> - -typedef struct CList CList; - -/** - * struct CList - Entry of a circular double linked list - * @next: next entry - * @prev: previous entry - * - * Each entry in a list must embed a CList object. This object contains - * pointers to its next and previous elements, which can be freely accessed by - * the API user at any time. Note that the list is circular, and the list head - * is linked in the list as well. - * - * The list head must be initialized via C_LIST_INIT before use. There is no - * reason to initialize entry objects before linking them. However, if you need - * a boolean state that tells you whether the entry is linked or not, you should - * initialize the entry via C_LIST_INIT as well. - */ -struct CList { - CList *next; - CList *prev; -}; - -#define C_LIST_INIT(_var) { .next = &(_var), .prev = &(_var) } - -/** - * c_list_init() - initialize list entry - * @what: list entry to initialize - */ -static inline void c_list_init(CList *what) { - *what = (CList)C_LIST_INIT(*what); -} - -/** - * c_list_entry() - get parent container of list entry - * @_what: list entry, or NULL - * @_t: type of parent container - * @_m: member name of list entry in @_t - * - * If the list entry @_what is embedded into a surrounding structure, this will - * turn the list entry pointer @_what into a pointer to the parent container - * (using offsetof(3), or sometimes called container_of(3)). - * - * If @_what is NULL, this will also return NULL. - * - * Return: Pointer to parent container, or NULL. - */ -#define c_list_entry(_what, _t, _m) \ - ((_t *)(void *)(((unsigned long)(void *)(_what) ?: \ - offsetof(_t, _m)) - offsetof(_t, _m))) - -/** - * c_list_is_linked() - check whether an entry is linked - * @what: entry to check, or NULL - * - * Return: True if @what is linked in a list, false if not. - */ -static inline _Bool c_list_is_linked(const CList *what) { - return what && what->next != what; -} - -/** - * c_list_is_empty() - check whether a list is empty - * @list: list to check, or NULL - * - * Return: True if @list is empty, false if not. - */ -static inline _Bool c_list_is_empty(const CList *list) { - return !list || !c_list_is_linked(list); -} - -/** - * c_list_link_before() - link entry into list - * @where: linked list entry used as anchor - * @what: entry to link - * - * This links @what directly in front of @where. @where can either be a list - * head or any entry in the list. - * - * If @where points to the list head, this effectively links @what as new tail - * element. Hence, the macro c_list_link_tail() is an alias to this. - * - * @what is not inspected prior to being linked. Hence, it better not be linked - * into another list, or the other list will be corrupted. - */ -static inline void c_list_link_before(CList *where, CList *what) { - CList *prev = where->prev, *next = where; - - next->prev = what; - what->next = next; - what->prev = prev; - prev->next = what; -} -#define c_list_link_tail(_list, _what) c_list_link_before((_list), (_what)) - -/** - * c_list_link_after() - link entry into list - * @where: linked list entry used as anchor - * @what: entry to link - * - * This links @what directly after @where. @where can either be a list head or - * any entry in the list. - * - * If @where points to the list head, this effectively links @what as new front - * element. Hence, the macro c_list_link_front() is an alias to this. - * - * @what is not inspected prior to being linked. Hence, it better not be linked - * into another list, or the other list will be corrupted. - */ -static inline void c_list_link_after(CList *where, CList *what) { - CList *prev = where, *next = where->next; - - next->prev = what; - what->next = next; - what->prev = prev; - prev->next = what; -} -#define c_list_link_front(_list, _what) c_list_link_after((_list), (_what)) - -/** - * c_list_unlink_stale() - unlink element from list - * @what: element to unlink - * - * This unlinks @what. If @what was initialized via C_LIST_INIT(), it has no - * effect. If @what was never linked, nor initialized, behavior is undefined. - * - * Note that this does not modify @what. It just modifies the previous and next - * elements in the list to no longer reference @what. If you want to make sure - * @what is re-initialized after removal, use c_list_unlink(). - */ -static inline void c_list_unlink_stale(CList *what) { - CList *prev = what->prev, *next = what->next; - - next->prev = prev; - prev->next = next; -} - -/** - * c_list_unlink() - unlink element from list and re-initialize - * @what: element to unlink - * - * This is like c_list_unlink_stale() but re-initializes @what after removal. - */ -static inline void c_list_unlink(CList *what) { - /* condition is not needed, but avoids STOREs in fast-path */ - if (c_list_is_linked(what)) { - c_list_unlink_stale(what); - *what = (CList)C_LIST_INIT(*what); - } -} - -/** - * c_list_swap() - exchange the contents of two lists - * @list1: the list to operate on - * @list2: the list to operate on - * - * This replaces the contents of the list @list1 with the contents - * of @list2, and vice versa. - */ -static inline void c_list_swap(CList *list1, CList *list2) { - CList t; - - /* make neighbors of list1 point to list2, and vice versa */ - t = *list1; - t.next->prev = list2; - t.prev->next = list2; - t = *list2; - t.next->prev = list1; - t.prev->next = list1; - - /* swap list1 and list2 now that their neighbors were fixed up */ - t = *list1; - *list1 = *list2; - *list2 = t; -} - -/** - * c_list_splice() - splice one list into another - * @target: the list to splice into - * @source: the list to splice - * - * This removes all the entries from @source and splice them into @target. - * The order of the two lists is preserved and the source is appended - * to the end of target. - * - * On return, the source list will be empty. - */ -static inline void c_list_splice(CList *target, CList *source) { - if (!c_list_is_empty(source)) { - /* attach the front of @source to the tail of @target */ - source->next->prev = target->prev; - target->prev->next = source->next; - - /* attach the tail of @source to the front of @target */ - source->prev->next = target; - target->prev = source->prev; - - /* clear source */ - *source = (CList)C_LIST_INIT(*source); - } -} - -/** - * c_list_for_each() - loop over all list entries - * @_iter: iterator to use - * @_list: list to loop over - * - * This is a macro to use as for-loop to iterate an entire list. It is meant as - * convenience macro. Feel free to code your own loop iterator. - */ -#define c_list_for_each(_iter, _list) \ - for (_iter = (_list)->next; \ - (_iter) != (_list); \ - _iter = (_iter)->next) - - -/** - * c_list_for_each_safe() - loop over all list entries, safe for removal - * @_iter: iterator to use - * @_safe: used to store pointer to next element - * @_list: list to loop over - * - * This is a macro to use as for-loop to iterate an entire list, safe against - * removal of the current element. It is meant as convenience macro. Feel free - * to code your own loop iterator. - * - * Note that this fetches the next element prior to executing the loop body. - * This makes it safe against removal of the current entry, but it will go - * havoc if you remove other list entries. You better not modify anything but - * the current list entry. - */ -#define c_list_for_each_safe(_iter, _safe, _list) \ - for (_iter = (_list)->next, _safe = (_iter)->next; \ - (_iter) != (_list); \ - _iter = (_safe), _safe = (_safe)->next) - -/** - * c_list_for_each_entry() - loop over all list entries - * @_iter: iterator to use - * @_list: list to loop over - * @_m: member name of CList object in list type - * - * This combines c_list_for_each() with c_list_entry(), making it easy to - * iterate over a list of a specific type. - */ -#define c_list_for_each_entry(_iter, _list, _m) \ - for (_iter = c_list_entry((_list)->next, __typeof__(*_iter), _m); \ - &(_iter)->_m != (_list); \ - _iter = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m)) - -/** - * c_list_for_each_entry_safe() - loop over all list entries, safe for removal - * @_iter: iterator to use - * @_safe: used to store pointer to next element - * @_list: list to loop over - * @_m: member name of CList object in list type - * - * This combines c_list_for_each_safe() with c_list_entry(), making it easy to - * iterate over a list of a specific type. - */ -#define c_list_for_each_entry_safe(_iter, _safe, _list, _m) \ - for (_iter = c_list_entry((_list)->next, __typeof__(*_iter), _m), \ - _safe = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m); \ - &(_iter)->_m != (_list); \ - _iter = (_safe), \ - _safe = c_list_entry((_safe)->_m.next, __typeof__(*_iter), _m)) \ - -/** - * c_list_first() - return pointer to first element, or NULL if empty - * @list: list to operate on, or NULL - * - * This returns a pointer to the first element, or NULL if empty. This never - * returns a pointer to the list head. - * - * Return: Pointer to first list element, or NULL if empty. - */ -static inline CList *c_list_first(CList *list) { - return c_list_is_empty(list) ? NULL : list->next; -} - -/** - * c_list_last() - return pointer to last element, or NULL if empty - * @list: list to operate on, or NULL - * - * This returns a pointer to the last element, or NULL if empty. This never - * returns a pointer to the list head. - * - * Return: Pointer to last list element, or NULL if empty. - */ -static inline CList *c_list_last(CList *list) { - return c_list_is_empty(list) ? NULL : list->prev; -} - -/** - * c_list_first_entry() - return pointer to first entry, or NULL if empty - * @_list: list to operate on, or NULL - * @_t: type of list entries - * @_m: name of CList member in @_t - * - * This is like c_list_first(), but also applies c_list_entry() on the result. - * - * Return: Pointer to first list entry, or NULL if empty. - */ -#define c_list_first_entry(_list, _t, _m) \ - c_list_entry(c_list_first(_list), _t, _m) - -/** - * c_list_last_entry() - return pointer to last entry, or NULL if empty - * @_list: list to operate on, or NULL - * @_t: type of list entries - * @_m: name of CList member in @_t - * - * This is like c_list_last(), but also applies c_list_entry() on the result. - * - * Return: Pointer to last list entry, or NULL if empty. - */ -#define c_list_last_entry(_list, _t, _m) \ - c_list_entry(c_list_last(_list), _t, _m) - -/** - * c_list_length() - return number of linked entries, excluding the head - * @list: list to operate on - * - * Returns the number of entries in the list, excluding the list head @list. - * That is, for a list that is empty according to c_list_is_empty(), the - * returned length is 0. This requires to iterate the list and has thus O(n) - * runtime. - * - * Note that this function is meant for debugging purposes only. If you need - * the list size during normal operation, you should maintain a counter - * separately. - * - * Return: Number of items in @list. - */ -static inline unsigned long c_list_length(const CList *list) { - unsigned long n = 0; - const CList *iter; - - c_list_for_each(iter, list) - ++n; - - return n; -} - -/** - * c_list_contains() - check whether an entry is linked in a certain list - * @list: list to operate on - * @what: entry to look for - * - * This checks whether @what is linked into @list. This requires a linear - * search through the list, as such runs in O(n). Note that the list-head is - * considered part of the list, and hence this returns true if @what equals - * @list. - * - * Note that this function is meant for debugging purposes, and consistency - * checks. You should always be aware whether your objects are linked in a - * specific list. - * - * Return: True if @what is in @list, false otherwise. - */ -static inline _Bool c_list_contains(const CList *list, const CList *what) { - const CList *iter; - - c_list_for_each(iter, list) - if (what == iter) - return 1; - - return what == list; -} - -#ifdef __cplusplus -} -#endif |