This repository has been archived on 2022-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
Luma3DS-3GX/sysmodules/sm/source/list.c
2020-04-25 13:42:10 +01:00

106 lines
2.5 KiB
C

/*
list.c
(c) TuxSH, 2017-2020
This is part of 3ds_sm, which is licensed under the MIT license (see LICENSE for details).
*/
#include "list.h"
#include "common.h"
struct ListBase;
typedef struct ListNodeBase
{
struct ListNodeBase *prev, *next;
struct ListBase *parent;
} ListNodeBase;
typedef struct ListBase
{
ListNodeBase *first, *last;
} ListBase;
void buildList(void *list, void *pool, u32 nb, u32 elementSize)
{
ListBase *listB = (ListBase *)list;
for(u32 i = 0; i < nb; i++)
{
ListNodeBase *node = (ListNodeBase *)((u8 *)pool + i * elementSize);
node->prev = i == 0 ? NULL : (ListNodeBase *)((u8 *)pool + (i - 1) * elementSize);
node->next = i == (nb - 1) ? NULL : (ListNodeBase *)((u8 *)pool + (i + 1) * elementSize);
node->parent = list;
}
listB->first = (ListNodeBase *)pool;
listB->last = (ListNodeBase *)((u8 *)pool + (nb - 1) * elementSize);
}
void moveNode(void *node, void *dst, bool back)
{
ListNodeBase *nodeB = (ListNodeBase *)node;
ListBase *dstB = (ListBase *)dst;
ListBase *srcB = nodeB->parent;
if(dstB == srcB)
return;
// Remove the node in the source list
if(nodeB->prev != NULL)
nodeB->prev->next = nodeB->next;
if(nodeB->next != NULL)
nodeB->next->prev = nodeB->prev;
// Update the source list if needed
if(nodeB == srcB->first)
srcB->first = nodeB->next;
if(nodeB == srcB->last)
srcB->last = nodeB->prev;
// Insert the node in the destination list
if(back)
{
if(dstB->last != NULL)
dstB->last->next = nodeB;
nodeB->prev = dstB->last;
nodeB->next = NULL;
dstB->last = nodeB;
}
else
{
if(dstB->first != NULL)
dstB->first->prev = nodeB;
nodeB->next = dstB->first;
nodeB->prev = NULL;
dstB->first = nodeB;
}
// Normalize the destination list
if(dstB->first != NULL && dstB->last == NULL)
dstB->last = dstB->first;
else if(dstB->first == NULL && dstB->last != NULL)
dstB->first = dstB->last;
nodeB->parent = dstB;
}
void *allocateNode(void *inUseList, void *freeList, u32 elementSize, bool back)
{
ListBase *freeListB = (ListBase *)freeList;
if(freeListB->first == NULL)
panic();
ListNodeBase *node = freeListB->first;
ListNodeBase nodeBk = *node;
memset(node, 0, elementSize);
*node = nodeBk;
moveNode(node, inUseList, back);
return node;
}