参考代码
This commit is contained in:
248
components/system/include/list/pslist.h
Executable file
248
components/system/include/list/pslist.h
Executable file
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* @file pslist.h
|
||||
* @author LokLiang (lokliang@163.com)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2023-05-01
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PSLIST_H__
|
||||
#define __PSLIST_H__
|
||||
|
||||
#include "sys_types.h"
|
||||
|
||||
typedef struct _psnode sys_psnode_t;
|
||||
|
||||
typedef struct _pslist sys_pslist_t;
|
||||
|
||||
struct _psnode
|
||||
{
|
||||
sys_psnode_t *const *next;
|
||||
};
|
||||
|
||||
struct _pslist
|
||||
{
|
||||
sys_psnode_t *const *head;
|
||||
sys_psnode_t *const *tail;
|
||||
};
|
||||
|
||||
#define _CONTAINER_OF(PTR, TYPE, MEMBER) ((TYPE *)&((uint8_t *)PTR)[-(int)&((TYPE *)0)->MEMBER])
|
||||
|
||||
#define SYS_PSLIST_FOR_EACH_NODE(__sl, __sn) \
|
||||
for (__sn = sys_pslist_peek_head(__sl); __sn; \
|
||||
__sn = sys_pslist_peek_next(__sn))
|
||||
|
||||
#define SYS_PSLIST_ITERATE_FROM_NODE(__sl, __sn) \
|
||||
for (__sn = __sn ? sys_pslist_peek_next_no_check(__sn) \
|
||||
: sys_pslist_peek_head(__sl); \
|
||||
__sn; \
|
||||
__sn = sys_pslist_peek_next(__sn))
|
||||
|
||||
#define SYS_PSLIST_FOR_EACH_NODE_SAFE(__sl, __sn, __sns) \
|
||||
for (__sn = sys_pslist_peek_head(__sl), \
|
||||
__sns = sys_pslist_peek_next(__sn); \
|
||||
__sn; \
|
||||
__sn = __sns, __sns = sys_pslist_peek_next(__sn))
|
||||
|
||||
#define SYS_PSLIST_CONTAINER(__ln, __cn, __n) \
|
||||
((__ln) ? _CONTAINER_OF((__ln), __typeof__(*(__cn)), __n) : NULL)
|
||||
|
||||
#define SYS_PSLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n) \
|
||||
SYS_PSLIST_CONTAINER(sys_pslist_peek_head(__sl), __cn, __n)
|
||||
|
||||
#define SYS_PSLIST_PEEK_TAIL_CONTAINER(__sl, __cn, __n) \
|
||||
SYS_PSLIST_CONTAINER(sys_pslist_peek_tail(__sl), __cn, __n)
|
||||
|
||||
#define SYS_PSLIST_PEEK_NEXT_CONTAINER(__cn, __n) \
|
||||
((__cn) ? SYS_PSLIST_CONTAINER(sys_pslist_peek_next(&((__cn)->__n)), \
|
||||
__cn, __n) \
|
||||
: NULL)
|
||||
|
||||
#define SYS_PSLIST_FOR_EACH_CONTAINER(__sl, __cn, __n) \
|
||||
for (__cn = SYS_PSLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n); \
|
||||
__cn; \
|
||||
__cn = SYS_PSLIST_PEEK_NEXT_CONTAINER(__cn, __n))
|
||||
|
||||
#define SYS_PSLIST_FOR_EACH_CONTAINER_SAFE(__sl, __cn, __cns, __n) \
|
||||
for (__cn = SYS_PSLIST_PEEK_HEAD_CONTAINER(__sl, __cn, __n), \
|
||||
__cns = SYS_PSLIST_PEEK_NEXT_CONTAINER(__cn, __n); \
|
||||
__cn; \
|
||||
__cn = __cns, __cns = SYS_PSLIST_PEEK_NEXT_CONTAINER(__cn, __n))
|
||||
|
||||
__static_inline void sys_pslist_init(sys_pslist_t *list)
|
||||
{
|
||||
list->head = NULL;
|
||||
list->tail = NULL;
|
||||
}
|
||||
|
||||
#define SYS_PSLIST_STATIC_INIT(ptr_to_list) \
|
||||
{ \
|
||||
NULL, NULL \
|
||||
}
|
||||
|
||||
__static_inline bool sys_pslist_is_empty(sys_pslist_t *list)
|
||||
{
|
||||
return (!list->head);
|
||||
}
|
||||
|
||||
__static_inline sys_psnode_t *const *sys_pslist_peek_head(sys_pslist_t *list)
|
||||
{
|
||||
return list->head;
|
||||
}
|
||||
|
||||
__static_inline sys_psnode_t *const *sys_pslist_peek_tail(sys_pslist_t *list)
|
||||
{
|
||||
return list->tail;
|
||||
}
|
||||
|
||||
__static_inline sys_psnode_t *const *sys_pslist_peek_next_no_check(sys_psnode_t *const *node)
|
||||
{
|
||||
return (*node)->next;
|
||||
}
|
||||
|
||||
__static_inline sys_psnode_t *const *sys_pslist_peek_next(sys_psnode_t *const *node)
|
||||
{
|
||||
return node ? sys_pslist_peek_next_no_check(node) : NULL;
|
||||
}
|
||||
|
||||
__static_inline void sys_pslist_prepend(sys_pslist_t *list,
|
||||
sys_psnode_t *const *node)
|
||||
{
|
||||
(*node)->next = list->head;
|
||||
list->head = node;
|
||||
|
||||
if (!list->tail)
|
||||
{
|
||||
list->tail = list->head;
|
||||
}
|
||||
}
|
||||
|
||||
__static_inline void sys_pslist_append(sys_pslist_t *list,
|
||||
sys_psnode_t *const *node)
|
||||
{
|
||||
(*node)->next = NULL;
|
||||
|
||||
if (!list->tail)
|
||||
{
|
||||
list->tail = node;
|
||||
list->head = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*(list->tail))->next = node;
|
||||
list->tail = node;
|
||||
}
|
||||
}
|
||||
|
||||
__static_inline void sys_pslist_append_list(sys_pslist_t *list,
|
||||
sys_psnode_t *const *head, sys_psnode_t *const *tail)
|
||||
{
|
||||
if (!list->tail)
|
||||
{
|
||||
list->head = head;
|
||||
list->tail = tail;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*(list->tail))->next = head;
|
||||
list->tail = tail;
|
||||
}
|
||||
}
|
||||
|
||||
__static_inline void sys_pslist_merge_pslist(sys_pslist_t *list,
|
||||
sys_pslist_t *list_to_append)
|
||||
{
|
||||
sys_pslist_append_list(list, list_to_append->head,
|
||||
list_to_append->tail);
|
||||
sys_pslist_init(list_to_append);
|
||||
}
|
||||
|
||||
__static_inline void sys_pslist_insert(sys_pslist_t *list,
|
||||
sys_psnode_t *const *prev,
|
||||
sys_psnode_t *const *node)
|
||||
{
|
||||
if (!prev)
|
||||
{
|
||||
sys_pslist_prepend(list, node);
|
||||
}
|
||||
else if (!(*prev)->next)
|
||||
{
|
||||
sys_pslist_append(list, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*node)->next = (*prev)->next;
|
||||
(*prev)->next = node;
|
||||
}
|
||||
}
|
||||
|
||||
__static_inline sys_psnode_t *const *sys_pslist_get_not_empty(sys_pslist_t *list)
|
||||
{
|
||||
sys_psnode_t *const *node = list->head;
|
||||
|
||||
list->head = (*node)->next;
|
||||
if (list->tail == node)
|
||||
{
|
||||
list->tail = list->head;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
__static_inline sys_psnode_t *const *sys_pslist_get(sys_pslist_t *list)
|
||||
{
|
||||
return sys_pslist_is_empty(list) ? NULL : sys_pslist_get_not_empty(list);
|
||||
}
|
||||
|
||||
__static_inline void sys_pslist_remove(sys_pslist_t *list,
|
||||
sys_psnode_t *const *prev_node,
|
||||
sys_psnode_t *const *node)
|
||||
{
|
||||
if (!prev_node)
|
||||
{
|
||||
list->head = (*node)->next;
|
||||
|
||||
/* Was node also the tail? */
|
||||
if (list->tail == node)
|
||||
{
|
||||
list->tail = list->head;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*prev_node)->next = (*node)->next;
|
||||
|
||||
/* Was node the tail? */
|
||||
if (list->tail == node)
|
||||
{
|
||||
list->tail = prev_node;
|
||||
}
|
||||
}
|
||||
|
||||
(*node)->next = NULL;
|
||||
}
|
||||
|
||||
__static_inline bool sys_pslist_find_and_remove(sys_pslist_t *list,
|
||||
sys_psnode_t *const *node)
|
||||
{
|
||||
sys_psnode_t *const *prev = NULL;
|
||||
sys_psnode_t *const *test;
|
||||
|
||||
SYS_PSLIST_FOR_EACH_NODE(list, test)
|
||||
{
|
||||
if (test == node)
|
||||
{
|
||||
sys_pslist_remove(list, prev, node);
|
||||
return true;
|
||||
}
|
||||
|
||||
prev = test;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user