Files
ESPC3-wireless/components/system/include/list/slist.h
2024-03-28 12:19:52 +08:00

413 lines
11 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file slist.h
* @author LokLiang (lokliang@163.com)
* @brief
* @version 0.1
* @date 2023-05-01
*
* @copyright Copyright (c) 2023
*
*/
#ifndef __SINGLELIST_H__
#define __SINGLELIST_H__
#include "sys_types.h"
#ifdef __cplusplus
extern "C"
{
#endif
#ifndef LIST_NODE_TYPE
#define LIST_NODE_TYPE 0 /* 0 -- 使用指针连结推荐1 -- 使用偏移量连结,内存的地址允许被迁移并继续管理(推荐) */
#endif
#if LIST_NODE_TYPE == 1
typedef int list_node_t;
#else
typedef void * list_node_t;
#endif
typedef struct
{
list_node_t next;
} slist_node_t;
typedef struct
{
list_node_t head;
list_node_t tail;
} slist_t;
__static_inline void slist_init_list (slist_t *list);
__static_inline void slist_init_node (slist_node_t *node);
__static_inline int slist_insert_font (slist_t *list, slist_node_t *node);
__static_inline int slist_insert_tail (slist_t *list, slist_node_t *node);
__static_inline int slist_remove (slist_t *list, slist_node_t *node);
__static_inline int slist_remove_next (slist_t *list, slist_node_t *prev_node, slist_node_t *remove_node);
__static_inline int slist_insert_next (slist_t *list, slist_node_t *tar_node, slist_node_t *new_node);
__static_inline int slist_insert_prev (slist_t *list, slist_node_t *tar_node, slist_node_t *new_node);
__static_inline slist_node_t *slist_take_head (slist_t *list);
__static_inline slist_node_t *slist_take_tail (slist_t *list);
__static_inline slist_node_t *slist_peek_head (slist_t *list);
__static_inline slist_node_t *slist_peek_tail (slist_t *list);
__static_inline slist_node_t *slist_peek_next (slist_node_t *node);
__static_inline slist_node_t *slist_peek_prev (slist_t *list, slist_node_t *node);
__static_inline slist_node_t *slist_peek_next_loop (slist_t *list, slist_node_t *node);
__static_inline slist_node_t *slist_peek_prev_loop (slist_t *list, slist_node_t *node);
__static_inline int slist_is_pending (slist_node_t *node);
#define SLIST_CONTAINER_OF(PTR, TYPE, MEMBER) ((TYPE *)&((uint8_t *)PTR)[-(int)&((TYPE *)0)->MEMBER])
#define SLIST_FOR_EACH_NODE(__sl, __sn) \
for (__sn = slist_peek_head(__sl); __sn; \
__sn = slist_peek_next(__sn))
#define SLIST_ITERATE_FROM_NODE(__sl, __sn) \
for (__sn = __sn ? slist_peek_next_no_check(__sn) \
: slist_peek_head(__sl); \
__sn; \
__sn = slist_peek_next(__sn))
#define SLIST_FOR_EACH_NODE_SAFE(__sl, __sn, __sns) \
for (__sn = slist_peek_head(__sl), \
__sns = slist_peek_next(__sn); \
__sn; \
__sn = __sns, __sns = slist_peek_next(__sn))
#define SLIST_CONTAINER(__ln, __cn, __n) \
((__ln) ? SLIST_CONTAINER_OF((__ln), __typeof__(*(__cn)), __n) : NULL)
#define SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n) \
SLIST_CONTAINER(slist_peek_head(__sl), __cn, __n)
#define SLIST_PEEK_TAIL_CONTAINER(__sl, __cn, __n) \
SLIST_CONTAINER(slist_peek_tail(__sl), __cn, __n)
#define SLIST_PEEK_NEXT_CONTAINER(__cn, __n) \
((__cn) ? SLIST_CONTAINER(slist_peek_next(&((__cn)->__n)), __cn, __n) : NULL)
#define SLIST_FOR_EACH_CONTAINER(__sl, __cn, __n) \
for (__cn = SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n); \
__cn; \
__cn = SLIST_PEEK_NEXT_CONTAINER(__cn, __n))
#define SLIST_FOR_EACH_CONTAINER_SAFE(__sl, __cn, __cns, __n) \
for (__cn = SLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n), \
__cns = SLIST_PEEK_NEXT_CONTAINER(__cn, __n); \
__cn; \
__cn = __cns, __cns = SLIST_PEEK_NEXT_CONTAINER(__cn, __n))
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if LIST_NODE_TYPE == 1
#define SLIST_SET(Value1, Value2) (Value1 = Value2 == 0 ? 0 : ((int)Value2 - (int)&Value1) | 1)
#define SLIST_GET(Value) ((slist_node_t*)(Value == 0 ? 0 : ((int)&Value + Value) & ~1))
#else
#define SLIST_SET(Value1, Value2) (Value1 = (list_node_t)Value2)
#define SLIST_GET(Value) ((slist_node_t*)(Value))
#endif
__static_inline void slist_init_list(slist_t *list)
{
SLIST_SET(list->head, 0);
SLIST_SET(list->tail, 0);
}
__static_inline void slist_init_node(slist_node_t *node)
{
SLIST_SET(node->next, 0);
}
__static_inline int slist_insert_font(slist_t *list, slist_node_t *node)
{
if (SLIST_GET(node->next) != NULL)
{
// SYS_LOG_WRN("Node is pending");
return -1;
}
slist_node_t *head_node = SLIST_GET(list->head);
if (head_node)
{
SLIST_SET(node->next, head_node);
}
else
{
SLIST_SET(node->next, node);
SLIST_SET(list->tail, node);
}
SLIST_SET(list->head, node);
return 0;
}
__static_inline int slist_insert_tail(slist_t *list, slist_node_t *node)
{
if (SLIST_GET(node->next) != NULL)
{
// SYS_LOG_WRN("Node is pending");
return -1;
}
SLIST_SET(node->next, node);
if (SLIST_GET(list->head) == NULL)
{
SLIST_SET(list->head, node);
}
else
{
slist_node_t *tail_node = (slist_node_t *)SLIST_GET(list->tail);
SLIST_SET(tail_node->next, node);
}
SLIST_SET(list->tail, node);
return 0;
}
__static_inline int slist_remove(slist_t *list, slist_node_t *node)
{
if (node == NULL || list == NULL)
{
return -1;
}
slist_node_t *list_head = SLIST_GET(list->head);
slist_node_t *node_next = SLIST_GET(node->next);
if (node_next == NULL || list_head == NULL)
{
return -1;
}
if (node == list_head) // node 是首个节点
{
if (node == SLIST_GET(list->tail)) // node 是最后一个节点
{
SLIST_SET(list->head, 0);
SLIST_SET(list->tail, 0);
}
else
{
SLIST_SET(list->head, node_next);
}
}
else // node 不是首个节点
{
slist_node_t *prev_node = slist_peek_prev(list, node);
if (prev_node == NULL)
{
return -1;
}
if (node == SLIST_GET(list->tail)) // node 是最后一个节点
{
SLIST_SET(list->tail, prev_node);
SLIST_SET(prev_node->next, prev_node);
}
else
{
SLIST_SET(prev_node->next, node_next);
}
}
SLIST_SET(node->next, 0);
return 0;
}
__static_inline int slist_remove_next(slist_t *list, slist_node_t *prev_node, slist_node_t *remove_node)
{
if (remove_node == NULL || list == NULL)
{
return -1;
}
slist_node_t *list_head = SLIST_GET(list->head);
slist_node_t *node_next = SLIST_GET(remove_node->next);
if (node_next == NULL || list_head == NULL)
{
return -1;
}
if (remove_node == list_head) // remove_node 是首个节点
{
if (remove_node == SLIST_GET(list->tail)) // remove_node 是最后一个节点
{
SLIST_SET(list->head, 0);
SLIST_SET(list->tail, 0);
}
else
{
SLIST_SET(list->head, node_next);
}
}
else // remove_node 不是首个节点
{
if (prev_node == NULL)
{
prev_node = slist_peek_prev(list, remove_node);
if (prev_node == NULL)
{
return -1;
}
}
if (remove_node == SLIST_GET(list->tail)) // remove_node 是最后一个节点
{
SLIST_SET(list->tail, prev_node);
SLIST_SET(prev_node->next, prev_node);
}
else
{
SLIST_SET(prev_node->next, node_next);
}
}
SLIST_SET(remove_node->next, 0);
return 0;
}
__static_inline int slist_insert_next(slist_t *list, slist_node_t *tar_node, slist_node_t *new_node)
{
slist_node_t *tar_node_next = SLIST_GET(tar_node->next);
if (SLIST_GET(list->head) == NULL || tar_node_next == NULL || SLIST_GET(new_node->next) != NULL)
{
return -1;
}
if (tar_node == SLIST_GET(list->tail)) // tar_node 是最后一个节点
{
SLIST_SET(new_node->next, new_node);
SLIST_SET(tar_node->next, new_node);
SLIST_SET(list->tail, new_node);
}
else
{
SLIST_SET(new_node->next, tar_node_next);
SLIST_SET(tar_node->next, new_node);
}
return 0;
}
__static_inline int slist_insert_prev(slist_t *list, slist_node_t *tar_node, slist_node_t *new_node)
{
slist_node_t *list_head = SLIST_GET(list->head);
if (list_head == NULL || SLIST_GET(tar_node->next) == NULL || SLIST_GET(new_node->next) != NULL)
{
return -1;
}
if (tar_node == list_head) // tar_node 是首个节点
{
SLIST_SET(new_node->next, list_head);
SLIST_SET(list->head, new_node);
}
else
{
slist_node_t *prev_node = slist_peek_prev(list, tar_node);
if (prev_node == NULL)
{
return -1;
}
SLIST_SET(new_node->next, tar_node);
SLIST_SET(prev_node->next, new_node);
}
return 0;
}
__static_inline slist_node_t *slist_take_head(slist_t *list)
{
slist_node_t *ret = SLIST_GET(list->head);
slist_remove(list, ret);
return ret;
}
__static_inline slist_node_t *slist_take_tail(slist_t *list)
{
slist_node_t *ret = SLIST_GET(list->tail);
slist_remove(list, ret);
return ret;
}
__static_inline slist_node_t *slist_peek_head(slist_t *list)
{
return SLIST_GET(list->head);
}
__static_inline slist_node_t *slist_peek_tail(slist_t *list)
{
return SLIST_GET(list->tail);
}
__static_inline slist_node_t *slist_peek_next(slist_node_t *node)
{
slist_node_t *next_node = SLIST_GET(node->next);
if (next_node == node)
{
return NULL;
}
else
{
return next_node;
}
}
__static_inline slist_node_t *slist_peek_prev(slist_t *list, slist_node_t *node)
{
slist_node_t *prev_node = NULL;
slist_node_t *test_node = SLIST_GET(list->head);
while (test_node && test_node != node && prev_node != test_node)
{
prev_node = test_node;
test_node = SLIST_GET(test_node->next);
}
if (test_node == node)
{
return prev_node;
}
return NULL;
}
__static_inline slist_node_t *slist_peek_next_loop(slist_t *list, slist_node_t *node)
{
slist_node_t *next_node = SLIST_GET(node->next);
if (next_node == node)
{
return SLIST_GET(list->head);
}
else
{
return next_node;
}
}
__static_inline slist_node_t *slist_peek_prev_loop(slist_t *list, slist_node_t *node)
{
slist_node_t *prev_node = SLIST_GET(list->tail);
slist_node_t *test_node = SLIST_GET(list->head);
while (test_node && test_node != node && prev_node != test_node)
{
prev_node = test_node;
test_node = SLIST_GET(test_node->next);
}
if (test_node == node)
{
return prev_node;
}
return NULL;
}
__static_inline int slist_is_pending(slist_node_t *node)
{
return (SLIST_GET(node->next) != NULL);
}
#ifdef __cplusplus
}
#endif
#endif