mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2024-11-15 08:51:22 +00:00
216 lines
3.7 KiB
C
216 lines
3.7 KiB
C
|
#include "g_local.h"
|
||
|
#include "z_list.h"
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
typedef struct listNode_s
|
||
|
{
|
||
|
void *data;
|
||
|
struct listNode_s *next;
|
||
|
struct listNode_s *prev;
|
||
|
} listNode_t;
|
||
|
|
||
|
void initializeList(list_t *list)
|
||
|
{
|
||
|
// initialize the list to be empty
|
||
|
memset(list, 0, sizeof(list_t));
|
||
|
list->head = NULL;
|
||
|
list->tail = NULL;
|
||
|
list->numNodes = 0;
|
||
|
list->curNode = 0;
|
||
|
list->currentNode = NULL;
|
||
|
}
|
||
|
|
||
|
void emptyList(list_t *list)
|
||
|
{
|
||
|
while (list->head != NULL)
|
||
|
{
|
||
|
// get the node
|
||
|
listNode_t *node = list->head;
|
||
|
list->head = node->next;
|
||
|
|
||
|
// free it up
|
||
|
Z_FREE(node);
|
||
|
}
|
||
|
initializeList(list);
|
||
|
}
|
||
|
|
||
|
int listLength(list_t const *list)
|
||
|
{
|
||
|
return list->numNodes;
|
||
|
}
|
||
|
|
||
|
void addHead(list_t *list, void *data)
|
||
|
{
|
||
|
// add a node to the head of the list
|
||
|
listNode_t *node = (listNode_t*)Z_MALLOC(sizeof(listNode_t));
|
||
|
|
||
|
// fill it and put it in the front of the list
|
||
|
node->data = data;
|
||
|
node->next = list->head;
|
||
|
node->prev = NULL;
|
||
|
list->head = node;
|
||
|
list->numNodes++;
|
||
|
|
||
|
if (list->numNodes == 1)
|
||
|
list->tail = list->head;
|
||
|
|
||
|
// reset the currentNode
|
||
|
list->currentNode = list->head;
|
||
|
list->curNode = 0;
|
||
|
}
|
||
|
|
||
|
void addTail(list_t *list, void *data)
|
||
|
{
|
||
|
// add a node to the head of the list
|
||
|
listNode_t *node = (listNode_t*)Z_MALLOC(sizeof(listNode_t));
|
||
|
|
||
|
// fill it and put it in the front of the list
|
||
|
node->data = data;
|
||
|
node->next = NULL;
|
||
|
node->prev = list->tail;
|
||
|
if (list->tail != NULL)
|
||
|
list->tail->next = node;
|
||
|
list->tail = node;
|
||
|
list->numNodes++;
|
||
|
|
||
|
if (list->numNodes == 1)
|
||
|
list->head = list->tail;
|
||
|
|
||
|
// reset the currentNode
|
||
|
list->currentNode = list->head;
|
||
|
list->curNode = 0;
|
||
|
}
|
||
|
|
||
|
void *getItem(list_t *list, int num)
|
||
|
{
|
||
|
listNode_t *node = NULL;
|
||
|
int indexNum = 0;
|
||
|
int diffH = 0;
|
||
|
int diffT = 0;
|
||
|
int diffC = 0;
|
||
|
|
||
|
// safety check
|
||
|
if (num >= list->numNodes || num < 0)
|
||
|
return NULL;
|
||
|
|
||
|
// which is closer, head, tail or currentNode?
|
||
|
diffH = num;
|
||
|
diffT = list->numNodes - num - 1;
|
||
|
diffC = abs(list->curNode - num);
|
||
|
|
||
|
if (diffH < diffT &&
|
||
|
diffH < diffC)
|
||
|
{
|
||
|
node = list->head;
|
||
|
indexNum = 0;
|
||
|
}
|
||
|
else if (diffT < diffC)
|
||
|
{
|
||
|
node = list->tail;
|
||
|
indexNum = list->numNodes - 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
node = list->currentNode;
|
||
|
indexNum = list->curNode;
|
||
|
}
|
||
|
|
||
|
// go thru the list searching
|
||
|
while (indexNum != num)
|
||
|
{
|
||
|
if (indexNum < num)
|
||
|
{
|
||
|
indexNum++;
|
||
|
node = node->next;
|
||
|
}
|
||
|
else if (indexNum > num)
|
||
|
{
|
||
|
indexNum--;
|
||
|
node = node->prev;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// update the current node
|
||
|
list->currentNode = node;
|
||
|
list->curNode = indexNum;
|
||
|
|
||
|
// return the current node
|
||
|
return list->currentNode->data;
|
||
|
}
|
||
|
|
||
|
void removeItem(list_t *list, int num)
|
||
|
{
|
||
|
// find the item
|
||
|
listNode_t *node = NULL;
|
||
|
void *item = getItem(list, num);
|
||
|
|
||
|
if (item == NULL)
|
||
|
return;
|
||
|
|
||
|
// ok, currentNode points to the node
|
||
|
// remove it
|
||
|
node = list->currentNode;
|
||
|
|
||
|
// previous?
|
||
|
if (node->prev == NULL) // front of the list
|
||
|
list->head = node->next;
|
||
|
else
|
||
|
node->prev->next = node->next;
|
||
|
|
||
|
if (node->next == NULL) // tail of the list
|
||
|
list->tail = node->prev;
|
||
|
else
|
||
|
node->next->prev = node->prev;
|
||
|
|
||
|
// delete the node
|
||
|
Z_FREE(node);
|
||
|
list->numNodes--;
|
||
|
|
||
|
// reset the current node
|
||
|
list->currentNode = list->head;
|
||
|
list->curNode = 0;
|
||
|
}
|
||
|
|
||
|
void copyList(list_t *src, list_t *dest)
|
||
|
{
|
||
|
// get and put the data
|
||
|
int i = 0;
|
||
|
|
||
|
// empty the destination
|
||
|
emptyList(dest);
|
||
|
for (i = 0; i < src->numNodes; i++)
|
||
|
{
|
||
|
void *item = getItem(src, i);
|
||
|
addTail(dest, item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void stealList(list_t *src, list_t *dest)
|
||
|
{
|
||
|
// copy over the pointer info
|
||
|
dest->head = src->head;
|
||
|
dest->tail = src->tail;
|
||
|
dest->numNodes = src->numNodes;
|
||
|
dest->curNode = src->curNode;
|
||
|
dest->currentNode = src->currentNode;
|
||
|
|
||
|
// init src
|
||
|
initializeList(src);
|
||
|
}
|
||
|
|
||
|
int findIndex(list_t *list, void *data)
|
||
|
{
|
||
|
listNode_t *node = list->head;
|
||
|
int i = 0;
|
||
|
while (node != NULL)
|
||
|
{
|
||
|
if (node->data == data)
|
||
|
return i;
|
||
|
|
||
|
i++;
|
||
|
node = node->next;
|
||
|
}
|
||
|
|
||
|
// failure
|
||
|
return -1;
|
||
|
}
|