Mercurial > unleashed > wips
view include/sys/ilist.h @ 20687:ac1492488560 draft
ilist: add generic circular doubly-linked list with a sentinel node
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Sun, 22 Mar 2020 10:48:20 -0400 |
parents | |
children |
line wrap: on
line source
/* * Copyright 2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef _SYS_ILIST_H #define _SYS_ILIST_H /* * Generic circular doubly-linked list with a sentinel node. * * The entire implementation is here as C99 static inline functions. We * hide them if we are not using a C99 compiler to expose the list_node * struct for list.h's benefit. * * Here's the summary of differences: * * (1) both ilist.h and list.h use the same struct list_node * (1) ilist.h uses static inlines while list.h uses normal functions * (2) list.h uses struct list to keep track of offsets into objects for the * struct list_node * (3) ilist.h uses struct list_head as a sentinel node and has no idea * about the structures containing each of the list entries */ #ifdef __cplusplus extern "C" { #endif struct list_node { struct list_node *list_next; struct list_node *list_prev; }; #ifdef _STDC_C99 #include <sys/null.h> static inline void ilist_init(struct list_node *node) { node->list_next = node; node->list_prev = node; } static inline int ilist_is_empty(struct list_node *list) { return list->list_next == list; } static int ilist_link_active(struct list_node *node) { return node->list_next != NULL; } static inline struct list_node *ilist_head(struct list_node *list) { if (ilist_is_empty(list)) return NULL; return list->list_next; } static inline struct list_node *ilist_tail(struct list_node *list) { if (ilist_is_empty(list)) return NULL; return list->list_prev; } static inline struct list_node *ilist_next(struct list_node *list, struct list_node *cur) { if (cur->list_next == list) return NULL; return cur->list_next; } static inline struct list_node *ilist_prev(struct list_node *list, struct list_node *cur) { if (cur->list_prev == list) return NULL; return cur->list_prev; } static inline void __ilist_insert(struct list_node *before, struct list_node *after, struct list_node *newnode) { before->list_next = newnode; newnode->list_prev = before; newnode->list_next = after; after->list_prev = newnode; } static inline void ilist_insert_after(struct list_node *reference, struct list_node *newnode) { __ilist_insert(reference, reference->list_next, newnode); } static inline void ilist_insert_before(struct list_node *reference, struct list_node *newnode) { __ilist_insert(reference->list_prev, reference, newnode); } #define ilist_insert_head(list, newnode) ilist_insert_after((list), (newnode)) #define ilist_insert_tail(list, newnode) ilist_insert_before((list), (newnode)) static inline void ilist_remove(struct list_node *node) { node->list_prev->list_next = node->list_next; node->list_next->list_prev = node->list_prev; node->list_prev = NULL; node->list_next = NULL; } static inline struct list_node *__ilist_remove(struct list_node *list, struct list_node *node) { if (ilist_is_empty(list)) return NULL; ilist_remove(node); return node; } static inline struct list_node *ilist_remove_head(struct list_node *list) { return __ilist_remove(list, list->list_next); } static inline struct list_node *ilist_remove_tail(struct list_node *list) { return __ilist_remove(list, list->list_prev); } #endif #ifdef __cplusplus } #endif #endif /* _SYS_ILIST_H */