#ifndef _LIST_H_
#define _LIST_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stddef.h>
#if (!defined list_head_init) && (!defined LIST_HEAD_INIT)
#define FUTILS_LIST 1
#define FUTILS_LIST_POISON1 ((void *)0xDEADBEEF)
#define FUTILS_LIST_POISON2 ((void *)0xDEADDEAD)
#define FUTILS_CONTAINER_OF(ptr, type, member) \
({ \
const __typeof__(((type *)0)->member) * __mptr = (ptr); \
(type *)((uintptr_t)__mptr - offsetof(type, member)); \
})
struct list_node {
struct list_node *next, *prev;
};
static inline void
list_node_unref(struct list_node *node)
{
node->next = (struct list_node *)FUTILS_LIST_POISON1;
node->prev = (struct list_node *)FUTILS_LIST_POISON2;
}
static inline int
list_node_is_unref(struct list_node *node)
{
return (node->next == (struct list_node *)FUTILS_LIST_POISON1) &&
(node->prev == (struct list_node *)FUTILS_LIST_POISON2);
}
static inline int
list_node_is_ref(struct list_node *node)
{
return !list_node_is_unref(node);
}
static inline void
list_init(struct list_node *list)
{
list->next = list;
list->prev = list;
}
static inline struct list_node*
list_prev(const struct list_node *list, const struct list_node *item)
{
return (item->prev != list) ? item->prev : NULL;
}
static inline struct list_node*
list_next(const struct list_node *list, const struct list_node *item)
{
return (item->next != list) ? item->next : NULL;
}
static inline struct list_node*
list_first(const struct list_node *list)
{
return list->next;
}
static inline int
list_is_empty(const struct list_node *list)
{
return list->next == list;
}
static inline struct list_node *
list_last(const struct list_node *list)
{
return list->prev;
}
static inline void
list_add(struct list_node *novel, struct list_node *prev,
struct list_node *next)
{
next->prev = novel;
novel->next = next;
novel->prev = prev;
prev->next = novel;
}
static inline void
list_add_after(struct list_node *node, struct list_node *novel)
{
list_add(novel, node, node->next);
}
static inline void
list_add_before(struct list_node *node, struct list_node *novel)
{
list_add(novel, node->prev, node);
}
static inline void
list_detach(struct list_node *prev, struct list_node *next)
{
next->prev = prev;
prev->next = next;
}
static inline void
list_del(struct list_node *node)
{
list_detach(node->prev, node->next);
list_node_unref(node);
}
static inline void
list_del_init(struct list_node *node)
{
list_detach(node->prev, node->next);
list_init(node);
}
static inline void
list_replace(struct list_node *old, struct list_node *novel)
{
novel->next = old->next;
novel->next->prev = novel;
novel->prev = old->prev;
novel->prev->next = novel;
}
static inline void
list_replace_init(struct list_node *old, struct list_node *novel)
{
list_replace(old, novel);
list_init(old);
}
static inline void
list_move_after(struct list_node *to, struct list_node *from)
{
list_detach(from->prev, from->next);
list_add_after(to, from);
}
static inline void
list_move_before(struct list_node *to, struct list_node *from)
{
list_detach(from->prev, from->next);
list_add_before(to, from);
}
static inline int
list_is_last(const struct list_node *list, const struct list_node *node)
{
return list->prev == node;
}
#define list_head_init(name) { &(name), &(name) }
#define list_entry(ptr, type, member)\
FUTILS_CONTAINER_OF(ptr, type, member)
#define list_walk_forward(list, pos)\
for (pos = (list)->next; pos != (list); pos = pos->next)
#define list_walk_backward(list, pos)\
for (pos = (list)->prev; pos != (list); pos = pos->prev)
#define list_walk_forward_safe(list, pos, tmp) \
for (pos = (list)->next, \
tmp = pos->next; pos != (list); \
pos = tmp, tmp = pos->next)
#define list_walk_backward_safe(list, pos, tmp) \
for (pos = (list)->prev, \
tmp = pos->prev; pos != (list); \
pos = tmp, tmp = pos->prev)
#define list_walk_entry_forward(list, pos, member) \
for (pos = list_entry((list)->next, __typeof__(*pos), member); \
&pos->member != (list); \
pos = list_entry(pos->member.next, __typeof__(*pos), member))
#define list_walk_entry_backward(list, pos, member) \
for (pos = list_entry((list)->prev, __typeof__(*pos), member); \
&pos->member != (list); \
pos = list_entry(pos->member.prev, __typeof__(*pos), member))
#define list_walk_entry_forward_safe(list, pos, tmp, member) \
for (pos = list_entry((list)->next, __typeof__(*pos), member), \
tmp = list_entry(pos->member.next, \
__typeof__(*pos), member); \
&pos->member != (list); \
pos = tmp, tmp = list_entry(tmp->member.next, \
__typeof__(*tmp), member))
#define list_walk_entry_backward_safe(list, pos, tmp, member) \
for (pos = list_entry((list)->prev, __typeof__(*pos), member), \
tmp = list_entry(pos->member.prev, \
__typeof__(*pos), member); \
&pos->member != (list); \
pos = tmp, tmp = list_entry(tmp->member.prev, \
__typeof__(*tmp), member))
static inline size_t
list_length(const struct list_node *list)
{
size_t length = 0;
const struct list_node *tmp;
const struct list_node *current;
list_walk_forward_safe(list, current, tmp) {
length++;
}
return length;
}
#define list_push(list, elem) list_add_before(list, elem)
#define list_pop(list, type, member) \
({ \
__typeof__(((type *)0)->member) * __pop_ptr = list_first(list);\
__pop_ptr == list ? NULL : ({ \
list_del(__pop_ptr); \
FUTILS_CONTAINER_OF(__pop_ptr, type, member); \
}); \
})
#endif
#ifdef __cplusplus
}
#endif
#endif