Files
pstrace/src/utils/list_head.h
T
2020-02-05 09:41:22 +04:00

339 lines
9.3 KiB
C

/*******************************************************************************
Copyright (c) 2006, Nikolay Nosov
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#ifndef __LIST_HEAD_H__
#define __LIST_HEAD_H__
/**
Double linked list for user space implementation
*/
#include <stddef.h> /* for NULL declaration */
/** Get offset of a member
@param TYPE the type of the struct
@param MEMBER the name of the member, which offset to be computed
*/
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
/** Casts a member of a structure out to the containing structure
@param ptr the pointer to the member.
@param type the type of the container struct this is embedded in
@param member the name of the member within the struct.
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type, member) );})
/** Get the struct for this entry
@param ptr the &struct list_head pointer.
@param type the type of the struct this is embedded in.
@param member the name of the list_struct within the struct
*/
#define list_entry(ptr, type, member) container_of(ptr, type, member)
/** Iterate over a list
@param pos the &struct list_head to use as a loop counter.
@param head the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->first; pos; \
pos = pos->next)
/**
* list_for_each_entry - iterate over list of given type
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct hlist_node to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
#define list_for_each_entry(tpos, pos, head, member) \
for (pos = (head)->first; \
pos && ({ tpos = list_entry(pos, typeof(*tpos), member); 1;}); \
pos = pos->next)
/** Iterate over list of given type safe against removal of list entry
* @tpos: the type * to use as a loop cursor.
* @pos: the &struct list_node to use as a loop cursor.
* @n: another &struct list_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_node within the struct.
*/
#define list_for_each_entry_safe(tpos, pos, n, head, member) \
for (pos = (head)->first; \
pos && ({ n = pos->next; 1; }) && \
({ tpos = list_entry(pos, typeof(*tpos), member); 1;}); \
pos = n)
/** Iterate over a list backwards
@param pos the &struct list_head to use as a loop counter.
@param head the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->last; pos; \
pos = pos->prev)
/** Iterate over a list safe against removal of list entry
@param pos the &struct list_head to use as a loop counter.
@param n another &struct list_head to use as temporary storage
@param head the head for your list.
*/
#if !defined(list_for_each_safe)
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
#endif
/* to compiler be happy */
struct list_head;
/** Node of the list
@param next next node in the list
@param prev previous node in the list
@param head head of the list
*/
typedef struct list_node
{
struct list_node *next, *prev;
struct list_head *head;
} list_node;
/** Head of the list
@param first first node in the list
@param last last node in the list
@param count cont of the nodes
*/
typedef struct list_head
{
struct list_node *first, *last;
int count;
} list_head;
/**
Compile time initialization of the head struct
*/
#define LIST_HEAD_INIT { .first = NULL, .last = NULL, .count = 0 }
/**
Compile time initialization of the node struct
*/
#define LIST_NODE_INIT { .prev = NULL, .next = NULL, .head = NULL }
/** Runtime initialization of the head struct
(should be applied before first using of the list)
@param node head, which to be initialized.
*/
static inline void list_head_init(struct list_head *head)
{
head->first = head->last = NULL;
head->count = 0;
}
/** Runtime initialization of the node struct
(should be applied before first using of the node)
@param node node, which to be initialized.
*/
static inline void list_node_init(struct list_node *node)
{
node->next = node->prev = NULL;
node->head = NULL;
}
/** Add node to begin of the list
@param head the head of the list
@param node node of the list, which to be added
*/
static inline void list_add_head(struct list_head *head, struct list_node *node)
{
struct list_node *pfirst = head->first;
head->first = node;
node->next = pfirst;
node->prev = NULL;
node->head = head;
if(pfirst) pfirst->prev = node;
else head->last = node;
head->count++;
}
/** Add node to the end of the list
@param head the head of the list;
@param node node of the list, which to be added
*/
static inline void list_add_bottom(struct list_head *head, struct list_node *node)
{
struct list_node *plast = head->last;
head->last = node;
node->next = NULL;
node->prev = plast;
node->head = head;
if(plast) plast->next = node;
else head->first = node;
head->count++;
}
/** Add node in the list after given 'base' node
@param base the base node, after that node will be added
@param node node of the list, which to be added
*/
static inline void list_add_after(struct list_node *base, struct list_node *node)
{
struct list_node *pnext = base->next;
base->next = node;
node->next = pnext;
node->prev = base;
node->head = base->head;
if(pnext) pnext->prev = node;
else base->head->last = node;
base->head->count++;
}
/** Adds node in the list before given 'base' node
@param base the base node, before that node will be added
@param node node of the list, which to be added
*/
static inline void list_add_before(struct list_node *base, struct list_node *node)
{
struct list_node *pprev = base->prev;
base->prev = node;
node->next = base;
node->prev = pprev;
node->head = base->head;
if(pprev) pprev->next = node;
else base->head->first = node;
base->head->count++;
}
/** Remove node from the list
@param node the node, which to be removed
*/
static inline void list_del(struct list_node *node)
{
if(node->head)
{
if(node->prev) node->prev->next = node->next;
else node->head->first = node->next;
if(node->next) node->next->prev = node->prev;
else node->head->last = node->prev;
node->head->count--;
}
node->prev = node->next = NULL;
node->head = NULL;
}
static inline void list_del_init(struct list_node *node)
{
list_del(node);
list_node_init(node);
}
/** Count of the nodes in the list
@param head the head of the list
@return count of the nodes in the list
*/
static inline int list_count(struct list_head *head)
{
return head->count;
}
/** First element of the list
@param head the head of the list
@return pointer to first element of the list
*/
static inline struct list_node* list_first(struct list_head *head)
{
return head->first;
}
/** Last element of the list
@param head the head of the list
@return pointer to last element of the list
*/
static inline struct list_node* list_last(struct list_head *head)
{
return head->last;
}
/** Next element of the list
@param head current element of the list
@return pointer to next element relatively of current
*/
static inline struct list_node* list_next(struct list_node *node)
{
return node->next;
}
/** Previous element of the list
@param head current element of the list
@return pointer to previous element relatively of current
*/
static inline struct list_node* list_prev(struct list_node *node)
{
return node->prev;
}
#endif // __LIST_HEAD_H__