@@ -0,0 +1,2 @@ | |||||
- Always check bounds before performing mutations (i.e. CRUD operations). | |||||
- Prefer declaring out variables over malloc'd variables. |
@@ -1,5 +1,70 @@ | |||||
#include <stdio.h> | |||||
#include "IZ_list.h" | #include "IZ_list.h" | ||||
void IZ_ListDoDeleteNode(IZ_ListNode* node) { | |||||
if (!(node && node->list)) { | |||||
// should we raise warnings here? | |||||
return; | |||||
} | |||||
if (node->previous) { | |||||
node->previous->next = node->next; | |||||
} else { | |||||
if (node->next) { | |||||
node->next->previous = NULL; | |||||
} | |||||
node->list->root = node->next; | |||||
} | |||||
if (node->list->length > 0) { | |||||
node->list->length -= 1; | |||||
} | |||||
IZ_free(node); | |||||
} | |||||
void IZ_ListDoAppendNode(IZ_List* list, void* node_value, IZ_ListNode** new_node_ref) { | |||||
IZ_ListNode* new_node = IZ_malloc(sizeof(IZ_ListNode)); | |||||
new_node->value = node_value; | |||||
new_node->next = NULL; | |||||
new_node->list = list; | |||||
new_node->list->length += 1; | |||||
if (!(new_node->list->root)) { | |||||
new_node->previous = NULL; | |||||
new_node->list->root = new_node; | |||||
if (new_node_ref) { | |||||
*new_node_ref = new_node; | |||||
} | |||||
return; | |||||
} | |||||
IZ_ListNode** cursor_node = &new_node->list->root; | |||||
while ((*cursor_node)->next) { | |||||
cursor_node = &(*cursor_node)->next; | |||||
} | |||||
new_node->previous = *cursor_node; | |||||
(*cursor_node)->next = new_node; | |||||
if (new_node_ref) { | |||||
*new_node_ref = new_node; | |||||
} | |||||
} | |||||
#ifdef IZ_DEBUG | |||||
void IZ_ListPrintNodeValues(IZ_List* list) { | |||||
list->iterator = &list->root; | |||||
u64 index = 0; | |||||
printf("\nlist@%p\n", list); | |||||
do { | |||||
printf(" %llu@%p:%u\n", index, *list->iterator, *((unsigned int*)(*list->iterator)->value)); | |||||
index += 1; | |||||
list->iterator = &(*list->iterator)->next; | |||||
} while (*list->iterator); | |||||
list->iterator = NULL; | |||||
} | |||||
#endif | |||||
/** | /** | ||||
* Initializes a list. | * Initializes a list. | ||||
* @param list - The list to initialize. | * @param list - The list to initialize. | ||||
@@ -16,7 +81,7 @@ void IZ_ListInitialize(IZ_List* list) { | |||||
*/ | */ | ||||
void IZ_ListTeardown(IZ_List* list) { | void IZ_ListTeardown(IZ_List* list) { | ||||
while (list->length > 0) { | while (list->length > 0) { | ||||
IZ_ListDeleteNode(list->root); | |||||
IZ_ListDoDeleteNode(list->root); | |||||
} | } | ||||
IZ_free(list); | IZ_free(list); | ||||
} | } | ||||
@@ -24,29 +89,11 @@ void IZ_ListTeardown(IZ_List* list) { | |||||
/** | /** | ||||
* Appends a node to the end of the list. | * Appends a node to the end of the list. | ||||
* @param list - The list to append to. | * @param list - The list to append to. | ||||
* @param node_value - The value of the node to append. | |||||
* @return Pointer to the newly created node. | * @return Pointer to the newly created node. | ||||
*/ | */ | ||||
IZ_ListNode** IZ_ListAppendNode(IZ_List* list, void* node_value) { | |||||
IZ_ListNode* new_node = IZ_malloc(sizeof(IZ_ListNode)); | |||||
new_node->value = node_value; | |||||
new_node->next = NULL; | |||||
new_node->list = list; | |||||
new_node->list->length += 1; | |||||
if (!(list->root)) { | |||||
new_node->previous = NULL; | |||||
new_node->list->root = new_node; | |||||
return &new_node->list->root; | |||||
} | |||||
IZ_ListNode *last_node = new_node->list->root; | |||||
while (last_node->next) { | |||||
last_node = last_node->next; | |||||
} | |||||
new_node->previous = last_node; | |||||
last_node->next = new_node; | |||||
return &last_node->next; | |||||
void IZ_ListAppendNode(IZ_List* list, void* node_value, IZ_ListNode** new_node) { | |||||
return IZ_ListDoAppendNode(list, node_value, new_node); | |||||
} | } | ||||
/** | /** | ||||
@@ -54,27 +101,7 @@ IZ_ListNode** IZ_ListAppendNode(IZ_List* list, void* node_value) { | |||||
* @param node - The node to delete. | * @param node - The node to delete. | ||||
*/ | */ | ||||
void IZ_ListDeleteNode(IZ_ListNode* node) { | void IZ_ListDeleteNode(IZ_ListNode* node) { | ||||
if (!node) { | |||||
// should we raise warnings here? | |||||
return; | |||||
} | |||||
if (node->previous) { | |||||
node->previous->next = node->next; | |||||
} else { | |||||
if (node->next) { | |||||
node->next->previous = NULL; | |||||
} | |||||
if (node->list) { | |||||
node->list->root = node->next; | |||||
} | |||||
} | |||||
if (node->list && node->list->length > 0) { | |||||
node->list->length -= 1; | |||||
} | |||||
IZ_free(node); | |||||
IZ_ListDoDeleteNode(node); | |||||
} | } | ||||
/** | /** | ||||
@@ -82,13 +109,16 @@ void IZ_ListDeleteNode(IZ_ListNode* node) { | |||||
* @param list - The list to search. | * @param list - The list to search. | ||||
* @param filter - The filter to use to find the node. | * @param filter - The filter to use to find the node. | ||||
* @return Pointer to the node that matches the filter. | * @return Pointer to the node that matches the filter. | ||||
* @see IZ_ListFindPredicate | |||||
* @see IZ_ListFindAllNodes | |||||
* @note This function will set the list's iterator to the node that was found. Ensure that the iterator is previously | |||||
* set to an existing node in the list before calling this function to know where to begin the search. | |||||
*/ | */ | ||||
IZ_ListNode** IZ_ListFindFirstNode(IZ_List* list, IZ_ListFindPredicate filter) { | |||||
void IZ_ListFindFirstNode(IZ_List* list, IZ_ListFindPredicate filter, IZ_ListNode** found_node) { | |||||
if (!(list && list->root)) { | if (!(list && list->root)) { | ||||
return NULL; | |||||
return; | |||||
} | } | ||||
list->iterator = &list->root; | |||||
u64 index = 0; | u64 index = 0; | ||||
do { | do { | ||||
if (!filter(list->iterator, index, list)) { | if (!filter(list->iterator, index, list)) { | ||||
@@ -96,8 +126,91 @@ IZ_ListNode** IZ_ListFindFirstNode(IZ_List* list, IZ_ListFindPredicate filter) { | |||||
index += 1; | index += 1; | ||||
continue; | continue; | ||||
} | } | ||||
return list->iterator; | |||||
*found_node = *list->iterator; | |||||
return; | |||||
} while (*list->iterator); | } while (*list->iterator); | ||||
return NULL; | |||||
} | |||||
/** | |||||
* Finds all nodes in the list that match the filter. | |||||
* @param list - The list to search. | |||||
* @param filter - The filter to use to find the node. | |||||
* @param found_nodes - The list to append the found nodes to. | |||||
* @return New list containing nodes that match the filter. | |||||
* @see IZ_ListFindPredicate | |||||
* @see IZ_ListFindFirstNode | |||||
* @note This function will set the list's iterator to the node that was found. Ensure that the iterator is previously | |||||
* set to an existing node in the list before calling this function to know where to begin the search. | |||||
*/ | |||||
void IZ_ListFindAllNodes(IZ_List* list, IZ_ListFindPredicate filter, IZ_List* found_nodes) { | |||||
if (!(list && list->root)) { | |||||
return; | |||||
} | |||||
list->iterator = &list->root; | |||||
u64 index; | |||||
for (index = 0; index < list->length; index += 1) { | |||||
if (filter(list->iterator, index, list)) { | |||||
IZ_ListDoAppendNode(found_nodes, (*list->iterator)->value, NULL); | |||||
} | |||||
list->iterator = &((*list->iterator)->next); | |||||
} | |||||
} | |||||
/** | |||||
* Inserts a node at the specified index. | |||||
* @param list - The list to append to. | |||||
* @param node_value - The value of the node to append. | |||||
* @param dest_index - The index to insert the node at. | |||||
* @return Pointer to the newly created node. | |||||
*/ | |||||
void IZ_ListInsertNodeAtIndex(IZ_List* list, void* node_value, u64 dest_index, IZ_ListNode** new_node_ref) { | |||||
if (dest_index > list->length) { | |||||
// to consumer: check your bounds first! | |||||
return; | |||||
} | |||||
if (dest_index == list->length) { | |||||
return IZ_ListDoAppendNode(list, node_value, new_node_ref); | |||||
} | |||||
IZ_ListNode* new_node = IZ_malloc(sizeof(IZ_ListNode)); | |||||
new_node->value = node_value; | |||||
new_node->list = list; | |||||
if (!(new_node->list->root)) { | |||||
new_node->previous = NULL; | |||||
new_node->next = NULL; | |||||
new_node->list->root = new_node; | |||||
if (new_node_ref) { | |||||
*new_node_ref = new_node; | |||||
} | |||||
return; | |||||
} | |||||
IZ_ListNode** cursor_node = NULL; | |||||
u64 index; | |||||
for ( | |||||
index = 0, cursor_node = &new_node->list->root; | |||||
index < dest_index; | |||||
index += 1, cursor_node = &((*cursor_node)->next) | |||||
); | |||||
new_node->next = *cursor_node; | |||||
new_node->previous = (*cursor_node)->previous; | |||||
if (dest_index == 0) { | |||||
new_node->list->root = new_node; | |||||
} else if (dest_index < list->length) { | |||||
(*cursor_node)->previous->next = new_node; | |||||
} else { | |||||
(*cursor_node)->next = new_node; | |||||
} | |||||
new_node->list->length += 1; | |||||
if (new_node_ref) { | |||||
*new_node_ref = new_node; | |||||
} | |||||
} | } |
@@ -10,8 +10,13 @@ struct IZ_List; | |||||
* A node in a linked list. | * A node in a linked list. | ||||
*/ | */ | ||||
typedef struct IZ_ListNode { | typedef struct IZ_ListNode { | ||||
/** | |||||
* The list that the node belongs to. | |||||
*/ | |||||
struct IZ_List* list; | struct IZ_List* list; | ||||
/** | |||||
* The previous node in the list. | |||||
*/ | |||||
struct IZ_ListNode* previous; | struct IZ_ListNode* previous; | ||||
/** | /** | ||||
* The value of the node. | * The value of the node. | ||||
@@ -24,7 +29,7 @@ typedef struct IZ_ListNode { | |||||
} IZ_ListNode; | } IZ_ListNode; | ||||
/** | /** | ||||
* A singly-linked list. | |||||
* A doubly-linked list. | |||||
*/ | */ | ||||
typedef struct IZ_List { | typedef struct IZ_List { | ||||
/** | /** | ||||
@@ -43,6 +48,10 @@ typedef struct IZ_List { | |||||
typedef bool IZ_ListFindPredicate(IZ_ListNode**, u64, IZ_List*); | typedef bool IZ_ListFindPredicate(IZ_ListNode**, u64, IZ_List*); | ||||
#ifdef IZ_DEBUG | |||||
void IZ_ListPrintNodeValues(IZ_List*); | |||||
#endif | |||||
/** | /** | ||||
* Initializes a list. | * Initializes a list. | ||||
*/ | */ | ||||
@@ -57,7 +66,7 @@ void IZ_ListTeardown(IZ_List*); | |||||
* Appends a node to the end of the list. | * Appends a node to the end of the list. | ||||
* @return Pointer to the newly created node. | * @return Pointer to the newly created node. | ||||
*/ | */ | ||||
IZ_ListNode** IZ_ListAppendNode(IZ_List*, void*); | |||||
void IZ_ListAppendNode(IZ_List*, void*, IZ_ListNode**); | |||||
/** | /** | ||||
* Deletes the first node in the list that matches the filter. | * Deletes the first node in the list that matches the filter. | ||||
@@ -67,7 +76,23 @@ 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. | ||||
* @return Pointer to the node that matches the filter. | * @return Pointer to the node that matches the filter. | ||||
* @see IZ_ListFindPredicate | |||||
* @see IZ_ListFindAllNodes | |||||
*/ | |||||
void IZ_ListFindFirstNode(IZ_List*, IZ_ListFindPredicate, IZ_ListNode**); | |||||
/** | |||||
* Finds all nodes in the list that match the filter. | |||||
* @return New list containing nodes that match the filter. | |||||
* @see IZ_ListFindPredicate | |||||
* @see IZ_ListFindFirstNode | |||||
*/ | |||||
void IZ_ListFindAllNodes(IZ_List*, IZ_ListFindPredicate, IZ_List*); | |||||
/** | |||||
* Inserts a node at the specified index. | |||||
* @return Pointer to the newly created node. | |||||
*/ | */ | ||||
IZ_ListNode** IZ_ListFindFirstNode(IZ_List*, IZ_ListFindPredicate); | |||||
void IZ_ListInsertNodeAtIndex(IZ_List*, void*, u64, IZ_ListNode**); | |||||
#endif | #endif |
@@ -11,10 +11,18 @@ bool NodeExists2(IZ_ListNode** node, u64 _index, IZ_List* list) { | |||||
return *((u64*) (*node)->value) == 69420; | return *((u64*) (*node)->value) == 69420; | ||||
} | } | ||||
bool NodeExists3(IZ_ListNode** node, u64 _index, IZ_List* list) { | |||||
return *((u64*) (*node)->value) == 69069; | |||||
} | |||||
bool NodeDoesNotExist(IZ_ListNode** node, u64 _index, IZ_List* list) { | bool NodeDoesNotExist(IZ_ListNode** node, u64 _index, IZ_List* list) { | ||||
return *((u64*) (*node)->value) == 55555; | return *((u64*) (*node)->value) == 55555; | ||||
} | } | ||||
bool NodeHasOddValue(IZ_ListNode** node, u64 _index, IZ_List* list) { | |||||
return *((u64*) (*node)->value) % 2 == 1; | |||||
} | |||||
spec("data") { | spec("data") { | ||||
describe("list") { | describe("list") { | ||||
describe("Initialize") { | describe("Initialize") { | ||||
@@ -44,9 +52,9 @@ spec("data") { | |||||
static u64 value3 = 69069u; | static u64 value3 = 69069u; | ||||
IZ_ListInitialize(&list); | IZ_ListInitialize(&list); | ||||
IZ_ListAppendNode(&list, &value1); | |||||
IZ_ListAppendNode(&list, &value2); | |||||
IZ_ListAppendNode(&list, &value3); | |||||
IZ_ListAppendNode(&list, &value1, NULL); | |||||
IZ_ListAppendNode(&list, &value2, NULL); | |||||
IZ_ListAppendNode(&list, &value3, NULL); | |||||
mock_mode(IZ_free, IZ_FREE_CALLS_TRACKED); | mock_mode(IZ_free, IZ_FREE_CALLS_TRACKED); | ||||
} | } | ||||
@@ -106,10 +114,12 @@ spec("data") { | |||||
it("appends new node to empty list and sets it as root") { | it("appends new node to empty list and sets it as root") { | ||||
static u64 value = 69420u; | static u64 value = 69420u; | ||||
IZ_ListAppendNode(&list, &value); | |||||
static IZ_ListNode* check_inserted_node; | |||||
IZ_ListAppendNode(&list, &value, &check_inserted_node); | |||||
u64 added_value = *((u64*) list.root->value); | u64 added_value = *((u64*) list.root->value); | ||||
check(added_value == 69420u, "Node not properly appended. Value: %u", added_value); | check(added_value == 69420u, "Node not properly appended. Value: %u", added_value); | ||||
check(*((u64*) check_inserted_node->value) == added_value, "Node value not properly set. Value: %u", added_value); | |||||
check( | check( | ||||
mock_is_called(IZ_malloc), | mock_is_called(IZ_malloc), | ||||
"Allocator function not called." | "Allocator function not called." | ||||
@@ -119,8 +129,9 @@ spec("data") { | |||||
it("appends new node to non-empty list") { | it("appends new node to non-empty list") { | ||||
static u64 value1 = 42069u; | static u64 value1 = 42069u; | ||||
IZ_ListAppendNode(&list2, &value1); | |||||
static IZ_ListNode* check_inserted_node; | |||||
IZ_ListAppendNode(&list2, &value1, &check_inserted_node); | |||||
check(*((u64*) check_inserted_node->value) == value1, "Node value not properly set. Value: %u", value1); | |||||
check(*((u64*) list2.root->next->value) == 42069u, "Node not properly appended."); | check(*((u64*) list2.root->next->value) == 42069u, "Node not properly appended."); | ||||
check( | check( | ||||
@@ -138,8 +149,8 @@ spec("data") { | |||||
before_each() { | before_each() { | ||||
IZ_ListInitialize(&list); | IZ_ListInitialize(&list); | ||||
IZ_ListAppendNode(&list, &value1); | |||||
IZ_ListAppendNode(&list, &value2); | |||||
IZ_ListAppendNode(&list, &value1, NULL); | |||||
IZ_ListAppendNode(&list, &value2, NULL); | |||||
} | } | ||||
after_each() { | after_each() { | ||||
@@ -148,14 +159,16 @@ spec("data") { | |||||
} | } | ||||
it("retrieves first node satisfying the filter condition") { | it("retrieves first node satisfying the filter condition") { | ||||
static IZ_ListNode** node; | |||||
node = IZ_ListFindFirstNode(&list, NodeExists); | |||||
check(*((u64*) (*node)->value) == 42069u, "Existing node not found."); | |||||
static IZ_ListNode* node; | |||||
list.iterator = &list.root; | |||||
IZ_ListFindFirstNode(&list, NodeExists, &node); | |||||
check(*((u64*) node->value) == 42069u, "Existing node not found."); | |||||
} | } | ||||
it("returns NULL when all nodes do not satisfy the filter condition") { | it("returns NULL when all nodes do not satisfy the filter condition") { | ||||
static IZ_ListNode** node; | |||||
node = IZ_ListFindFirstNode(&list, NodeDoesNotExist); | |||||
static IZ_ListNode* node; | |||||
list.iterator = &list.root; | |||||
IZ_ListFindFirstNode(&list, NodeDoesNotExist, &node); | |||||
check(node == NULL, "Non-existing node found."); | check(node == NULL, "Non-existing node found."); | ||||
} | } | ||||
} | } | ||||
@@ -169,9 +182,9 @@ spec("data") { | |||||
static u64 value3 = 69069u; | static u64 value3 = 69069u; | ||||
IZ_ListInitialize(&list); | IZ_ListInitialize(&list); | ||||
IZ_ListAppendNode(&list, &value1); | |||||
IZ_ListAppendNode(&list, &value2); | |||||
IZ_ListAppendNode(&list, &value3); | |||||
IZ_ListAppendNode(&list, &value1, NULL); | |||||
IZ_ListAppendNode(&list, &value2, NULL); | |||||
IZ_ListAppendNode(&list, &value3, NULL); | |||||
mock_mode(IZ_free, IZ_FREE_CALLS_TRACKED); | mock_mode(IZ_free, IZ_FREE_CALLS_TRACKED); | ||||
} | } | ||||
@@ -181,26 +194,181 @@ 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_ListDeleteNode(*existing_node); | |||||
list.iterator = &list.root; | |||||
static IZ_ListNode* existing_node; | |||||
static IZ_ListNode* check_node; | |||||
IZ_ListFindFirstNode(&list, NodeExists, &existing_node); | |||||
IZ_ListDeleteNode(existing_node); | |||||
check( | check( | ||||
mock_is_called(IZ_free), | mock_is_called(IZ_free), | ||||
"Deallocator function not called." | "Deallocator function not called." | ||||
); | ); | ||||
check( | |||||
IZ_ListFindFirstNode(&list, NodeExists2), | |||||
"Node supposed to be present in list is absent." | |||||
); | |||||
check_node = NULL; | |||||
list.iterator = &list.root; | |||||
IZ_ListFindFirstNode(&list, NodeExists2, &check_node); | |||||
check(check_node, "Node supposed to be present in list is absent."); | |||||
check( | |||||
!IZ_ListFindFirstNode(&list, NodeExists), | |||||
"Deleted node still present in list." | |||||
); | |||||
list.iterator = &list.root; | |||||
check_node = NULL; | |||||
IZ_ListFindFirstNode(&list, NodeExists, &check_node); | |||||
check(!check_node, "Deleted node still present in list."); | |||||
check(list.length == 2, "Length mismatch."); | check(list.length == 2, "Length mismatch."); | ||||
} | } | ||||
} | } | ||||
describe("FindAllNodes") { | |||||
static IZ_List list; | |||||
static IZ_List out; | |||||
before_each() { | |||||
static u64 value1 = 69420u; | |||||
static u64 value2 = 42069u; | |||||
static u64 value3 = 69069u; | |||||
IZ_ListInitialize(&list); | |||||
IZ_ListAppendNode(&list, &value1, NULL); | |||||
IZ_ListAppendNode(&list, &value2, NULL); | |||||
IZ_ListAppendNode(&list, &value3, NULL); | |||||
mock_mode(IZ_free, IZ_FREE_CALLS_UNTRACKED); | |||||
} | |||||
before_each() { | |||||
IZ_ListInitialize(&out); | |||||
} | |||||
after_each() { | |||||
IZ_ListTeardown(&out); | |||||
} | |||||
after_each() { | |||||
IZ_ListTeardown(&list); | |||||
} | |||||
it("finds all nodes satisfying the filter condition") { | |||||
list.iterator = &list.root; | |||||
IZ_ListFindAllNodes(&list, NodeHasOddValue, &out); | |||||
check(out.length == 2, "Length mismatch. Length: %u", out.length); | |||||
out.iterator = &out.root; | |||||
static IZ_ListNode* check_node; | |||||
check_node = NULL; | |||||
IZ_ListFindFirstNode(&out, NodeExists, &check_node); | |||||
check(check_node, "Node supposed to be present in list is absent."); | |||||
out.iterator = &out.root; | |||||
check_node = NULL; | |||||
IZ_ListFindFirstNode(&out, NodeExists3, &check_node); | |||||
check(check_node, "Node supposed to be present in list is absent."); | |||||
out.iterator = &out.root; | |||||
check_node = NULL; | |||||
IZ_ListFindFirstNode(&out, NodeExists2, &check_node); | |||||
check(!check_node, "Node not supposed to be present in list is present."); | |||||
} | |||||
} | |||||
describe("InsertNodeAtIndex") { | |||||
static IZ_List list; | |||||
before_each() { | |||||
static u64 value1 = 69420u; | |||||
static u64 value2 = 42069u; | |||||
static u64 value3 = 69069u; | |||||
IZ_ListInitialize(&list); | |||||
IZ_ListAppendNode(&list, &value1, NULL); | |||||
IZ_ListAppendNode(&list, &value2, NULL); | |||||
IZ_ListAppendNode(&list, &value3, NULL); | |||||
mock_mode(IZ_free, IZ_FREE_CALLS_UNTRACKED); | |||||
} | |||||
after_each() { | |||||
IZ_ListTeardown(&list); | |||||
} | |||||
it("inserts node at the beginning of the list") { | |||||
static u64 value = 1337u; | |||||
static IZ_ListNode* check_node; | |||||
IZ_ListInsertNodeAtIndex(&list, &value, 0, &check_node); | |||||
check(*((u64*) check_node->value) == value, "Incorrect value of inserted node."); | |||||
static IZ_ListNode* check_other_node; | |||||
list.iterator = &list.root; | |||||
check_other_node = NULL; | |||||
IZ_ListFindFirstNode(&list, NodeExists, &check_other_node); | |||||
check(check_other_node, "Node supposed to be present in list is absent."); | |||||
list.iterator = &list.root; | |||||
check_other_node = NULL; | |||||
IZ_ListFindFirstNode(&list, NodeExists2, &check_other_node); | |||||
check(check_other_node, "Node supposed to be present in list is absent."); | |||||
list.iterator = &list.root; | |||||
check_other_node = NULL; | |||||
IZ_ListFindFirstNode(&list, NodeExists3, &check_other_node); | |||||
check(check_other_node, "Node supposed to be present in list is absent."); | |||||
check(list.length == 4, "Length mismatch."); | |||||
//IZ_ListPrintNodeValues(&list); | |||||
} | |||||
it("inserts node at the end of the list") { | |||||
static u64 value = 1337u; | |||||
static IZ_ListNode* check_node; | |||||
IZ_ListInsertNodeAtIndex(&list, &value, 3, &check_node); | |||||
check(*((u64*) check_node->value) == value, "Incorrect value of inserted node."); | |||||
static IZ_ListNode* check_other_node; | |||||
list.iterator = &list.root; | |||||
check_other_node = NULL; | |||||
IZ_ListFindFirstNode(&list, NodeExists, &check_other_node); | |||||
check(check_other_node, "Node supposed to be present in list is absent."); | |||||
list.iterator = &list.root; | |||||
check_other_node = NULL; | |||||
IZ_ListFindFirstNode(&list, NodeExists2, &check_other_node); | |||||
check(check_other_node, "Node supposed to be present in list is absent."); | |||||
list.iterator = &list.root; | |||||
check_other_node = NULL; | |||||
IZ_ListFindFirstNode(&list, NodeExists3, &check_other_node); | |||||
check(check_other_node, "Node supposed to be present in list is absent."); | |||||
check(list.length == 4, "Length mismatch."); | |||||
//IZ_ListPrintNodeValues(&list); | |||||
} | |||||
it("inserts node in the middle of the list") { | |||||
static u64 value = 1337u; | |||||
static IZ_ListNode* check_node; | |||||
IZ_ListInsertNodeAtIndex(&list, &value, 1, &check_node); | |||||
check(*((u64*) check_node->value) == value, "Incorrect value of inserted node."); | |||||
static IZ_ListNode* check_other_node; | |||||
list.iterator = &list.root; | |||||
check_other_node = NULL; | |||||
IZ_ListFindFirstNode(&list, NodeExists, &check_other_node); | |||||
check(check_other_node, "Node supposed to be present in list is absent."); | |||||
list.iterator = &list.root; | |||||
check_other_node = NULL; | |||||
IZ_ListFindFirstNode(&list, NodeExists2, &check_other_node); | |||||
check(check_other_node, "Node supposed to be present in list is absent."); | |||||
list.iterator = &list.root; | |||||
check_other_node = NULL; | |||||
IZ_ListFindFirstNode(&list, NodeExists3, &check_other_node); | |||||
check(check_other_node, "Node supposed to be present in list is absent."); | |||||
check(list.length == 4, "Length mismatch."); | |||||
//IZ_ListPrintNodeValues(&list); | |||||
} | |||||
} | |||||
} | } | ||||
} | } |
@@ -27,15 +27,16 @@ IZ_PoolItem* IZ_PoolAllocate(IZ_Pool* pool, IZ_PoolAllocationArgs args) { | |||||
} | } | ||||
void* pointer = &pool->memory[pool->next_address]; | void* pointer = &pool->memory[pool->next_address]; | ||||
IZ_ListNode** new_item = IZ_ListAppendNode(&pool->items, &(IZ_PoolItem) { | |||||
IZ_ListNode* new_item; | |||||
IZ_ListAppendNode(&pool->items, &(IZ_PoolItem) { | |||||
.pointer = pointer, | .pointer = pointer, | ||||
.args = args, | .args = args, | ||||
.pool = pool, | .pool = pool, | ||||
}); | |||||
}, &new_item); | |||||
pool->next_address = (pool->next_address + args.size) % POOL_MAX_SIZE; | pool->next_address = (pool->next_address + args.size) % POOL_MAX_SIZE; | ||||
pool->allocated_memory += args.size; | pool->allocated_memory += args.size; | ||||
return (*new_item)->value; | |||||
return new_item->value; | |||||
} | } | ||||
bool IZ_PoolGetSameItem(IZ_ListNode** node, u64 _index, IZ_List* list) { | bool IZ_PoolGetSameItem(IZ_ListNode** node, u64 _index, IZ_List* list) { | ||||
@@ -43,9 +44,10 @@ bool IZ_PoolGetSameItem(IZ_ListNode** node, u64 _index, IZ_List* list) { | |||||
} | } | ||||
void IZ_PoolDeallocate(IZ_PoolItem* item) { | void IZ_PoolDeallocate(IZ_PoolItem* item) { | ||||
IZ_ListNode** node = IZ_ListFindFirstNode(&item->pool->items, IZ_PoolGetSameItem); | |||||
IZ_ListNode* node; | |||||
IZ_ListFindFirstNode(&item->pool->items, IZ_PoolGetSameItem, &node); | |||||
if (node) { | if (node) { | ||||
IZ_ListDeleteNode(*node); | |||||
IZ_ListDeleteNode(node); | |||||
} | } | ||||
} | } | ||||
@@ -151,7 +151,7 @@ spec("memory") { | |||||
"Free memory not properly utilized." | "Free memory not properly utilized." | ||||
); | ); | ||||
void* p4 = IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs){ | |||||
void* p4 = IZ_PoolAllocate(&pool, (IZ_PoolAllocationArgs) { | |||||
.size = sizeof(u8), | .size = sizeof(u8), | ||||
.priority = 0, | .priority = 0, | ||||
.timestamp = 5, | .timestamp = 5, | ||||
@@ -159,7 +159,7 @@ spec("memory") { | |||||
check( | check( | ||||
p4 == p3 + sizeof(u8), | p4 == p3 + sizeof(u8), | ||||
"Free memory not properly utilized." | |||||
"Free memory not properly allocated." | |||||
); | ); | ||||
} | } | ||||
} | } | ||||