liba 0.1.15

An algorithm library based on C/C++
Documentation
/*!
 @file slist.h
 @brief singly linked list implementation
*/

#ifndef LIBA_SLIST_H
#define LIBA_SLIST_H

#include "a.h"

/*!
 @ingroup liba
 @addtogroup a_slist singly linked list
 @{
*/

// clang-format off
#define A_SLIST_NODE {A_NULL}
#define A_SLIST_INIT(list) {{A_NULL}, &(list).head}
// clang-format on

/*!
 @brief instance structure for singly linked list node
*/
typedef struct a_slist_node
{
    struct a_slist_node *next;
} a_slist_node;

/*!
 @brief cast a list pointer from another type pointer
 @param[in] _ additional attributes of specified type
 @param[in] x points to singly linked list node
 @return a pointer to singly linked list node
*/
#define a_slist_(_, x) a_cast_s(a_slist_node _, a_cast_s(void _, x))

/*!
 @brief instance structure for singly linked list head
*/
typedef struct a_slist
{
    a_slist_node head;
    a_slist_node *tail;
} a_slist;

/*!
 @brief access the struct for this entry
 @param ptr the &a_slist_node pointer
 @param type the type of the struct this is embedded in
 @param member the name of the a_slist_node within the struct
*/
#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)

/*!
 @brief iterate over a list
 @param it the &a_slist_node to use as a loop counter
 @param ctx points to singly linked list head
*/
#define a_slist_foreach(it, ctx) \
    for (a_slist_node *it = (ctx)->head.next; it; it = it->next)

/*!
 @brief iterate over a list safe against removal of list entry
 @param it the &a_slist_node to use as a loop counter
 @param at another &a_slist_node to use as temporary storage
 @param ctx points to singly linked list head
*/
#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)

/*!
 @brief constructor for singly linked list head
 @param[in,out] ctx points to singly linked list head
*/
A_INTERN void a_slist_ctor(a_slist *ctx)
{
    ctx->head.next = A_NULL;
    ctx->tail = &ctx->head;
}

/*!
 @brief initialize for singly linked list head
 @param[in,out] ctx points to singly linked list head
*/
A_INTERN void a_slist_init(a_slist *ctx)
{
    ctx->head.next = A_NULL;
    ctx->tail = &ctx->head;
}

/*!
 @brief destructor for singly linked list head
 @param[in,out] ctx points to singly linked list head
*/
A_INTERN void a_slist_dtor(a_slist *ctx)
{
    ctx->head.next = A_NULL;
    ctx->tail = &ctx->head;
}

/*!
 @brief link head node and tail node
 @param[in,out] head the head node of a list
 @param[in,out] tail the tail node of a list
*/
A_INTERN void a_slist_link(a_slist_node *head, a_slist_node *tail) { head->next = tail; }

/*!
 @brief insert a node to a list
 @param[in,out] ctx points to singly linked list head
 @param[in] prev previous singly linked list node
 @param[in] node a singly linked list node
*/
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);
}

/*!
 @brief insert a node to a list head
 @param[in,out] ctx points to singly linked list head
 @param[in] node a singly linked list node
*/
A_INTERN void a_slist_add_head(a_slist *ctx, a_slist_node *node)
{
    a_slist_add(ctx, &ctx->head, node);
}

/*!
 @brief insert a node to a list tail
 @param[in,out] ctx points to singly linked list head
 @param[in] node a singly linked list 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;
}

/*!
 @brief delete a node from a list
 @param[in,out] ctx points to singly linked list head
 @param[in] prev previous singly linked list 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; }
    }
}

/*!
 @brief delete a node from a list head
 @param[in,out] ctx points to singly linked list head
*/
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; }
    }
}

/*!
 @brief moving a list to another list
 @param[in] ctx points to singly linked list head
 @param[in,out] to another linked list to be inserted
 @param[in] at the previous &a_slist_node of the inserted node
*/
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);
    }
}

/*!
 @brief rotate a node in the list
 @param[in,out] ctx points to singly linked list head
*/
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;
    }
}

/*! @} a_slist */

#endif /* a/slist.h */