clist: add circular list api
parent
a34fd6caaa
commit
89e7a4eb47
@ -0,0 +1,158 @@
|
||||
/* See the end of this file for copyright and license terms. */
|
||||
|
||||
/**
|
||||
* @file gay/clist.h
|
||||
* @brief Plain and simple circular list implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gay/cdefs.h>
|
||||
|
||||
/**
|
||||
* @brief Simple circular list header.
|
||||
* Embed this into other structures to make them part of a list.
|
||||
*/
|
||||
struct clist {
|
||||
struct clist *next;
|
||||
struct clist *prev;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Declare and define a clist.
|
||||
*
|
||||
* @param name Name of the list
|
||||
*/
|
||||
#define CLIST(name) \
|
||||
struct clist name = { \
|
||||
.next = &name, \
|
||||
.prev = &name, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize a new clist.
|
||||
* Use this only for dynamically allocated lists,
|
||||
* there is the `CLIST()` macro for globals.
|
||||
*
|
||||
* @param list List to initialize
|
||||
*/
|
||||
void clist_init(struct clist *list);
|
||||
|
||||
/**
|
||||
* @brief Add a new node at the end of a clist.
|
||||
*
|
||||
* @param head Head of the list
|
||||
* @param new New node to insert at the end
|
||||
*/
|
||||
void clist_add(struct clist *head, struct clist *new);
|
||||
|
||||
/**
|
||||
* @brief Add a new node at the beginning of a clist.
|
||||
*
|
||||
* @param head Head of the list
|
||||
* @param new New node to insert at the beginning
|
||||
*/
|
||||
void clist_add_first(struct clist *head, struct clist *new);
|
||||
|
||||
/**
|
||||
* @brief Remove a node from a clist.
|
||||
*
|
||||
* @param node Node to remove
|
||||
*/
|
||||
void clist_del(struct clist *node);
|
||||
|
||||
/**
|
||||
* @brief Iterate over every node in a clist.
|
||||
*
|
||||
* @param head The `struct clist *` acting as the head of the clist
|
||||
* @param cursor A `struct clist *` to use as a cursor for iteration
|
||||
*/
|
||||
#define clist_foreach(head, cursor) \
|
||||
for ((cursor) = (head)->next; \
|
||||
(cursor) != (head); \
|
||||
(cursor) = (cursor)->next)
|
||||
|
||||
/**
|
||||
* @brief Iterate over every node in a clist in reverse order.
|
||||
*
|
||||
* @param head The `struct clist *` acting as the head of the clist
|
||||
* @param cursor A `struct clist *` to use as a cursor for iteration
|
||||
*/
|
||||
#define clist_foreach_rev(head, cursor, member) \
|
||||
for ((cursor) = (head)->prev; \
|
||||
(cursor) != (head); \
|
||||
(cursor) = (cursor)->prev)
|
||||
|
||||
/**
|
||||
* @brief Get the structure embedding a clist.
|
||||
*
|
||||
* @param node The `struct clist *` to cast out of
|
||||
* @param type Type of the containing structure
|
||||
* @param member Name of the `struct clist` within the containing structure
|
||||
* @returns The `struct *` the list node is embedded in
|
||||
*/
|
||||
#define clist_entry(node, type, member) \
|
||||
container_of(node, type, member)
|
||||
|
||||
/**
|
||||
* @brief Get the first entry in a list.
|
||||
*
|
||||
* @param head The `struct clist *` that is the head node
|
||||
* @param type Type of the structure embedding the list nodes
|
||||
* @param member Name of the `struct clist` within the embedding structure
|
||||
* @returns The `struct *` the list is embedded in
|
||||
*/
|
||||
#define clist_first_entry(head, type, member) \
|
||||
clist_entry((head)->next, type, member)
|
||||
|
||||
/**
|
||||
* @brief Get the next entry in a clist.
|
||||
*
|
||||
* @param entry The `struct *` embedding a clist to get the sccessor of
|
||||
* @param member Name of the `struct clist` embedded within the entry
|
||||
* @returns The next `struct *` in the list
|
||||
*/
|
||||
#define clist_next_entry(entry, member) \
|
||||
clist_entry((entry)->member.next, typeof(*(entry)), member)
|
||||
|
||||
/**
|
||||
* @brief Iterate over each entry within a list.
|
||||
*
|
||||
* @param head The `struct clist *` that is the head node in the list
|
||||
* @param cursor A `struct *` the list nodes are embedded in to use as the cursor
|
||||
* @param member Name of the `struct clist` within the embedding structure
|
||||
*/
|
||||
#define clist_foreach_entry(head, cursor, member) \
|
||||
for ((cursor) = clist_first_entry(head, typeof((*cursor)), member); \
|
||||
&(cursor)->member != (head); \
|
||||
(cursor) = clist_next_entry(cursor, member))
|
||||
|
||||
/**
|
||||
* @brief Iterate over each entry within a list, this is safe from element removal.
|
||||
*
|
||||
* @param head The `struct clist *` that is the head node in the list
|
||||
* @param cursor A `struct *` the list nodes are embedded in to use as the cursor.
|
||||
* This is the element that may be removed from the list.
|
||||
* @param tmp An addional `struct *` of the same type as `cursor` (don't touch)
|
||||
* @param member Name of the `struct clist` within the embedding structure
|
||||
*/
|
||||
#define clist_foreach_entry_safe(head, cursor, tmp, member) \
|
||||
for ((cursor) = clist_first_entry(head, typeof(*(cursor)), member), \
|
||||
(tmp) = clist_next_entry(cursor, member); \
|
||||
(tmp)->member.prev != (head); \
|
||||
(cursor) = (tmp), \
|
||||
(tmp) = clist_next_entry(tmp, member))
|
||||
|
||||
/*
|
||||
* This file is part of GayBSD.
|
||||
* Copyright (c) 2021 fef <owo@fef.moe>.
|
||||
*
|
||||
* GayBSD is nonviolent software: you may only use, redistribute, and/or
|
||||
* modify it under the terms of the Cooperative Nonviolent Public License
|
||||
* (CNPL) as found in the LICENSE file in the source code root directory
|
||||
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
|
||||
* of the license, or (at your option) any later version.
|
||||
*
|
||||
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
|
||||
* permitted by applicable law. See the CNPL for details.
|
||||
*/
|
@ -0,0 +1,47 @@
|
||||
/* See the end of this file for copyright and license terms. */
|
||||
|
||||
#include <gay/clist.h>
|
||||
|
||||
void clist_init(struct clist *head)
|
||||
{
|
||||
head->next = head;
|
||||
head->prev = head;
|
||||
}
|
||||
|
||||
void clist_add(struct clist *head, struct clist *new)
|
||||
{
|
||||
head->next->prev = new;
|
||||
new->next = head->next;
|
||||
|
||||
new->prev = head;
|
||||
head->next = new;
|
||||
}
|
||||
|
||||
void clist_add_end(struct clist *head, struct clist *new)
|
||||
{
|
||||
head->prev->next = new;
|
||||
new->next = head;
|
||||
|
||||
new->prev = head->prev;
|
||||
head->prev = new;
|
||||
}
|
||||
|
||||
void clist_del(struct clist *node)
|
||||
{
|
||||
node->next->prev = node->prev;
|
||||
node->prev->next = node->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* This file is part of GayBSD.
|
||||
* Copyright (c) 2021 fef <owo@fef.moe>.
|
||||
*
|
||||
* GayBSD is nonviolent software: you may only use, redistribute, and/or
|
||||
* modify it under the terms of the Cooperative Nonviolent Public License
|
||||
* (CNPL) as found in the LICENSE file in the source code root directory
|
||||
* or at <https://git.pixie.town/thufie/npl-builder>; either version 7
|
||||
* of the license, or (at your option) any later version.
|
||||
*
|
||||
* GayBSD comes with ABSOLUTELY NO WARRANTY, to the extent
|
||||
* permitted by applicable law. See the CNPL for details.
|
||||
*/
|
Loading…
Reference in New Issue