diff options
| author | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2023-07-22 03:03:09 +0300 | 
|---|---|---|
| committer | Yaroslav de la Peña Smirnov <yps@yaroslavps.com> | 2023-07-22 03:03:09 +0300 | 
| commit | cb1a40859029f33184355475e51fec95afb79a73 (patch) | |
| tree | 5aea859d3a3e10ddd058beac9d6734d17979d560 /list | |
| download | c-wares-cb1a40859029f33184355475e51fec95afb79a73.tar.gz c-wares-cb1a40859029f33184355475e51fec95afb79a73.zip | |
init
Just some C wares; hmap, list, optional, unit tests.
Diffstat (limited to 'list')
| -rw-r--r-- | list/list.h | 205 | 
1 files changed, 205 insertions, 0 deletions
| diff --git a/list/list.h b/list/list.h new file mode 100644 index 0000000..e944a0a --- /dev/null +++ b/list/list.h @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2002 Free Software Foundation, Inc. + * (originally part of the GNU C Library and Userspace RCU; extracted from Git) + * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + * + * Copyright (C) 2009 Pierre-Marc Fournier + * Conversion to RCU list. + * Copyright (C) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef LIST_H +#define LIST_H 1 + +#include <stddef.h> + +/* + * The definitions of this file are adopted from those which can be + * found in the Linux kernel headers to enable people familiar with the + * latter find their way in these sources as well. + */ + +/* Basic type for the double-link list. */ +struct list_head { +	struct list_head *next, *prev; +}; + +/* avoid conflicts with BSD-only sys/queue.h */ +#undef LIST_HEAD +/* Define a variable with the head and tail of the list. */ +#define LIST_HEAD(name) struct list_head name = { &(name), &(name) } + +/* Initialize a new list head. */ +#define INIT_LIST_HEAD(ptr) (ptr)->next = (ptr)->prev = (ptr) + +#define LIST_HEAD_INIT(name)              \ +	{                                     \ +		.next = &(name), .prev = &(name), \ +	} + +/* Add new element at the head of the list. */ +static inline void list_add(struct list_head *newp, struct list_head *head) +{ +	head->next->prev = newp; +	newp->next		 = head->next; +	newp->prev		 = head; +	head->next		 = newp; +} + +/* Add new element at the tail of the list. */ +static inline void list_add_tail(struct list_head *newp, struct list_head *head) +{ +	head->prev->next = newp; +	newp->next		 = head; +	newp->prev		 = head->prev; +	head->prev		 = newp; +} + +/* Remove element from list. */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ +	next->prev = prev; +	prev->next = next; +} + +/* Remove element from list. */ +static inline void list_del(struct list_head *elem) +{ +	__list_del(elem->prev, elem->next); +} + +/* Remove element from list, initializing the element's list pointers. */ +static inline void list_del_init(struct list_head *elem) +{ +	list_del(elem); +	INIT_LIST_HEAD(elem); +} + +/* Delete from list, add to another list as head. */ +static inline void list_move(struct list_head *elem, struct list_head *head) +{ +	__list_del(elem->prev, elem->next); +	list_add(elem, head); +} + +/* Replace an old entry. */ +static inline void list_replace(struct list_head *old, struct list_head *newp) +{ +	newp->next		 = old->next; +	newp->prev		 = old->prev; +	newp->prev->next = newp; +	newp->next->prev = newp; +} + +/* Join two lists. */ +static inline void list_splice(struct list_head *add, struct list_head *head) +{ +	/* Do nothing if the list which gets added is empty. */ +	if (add != add->next) { +		add->next->prev	 = head; +		add->prev->next	 = head->next; +		head->next->prev = add->prev; +		head->next		 = add->next; +	} +} + +/* Get typed element from list at a given position. */ +#define list_entry(ptr, type, member) \ +	((type *)((char *)(ptr)-offsetof(type, member))) + +/* Get first entry from a list. */ +#define list_first_entry(ptr, type, member) \ +	list_entry((ptr)->next, type, member) + +/* Iterate forward over the elements of the list. */ +#define list_for_each(pos, head) \ +	for (pos = (head)->next; pos != (head); pos = pos->next) + +/* + * Iterate forward over the elements list. The list elements can be + * removed from the list while doing this. + */ +#define list_for_each_safe(pos, p, head)                   \ +	for (pos = (head)->next, p = pos->next; pos != (head); \ +		 pos = p, p = pos->next) + +/* Iterate backward over the elements of the list. */ +#define list_for_each_prev(pos, head) \ +	for (pos = (head)->prev; pos != (head); pos = pos->prev) + +/* + * Iterate backwards over the elements list. The list elements can be + * removed from the list while doing this. + */ +#define list_for_each_prev_safe(pos, p, head)              \ +	for (pos = (head)->prev, p = pos->prev; pos != (head); \ +		 pos = p, p = pos->prev) + +static inline int list_empty(struct list_head *head) +{ +	return head == head->next; +} + +static inline void list_replace_init(struct list_head *old, +									 struct list_head *newp) +{ +	struct list_head *head = old->next; + +	list_del(old); +	list_add_tail(newp, head); +	INIT_LIST_HEAD(old); +} + +/* + * This is exactly the same as a normal list_head, except that it can be + * declared volatile (e.g., if you have a list that may be accessed from signal + * handlers). + */ +struct volatile_list_head { +	volatile struct volatile_list_head *next, *prev; +}; + +#define VOLATILE_LIST_HEAD(name) \ +	volatile struct volatile_list_head name = { &(name), &(name) } + +static inline void __volatile_list_del(volatile struct volatile_list_head *prev, +									   volatile struct volatile_list_head *next) +{ +	next->prev = prev; +	prev->next = next; +} + +static inline void volatile_list_del(volatile struct volatile_list_head *elem) +{ +	__volatile_list_del(elem->prev, elem->next); +} + +static inline int volatile_list_empty(volatile struct volatile_list_head *head) +{ +	return head == head->next; +} + +static inline void volatile_list_add(volatile struct volatile_list_head *newp, +									 volatile struct volatile_list_head *head) +{ +	head->next->prev = newp; +	newp->next		 = head->next; +	newp->prev		 = head; +	head->next		 = newp; +} + +#endif /* LIST_H */ | 
