413 lines
11 KiB
C
413 lines
11 KiB
C
|
|
/**
|
|||
|
|
* @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
|