190 lines
7.4 KiB
C
190 lines
7.4 KiB
C
|
|
/*
|
||
|
|
* Copyright (C) 2018 Alibaba Group Holding Limited
|
||
|
|
*/
|
||
|
|
|
||
|
|
/* double linked list header */
|
||
|
|
|
||
|
|
#ifndef __dl_list_h__
|
||
|
|
#define __dl_list_h__
|
||
|
|
|
||
|
|
#ifdef __cplusplus
|
||
|
|
extern "C" {
|
||
|
|
#endif
|
||
|
|
|
||
|
|
/* defines */
|
||
|
|
|
||
|
|
/* typedefs */
|
||
|
|
|
||
|
|
typedef struct _rhino_dlnode /* Node of a linked list. */
|
||
|
|
{
|
||
|
|
struct _rhino_dlnode* next; /* Points at the next node in the list */
|
||
|
|
struct _rhino_dlnode* previous; /* Points at the previous node in the list */
|
||
|
|
} _RHINO_DL_NODE;
|
||
|
|
|
||
|
|
typedef struct /* Header for a linked list. */
|
||
|
|
{
|
||
|
|
_RHINO_DL_NODE* head; /* header of list */
|
||
|
|
_RHINO_DL_NODE* tail; /* tail of list */
|
||
|
|
} _RHINO_DL_LIST;
|
||
|
|
|
||
|
|
typedef _RHINO_DL_NODE DL_NODE;
|
||
|
|
typedef _RHINO_DL_LIST DL_LIST;
|
||
|
|
|
||
|
|
/* DLL_INIT() initialize the specified list to an empty list. */
|
||
|
|
|
||
|
|
#define DLL_INIT(list) \
|
||
|
|
{ \
|
||
|
|
((DL_LIST *)(list))->head = NULL; \
|
||
|
|
((DL_LIST *)(list))->tail = NULL; \
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/* DLL_ADD() adds the specified node to the end of the specified list. */
|
||
|
|
|
||
|
|
#define DLL_ADD(list, node) \
|
||
|
|
{ \
|
||
|
|
DL_NODE* listTail = (list)->tail; \
|
||
|
|
DLL_INSERT ((list), listTail, (node)); \
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* DLL_INSERT() inserts the specified node in the specified list.
|
||
|
|
* The new node is placed following the specified 'previous' node in the list.
|
||
|
|
* If the specified previous node is NULL, the node is inserted at the head
|
||
|
|
* of the list.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define DLL_INSERT(list, previousNode, node) \
|
||
|
|
{ \
|
||
|
|
DL_NODE *temp; \
|
||
|
|
if ((previousNode) == NULL) \
|
||
|
|
{ \
|
||
|
|
temp = ((DL_LIST *)(list))->head; \
|
||
|
|
((DL_LIST *)(list))->head = (DL_NODE *)(node); \
|
||
|
|
} \
|
||
|
|
else \
|
||
|
|
{ \
|
||
|
|
temp = ((DL_NODE *)(previousNode))->next; \
|
||
|
|
((DL_NODE *)(previousNode))->next = (DL_NODE *)(node); \
|
||
|
|
} \
|
||
|
|
if (temp == NULL) \
|
||
|
|
{ \
|
||
|
|
((DL_LIST *)(list))->tail = (DL_NODE *)(node); \
|
||
|
|
} \
|
||
|
|
else \
|
||
|
|
{ \
|
||
|
|
temp->previous = (DL_NODE *)(node); \
|
||
|
|
} \
|
||
|
|
((DL_NODE *)(node))->next = temp; \
|
||
|
|
((DL_NODE *)(node))->previous = (DL_NODE *)(previousNode); \
|
||
|
|
}
|
||
|
|
|
||
|
|
/* DLL_REMOVE() Remove the specified node in the doubly linked list.*/
|
||
|
|
|
||
|
|
#define DLL_REMOVE(list, node) \
|
||
|
|
{ \
|
||
|
|
if (((DL_NODE *)(node))->previous == NULL) \
|
||
|
|
{ \
|
||
|
|
((DL_LIST *)(list))->head = ((DL_NODE *)(node))->next; \
|
||
|
|
} \
|
||
|
|
else \
|
||
|
|
{ \
|
||
|
|
((DL_NODE *)(node))->previous->next = ((DL_NODE *)(node))->next; \
|
||
|
|
} \
|
||
|
|
if (((DL_NODE *)(node))->next == NULL) \
|
||
|
|
{ \
|
||
|
|
((DL_LIST *)(list))->tail = ((DL_NODE *)(node))->previous; \
|
||
|
|
} \
|
||
|
|
else \
|
||
|
|
{ \
|
||
|
|
((DL_NODE *)(node))->next->previous = ((DL_NODE *)(node))->previous; \
|
||
|
|
} \
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
* DLL_FIRST() finds the first node in a doubly linked list.
|
||
|
|
*
|
||
|
|
* RETURNS: Pointer to the first node in a list, or NULL if the list is empty.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define DLL_FIRST(pList) \
|
||
|
|
( \
|
||
|
|
(((DL_LIST *)(pList))->head) \
|
||
|
|
)
|
||
|
|
|
||
|
|
/*
|
||
|
|
* DLL_LAST () finds the last node in a doubly linked list.
|
||
|
|
*
|
||
|
|
* RETURNS: Pointer to the last node in list, or NULL if the list is empty.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define DLL_LAST(pList) \
|
||
|
|
( \
|
||
|
|
(((DL_LIST *)(pList))->tail) \
|
||
|
|
)
|
||
|
|
|
||
|
|
/*
|
||
|
|
* DLL_NEXT() locates the node immediately after the node pointed to by the pNode.
|
||
|
|
*
|
||
|
|
* RETURNS: Pointer to the next node in list, or NULL if there is no next node.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define DLL_NEXT(pNode) \
|
||
|
|
( \
|
||
|
|
(((DL_NODE *)(pNode))->next) \
|
||
|
|
)
|
||
|
|
|
||
|
|
/*
|
||
|
|
* DLL_PREVIOUS() locates the node immediately before the node pointed
|
||
|
|
* to by the pNode.
|
||
|
|
*
|
||
|
|
* RETURNS: Pointer to the preceding node in the list, or
|
||
|
|
* NULL if there is no next node.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define DLL_PREVIOUS(pNode) \
|
||
|
|
( \
|
||
|
|
(((DL_NODE *)(pNode))->previous) \
|
||
|
|
)
|
||
|
|
|
||
|
|
/*
|
||
|
|
* DLL_EMPTY() is used to check if list is empty.
|
||
|
|
* RETURNS: TRUE if list is empty. FALSE otherwise
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define DLL_EMPTY(pList) \
|
||
|
|
( \
|
||
|
|
(((DL_LIST *)pList)->head == NULL) \
|
||
|
|
)
|
||
|
|
|
||
|
|
/*
|
||
|
|
* DLL_GET() gets the first node from the specified list, deletes the node
|
||
|
|
* from the list, and returns a pointer to the node gotten.
|
||
|
|
*
|
||
|
|
* RETURNS: Pointer to the first node in list, or NULL if there is list empty.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#define DLL_GET(list, node) \
|
||
|
|
{ \
|
||
|
|
(node) = (void *)((DL_LIST *)(list))->head; \
|
||
|
|
if ((node) != NULL) \
|
||
|
|
{ \
|
||
|
|
((DL_LIST *)(list))->head = ((DL_NODE *)(node))->next; \
|
||
|
|
if (((DL_NODE *)(node))->next == NULL) \
|
||
|
|
{ \
|
||
|
|
((DL_LIST *)(list))->tail = NULL; \
|
||
|
|
} \
|
||
|
|
else \
|
||
|
|
{ \
|
||
|
|
((DL_NODE *)(node))->next->previous = NULL; \
|
||
|
|
} \
|
||
|
|
} \
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifdef __cplusplus
|
||
|
|
}
|
||
|
|
#endif /* __cplusplus */
|
||
|
|
|
||
|
|
#endif /* __dl_list_h__ */
|
||
|
|
|