mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-12-23 19:20:56 +00:00
231 lines
3.9 KiB
C
231 lines
3.9 KiB
C
|
/*
|
||
|
From the 'Wizard2' engine by Spaddlewit Inc. ( http://www.spaddlewit.com )
|
||
|
An experimental work-in-progress.
|
||
|
|
||
|
Donated to Sonic Team Junior and adapted to work with
|
||
|
Sonic Robo Blast 2. The license of this code matches whatever
|
||
|
the licensing is for Sonic Robo Blast 2.
|
||
|
*/
|
||
|
|
||
|
#include "u_list.h"
|
||
|
#include "../z_zone.h"
|
||
|
|
||
|
// Utility for managing
|
||
|
// structures in a linked
|
||
|
// list.
|
||
|
//
|
||
|
// Struct must have "next" and "prev" pointers
|
||
|
// as its first two variables.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// ListAdd
|
||
|
//
|
||
|
// Adds an item to the list
|
||
|
//
|
||
|
void ListAdd(void *pItem, listitem_t **itemHead)
|
||
|
{
|
||
|
listitem_t *item = (listitem_t*)pItem;
|
||
|
|
||
|
if (*itemHead == NULL)
|
||
|
{
|
||
|
*itemHead = item;
|
||
|
(*itemHead)->prev = (*itemHead)->next = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
listitem_t *tail;
|
||
|
tail = *itemHead;
|
||
|
|
||
|
while (tail->next != NULL)
|
||
|
tail = tail->next;
|
||
|
|
||
|
tail->next = item;
|
||
|
|
||
|
tail->next->prev = tail;
|
||
|
|
||
|
item->next = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ListAddFront
|
||
|
//
|
||
|
// Adds an item to the front of the list
|
||
|
// (This is much faster)
|
||
|
//
|
||
|
void ListAddFront(void *pItem, listitem_t **itemHead)
|
||
|
{
|
||
|
listitem_t *item = (listitem_t*)pItem;
|
||
|
|
||
|
if (*itemHead == NULL)
|
||
|
{
|
||
|
*itemHead = item;
|
||
|
(*itemHead)->prev = (*itemHead)->next = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
(*itemHead)->prev = item;
|
||
|
item->next = (*itemHead);
|
||
|
item->prev = NULL;
|
||
|
*itemHead = item;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ListAddBefore
|
||
|
//
|
||
|
// Adds an item before the item specified in the list
|
||
|
//
|
||
|
void ListAddBefore(void *pItem, void *pSpot, listitem_t **itemHead)
|
||
|
{
|
||
|
listitem_t *item = (listitem_t*)pItem;
|
||
|
listitem_t *spot = (listitem_t*)pSpot;
|
||
|
|
||
|
listitem_t *prev = spot->prev;
|
||
|
|
||
|
if (!prev)
|
||
|
ListAddFront(pItem, itemHead);
|
||
|
else
|
||
|
{
|
||
|
item->next = spot;
|
||
|
spot->prev = item;
|
||
|
item->prev = prev;
|
||
|
prev->next = item;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ListAddAfter
|
||
|
//
|
||
|
// Adds an item after the item specified in the list
|
||
|
//
|
||
|
void ListAddAfter(void *pItem, void *pSpot, listitem_t **itemHead)
|
||
|
{
|
||
|
listitem_t *item = (listitem_t*)pItem;
|
||
|
listitem_t *spot = (listitem_t*)pSpot;
|
||
|
|
||
|
listitem_t *next = spot->next;
|
||
|
|
||
|
if (!next)
|
||
|
ListAdd(pItem, itemHead);
|
||
|
else
|
||
|
{
|
||
|
item->prev = spot;
|
||
|
spot->next = item;
|
||
|
item->next = next;
|
||
|
next->prev = item;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ListRemove
|
||
|
//
|
||
|
// Take an item out of the list and free its memory.
|
||
|
//
|
||
|
void ListRemove(void *pItem, listitem_t **itemHead)
|
||
|
{
|
||
|
listitem_t *item = (listitem_t*)pItem;
|
||
|
|
||
|
if (item == *itemHead) // Start of list
|
||
|
{
|
||
|
*itemHead = item->next;
|
||
|
|
||
|
if (*itemHead)
|
||
|
(*itemHead)->prev = NULL;
|
||
|
}
|
||
|
else if (item->next == NULL) // end of list
|
||
|
{
|
||
|
item->prev->next = NULL;
|
||
|
}
|
||
|
else // Somewhere in between
|
||
|
{
|
||
|
item->prev->next = item->next;
|
||
|
item->next->prev = item->prev;
|
||
|
}
|
||
|
|
||
|
Z_Free (item);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ListRemoveAll
|
||
|
//
|
||
|
// Removes all items from the list, freeing their memory.
|
||
|
//
|
||
|
void ListRemoveAll(listitem_t **itemHead)
|
||
|
{
|
||
|
listitem_t *item;
|
||
|
listitem_t *next;
|
||
|
for (item = *itemHead; item; item = next)
|
||
|
{
|
||
|
next = item->next;
|
||
|
ListRemove(item, itemHead);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ListRemoveNoFree
|
||
|
//
|
||
|
// Take an item out of the list, but don't free its memory.
|
||
|
//
|
||
|
void ListRemoveNoFree(void *pItem, listitem_t **itemHead)
|
||
|
{
|
||
|
listitem_t *item = (listitem_t*)pItem;
|
||
|
|
||
|
if (item == *itemHead) // Start of list
|
||
|
{
|
||
|
*itemHead = item->next;
|
||
|
|
||
|
if (*itemHead)
|
||
|
(*itemHead)->prev = NULL;
|
||
|
}
|
||
|
else if (item->next == NULL) // end of list
|
||
|
{
|
||
|
item->prev->next = NULL;
|
||
|
}
|
||
|
else // Somewhere in between
|
||
|
{
|
||
|
item->prev->next = item->next;
|
||
|
item->next->prev = item->prev;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ListGetCount
|
||
|
//
|
||
|
// Counts the # of items in a list
|
||
|
// Should not be used in performance-minded code
|
||
|
//
|
||
|
unsigned int ListGetCount(void *itemHead)
|
||
|
{
|
||
|
listitem_t *item = (listitem_t*)itemHead;
|
||
|
|
||
|
unsigned int count = 0;
|
||
|
for (; item; item = item->next)
|
||
|
count++;
|
||
|
|
||
|
return count;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// ListGetByIndex
|
||
|
//
|
||
|
// Gets an item in the list by its index
|
||
|
// Should not be used in performance-minded code
|
||
|
//
|
||
|
listitem_t *ListGetByIndex(void *itemHead, unsigned int index)
|
||
|
{
|
||
|
listitem_t *head = (listitem_t*)itemHead;
|
||
|
unsigned int count = 0;
|
||
|
listitem_t *node;
|
||
|
for (node = head; node; node = node->next)
|
||
|
{
|
||
|
if (count == index)
|
||
|
return node;
|
||
|
|
||
|
count++;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|