Linked List #10

Merged
wesley merged 1 commits from linked-list into main 2024-02-14 20:14:28 -05:00
5 changed files with 392 additions and 37 deletions

View File

@@ -2,12 +2,16 @@ cmake_minimum_required(VERSION 3.28.1)
project(quantum-utils) project(quantum-utils)
add_compile_options(-g)
set(quantum-src "./quantum/src/") set(quantum-src "./quantum/src/")
set(test_stuff-src "./test_stuff/src/") set(test_stuff-src "./test_stuff/src/")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_library(quantum SHARED ${quantum-src}memory/zone.c add_library(
${quantum-src}logger/logger.c) 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) add_executable(test_stuff ${test_stuff-src}main.c)
target_link_libraries(test_stuff quantum) target_link_libraries(test_stuff quantum)

View File

@@ -2,8 +2,6 @@
#include <stddef.h> // size_t definition #include <stddef.h> // size_t definition
#include "../defines.h"
typedef struct _Zone Zone; typedef struct _Zone Zone;
Zone *zoneCreate(size_t sizeBytes); Zone *zoneCreate(size_t sizeBytes);

View File

@@ -0,0 +1,324 @@
#include "linked_list.h"
#include "../defines.h"
#include "../logger/logger.h"
#include <stddef.h>
#include <stdlib.h>
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--;
}

View File

@@ -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);

View File

@@ -1,55 +1,60 @@
#include "types/linked_list.h"
#include <defines.h> #include <defines.h>
#include <logger/logger.h> #include <logger/logger.h>
#include <memory/zone.h> #include <memory/zone.h>
#include <stdio.h>
int main() { int main() {
printf("Size of i16: %" PRId16 "\n", sizeof(i16)); QINFO("Size of i16: %" PRId16, sizeof(i16));
printf("Size of u16: %" PRIu16 "\n", sizeof(u16)); QINFO("Size of u16: %" PRIu16, sizeof(u16));
printf("Size of i32: %" PRId32 "\n", sizeof(i32)); QINFO("Size of i32: %" PRId32, sizeof(i32));
printf("Size of u32: %" PRIu32 "\n", sizeof(u32)); QINFO("Size of u32: %" PRIu32, sizeof(u32));
printf("Size of i64: %" PRId64 "\n", sizeof(i64)); QINFO("Size of i64: %" PRId64, sizeof(i64));
printf("Size of u64: %" PRIu64 "\n", sizeof(u64)); QINFO("Size of u64: %" PRIu64, sizeof(u64));
printf("Size of f32: %lu\n", sizeof(f32)); QINFO("Size of f32: %lu", sizeof(f32));
printf("Size of f64: %lu\n", sizeof(f64)); QINFO("Size of f64: %lu", sizeof(f64));
QFATAL("Test"); QINFO("Creating a List...");
QERROR("Test"); List my_list = listCreate();
QWARN("Test"); QINFO("Pushing to my_list...")
QINFO("Test"); i32 pushVal = 42;
QDEBUG("Test"); listPush(&my_list, &pushVal);
i32 peekVal = *(i32 *)listPeek(&my_list);
printf("\nCreating new zone 4K in size...\n"); QDEBUG("Peeking value off of my_list: %" PRId32, peekVal);
Zone *test_zone = zoneCreate(4096);
void *test_alloc = zoneAlloc(test_zone, 4); QINFO("Pushing another number to my_list...");
void *test_alloc2 = zoneAlloc(test_zone, 4); i32 pushVal2 = 169420;
listPush(&my_list, &pushVal2);
peekVal = *(i32 *)listPeek(&my_list);
printf("Address of test_zone: %p\n", (void *)test_zone); QDEBUG("Peeking value off of my_list: %" PRId32, peekVal);
printf("Address of test_alloc: %p\n", test_alloc);
printf("Address of test_alloc2: %p\n\n", test_alloc2);
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); peekVal = *(i32 *)listPeek(&my_list);
printf("Freeing test_free...\n");
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; return 0;
} }