summary refs log tree commit diff
path: root/shared/nm-utils/c-list.h
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-06-04 00:07:45 +0200
committerMichael Biebl <biebl@debian.org>2018-06-04 00:07:45 +0200
commit04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (patch)
treed10c354b1b980ca8a7b9e48ec9019e8ed88bde2b /shared/nm-utils/c-list.h
parentee9c73a923909e23a649407be77e25235d769e25 (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.h397
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