106 lines
2.5 KiB
C
106 lines
2.5 KiB
C
|
/*
|
||
|
list.c
|
||
|
|
||
|
(c) TuxSH, 2017
|
||
|
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;
|
||
|
}
|