blob: 0d96c65381748f5e829817ea49e9ecadf7b83b42 [file] [log] [blame]
/*
* Single linked list support (LIFO/FIFO order).
*
* Copyright (c) 2008-2014 Daniel Phillips
* Copyright (c) 2008-2014 OGAWA Hirofumi
*/
#ifndef TUX3_LINK_H
#define TUX3_LINK_H
/* Single linked list (LIFO order) */
struct link { struct link *next; };
#define LINK_INIT_CIRCULAR(name) { &(name), }
#define link_entry(ptr, type, member) container_of(ptr, type, member)
/* take care: this doesn't check member is `struct link *' or not */
#define __link_entry(ptr, type, member) \
container_of((typeof(((type *)0)->member) *)ptr, type, member)
static inline void init_link_circular(struct link *head)
{
head->next = head;
}
static inline int link_empty(const struct link *head)
{
return head->next == head;
}
static inline void link_add(struct link *node, struct link *head)
{
node->next = head->next;
head->next = node;
}
static inline void link_del_next(struct link *node)
{
node->next = node->next->next;
}
#define link_for_each_safe(pos, prev, n, head) \
for (pos = (head)->next, prev = (head), n = pos->next; \
pos != (head); \
prev = ((prev->next == n) ? prev : pos), pos = n, n = pos->next)
/* Single linked list (FIFO order) */
struct flink_head { struct link *tail; };
#define FLINK_HEAD_INIT(name) { NULL, }
#define flink_next_entry(head, type, member) \
link_entry(flink_next(head), type, member)
/* take care: this doesn't check member is `struct link *' or not */
#define __flink_next_entry(head, type, member) ({ \
struct link *next = flink_next(head); \
link_entry((typeof(((type *)0)->member) *)next, type, member); \
})
static inline void init_flink_head(struct flink_head *head)
{
head->tail = NULL;
}
static inline int flink_empty(const struct flink_head *head)
{
return head->tail == NULL;
}
static inline int flink_is_last(const struct flink_head *head)
{
return link_empty(head->tail);
}
static inline struct link *flink_next(const struct flink_head *head)
{
return head->tail->next;
}
static inline void flink_first_add(struct link *node, struct flink_head *head)
{
assert(flink_empty(head));
init_link_circular(node);
head->tail = node;
}
static inline void flink_add(struct link *node, struct flink_head *head)
{
link_add(node, head->tail);
head->tail = node;
}
static inline void flink_del_next(struct flink_head *head)
{
link_del_next(head->tail);
}
static inline void flink_last_del(struct flink_head *head)
{
assert(flink_is_last(head));
init_flink_head(head);
}
#endif /* !TUX3_LINK_H */