diff --git a/CMakeLists.txt b/CMakeLists.txt index d00af91..156a0c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,12 +2,16 @@ cmake_minimum_required(VERSION 3.28.1) project(quantum-utils) +add_compile_options(-g) + set(quantum-src "./quantum/src/") set(test_stuff-src "./test_stuff/src/") set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -add_library(quantum SHARED ${quantum-src}memory/zone.c - ${quantum-src}logger/logger.c) +add_library( + quantum SHARED ${quantum-src}memory/zone.c ${quantum-src}logger/logger.c + ${quantum-src}types/linked_list.c) + add_executable(test_stuff ${test_stuff-src}main.c) target_link_libraries(test_stuff quantum) diff --git a/quantum/src/memory/zone.h b/quantum/src/memory/zone.h index ff4684f..bd6b654 100644 --- a/quantum/src/memory/zone.h +++ b/quantum/src/memory/zone.h @@ -2,8 +2,6 @@ #include // size_t definition -#include "../defines.h" - typedef struct _Zone Zone; Zone *zoneCreate(size_t sizeBytes); diff --git a/quantum/src/types/linked_list.c b/quantum/src/types/linked_list.c new file mode 100644 index 0000000..f975164 --- /dev/null +++ b/quantum/src/types/linked_list.c @@ -0,0 +1,324 @@ +#include "linked_list.h" + +#include "../defines.h" +#include "../logger/logger.h" + +#include +#include + +typedef struct Node { + struct Node *next; + struct Node *prev; + void *data; +} Node; + +List listCreate() { + List new_list; + + new_list.cur_size = 0; + new_list.cur_head = NULL; + new_list.cur_tail = NULL; + + return new_list; +} + +void listDestroy(List *list) { + // First lets make sure we don't have a null pointer passed in + if (list == NULL) { + QWARN("Null list passed to listDestroy()."); + return; + } + + u64 list_size = list->cur_size; + Node *del_node = list->cur_tail; + Node *next_node = list->cur_tail->prev; + + while (list_size > 0) { + // First we want to free del_node + free(del_node); + + // Now we want to set del_node to the next_node to free + del_node = next_node; + + // Now we set next_node equal to the del_node's previous node + if (next_node->prev != NULL) { + next_node = next_node->prev; + } else if (next_node->prev == NULL) { + next_node->next = NULL; + } + + // Now we decrement list_size + list_size--; + } + + // Now we null out the cur_head and cur_tail of our list + list->cur_tail = NULL; + list->cur_head = NULL; + + // Now we null out the list and make it point to nothing + list = NULL; +} + +u64 listSize(const List *list) { + if (list != NULL) + return list->cur_size; + + return 0; +} + +void *listPeek(List *list) { + if (list != NULL && list->cur_size > 0) + return list->cur_tail->data; + + return NULL; +} + +void *listPop(List *list) { + if (list == NULL) { + QWARN("Null list passed to listPop()"); + return NULL; + } + + Node *pop_node = list->cur_tail; + Node *prev_node = list->cur_head == list->cur_tail ? NULL : pop_node->prev; + void *data = pop_node->data; + + if (prev_node != NULL) + prev_node->next = NULL; + + list->cur_size--; + + list->cur_tail = prev_node; + + free(pop_node); + + return data; +} + +void listPush(List *list, void *data) { + // Allocate the space for our new node + Node *new_node = malloc(sizeof(Node)); + + // Make sure that we were able to allocate the space, and if not we write an + // error and return + if (new_node == NULL) { + QERROR("Could not allocate space to insert data into list."); + return; + } + + // If the current size of our list is 0 + if (list->cur_size == 0) { + // Set the head and tail pointer to the new node as we are about to have + // only 1 element + list->cur_tail = new_node; + list->cur_head = new_node; + + // Set the next and previous of the new node to NULL as we will only + // have 1 element and nothing to point to + new_node->next = NULL; + new_node->prev = NULL; + } else { + // Set the next of new_node to NULL as it is the new tail, + // and also update prev of new_node to point to the current tail + new_node->next = NULL; + new_node->prev = list->cur_tail; + // Set the next of our current tail to point to the new tail + list->cur_tail->next = new_node; + } + + // Set the data of the new node to the data we passed in + new_node->data = data; + + // Update the list size + list->cur_size++; + + // Set the list tail pointer to the new node + list->cur_tail = new_node; +} + +void *listPeekFromFront(List *list) { + if (list != NULL && list->cur_size > 0) + return list->cur_head->data; + + return NULL; +} + +void *listPopFromFront(List *list) { + if (list == NULL) { + QERROR("Null list passed to listPopFromFront()"); + return NULL; + } + + Node *pop_node = list->cur_head; + Node *next_node = list->cur_head == list->cur_tail ? NULL : pop_node->next; + void *data = pop_node->data; + + if (next_node != NULL) + next_node->next = NULL; + + list->cur_size--; + + list->cur_head = next_node; + + free(pop_node); + + return data; +} + +void listPushFromFront(List *list, void *data) { + // Allocate the space for our new node + Node *new_node = malloc(sizeof(Node)); + + // Make sure that we were able to allocate the space, and if not we write an + // error and return + if (new_node == NULL) { + QERROR("Could not allocate space to insert data into list."); + return; + } + + // If the current size of our list is 0 + if (list->cur_size == 0) { + // Set the head and tail pointer to the new node as we are about to have + // only 1 element + list->cur_tail = new_node; + list->cur_head = new_node; + + // Set the next and previous of the new node to NULL as we will only + // have 1 element and nothing to point to + new_node->next = NULL; + new_node->prev = NULL; + } else { + // Set the prev of new_node to NULL as it is the new head, + // and also update next of new_node to point to the current head + new_node->next = list->cur_head; + new_node->prev = NULL; + // Set the prev of our current head to point to the new head + list->cur_head->prev = new_node; + } + + // Set the data of the new node to the data we passed in + new_node->data = data; + + // Update the list size + list->cur_size++; + + // Set the list head pointer to the new node + list->cur_head = new_node; +} + +void *listDataAt(List *list, u64 pos) { + // Make sure our list isn't NULL or empty, if it is return NULL + if (list == NULL || list->cur_size == 0) { + QWARN("Null or empty list passed into listDataAt()"); + return NULL; + } + + // Next we want to make sure that our position is in range + if (pos < 1 || pos > list->cur_size) { + QERROR("Position given is out of range: %" PRId64, pos); + return NULL; + } + + // This is the pointer to the node with the data we will be returning + Node *data_addr = list->cur_head; + + // This is to keep track of what position in the list we are on + u64 counter = 1; + + // While we arent at our position yet + while (counter != pos) { + // Get the next nodes address + data_addr = data_addr->next; + // And increment the counter + counter++; + } + + // Return the data from the node + return data_addr->data; +} + +void listInsertAt(List *list, u64 pos, void *data) { + // If our list is null return. + if (list == NULL) { + QWARN("A null list was passed into listInsertAt()"); + return; + } + + u64 counter = 1; + Node *insert_pos; + Node *prev_node; + Node *new_node = malloc(sizeof(Node)); + + if (list->cur_size == 0) { + insert_pos = new_node; + new_node->next = NULL; + new_node->prev = NULL; + pos = 1; + } else { + insert_pos = list->cur_head; + } + + new_node->data = data; + + while (counter != pos) { + insert_pos = insert_pos->next; + counter++; + } + + if (insert_pos->prev != NULL) + prev_node = insert_pos->prev; + + if (list->cur_size > 1) { + new_node->next = insert_pos; + new_node->prev = prev_node; + insert_pos->prev = new_node; + prev_node->next = new_node; + } + + list->cur_size++; +} + +void listRemoveAt(List *list, u64 pos) { + // If we were passed a null or empty list return + if (list == NULL || list->cur_size == 0) { + QWARN("A null list was passed into listRemoveAt()"); + return; + } + + // If we give a value that is outside of our list return + if (pos < 1 || pos > list->cur_size) { + QERROR("An invalid index was passed to listRemoveAt()"); + return; + } + + // This is the node we are going to be removing + Node *del_node = list->cur_head; + + // This is a counter to keep our position in the list + u64 counter = 1; + + // While we aren't at our position + while (counter != pos) { + // Set the node to the next node + del_node = del_node->next; + // And increase the counter + counter++; + } + + // Now we are at the position we want to delete, so let's get the address of + // the next and previous nodes + Node *prev_node = del_node->prev; + Node *next_node = del_node->next; + + // Now let's update their prev/next values accordingly + if (prev_node != NULL || next_node != NULL) { + prev_node->next = next_node; + next_node->prev = prev_node; + } + + // Finally we can free del_node + free(del_node); + + // Then we decrement the size of our list + list->cur_size--; +} diff --git a/quantum/src/types/linked_list.h b/quantum/src/types/linked_list.h new file mode 100644 index 0000000..2e2a11f --- /dev/null +++ b/quantum/src/types/linked_list.h @@ -0,0 +1,24 @@ +#pragma once + +#include "../defines.h" + +typedef struct Node Node; + +typedef struct List { + Node *cur_head; + Node *cur_tail; + u64 cur_size; +} List; + +List listCreate(); +void listDestroy(List *list); +u64 listSize(const List *list); +void *listPeek(List *list); +void *listPop(List *list); +void listPush(List *list, void *data); +void *listPeekFromFront(List *list); +void *listPopFromFront(List *list); +void listPushFromFront(List *list, void *data); +void *listDataAt(List *list, u64 pos); +void listInsertAt(List *list, u64 pos, void *data); +void listRemoveAt(List *list, u64 pos); diff --git a/test_stuff/src/main.c b/test_stuff/src/main.c index 169cb2f..3d06bcf 100644 --- a/test_stuff/src/main.c +++ b/test_stuff/src/main.c @@ -1,55 +1,60 @@ +#include "types/linked_list.h" #include #include #include -#include int main() { - printf("Size of i16: %" PRId16 "\n", sizeof(i16)); - printf("Size of u16: %" PRIu16 "\n", sizeof(u16)); - printf("Size of i32: %" PRId32 "\n", sizeof(i32)); - printf("Size of u32: %" PRIu32 "\n", sizeof(u32)); - printf("Size of i64: %" PRId64 "\n", sizeof(i64)); - printf("Size of u64: %" PRIu64 "\n", sizeof(u64)); - printf("Size of f32: %lu\n", sizeof(f32)); - printf("Size of f64: %lu\n", sizeof(f64)); + QINFO("Size of i16: %" PRId16, sizeof(i16)); + QINFO("Size of u16: %" PRIu16, sizeof(u16)); + QINFO("Size of i32: %" PRId32, sizeof(i32)); + QINFO("Size of u32: %" PRIu32, sizeof(u32)); + QINFO("Size of i64: %" PRId64, sizeof(i64)); + QINFO("Size of u64: %" PRIu64, sizeof(u64)); + QINFO("Size of f32: %lu", sizeof(f32)); + QINFO("Size of f64: %lu", sizeof(f64)); - QFATAL("Test"); - QERROR("Test"); - QWARN("Test"); - QINFO("Test"); - QDEBUG("Test"); + QINFO("Creating a List..."); + List my_list = listCreate(); + QINFO("Pushing to my_list...") + i32 pushVal = 42; + listPush(&my_list, &pushVal); + i32 peekVal = *(i32 *)listPeek(&my_list); - printf("\nCreating new zone 4K in size...\n"); - Zone *test_zone = zoneCreate(4096); + QDEBUG("Peeking value off of my_list: %" PRId32, peekVal); - void *test_alloc = zoneAlloc(test_zone, 4); - void *test_alloc2 = zoneAlloc(test_zone, 4); + QINFO("Pushing another number to my_list..."); + i32 pushVal2 = 169420; + listPush(&my_list, &pushVal2); + peekVal = *(i32 *)listPeek(&my_list); - printf("Address of test_zone: %p\n", (void *)test_zone); - printf("Address of test_alloc: %p\n", test_alloc); - printf("Address of test_alloc2: %p\n\n", test_alloc2); + QDEBUG("Peeking value off of my_list: %" PRId32, peekVal); - zoneClear(test_zone); + i32 pushVal3 = 69; + listPush(&my_list, &pushVal3); + QDEBUG("Peeking a 3rd value off of my_list: %" PRId32, peekVal); - u64 *test_free = zoneAlloc(test_zone, sizeof(u64)); + i32 popVal = *(i32 *)listPop(&my_list); + QDEBUG("Popped a value off of my_list: %" PRId32, popVal); - printf("Address of test_free: %p\n", (void *)test_free); - printf("Freeing test_free...\n"); + peekVal = *(i32 *)listPeek(&my_list); - zoneFree(&test_free, sizeof(u64)); + QDEBUG("Peeking value off of my_list: %" PRId32, peekVal); - printf("Is test_free NULL: %s\n\n", test_free == NULL ? "true" : "false"); + i32 insertValue = 80085; - zoneDestroy(test_zone); + QINFO("Inserting a value at position 2."); + listInsertAt(&my_list, 2, &insertValue); - const u64 FOUR_GIGS = (u64)4 * 1024 * 1024 * 1024; + QDEBUG("Data at position 2 is: %" PRId32, *(i32 *)listDataAt(&my_list, 2)); - Zone *break_zone = zoneCreate(FOUR_GIGS); + QINFO("Removing a value at position 2."); + listRemoveAt(&my_list, 2); - while (zoneAlloc(break_zone, 1024 * 1024 * 1024) != NULL) { - } + QDEBUG("Data at position 2 is now: %" PRId32, + *(i32 *)listDataAt(&my_list, 2)); - zoneDestroy(break_zone); + QINFO("Destorying List..."); + listDestroy(&my_list); return 0; }