///
///_LIST_ENTRY structure definition.
///
struct_LIST_ENTRY {
LIST_ENTRY *ForwardLink;
LIST_ENTRY *BackLink;
};
LIST_ENTRY*
EFIAPI
InitializeListHead(
IN OUT LIST_ENTRY *ListHead
)
{
ASSERT (ListHead != NULL);
ListHead->ForwardLink = ListHead;
ListHead->BackLink = ListHead;
return ListHead;
}
LIST_ENTRY*
EFIAPI
InsertHeadList(
IN OUT LIST_ENTRY *ListHead,
IN OUT LIST_ENTRY *Entry
)
{
Entry->ForwardLink =ListHead->ForwardLink;
Entry->BackLink = ListHead;
ListHead->ForwardLink->BackLink =Entry;
ListHead->ForwardLink = Entry;
return ListHead;
}
/**
Adds a node to the end of a doubly-linkedlist, and returns the pointer to
the head node of the doubly-linked list.
Adds the node Entry to the end of thedoubly-linked list denoted by ListHead,
and returns ListHead.
If ListHead is NULL, then ASSERT().
If Entry is NULL, then ASSERT().
If ListHead was not initialized with INTIALIZE_LIST_HEAD_VARIABLE()or
InitializeListHead(), then ASSERT().
If PcdMaximumLinkedListLenth is not zero, andprior to insertion the number
of nodes in ListHead, including the ListHeadnode, is greater than or
equal to PcdMaximumLinkedListLength, thenASSERT().
@param ListHead A pointer to the headnode of a doubly-linked list.
@param Entry A pointer to a node thatis to be added at the end of the
doubly-linked list.
@return ListHead
**/
LIST_ENTRY*
EFIAPI
InsertTailList(
IN OUT LIST_ENTRY *ListHead,
IN OUT LIST_ENTRY *Entry
)
{
Entry->ForwardLink = ListHead;
Entry->BackLink = ListHead->BackLink;
ListHead->BackLink->ForwardLink =Entry;
ListHead->BackLink = Entry;
return ListHead;
}
/**
Checks to see if a doubly-linked list isempty or not.
Checks to see if the doubly-linked list isempty. If the linked list contains
zero nodes, this function returns TRUE.Otherwise, it returns FALSE.
If ListHead is NULL, then ASSERT().
If ListHead was not initialized withINTIALIZE_LIST_HEAD_VARIABLE() or
InitializeListHead(), then ASSERT().
If PcdMaximumLinkedListLenth is not zero, andthe number of nodes
in List, including the List node, is greaterthan or equal to
PcdMaximumLinkedListLength, then ASSERT().
@param ListHead A pointer to the headnode of a doubly-linked list.
@retval TRUE The linked list is empty.
@retval FALSE The linked list is not empty.
**/
BOOLEAN
EFIAPI
IsListEmpty(
IN CONST LIST_ENTRY *ListHead
)
{
return (BOOLEAN)(ListHead->ForwardLink ==ListHead);
}
/**
Removes a node from a doubly-linked list, andreturns the node that follows
the removed node.
Removes the node Entry from a doubly-linkedlist. It is up to the caller of
this function to release the memory used bythis node if that is required. On
exit, the node following Entry in thedoubly-linked list is returned. If
Entry is the only node in the linked list,then the head node of the linked
list is returned.
If Entry is NULL, then ASSERT().
If Entry is the head node of an empty list,then ASSERT().
If PcdMaximumLinkedListLength is not zero,and the number of nodes in the
linked list containing Entry, including theEntry node, is greater than
or equal to PcdMaximumLinkedListLength, thenASSERT().
@param Entry A pointer to a node in a linked list.
@return Entry.
**/
LIST_ENTRY*
EFIAPI
RemoveEntryList(
IN CONST LIST_ENTRY *Entry
)
{
ASSERT (!IsListEmpty (Entry));
Entry->ForwardLink->BackLink =Entry->BackLink;
Entry->BackLink->ForwardLink =Entry->ForwardLink;
return Entry->ForwardLink;
}
/**
Swaps the location of two nodes in adoubly-linked list, and returns the
first node after the swap.
If FirstEntry is identical to SecondEntry,then SecondEntry is returned.
Otherwise, the location of the FirstEntrynode is swapped with the location
of the SecondEntry node in a doubly-linkedlist. SecondEntry must be in the
same double linked list as FirstEntry andthat double linked list must have
been initialized withINTIALIZE_LIST_HEAD_VARIABLE() or InitializeListHead().
SecondEntry is returned after the nodes areswapped.
If FirstEntry is NULL, then ASSERT().
If SecondEntry is NULL, then ASSERT().
If PcdVerifyNodeInList is TRUE andSecondEntry and FirstEntry are not in the
same linked list, then ASSERT().
If PcdMaximumLinkedListLength is not zero,and the number of nodes in the
linked list containing the FirstEntry andSecondEntry nodes, including
the FirstEntry and SecondEntry nodes, isgreater than or equal to
PcdMaximumLinkedListLength, then ASSERT().
@param FirstEntry A pointer to a node ina linked list.
@param SecondEntry A pointer to another node in the same linked list.
@return SecondEntry.
**/
LIST_ENTRY*
EFIAPI
SwapListEntries(
IN OUT LIST_ENTRY *FirstEntry,
IN OUT LIST_ENTRY *SecondEntry
)
{
LIST_ENTRY *Ptr;
if (FirstEntry == SecondEntry) {
return SecondEntry;
}
//
// Ptr is the node pointed to byFirstEntry->ForwardLink
//
Ptr = RemoveEntryList (FirstEntry);
//
// If FirstEntry immediately followsSecondEntry, FirstEntry will be placed
// immediately in front of SecondEntry
// 如果第一个节点在第二个节点的后面
//
if (Ptr->BackLink == SecondEntry) {
// 把第一个节点放在的第二个节点的前面
return InsertTailList (SecondEntry,FirstEntry);
}
//
// Ptr == SecondEntry means SecondEntryimmediately follows FirstEntry,
// then there are no further steps necessary
// 如果第一个节点在第二个节点的前面
//
if (Ptr == InsertHeadList (SecondEntry,FirstEntry)) {
//把第一个节点放在的第二个节点的后面
return Ptr;
}
//
// Move SecondEntry to the front of Ptr
// 如果两个节点不相邻,前面已经将第一个节点断开,然后放在第二个节点的后面
// 现在只需要把第二个节点断开,放在第一个节点的位置
//
RemoveEntryList (SecondEntry);
InsertTailList (Ptr, SecondEntry);
return SecondEntry;
}
总结:
如果要将一个节点B放在当前节点A的前面,以节点A作为head,调用InsertTailList.
如果要将一个节点B放在当前节点A的后面,以节点A作为head,调用InsertHeadList.