612 lines
24 KiB
C
Executable File
612 lines
24 KiB
C
Executable File
/*
|
|
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the
|
|
* distribution.
|
|
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef _SYS_LIST_H_
|
|
#define _SYS_LIST_H_
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include "compiler.h"
|
|
#include "sys/defs.h"
|
|
|
|
/* Backward compatibility for old macro definitions */
|
|
#define XR_LIST_BACKWARD_COMPATIBILITY 1
|
|
|
|
#if XR_LIST_BACKWARD_COMPATIBILITY
|
|
|
|
typedef struct list_head {
|
|
struct list_head *next;
|
|
struct list_head *prev;
|
|
} xr_list_t;
|
|
|
|
#else /* XR_LIST_BACKWARD_COMPATIBILITY */
|
|
|
|
typedef struct xr_list {
|
|
struct xr_list *next;
|
|
struct xr_list *prev;
|
|
} xr_list_t;
|
|
|
|
#endif /* XR_LIST_BACKWARD_COMPATIBILITY */
|
|
|
|
#define XR_LIST_HEAD(l) { &(l), &(l) }
|
|
|
|
#define XR_LIST_DEFINE(l) \
|
|
xr_list_t l = { &(l), &(l) }
|
|
|
|
static __always_inline void _XR_List_InsertNode(xr_list_t *insert_node,
|
|
xr_list_t *left,
|
|
xr_list_t *right)
|
|
{
|
|
right->prev = insert_node;
|
|
insert_node->next = right;
|
|
insert_node->prev = left;
|
|
left->next = insert_node;
|
|
}
|
|
|
|
static __always_inline void _XR_List_DelNode(xr_list_t *left, xr_list_t *right)
|
|
{
|
|
right->prev = left;
|
|
left->next = right;
|
|
}
|
|
|
|
static __always_inline void _XR_List_InsertList(xr_list_t *insert_list,
|
|
xr_list_t *left,
|
|
xr_list_t *right)
|
|
{
|
|
/* link the last node of 'inserted_list' to 'right' */
|
|
insert_list->next->prev = left;
|
|
left->next = insert_list->next;
|
|
/* link the first node of 'inserted_list' to 'left' */
|
|
insert_list->prev->next = right;
|
|
right->prev = insert_list->prev;
|
|
}
|
|
|
|
#define _XR_LIST_IS_EMPTY(list_head) ((list_head)->next == (list_head))
|
|
#define _XR_LIST_NODE_IS_FIRST(node, list_head) ((list_head)->next == (node))
|
|
#define _XR_LIST_NODE_IS_LAST(node, list_head) ((node)->next == (list_head))
|
|
#define _XR_LIST_IS_ONLY_ONE_NODE(list) \
|
|
(!_XR_LIST_IS_EMPTY(list) && ((list)->next == (list)->prev))
|
|
|
|
/**
|
|
* @brief Initialize a doubly linked list
|
|
*/
|
|
#define XR_List_Init(list) \
|
|
do { \
|
|
(list)->prev = (list); \
|
|
(list)->next = (list); \
|
|
} while (0)
|
|
|
|
/**
|
|
* @brief Insert a node from the head of the double linked list
|
|
* @param[in] node new node to be inserted
|
|
* @param[in] list dl-list where the new node is inserted
|
|
* @return None
|
|
*/
|
|
static __always_inline void XR_List_Insert(xr_list_t *node, xr_list_t *list)
|
|
{
|
|
_XR_List_InsertNode(node, list, list->next);
|
|
}
|
|
|
|
/**
|
|
* @brief Insert a node from the tail of the double linked list
|
|
* @param[in] node New node to be inserted
|
|
* @param[in] list dl-list where the new node is inserted
|
|
* @return None
|
|
*/
|
|
static __always_inline void XR_List_InsertTail(xr_list_t *node, xr_list_t *list)
|
|
{
|
|
_XR_List_InsertNode(node, list->prev, list);
|
|
}
|
|
|
|
/**
|
|
* @brief Delete a specified node in the double linked list
|
|
* @param[in] node Node to be deleted
|
|
* @return None
|
|
*
|
|
* @note The deleted node will be initialized
|
|
*/
|
|
static __always_inline void XR_List_Del(xr_list_t *node)
|
|
{
|
|
_XR_List_DelNode(node->prev, node->next);
|
|
XR_List_Init(node);
|
|
}
|
|
|
|
/**
|
|
* @brief Replace the old node in the double linked list
|
|
* @param[in] new_node The new node in this double linked list
|
|
* @param[in] old_node Old node to be replaced
|
|
* @return None
|
|
*/
|
|
static __always_inline void XR_List_Replace(xr_list_t *new_node, xr_list_t *old_node)
|
|
{
|
|
new_node->next = old_node->next;
|
|
old_node->next->prev = new_node;
|
|
new_node->prev = old_node->prev;
|
|
old_node->prev->next = new_node;
|
|
}
|
|
|
|
/**
|
|
* @brief Move a node to the head of the double linked list
|
|
* @param[in] node Node to be moved
|
|
* @param[in] list Double linked list of this node
|
|
* @return None
|
|
*/
|
|
static __always_inline void XR_List_Move(xr_list_t *node, xr_list_t *list)
|
|
{
|
|
_XR_List_DelNode(node->prev, node->next);
|
|
XR_List_Insert(node, list);
|
|
}
|
|
|
|
/**
|
|
* @brief Move a node to the tail of the double linked list
|
|
* @param[in] node Node to be moved
|
|
* @param[in] list Double linked list of this node
|
|
* @return None
|
|
*/
|
|
static __always_inline void XR_List_MoveTail(xr_list_t *node, xr_list_t *list)
|
|
{
|
|
_XR_List_DelNode(node->prev, node->next);
|
|
XR_List_InsertTail(node, list);
|
|
}
|
|
|
|
/**
|
|
* @brief Judge whether a node is the first one in the double linked list
|
|
* @param[in] node Nodes to be judged
|
|
* @param[in] list Double linked list of nodes
|
|
* @retval Status of check:
|
|
* 1: this node is the first
|
|
* 0: this node is not the first
|
|
*/
|
|
static __always_inline int XR_List_IsFirst(const xr_list_t *node, const xr_list_t *list)
|
|
{
|
|
return _XR_LIST_NODE_IS_FIRST(node, list);
|
|
}
|
|
|
|
/**
|
|
* @brief Judge whether a node is the last one in the double linked list
|
|
* @param[in] node Nodes to be judged
|
|
* @param[in] list Double linked list of nodes
|
|
* @retval Status of check:
|
|
* 1: this node is the last
|
|
* 0: this node is not the last
|
|
*/
|
|
static __always_inline int XR_List_IsLast(const xr_list_t *node, const xr_list_t *list)
|
|
{
|
|
return _XR_LIST_NODE_IS_LAST(node, list);
|
|
}
|
|
|
|
/**
|
|
* @brief Check whether a double linked list is empty
|
|
* @param[in] list List to be checked
|
|
* @retval Status of check:
|
|
* 1: this list is empty
|
|
* 0: this list is not empty
|
|
*/
|
|
static __always_inline int XR_List_IsEmpty(const xr_list_t *list)
|
|
{
|
|
return _XR_LIST_IS_EMPTY(list);
|
|
}
|
|
|
|
/**
|
|
* @brief Check whether the double linked list has only one element
|
|
* @param[in] list List to be checked
|
|
* @retval Status of check:
|
|
* 1: This double linked list has only one node
|
|
* 0: This double linked list is empty or has multiple nodes
|
|
*/
|
|
static __always_inline int XR_List_IsOnlyOne(const xr_list_t *list)
|
|
{
|
|
return _XR_LIST_IS_ONLY_ONE_NODE(list);
|
|
}
|
|
|
|
/**
|
|
* @brief Insert a double linked list from the head to the specified double linked list
|
|
* @param[in] ori_list Dest double linked list
|
|
* @param[in] insert_list double linked list to be inserted
|
|
* @return None
|
|
*/
|
|
static __always_inline void XR_List_Concat(xr_list_t *ori_list, xr_list_t *insert_list)
|
|
{
|
|
if (_XR_LIST_IS_EMPTY(insert_list))
|
|
return;
|
|
_XR_List_InsertList(insert_list, ori_list, ori_list->next);
|
|
}
|
|
|
|
/**
|
|
* @brief Insert a double linked list from the tail to the specified double linked list
|
|
* @param[in] ori_list Dest double linked list
|
|
* @param[in] insert_list Double linked list to be inserted
|
|
* @return None
|
|
*/
|
|
static __always_inline void XR_List_ConcatTail(xr_list_t *ori_list, xr_list_t *insert_list)
|
|
{
|
|
if (_XR_LIST_IS_EMPTY(insert_list))
|
|
return;
|
|
_XR_List_InsertList(insert_list, ori_list->prev, ori_list);
|
|
}
|
|
|
|
/**
|
|
* @brief Split all nodes before the specified node into a sub double linked list
|
|
* @param[in] node Specified node
|
|
* @param[in] ori_list Source double linked list to be split
|
|
* @param[in] sub_list Sub double linked list generated by splitting
|
|
* @return None
|
|
*
|
|
* @note From ori_list first element to param 'node', all elements are split into sub_list,
|
|
* and the remaining elements are refreshed to ori_list.
|
|
* The param 'node' must to be an element node, not ori_list head!
|
|
*
|
|
* @examples are as follows:
|
|
* ori_list is: element1 <-> element2 <-> element3 <-> element4 <-> element5
|
|
* sub_list is: empty
|
|
*
|
|
* if param 'node' is element3, the split results are as follows:
|
|
* ori_list is: element4 <-> element5
|
|
* sub_list is: element1 <-> element2 <-> element3
|
|
*/
|
|
static __always_inline void XR_List_Split(xr_list_t *node, xr_list_t *ori_list,
|
|
xr_list_t *sub_list)
|
|
{
|
|
/* record the first new node for the origin list */
|
|
xr_list_t *ori_first = node->next;
|
|
|
|
/* check assert */
|
|
if ((_XR_LIST_IS_EMPTY(ori_list) || node == ori_list) ||
|
|
(_XR_LIST_IS_ONLY_ONE_NODE(ori_list) && !_XR_LIST_NODE_IS_FIRST(node, ori_list)))
|
|
return;
|
|
|
|
/* construct sublist */
|
|
sub_list->next = ori_list->next;
|
|
ori_list->next->prev = sub_list;
|
|
node->next = sub_list;
|
|
sub_list->prev = node;
|
|
|
|
/* update origin list */
|
|
ori_list->next = ori_first;
|
|
ori_first->prev = ori_list;
|
|
}
|
|
|
|
/**
|
|
* @brief Get the pointer to a structure that contains a doubly linked list
|
|
* @param[in] item_ptr The pointer of struct xr_dl_list_s node
|
|
* @param[in] type Structure type
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*/
|
|
#define XR_LIST_ENTRY(item_ptr, type, field) \
|
|
XR_CONTAINER_OF(item_ptr, type, field)
|
|
|
|
/**
|
|
* @brief Get the the last entry from a list
|
|
* @param[in] list_ptr The double linked list head
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*/
|
|
#define XR_LIST_LAST_ENTRY(list_ptr, type, field) \
|
|
XR_LIST_ENTRY((list_ptr)->prev, type, field)
|
|
|
|
/**
|
|
* @brief Get the the first entry from a list
|
|
* @param[in] list_ptr The double linked list head
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*/
|
|
#define XR_LIST_FIRST_ENTRY(list_ptr, type, field) \
|
|
XR_LIST_ENTRY((list_ptr)->next, type, field)
|
|
|
|
/**
|
|
* @brief Get the structure pointer containing the first member
|
|
* of the linked list.
|
|
* @param[in] list_ptr The double linked list head
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*
|
|
* @note If the first member of the linked list does not exist,
|
|
* null will be returned
|
|
*/
|
|
#define XR_LIST_FIRST_ENTRY_OR_NULL(list_ptr, type, field) \
|
|
(_XR_LIST_IS_EMPTY(list_ptr) ? NULL : XR_LIST_FIRST_ENTRY(list_ptr, type, field))
|
|
|
|
|
|
/**
|
|
* @brief iterate a double linked list in positive order from the head
|
|
* @param[in] cur A xr_list_t pointer, used to point to the node traversed
|
|
* @param[in] list Iterated double linked list header
|
|
*
|
|
* @note XR_List_Del() nodes during iteration is not recommended,
|
|
* because it is unsafe, if you need to do so, you can refer to
|
|
* the use of XR_LIST_FOR_EACH_SAFE()
|
|
*/
|
|
#define XR_LIST_FOR_EACH(cur, list) \
|
|
for (cur = (list)->next; \
|
|
cur != (list); \
|
|
cur = cur->next)
|
|
|
|
/**
|
|
* @brief iterate a double linked list in reverse order from the tail
|
|
* @param[in] cur A xr_list_t pointer, used to point to the node traversed
|
|
* @param[in] list Iterated double linked list header
|
|
*
|
|
* @note XR_List_Del() nodes during iteration is not recommended,
|
|
* because it is unsafe, if you need to do so, you can refer to
|
|
* the use of XR_LIST_FOR_EACH_PREV_SAFE()
|
|
*/
|
|
#define XR_LIST_FOR_EACH_PREV(cur, list) \
|
|
for (cur = (list)->prev; \
|
|
cur != (list); \
|
|
cur = cur->prev)
|
|
|
|
/**
|
|
* @brief Safely iterate a double linked list in positive order from the head
|
|
* @param[in] cur A xr_list_t pointer, used to point to the node traversed
|
|
* @param[in] tmp A xr_list_t pointer, Used to cache the next node during iteration,
|
|
* Prevent the loss of the next node due to deletion during iteration
|
|
* @param[in] list Iterated double linked list header
|
|
*/
|
|
#define XR_LIST_FOR_EACH_SAFE(cur, tmp, list) \
|
|
for (cur = (list)->next, tmp = cur->next; \
|
|
cur != (list); \
|
|
cur = tmp, tmp = cur->next)
|
|
|
|
/**
|
|
* @brief Safely iterate a double linked list in reverse order from the tail
|
|
* @param[in] cur A xr_list_t pointer, used to point to the node traversed
|
|
* @param[in] tmp A xr_list_t pointer, Used to cache the next node during iteration,
|
|
* Prevent the loss of the next node due to deletion during iteration
|
|
* @param[in] list Iterated double linked list header
|
|
*/
|
|
#define XR_LIST_FOR_EACH_PREV_SAFE(cur, tmp, list) \
|
|
for (cur = (list)->prev, tmp = cur->prev; \
|
|
cur != (list); \
|
|
cur = tmp, tmp = cur->prev)
|
|
|
|
/**
|
|
* @brief Iterate the structure entity of the embedded double linked list
|
|
* in positive order from the head
|
|
* @param[in] list Iterated double linked list header
|
|
* @param[in] entry The pointer to a entity type
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*/
|
|
#define XR_LIST_FOR_EACH_ENTRY(list, entry, type, field) \
|
|
for (entry = XR_LIST_ENTRY((list)->next, type, field); \
|
|
&entry->field != (list); \
|
|
entry = XR_LIST_ENTRY((entry)->field.next, type, field))
|
|
|
|
/**
|
|
* @brief Iterate the structure entity of the embedded double linked list
|
|
* in reverse order from the tail
|
|
* @param[in] list Iterated double linked list header
|
|
* @param[in] entry The pointer to a entity type
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*/
|
|
#define XR_LIST_FOR_EACH_ENTRY_REVERSE(list, entry, type, field) \
|
|
for (entry = XR_LIST_ENTRY((list)->prev, type, field); \
|
|
&entry->field != (list); \
|
|
entry = XR_LIST_ENTRY((entry)->field.prev, type, field))
|
|
|
|
/**
|
|
* @brief Safely iterate the structure entity of the embedded double linked list
|
|
* in positive order from the head
|
|
* @param[in] list Iterated double linked list header
|
|
* @param[in] entry The pointer to a entity type
|
|
* @param[in] tmp Another xr_list_t pointer to use as temporary storage
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*/
|
|
#define XR_LIST_FOR_EACH_ENTRY_SAFE(list, entry, tmp, type, field) \
|
|
for (entry = XR_LIST_ENTRY((list)->next, type, field), \
|
|
tmp = XR_LIST_ENTRY((entry)->field.next, type, field); \
|
|
&entry->field != (list); \
|
|
entry = tmp, tmp = XR_LIST_ENTRY((entry)->field.next, type, field))
|
|
|
|
/**
|
|
* @brief Safely iterate the structure entity of the embedded double linked list
|
|
* in reverse order from the tail
|
|
* @param[in] list Iterated double linked list header
|
|
* @param[in] entry The pointer to a entity type
|
|
* @param[in] tmp Another xr_list_t pointer to use as temporary storage
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*/
|
|
#define XR_LIST_FOR_EACH_ENTRY_SAFE_REVERSE(list, entry, tmp, type, field) \
|
|
for (entry = XR_LIST_ENTRY((list)->prev, type, field), \
|
|
tmp = XR_LIST_ENTRY((entry)->field.prev, type, field); \
|
|
&entry->field != (list); \
|
|
entry = tmp, tmp = XR_LIST_ENTRY((entry)->field.prev, type, field))
|
|
|
|
/**
|
|
* @brief Prepare a structure entity node to use
|
|
* @param[in] list Double linked list header
|
|
* @param[in] entry The pointer to a entity type
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*
|
|
* @note If the 'entry' is not null, the value of the 'entry' is itself,
|
|
* if the 'entry' is null, a virtual entry pointer is forcibly extended
|
|
* from the list header.
|
|
* It generally used with XR_LIST_FOR_EACH_ENTRY_CONTINUE()
|
|
*/
|
|
#define XR_LIST_PREPARE_ENTRY(list, entry, type, field) \
|
|
((!entry) ? XR_LIST_ENTRY(list, type, field) : (entry))
|
|
|
|
/**
|
|
* @brief Iterate the structure entity of the embedded double linked list
|
|
* in positive order from the specified entity node
|
|
* @param[in] list Iterated double linked list header
|
|
* @param[in] entry The pointer to a entity type
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*/
|
|
#define XR_LIST_FOR_EACH_ENTRY_CONTINUE(list, entry, type, field) \
|
|
for (entry = XR_LIST_ENTRY((entry)->field.next, type, field); \
|
|
&entry->field != (list); \
|
|
entry = XR_LIST_ENTRY((entry)->field.next, type, field))
|
|
|
|
/**
|
|
* @brief Iterate the structure entity of the embedded double linked list
|
|
* in reverse order from the specified entity node
|
|
* @param[in] list Iterated double linked list header
|
|
* @param[in] entry The pointer to a entity type
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*/
|
|
#define XR_LIST_FOR_EACH_ENTRY_CONTINUE_REVERSE(list, entry, type, field) \
|
|
for (entry = XR_LIST_ENTRY((entry)->field.prev, type, field); \
|
|
&entry->field != (list); \
|
|
entry = XR_LIST_ENTRY((entry)->field.prev, type, field))
|
|
|
|
/**
|
|
* @brief Safely iterate the structure entity of the embedded double linked list
|
|
* in positive order from the specified entity node
|
|
* @param[in] list Iterated double linked list header
|
|
* @param[in] entry The pointer to a entity type
|
|
* @param[in] type Structure type of this entry
|
|
* @param[in] field Field name of the doubly linked list in the structure
|
|
*/
|
|
#define XR_LIST_FOR_EACH_ENTRY_SAFE_CONTINUE(list, entry, tmp, type, field) \
|
|
for (entry = XR_LIST_ENTRY((entry)->field.next, type, field), \
|
|
tmp = XR_LIST_ENTRY((entry)->field.next, type, field); \
|
|
&entry->field != (list); \
|
|
entry = tmp, tmp = XR_LIST_ENTRY((tmp)->field.next, type, field))
|
|
|
|
#if XR_LIST_BACKWARD_COMPATIBILITY
|
|
|
|
/* old macro definitions for backward compatibility */
|
|
#define list_for_each(pos, head) XR_LIST_FOR_EACH(pos, head)
|
|
#define list_for_each_prev(pos, head) XR_LIST_FOR_EACH_PREV(pos, head)
|
|
#define list_for_each_safe(pos, n, head) XR_LIST_FOR_EACH_SAFE(pos, n, head)
|
|
#define list_for_each_prev_safe(pos, n, head) XR_LIST_FOR_EACH_PREV_SAFE(pos, n, head)
|
|
#define list_entry(ptr, type, member) XR_LIST_ENTRY(ptr, type, member)
|
|
#define list_first_entry(ptr, type, member) XR_LIST_FIRST_ENTRY(ptr, type, member)
|
|
#define list_last_entry(ptr, type, member) XR_LIST_LAST_ENTRY(ptr, type, member)
|
|
|
|
#define list_first_entry_or_null(ptr, type, member) \
|
|
XR_LIST_FIRST_ENTRY_OR_NULL(ptr, type, member)
|
|
|
|
#define list_next_entry(pos, member) \
|
|
XR_LIST_ENTRY((pos)->member.next, typeof(*(pos)), member)
|
|
|
|
#define list_prev_entry(pos, member) \
|
|
XR_LIST_ENTRY((pos)->member.prev, typeof(*(pos)), member)
|
|
|
|
#define list_safe_reset_next(pos, n, member) \
|
|
(n = XR_LIST_ENTRY((pos)->member.next, typeof(*(pos)), member))
|
|
|
|
#define list_for_each_entry(pos, head, member) \
|
|
XR_LIST_FOR_EACH_ENTRY(head, pos, typeof(*(pos)), member)
|
|
|
|
#define list_for_each_entry_reverse(pos, head, member) \
|
|
XR_LIST_FOR_EACH_ENTRY_REVERSE(head, pos, typeof(*(pos)), member)
|
|
|
|
#define list_for_each_entry_safe(pos, n, head, member) \
|
|
XR_LIST_FOR_EACH_ENTRY_SAFE(head, pos, n, typeof(*(pos)), member)
|
|
|
|
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
|
|
XR_LIST_FOR_EACH_ENTRY_SAFE_REVERSE(head, pos, n, typeof(*(pos)), member)
|
|
|
|
#define list_prepare_entry(pos, head, member) \
|
|
XR_LIST_PREPARE_ENTRY(head, pos, typeof(*(pos)), member)
|
|
|
|
#define list_for_each_entry_continue(pos, head, member) \
|
|
XR_LIST_FOR_EACH_ENTRY_CONTINUE(head, pos, typeof(*(pos)), member)
|
|
|
|
#define list_for_each_entry_continue_reverse(pos, head, member) \
|
|
XR_LIST_FOR_EACH_ENTRY_CONTINUE_REVERSE(head, pos, typeof(*(pos)), member)
|
|
|
|
#define list_for_each_entry_safe_continue(pos, n, head, member) \
|
|
XR_LIST_FOR_EACH_ENTRY_SAFE_CONTINUE(head, pos, n, typeof(*(pos)), member)
|
|
|
|
#define list_for_each_entry_from(pos, head, member) \
|
|
for (; &pos->member != (head); \
|
|
pos = XR_LIST_ENTRY((pos)->member.next, typeof(*(pos)), member)
|
|
|
|
#define list_for_each_entry_safe_from(pos, n, head, member) \
|
|
for (n = XR_LIST_ENTRY((pos)->member.next, typeof(*(pos)), member); \
|
|
&pos->member != (head); \
|
|
pos = n, n = XR_LIST_ENTRY((n)->member.next, typeof(*(n)), member)
|
|
|
|
#define LIST_HEAD_INIT(name) XR_LIST_HEAD(name)
|
|
#define LIST_HEAD_DEF(name) XR_LIST_DEFINE(name)
|
|
#define INIT_LIST_HEAD(list) XR_List_Init(list)
|
|
#define list_add(newl, head) XR_List_Insert(newl, head)
|
|
#define list_add_tail(newl, head) XR_List_InsertTail(newl, head)
|
|
#define list_del(entry) XR_List_Del(entry)
|
|
#define list_replace(old, newl) XR_List_Replace(newl, old)
|
|
#define list_del_init(entry) list_del(entry)
|
|
#define list_move(list, head) XR_List_Move(list, head)
|
|
#define list_move_tail(list, head) XR_List_MoveTail(list, head)
|
|
#define list_is_last(list, head) XR_List_IsLast(list, head)
|
|
#define list_empty(head) XR_List_IsEmpty(head)
|
|
#define list_empty_careful(head) list_empty(head)
|
|
#define list_is_singular(head) XR_List_IsOnlyOne(head)
|
|
#define list_cut_position(list, head, entry) XR_List_Split(entry, head, list)
|
|
#define list_splice(list, head) XR_List_Concat(head, list)
|
|
#define list_splice_tail(list, head) XR_List_ConcatTail(head, list)
|
|
|
|
/* move first node of 'list' to tail */
|
|
#define list_rotate_left(list) \
|
|
do { \
|
|
if (XR_List_IsEmpty(list)) \
|
|
break; \
|
|
XR_List_MoveTail(list->next, list); \
|
|
} while (0) \
|
|
|
|
#define list_splice_init(list, head) \
|
|
do { \
|
|
if (XR_List_IsEmpty(list)) \
|
|
break; \
|
|
XR_List_Concat(head, list); \
|
|
XR_List_Init(list); \
|
|
} while (0) \
|
|
|
|
#define list_splice_tail_init(list, head) \
|
|
do { \
|
|
if (XR_List_IsEmpty(list)) \
|
|
break; \
|
|
XR_List_ConcatTail(head, list); \
|
|
XR_List_Init(list); \
|
|
} while (0) \
|
|
|
|
#define list_replace_init(old, newl) \
|
|
do { \
|
|
XR_List_Replace(newl, old); \
|
|
XR_List_Init(old); \
|
|
} while (0) \
|
|
|
|
#endif /* XR_LIST_BACKWARD_COMPATIBILITY */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _SYS_LIST_H_ */
|