/**
 * @file    list.h
 * @brief   Linux 内核风格侵入式双向循环链表（纯头文件，C/C++ 兼容）
 * @details 将 struct list_head 嵌入宿主结构体，通过 list_entry 取回宿主指针。
 *          所有操作 O(1)，遍历 O(n)。
 *          C++ 兼容：变量名不使用 new/class/typeof 等关键字。
 */

#ifndef _LIST_H_
#define _LIST_H_

#include <stddef.h>

#ifdef __cplusplus
extern "C"
{
#endif

/* ---- 链表节点 ---- */
struct list_head
{
	struct list_head *next;
	struct list_head *prev;
};

/* ---- 初始化 ---- */
#define LIST_HEAD_INIT(n) { &(n), &(n) }
#define LIST_HEAD(n)      struct list_head n = LIST_HEAD_INIT(n)

/**
 * @brief  运行时初始化链表头
 */
static inline void INIT_LIST_HEAD(struct list_head *h)
{
	h->next = h;
	h->prev = h;
}

/* ---- 内部辅助：在 prev 和 next 之间插入 node ---- */
static inline void __list_add(struct list_head *node,
                              struct list_head *prev,
                              struct list_head *next)
{
	next->prev = node;
	node->next = next;
	node->prev = prev;
	prev->next = node;
}

/* ---- 内部辅助：移除 prev 和 next 之间的节点 ---- */
static inline void __list_del(struct list_head *prev,
                              struct list_head *next)
{
	next->prev = prev;
	prev->next = next;
}

/* ---- 添加操作 ---- */

/** 头插法：插入到 head 之后（作为第一个元素） */
static inline void list_add(struct list_head *node, struct list_head *head)
{
	__list_add(node, head, head->next);
}

/** 尾插法：插入到 head 之前（作为最后一个元素） */
static inline void list_add_tail(struct list_head *node, struct list_head *head)
{
	__list_add(node, head->prev, head);
}

/* ---- 删除操作 ---- */

/** 从链表移除节点（不释放内存） */
static inline void list_del(struct list_head *e)
{
	__list_del(e->prev, e->next);
}

/** 移除并重新初始化节点（安全删除，防止悬空指针） */
static inline void list_del_init(struct list_head *e)
{
	__list_del(e->prev, e->next);
	INIT_LIST_HEAD(e);
}

/* ---- 移动操作 ---- */

/** 将节点移动到新链表头部 */
static inline void list_move(struct list_head *l, struct list_head *h)
{
	__list_del(l->prev, l->next);
	list_add(l, h);
}

/** 将节点移动到新链表尾部 */
static inline void list_move_tail(struct list_head *l, struct list_head *h)
{
	__list_del(l->prev, l->next);
	list_add_tail(l, h);
}

/* ---- 替换操作 ---- */

/** 用 node 替换 old */
static inline void list_replace(struct list_head *old, struct list_head *node)
{
	node->next = old->next;
	node->next->prev = node;
	node->prev = old->prev;
	node->prev->next = node;
}

/** 替换后初始化被替换节点 */
static inline void list_replace_init(struct list_head *old,
                                     struct list_head *node)
{
	list_replace(old, node);
	INIT_LIST_HEAD(old);
}

/* ---- 判断操作 ---- */

/** 判断链表是否为空 */
static inline int list_empty(const struct list_head *h)
{
	return h->next == h;
}

/** 判断节点是否已链入链表 */
static inline int list_is_linked(const struct list_head *e)
{
	return e->next != e;
}

/* ---- 节点 ↔ 宿主指针转换 ---- */

/** 从链表节点指针取回宿主结构体指针 */
#define list_entry(ptr, type, member) \
	((type *)((char *)(ptr) - offsetof(type, member)))

/** 获取第一个宿主元素 */
#define list_first_entry(h, type, member) \
	list_entry((h)->next, type, member)

/** 获取最后一个宿主元素 */
#define list_last_entry(h, type, member) \
	list_entry((h)->prev, type, member)

/** 安全获取第一个元素（链表空返回 NULL） */
#define list_first_entry_or_null(h, type, member) \
	(list_empty(h) ? NULL : list_first_entry(h, type, member))

/* ---- 遍历操作 ---- */

/** 遍历链表节点（仅获取 struct list_head 指针） */
#define list_for_each(pos, head) \
	for (pos = (head)->next; pos != (head); pos = pos->next)

/** 安全遍历节点（可在遍历中删除 pos） */
#define list_for_each_safe(pos, n, head) \
	for (pos = (head)->next, n = pos->next; pos != (head); \
	     pos = n, n = pos->next)

/** 遍历宿主元素 */
#define list_for_each_entry(pos, head, member) \
	for (pos = list_first_entry(head, __typeof__(*pos), member); \
	     &pos->member != (head); \
	     pos = list_entry(pos->member.next, __typeof__(*pos), member))

/** 安全遍历宿主元素（可在遍历中删除 pos） */
#define list_for_each_entry_safe(pos, n, head, member) \
	for (pos = list_first_entry(head, __typeof__(*pos), member), \
	     n = list_entry(pos->member.next, __typeof__(*pos), member); \
	     &pos->member != (head); \
	     pos = n, \
	     n = list_entry(n->member.next, __typeof__(*n), member))

/* ---- 拼接操作 ---- */

/** 将 src 链表拼接到 dst 头部，src 被清空 */
static inline void list_splice_init(struct list_head *src,
                                    struct list_head *dst)
{
	if (!list_empty(src))
	{
		struct list_head *f = src->next;
		struct list_head *l = src->prev;
		struct list_head *a = dst->next;

		f->prev = dst;
		dst->next = f;
		l->next = a;
		a->prev = l;
		INIT_LIST_HEAD(src);
	}
}

#ifdef __cplusplus
}
#endif

#endif /* _LIST_H_ */
