/** * PROJECT: ExectOS * COPYRIGHT: See COPYING.md in the top level directory * FILE: xtoskrnl/rtl/slist.cc * DESCRIPTION: Singly linked list manipulation routines * DEVELOPERS: Rafal Kupiec */ #include /** * Retrieves the first entry from a singly linked list without removing it from the list. * * @param ListHead * Supplies a pointer to a structure that serves as the list header. * * @return This routine returns a pointer to the first entry in the list, or NULLPTR if the list is empty. * * @since XT 1.0 */ XTCDECL PSINGLE_LIST_ENTRY RTL::SinglyList::GetFirstEntry(IN PSINGLE_LIST_HEADER ListHead) { /* Check if the list is empty */ if(ListEmpty(ListHead)) { /* Empty list, return NULLPTR */ return NULLPTR; } /* Return first entry in the list */ return ListHead->Next.Next; } /** * Initializes a structure representing the head of a singly linked list. * * @param ListHead * Supplies a pointer to a structure that serves as the list header. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::SinglyList::InitializeListHead(IN PSINGLE_LIST_HEADER ListHead) { /* Initialize the list head */ ListHead->Alignment = 0; } /** * Inserts an entry at the head of a singly linked list. * * @param ListHead * Supplies a pointer to the head of the list. * * @param Entry * Supplies a pointer to the entry that will be inserted in the list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::SinglyList::InsertHeadList(IN OUT PSINGLE_LIST_HEADER ListHead, IN PSINGLE_LIST_ENTRY Entry) { /* Insert entry at the head of the list and increment depth */ Entry->Next = ListHead->Next.Next; ListHead->Next.Next = Entry; ListHead->Depth++; } /** * Inserts an entry at the tail of a singly linked list. * * @param ListHead * Supplies a pointer to the head of the list. * * @param Entry * Supplies a pointer to the entry that will be inserted in the list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::SinglyList::InsertTailList(IN OUT PSINGLE_LIST_HEADER ListHead, IN PSINGLE_LIST_ENTRY Entry) { PSINGLE_LIST_ENTRY CurrentEntry; /* Set Next pointer of the new entry to NULLPTR */ Entry->Next = NULLPTR; /* Check if the list is empty */ if(ListEmpty(ListHead)) { /* Insert entry at the head */ ListHead->Next.Next = Entry; } else { /* Traverse the list to find the last entry */ CurrentEntry = ListHead->Next.Next; while(CurrentEntry->Next != NULLPTR) { /* Move to the next entry */ CurrentEntry = CurrentEntry->Next; } /* Insert entry at the tail */ CurrentEntry->Next = Entry; } /* Increment list depth */ ListHead->Depth++; } /** * Indicates whether a singly linked list structure is empty, or not initialized at all. * * @param ListHead * Supplies a pointer to a structure that represents the head of the list. * * @return This routine returns TRUE if there are currently no entries in the list or FALSE otherwise. * * @since XT 1.0 */ XTCDECL BOOLEAN RTL::SinglyList::ListEmpty(IN PSINGLE_LIST_HEADER ListHead) { /* Check if the list is empty */ return (ListHead == NULLPTR || ListHead->Next.Next == NULLPTR); } /** * Queries the current depth (number of entries) of a singly linked list. * * @param ListHead * Supplies a pointer to a structure that represents the head of the singly linked list. * * @return This routine returns the number of entries currently in the list, or zero if the list head is NULLPTR. * * @since XT 1.0 */ XTAPI USHORT RTL::SinglyList::QueryListDepth(IN PSINGLE_LIST_HEADER ListHead) { /* Check if the list head is initialized and valid */ if(ListHead == NULLPTR) { /* Return zero */ return 0; } /* Return the list depth */ return ListHead->Depth; } /** * Removes an entry from a singly linked list. * * @param ListHead * Supplies a pointer to the head of the list. * * @param Entry * Supplies a pointer to the entry that will be removed from the list. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::SinglyList::RemoveEntryList(IN PSINGLE_LIST_HEADER ListHead, IN PSINGLE_LIST_ENTRY Entry) { PSINGLE_LIST_ENTRY PreviousEntry; /* Check if the list is empty */ if(ListEmpty(ListHead)) { /* List is empty, nothing to remove */ return; } /* Check if the entry is the first one */ if(ListHead->Next.Next == Entry) { /* Remove the first entry and decrement depth */ ListHead->Next.Next = Entry->Next; ListHead->Depth--; /* Nothing else to do */ return; } /* Find the previous entry */ PreviousEntry = ListHead->Next.Next; while(PreviousEntry->Next != Entry) { /* Move to the next entry */ PreviousEntry = PreviousEntry->Next; /* Check if we reached the end of the list */ if(PreviousEntry == NULLPTR) { /* Entry not found */ return; } } /* Remove the entry and decrement depth */ PreviousEntry->Next = Entry->Next; ListHead->Depth--; } /** * Splices a singly linked list at the head of another list. The source list is reinitialized to empty. * * @param ListHead * Supplies a pointer to a structure that represents the head of the list. * * @param SpliceList * Supplies a pointer to a structure that represents the head of the list that will be spliced. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::SinglyList::SpliceHeadList(IN OUT PSINGLE_LIST_HEADER ListHead, IN OUT PSINGLE_LIST_HEADER SpliceList) { PSINGLE_LIST_ENTRY LastEntry; /* Check if the list to splice is empty */ if(ListEmpty(SpliceList)) { /* Nothing to splice, return */ return; } /* Find the last entry of the list to splice */ LastEntry = SpliceList->Next.Next; while(LastEntry->Next != NULLPTR) { /* Move to the next entry */ LastEntry = LastEntry->Next; } /* Splice the list at the head of destination */ LastEntry->Next = ListHead->Next.Next; ListHead->Next.Next = SpliceList->Next.Next; /* Update depth of the destination list */ ListHead->Depth += SpliceList->Depth; /* Reinitialize the source list to empty */ SpliceList->Next.Next = NULLPTR; SpliceList->Depth = 0; } /** * Splices a singly linked list at the tail of another list. The source list is reinitialized to empty. * * @param ListHead * Supplies a pointer to the head of the destination list. * * @param SpliceList * Supplies a pointer to the head of the list that will be spliced. * * @return This routine does not return any value. * * @since XT 1.0 */ XTCDECL VOID RTL::SinglyList::SpliceTailList(IN OUT PSINGLE_LIST_HEADER ListHead, IN OUT PSINGLE_LIST_HEADER SpliceList) { PSINGLE_LIST_ENTRY LastEntry; /* Check if the list to splice is empty */ if(ListEmpty(SpliceList)) { /* Nothing to splice, return */ return; } /* Check if the destination list is empty */ if(ListHead->Next.Next == NULLPTR) { /* Simply move the splice list to the destination head */ ListHead->Next.Next = SpliceList->Next.Next; } else { /* Find the last entry of the destination list */ LastEntry = ListHead->Next.Next; while(LastEntry->Next != NULLPTR) { /* Move to the next entry */ LastEntry = LastEntry->Next; } /* Splice the list at the tail of destination */ LastEntry->Next = SpliceList->Next.Next; } /* Update depth of the destination list */ ListHead->Depth += SpliceList->Depth; /* Reinitialize the source list to empty */ SpliceList->Next.Next = NULLPTR; SpliceList->Depth = 0; }