Browse Source

Fix list tests

Convert list to doubly-linked list for easy traversal.
master
TheoryOfNekomata 1 year ago
parent
commit
0fda7dd8ba
3 changed files with 36 additions and 37 deletions
  1. +24
    -34
      src/packages/game/data/IZ_list.c
  2. +7
    -2
      src/packages/game/data/IZ_list.h
  3. +5
    -1
      src/packages/game/data/data.test.c

+ 24
- 34
src/packages/game/data/IZ_list.c View File

@@ -15,8 +15,8 @@ void IZ_ListInitialize(IZ_List* list) {
* @param list - The list to clean up. * @param list - The list to clean up.
*/ */
void IZ_ListTeardown(IZ_List* list) { void IZ_ListTeardown(IZ_List* list) {
while (list->root) {
IZ_ListDeleteNode(list, &list->root);
while (list->length > 0) {
IZ_ListDeleteNode(list->root);
} }
IZ_free(list); IZ_free(list);
} }
@@ -30,61 +30,51 @@ IZ_ListNode** IZ_ListAppendNode(IZ_List* list, void* node_value) {
IZ_ListNode* new_node = IZ_malloc(sizeof(IZ_ListNode)); IZ_ListNode* new_node = IZ_malloc(sizeof(IZ_ListNode));
new_node->value = node_value; new_node->value = node_value;
new_node->next = NULL; new_node->next = NULL;
list->length += 1;
new_node->list = list;
new_node->list->length += 1;


if (!(list->root)) { if (!(list->root)) {
list->root = new_node;
return &list->root;
new_node->previous = NULL;
new_node->list->root = new_node;
return &new_node->list->root;
} }


IZ_ListNode *last_node = list->root;
IZ_ListNode *last_node = new_node->list->root;
while (last_node->next) { while (last_node->next) {
last_node = last_node->next; last_node = last_node->next;
} }


new_node->previous = last_node;
last_node->next = new_node; last_node->next = new_node;
return &last_node->next; return &last_node->next;
} }


/** /**
* Deletes the first node in the list that matches the filter. * Deletes the first node in the list that matches the filter.
* @param list - The list to delete from.
* @param node - The node to delete. * @param node - The node to delete.
*/ */
void IZ_ListDeleteNode(IZ_List* list, IZ_ListNode** node) {
if (!(list && list->root && node)) {
void IZ_ListDeleteNode(IZ_ListNode* node) {
if (!node) {
// should we raise warnings here? // should we raise warnings here?
return; return;
} }


// FIXME Teardown having problems here
list->iterator = &list->root;
IZ_ListNode** previous_node = NULL;
do {
if (list->iterator != node) {
previous_node = list->iterator;
list->iterator = &((*list->iterator)->next);
// we haven't found the node we're looking for, go to the next one
continue;
if (node->previous) {
node->previous->next = node->next;
} else {
if (node->next) {
node->next->previous = NULL;
} }

if (previous_node) {
// this is not the first node in the list
(*previous_node)->next = (*list->iterator)->next;
} else {
// this is the first node, set it as new root
list->root = (*list->iterator)->next;
// if there is only one item in the list, root, gets set to NULL
if (node->list) {
node->list->root = node->next;
} }
}


IZ_free(*list->iterator);
list->iterator = NULL;
if (list->length > 0) {
// avoid underflow
list->length -= 1;
}
return;
} while (*list->iterator);
if (node->list && node->list->length > 0) {
node->list->length -= 1;
}

IZ_free(node);
} }


/** /**


+ 7
- 2
src/packages/game/data/IZ_list.h View File

@@ -4,10 +4,15 @@
#include "../../common/IZ_common.h" #include "../../common/IZ_common.h"
#include "../../stdinc/IZ_stdlib.h" #include "../../stdinc/IZ_stdlib.h"


struct IZ_List;

/** /**
* A node in a linked list. * A node in a linked list.
*/ */
typedef struct IZ_ListNode { typedef struct IZ_ListNode {
struct IZ_List* list;

struct IZ_ListNode* previous;
/** /**
* The value of the node. * The value of the node.
*/ */
@@ -21,7 +26,7 @@ typedef struct IZ_ListNode {
/** /**
* A singly-linked list. * A singly-linked list.
*/ */
typedef struct {
typedef struct IZ_List {
/** /**
* The first node in the list. * The first node in the list.
*/ */
@@ -57,7 +62,7 @@ IZ_ListNode** IZ_ListAppendNode(IZ_List*, void*);
/** /**
* Deletes the first node in the list that matches the filter. * Deletes the first node in the list that matches the filter.
*/ */
void IZ_ListDeleteNode(IZ_List*, IZ_ListNode**);
void IZ_ListDeleteNode(IZ_ListNode*);


/** /**
* Finds the first node in the list that matches the filter. * Finds the first node in the list that matches the filter.


+ 5
- 1
src/packages/game/data/data.test.c View File

@@ -22,6 +22,7 @@ spec("data") {


after_each() { after_each() {
IZ_ListTeardown(&list); IZ_ListTeardown(&list);
mock_reset(IZ_free);
} }


it("sets root to NULL") { it("sets root to NULL") {
@@ -77,10 +78,13 @@ spec("data") {
IZ_ListInitialize(&list2); IZ_ListInitialize(&list2);
static u64 existing_value = 69420u; static u64 existing_value = 69420u;
static IZ_ListNode existing_node = { static IZ_ListNode existing_node = {
.list = NULL,
.previous = NULL,
.value = &existing_value, .value = &existing_value,
.next = NULL, .next = NULL,
}; };
list2.root = &existing_node; list2.root = &existing_node;
existing_node.list = &list2;
list2.length = 1; list2.length = 1;
} }


@@ -171,7 +175,7 @@ spec("data") {


it("removes first node satisfying the filter condition") { it("removes first node satisfying the filter condition") {
IZ_ListNode** existing_node = IZ_ListFindFirstNode(&list, NodeExists); IZ_ListNode** existing_node = IZ_ListFindFirstNode(&list, NodeExists);
IZ_ListDeleteNode(&list, existing_node);
IZ_ListDeleteNode(*existing_node);


check( check(
mock_is_called(IZ_free), mock_is_called(IZ_free),


Loading…
Cancel
Save