#ifndef LIBA_SLIST_H
#define LIBA_SLIST_H
#include "a.h"
#define A_SLIST_NODE {A_NULL}
#define A_SLIST_INIT(list) {{A_NULL}, &(list).head}
typedef struct a_slist_node
{
struct a_slist_node *next;
} a_slist_node;
#define a_slist_(_, x) a_cast_s(a_slist_node _, a_cast_s(void _, x))
typedef struct a_slist
{
a_slist_node head;
a_slist_node *tail;
} a_slist;
#define a_slist_entry(ptr, type, member) a_container_of(ptr, type, member)
#define a_slist_entry_next(ptr, type, member) a_slist_entry((ptr)->next, type, member)
#define a_slist_foreach(it, ctx) \
for (a_slist_node *it = (ctx)->head.next; it; it = it->next)
#define a_slist_forsafe(it, at, ctx) \
for (a_slist_node *at = &(ctx)->head, *it = at->next; \
it; at = it ? it : at, it = at->next)
A_INTERN void a_slist_ctor(a_slist *ctx)
{
ctx->head.next = A_NULL;
ctx->tail = &ctx->head;
}
A_INTERN void a_slist_init(a_slist *ctx)
{
ctx->head.next = A_NULL;
ctx->tail = &ctx->head;
}
A_INTERN void a_slist_dtor(a_slist *ctx)
{
ctx->head.next = A_NULL;
ctx->tail = &ctx->head;
}
A_INTERN void a_slist_link(a_slist_node *head, a_slist_node *tail) { head->next = tail; }
A_INTERN void a_slist_add(a_slist *ctx, a_slist_node *prev, a_slist_node *node)
{
if (!prev->next) { ctx->tail = node; }
a_slist_link(node, prev->next);
a_slist_link(prev, node);
}
A_INTERN void a_slist_add_head(a_slist *ctx, a_slist_node *node)
{
a_slist_add(ctx, &ctx->head, node);
}
A_INTERN void a_slist_add_tail(a_slist *ctx, a_slist_node *node)
{
a_slist_link(ctx->tail, node);
node->next = A_NULL;
ctx->tail = node;
}
A_INTERN void a_slist_del(a_slist *ctx, a_slist_node *prev)
{
a_slist_node *const node = prev->next;
if (node)
{
a_slist_link(prev, node->next);
if (!node->next) { ctx->tail = prev; }
}
}
A_INTERN void a_slist_del_head(a_slist *ctx)
{
a_slist_node *const node = ctx->head.next;
if (node)
{
a_slist_link(&ctx->head, node->next);
if (!node->next) { ctx->tail = &ctx->head; }
}
}
A_INTERN void a_slist_mov(a_slist *ctx, a_slist *to, a_slist_node *at)
{
a_slist_node *const node = ctx->head.next;
if (node)
{
if (!at->next) { to->tail = ctx->tail; }
a_slist_link(ctx->tail, at->next);
a_slist_link(at, node);
}
}
A_INTERN void a_slist_rot(a_slist *ctx)
{
a_slist_node *const node = ctx->head.next;
if (node)
{
a_slist_link(&ctx->head, node->next);
a_slist_link(ctx->tail, node);
node->next = A_NULL;
ctx->tail = node;
}
}
#endif