Implement singly linked list support
All checks were successful
Builds / ExectOS (amd64, release) (push) Successful in 35s
Builds / ExectOS (i686, debug) (push) Successful in 33s
Builds / ExectOS (i686, release) (push) Successful in 51s
Builds / ExectOS (amd64, debug) (push) Successful in 56s

This commit is contained in:
2026-02-22 12:25:51 +01:00
parent 70d758ec5b
commit 2bbc21b667
4 changed files with 367 additions and 0 deletions

327
xtoskrnl/rtl/slist.cc Normal file
View File

@@ -0,0 +1,327 @@
/**
* 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 <belliash@codingworkshop.eu.org>
*/
#include <xtos.hh>
/**
* 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;
}