From 9b2c601a82f5448389489342d030be5f9975d9c4 Mon Sep 17 00:00:00 2001 From: Mineplay Date: Wed, 9 Jul 2025 13:33:48 -0500 Subject: [PATCH] perf(linked list): changed linked list to be defined using macros to improve performance --- Include/Fledasty/Core/DynamicArray.h | 42 +-- Include/Fledasty/Core/HashTable.h | 52 ++-- Include/Fledasty/Core/LinkedList.h | 310 +++++++++++++++++++-- Include/Fledasty/Core/Queue.h | 32 +-- Src/Core/LinkedList.c | 393 --------------------------- Tests/Main.c | 44 ++- 6 files changed, 368 insertions(+), 505 deletions(-) delete mode 100644 Src/Core/LinkedList.c diff --git a/Include/Fledasty/Core/DynamicArray.h b/Include/Fledasty/Core/DynamicArray.h index e2ebf4b..feeaeff 100644 --- a/Include/Fledasty/Core/DynamicArray.h +++ b/Include/Fledasty/Core/DynamicArray.h @@ -34,27 +34,27 @@ static const size_t FLEDASTY_DYNAMIC_ARRAY_DEFAULT_ALLOCATION_SIZE = 16; -#define FLEDASTY_DYNAMIC_ARRAY_DEFINE(type, name) \ -typedef struct { \ - size_t size, capacity; \ - type *buffer; \ -} FledastyDynamicArray_##name; \ - \ -FledastyError fledasty_dynamic_array_##name##_free(FledastyDynamicArray_##name *current_dynamic_array); \ - \ -FledastyError fledasty_dynamic_array_##name##_append(FledastyDynamicArray_##name *current_dynamic_array, type value); \ - \ -FledastyError fledasty_dynamic_array_##name##_insert_at_index(FledastyDynamicArray_##name *current_dynamic_array, const size_t index, type value); \ -FledastyError fledasty_dynamic_array_##name##_insert_before_value(FledastyDynamicArray_##name *current_dynamic_array, type before_value, type value); \ -FledastyError fledasty_dynamic_array_##name##_insert_after_value(FledastyDynamicArray_##name *current_dynamic_array, type after_value, type value); \ - \ -FledastyError fledasty_dynamic_array_##name##_remove_at_index(FledastyDynamicArray_##name *current_dynamic_array, const size_t index); \ -FledastyError fledasty_dynamic_array_##name##_remove_value(FledastyDynamicArray_##name *current_dynamic_array, type value); \ - \ -FledastyError fledasty_dynamic_array_##name##_clear(FledastyDynamicArray_##name *current_dynamic_array); \ -FledastyError fledasty_dynamic_array_##name##_shrink_to_fit(FledastyDynamicArray_##name *current_dynamic_array); \ - \ -bool fledasty_dynamic_array_##name##_has_value(const FledastyDynamicArray_##name *current_dynamic_array, type value); \ +#define FLEDASTY_DYNAMIC_ARRAY_DEFINE(type, name) \ +typedef struct { \ + size_t size, capacity; \ + type *buffer; \ +} FledastyDynamicArray_##name; \ + \ +FledastyError fledasty_dynamic_array_##name##_free(FledastyDynamicArray_##name *current_dynamic_array); \ + \ +FledastyError fledasty_dynamic_array_##name##_append(FledastyDynamicArray_##name *current_dynamic_array, type value); \ + \ +FledastyError fledasty_dynamic_array_##name##_insert_at_index(FledastyDynamicArray_##name *current_dynamic_array, const size_t index, type value); \ +FledastyError fledasty_dynamic_array_##name##_insert_before_value(FledastyDynamicArray_##name *current_dynamic_array, type before_value, type value); \ +FledastyError fledasty_dynamic_array_##name##_insert_after_value(FledastyDynamicArray_##name *current_dynamic_array, type after_value, type value); \ + \ +FledastyError fledasty_dynamic_array_##name##_remove_at_index(FledastyDynamicArray_##name *current_dynamic_array, const size_t index); \ +FledastyError fledasty_dynamic_array_##name##_remove_value(FledastyDynamicArray_##name *current_dynamic_array, type value); \ + \ +FledastyError fledasty_dynamic_array_##name##_clear(FledastyDynamicArray_##name *current_dynamic_array); \ +FledastyError fledasty_dynamic_array_##name##_shrink_to_fit(FledastyDynamicArray_##name *current_dynamic_array); \ + \ +bool fledasty_dynamic_array_##name##_has_value(const FledastyDynamicArray_##name *current_dynamic_array, type value); \ inline static bool fledasty_dynamic_array_##name##_is_empty(const FledastyDynamicArray_##name *current_dynamic_array) { return current_dynamic_array == NULL || current_dynamic_array->size == 0; } #define FLEDASTY_DYNAMIC_ARRAY_IMPLEMENT(type, name, compare_function) \ diff --git a/Include/Fledasty/Core/HashTable.h b/Include/Fledasty/Core/HashTable.h index fc5f1f4..7e23655 100644 --- a/Include/Fledasty/Core/HashTable.h +++ b/Include/Fledasty/Core/HashTable.h @@ -37,32 +37,32 @@ static const int FLEDASTY_HASH_TABLE_TOTAL_SIZE_PERCENTAGE = 100; static const int FLEDASTY_HASH_TABLE_THRESHOLD_SIZE_PERCENTAGE = 75; static const size_t FLEDASTY_HASH_TABLE_DEFAULT_ALLOCATION_SIZE = 1024; -#define FLEDASTY_HASH_TABLE_DEFINE(key_type, value_type, name, compare_key_function) \ -typedef struct { \ - key_type key; \ - value_type value; \ -} FledastyHashTablePair_##name; \ - \ -FLEDASTY_DYNAMIC_ARRAY_DEFINE(FledastyHashTablePair_##name, fledasty_internal_pair) \ - \ -typedef struct { \ - size_t size, capacity; \ - FledastyDynamicArray_fledasty_internal_pair *Table; \ - \ - size_t (*hash_function)(const key_type key); \ -} FledastyHashTable_##name; \ - \ -FledastyError fledasty_hash_table_##name##_free(FledastyHashTable_##name *current_hash_table); \ - \ -FledastyError fledasty_hash_table_##name##_insert(FledastyHashTable_##name *current_hash_table, key_type key, value_type value); \ -value_type fledasty_hash_table_##name##_get(const FledastyHashTable_##name *current_hash_table, key_type key); \ -FledastyError fledasty_hash_table_##name##_remove(FledastyHashTable_##name *current_hash_table, key_type key); \ - \ -FledastyError fledasty_hash_table_##name##_clear(FledastyHashTable_##name *current_hash_table); \ -FledastyError fledasty_hash_table_##name##_shrink_to_fit(FledastyHashTable_##name *current_hash_table); \ - \ -bool fledasty_hash_table_##name##_has_key(const FledastyHashTable_##name *current_hash_table, key_type key); \ -static inline bool fledasty_hash_table_##name##_is_empty(const FledastyHashTable_##name *current_hash_table) { return current_hash_table == NULL || current_hash_table->size == 0; } \ +#define FLEDASTY_HASH_TABLE_DEFINE(key_type, value_type, name, compare_key_function) \ +typedef struct { \ + key_type key; \ + value_type value; \ +} FledastyHashTablePair_##name; \ + \ +FLEDASTY_DYNAMIC_ARRAY_DEFINE(FledastyHashTablePair_##name, fledasty_internal_pair) \ + \ +typedef struct { \ + size_t size, capacity; \ + FledastyDynamicArray_fledasty_internal_pair *Table; \ + \ + size_t (*hash_function)(const key_type key); \ +} FledastyHashTable_##name; \ + \ +FledastyError fledasty_hash_table_##name##_free(FledastyHashTable_##name *current_hash_table); \ + \ +FledastyError fledasty_hash_table_##name##_insert(FledastyHashTable_##name *current_hash_table, key_type key, value_type value); \ +value_type fledasty_hash_table_##name##_get(const FledastyHashTable_##name *current_hash_table, key_type key); \ +FledastyError fledasty_hash_table_##name##_remove(FledastyHashTable_##name *current_hash_table, key_type key); \ + \ +FledastyError fledasty_hash_table_##name##_clear(FledastyHashTable_##name *current_hash_table); \ +FledastyError fledasty_hash_table_##name##_shrink_to_fit(FledastyHashTable_##name *current_hash_table); \ + \ +bool fledasty_hash_table_##name##_has_key(const FledastyHashTable_##name *current_hash_table, key_type key); \ +static inline bool fledasty_hash_table_##name##_is_empty(const FledastyHashTable_##name *current_hash_table) { return current_hash_table == NULL || current_hash_table->size == 0; } \ static inline bool fledasty_hash_table_##name##_compare_pair(const FledastyHashTablePair_##name first_pair, const FledastyHashTablePair_##name second_pair) { return compare_key_function(first_pair.key, second_pair.key); } #define FLEDASTY_HASH_TABLE_IMPLEMENT(key_type, value_type, name, compare_key_function) \ diff --git a/Include/Fledasty/Core/LinkedList.h b/Include/Fledasty/Core/LinkedList.h index 49f5bc7..e496808 100644 --- a/Include/Fledasty/Core/LinkedList.h +++ b/Include/Fledasty/Core/LinkedList.h @@ -26,34 +26,294 @@ #include #include +#include +#include +#include #include "../Utils/Error.h" -typedef struct FledastyLinkedListNode{ - void *value; - struct FledastyLinkedListNode *next; -} FledastyLinkedListNode; +#define FLEDASTY_LINKED_LIST_DEFINE(type, name) \ +typedef struct FledastyLinkedListNode_##name { \ + type value; \ + struct FledastyLinkedListNode_##name *next; \ +} FledastyLinkedListNode_##name; \ + \ +typedef struct { \ + size_t size; \ + FledastyLinkedListNode_##name *start, *end; \ +} FledastyLinkedList_##name; \ + \ +FledastyError fledasty_linked_list_##name##_free(FledastyLinkedList_##name *current_linked_list); \ + \ +FledastyError fledasty_linked_list_##name##_append(FledastyLinkedList_##name *current_linked_list, type value); \ + \ +FledastyError fledasty_linked_list_##name##_insert_at_index(FledastyLinkedList_##name *current_linked_list, const size_t index, type value); \ +FledastyError fledasty_linked_list_##name##_insert_before_value(FledastyLinkedList_##name *current_linked_list, type before_value, type value); \ +FledastyError fledasty_linked_list_##name##_insert_after_value(FledastyLinkedList_##name *current_linked_list, type after_value, type value); \ + \ +FledastyError fledasty_linked_list_##name##_remove_at_index(FledastyLinkedList_##name *current_linked_list, const size_t index); \ +FledastyError fledasty_linked_list_##name##_remove_value(FledastyLinkedList_##name *current_linked_list, type value); \ + \ +FledastyError fledasty_linked_list_##name##_clear(FledastyLinkedList_##name *current_linked_list); \ + \ +bool fledasty_linked_list_##name##_has_value(const FledastyLinkedList_##name *current_linked_list, type value); \ +static inline bool fledasty_linked_list_##name##_is_empty(const FledastyLinkedList_##name *current_linked_list) { return current_linked_list == NULL || current_linked_list->size == 0; } -typedef struct { - size_t size, element_byte_size; - FledastyLinkedListNode *start, *end; -} FledastyLinkedList; - -FledastyError fledasty_linked_list_initialize(FledastyLinkedList *new_linked_list, void *values, const size_t values_size, const size_t element_byte_size); -FledastyError fledasty_linked_list_destroy(FledastyLinkedList *current_linked_list); - -FledastyError fledasty_linked_list_append(FledastyLinkedList *current_linked_list, void *value); - -FledastyError fledasty_linked_list_insert_at_index(FledastyLinkedList *current_linked_list, const size_t index, void *value); -FledastyError fledasty_linked_list_insert_before_value(FledastyLinkedList *current_linked_list, void *before_value, void *value); -FledastyError fledasty_linked_list_insert_after_value(FledastyLinkedList *current_linked_list, void *after_value, void *value); - -FledastyError fledasty_linked_list_remove_at_index(FledastyLinkedList *current_linked_list, const size_t index); -FledastyError fledasty_linked_list_remove_value(FledastyLinkedList *current_linked_list, void *value); - -FledastyError fledasty_linked_list_clear(FledastyLinkedList *current_linked_list); - -bool fledasty_linked_list_has_value(const FledastyLinkedList *current_linked_list, void *value); -static inline bool fledasty_linked_list_is_empty(const FledastyLinkedList *current_linked_list) { return current_linked_list == NULL || current_linked_list->size == 0; } +#define FLEDASTY_LINKED_LIST_IMPLEMENT(type, name, compare_function) \ +FledastyError fledasty_linked_list_##name##_free(FledastyLinkedList_##name *current_linked_list) { \ + if (current_linked_list == NULL) { \ + return FLEDASTY_ERROR_INVALID_POINTER; \ + } \ + \ + FledastyLinkedListNode_##name *previous_node = NULL; \ + FledastyLinkedListNode_##name *current_node = current_linked_list->start; \ + while (current_node != NULL) { \ + previous_node = current_node; \ + current_node = current_node->next; \ + \ + if (hallocy_free(previous_node) != HALLOCY_ERROR_NONE) { \ + return FLEDASTY_ERROR_FAILED_ALLOCATION; \ + } \ + } \ + \ + return FLEDASTY_ERROR_NONE; \ +} \ + \ +FledastyError fledasty_linked_list_##name##_append(FledastyLinkedList_##name *current_linked_list, type value) { \ + if (current_linked_list == NULL) { \ + return FLEDASTY_ERROR_INVALID_POINTER; \ + } \ + \ + FledastyLinkedListNode_##name *new_node = (FledastyLinkedListNode_##name*)hallocy_malloc(sizeof(FledastyLinkedListNode_##name)); \ + if (new_node == NULL) { \ + return FLEDASTY_ERROR_FAILED_ALLOCATION; \ + } \ + \ + new_node->value = value; \ + new_node->next = NULL; \ + \ + if (current_linked_list->start == NULL) { \ + current_linked_list->start = new_node; \ + current_linked_list->end = new_node; \ + } else { \ + current_linked_list->end->next = new_node; \ + current_linked_list->end = new_node; \ + } \ + \ + current_linked_list->size += 1; \ + return FLEDASTY_ERROR_NONE; \ +} \ + \ +FledastyError fledasty_linked_list_##name##_insert_at_index(FledastyLinkedList_##name *current_linked_list, const size_t index, type value) { \ + if (current_linked_list == NULL) { \ + return FLEDASTY_ERROR_INVALID_POINTER; \ + } \ + \ + if (index > current_linked_list->size) { \ + return FLEDASTY_ERROR_INDEX_OUT_OF_RANGE; \ + } \ + \ + FledastyLinkedListNode_##name *new_node = (FledastyLinkedListNode_##name*)hallocy_malloc(sizeof(FledastyLinkedListNode_##name)); \ + if (new_node == NULL) { \ + return FLEDASTY_ERROR_FAILED_ALLOCATION; \ + } \ + \ + new_node->value = value; \ + if (index == 0) { \ + new_node->next = current_linked_list->start; \ + current_linked_list->start = new_node; \ + } else if (index == current_linked_list->size) { \ + new_node->next = NULL; \ + current_linked_list->end->next = new_node; \ + current_linked_list->end = new_node; \ + } else { \ + FledastyLinkedListNode_##name *current_node = current_linked_list->start; \ + for (size_t node = 0; node < index - 1; node += 1) { \ + current_node = current_node->next; \ + } \ + \ + new_node->next = current_node->next; \ + current_node->next = new_node; \ + } \ + \ + current_linked_list->size += 1; \ + return FLEDASTY_ERROR_NONE; \ +} \ + \ +FledastyError fledasty_linked_list_##name##_insert_before_value(FledastyLinkedList_##name *current_linked_list, type before_value, type value) { \ + if (current_linked_list == NULL) { \ + return FLEDASTY_ERROR_INVALID_POINTER; \ + } \ + \ + FledastyLinkedListNode_##name *previous_node = NULL; \ + FledastyLinkedListNode_##name *current_node = current_linked_list->start; \ + while (current_node != NULL) { \ + if (compare_function(current_node->value, before_value)) { \ + FledastyLinkedListNode_##name *new_node = (FledastyLinkedListNode_##name*)hallocy_malloc(sizeof(FledastyLinkedListNode_##name)); \ + if (new_node == NULL) { \ + return FLEDASTY_ERROR_FAILED_ALLOCATION; \ + } \ + \ + new_node->value = value; \ + if (previous_node == NULL) { \ + new_node->next = current_linked_list->start; \ + current_linked_list->start = new_node; \ + } else { \ + new_node->next = current_node; \ + previous_node->next = new_node; \ + } \ + \ + current_linked_list->size += 1; \ + return FLEDASTY_ERROR_NONE; \ + } \ + \ + previous_node = current_node; \ + current_node = current_node->next; \ + } \ + \ + return FLEDASTY_ERROR_VALUE_NOT_FOUND; \ +} \ + \ +FledastyError fledasty_linked_list_##name##_insert_after_value(FledastyLinkedList_##name *current_linked_list, type after_value, type value) { \ + if (current_linked_list == NULL) { \ + return FLEDASTY_ERROR_INVALID_POINTER; \ + } \ + \ + FledastyLinkedListNode_##name *current_node = current_linked_list->start; \ + while (current_node != NULL) { \ + if (compare_function(current_node->value, after_value)) { \ + FledastyLinkedListNode_##name *new_node = (FledastyLinkedListNode_##name*)hallocy_malloc(sizeof(FledastyLinkedListNode_##name)); \ + if (new_node == NULL) { \ + return FLEDASTY_ERROR_FAILED_ALLOCATION; \ + } \ + \ + new_node->value = value; \ + if (current_node == current_linked_list->end) { \ + new_node->next = NULL; \ + \ + current_linked_list->end->next = new_node; \ + current_linked_list->end = new_node; \ + } else { \ + new_node->next = current_node->next; \ + current_node->next = new_node; \ + } \ + \ + current_linked_list->size += 1; \ + return FLEDASTY_ERROR_NONE; \ + } \ + \ + current_node = current_node->next; \ + } \ + \ + return FLEDASTY_ERROR_VALUE_NOT_FOUND; \ +} \ + \ +FledastyError fledasty_linked_list_##name##_remove_at_index(FledastyLinkedList_##name *current_linked_list, const size_t index) { \ + if (current_linked_list == NULL) { \ + return FLEDASTY_ERROR_INVALID_POINTER; \ + } \ + \ + if (index >= current_linked_list->size) { \ + return FLEDASTY_ERROR_INDEX_OUT_OF_RANGE; \ + } \ + \ + FledastyLinkedListNode_##name *previous_node = NULL; \ + FledastyLinkedListNode_##name *current_node = current_linked_list->start; \ + for (size_t node = 0; node < index; node += 1) { \ + previous_node = current_node; \ + current_node = current_node->next; \ + } \ + \ + if (current_node == current_linked_list->end) { \ + current_linked_list->end = previous_node; \ + } \ + \ + if (previous_node == NULL) { \ + current_linked_list->start = current_node->next; \ + } else { \ + previous_node->next = current_node->next; \ + } \ + \ + if (hallocy_free(current_node) != HALLOCY_ERROR_NONE) { \ + return FLEDASTY_ERROR_FAILED_ALLOCATION; \ + } \ + \ + current_linked_list->size -= 1; \ + return FLEDASTY_ERROR_NONE; \ +} \ + \ +FledastyError fledasty_linked_list_##name##_remove_value(FledastyLinkedList_##name *current_linked_list, type value) { \ + if (current_linked_list == NULL) { \ + return FLEDASTY_ERROR_INVALID_POINTER; \ + } \ + \ + FledastyLinkedListNode_##name *previous_node = NULL; \ + FledastyLinkedListNode_##name *current_node = current_linked_list->start; \ + while (current_node != NULL) { \ + if (compare_function(current_node->value, value)) { \ + if (current_node == current_linked_list->end) { \ + current_linked_list->end = previous_node; \ + } \ + \ + if (previous_node == NULL) { \ + current_linked_list->start = current_node->next; \ + } else { \ + previous_node->next = current_node->next; \ + } \ + \ + if (hallocy_free(current_node) != HALLOCY_ERROR_NONE) { \ + return FLEDASTY_ERROR_FAILED_ALLOCATION; \ + } \ + \ + current_linked_list->size -= 1; \ + return FLEDASTY_ERROR_NONE; \ + } \ + \ + previous_node = current_node; \ + current_node = current_node->next; \ + } \ + \ + return FLEDASTY_ERROR_VALUE_NOT_FOUND; \ +} \ + \ +FledastyError fledasty_linked_list_##name##_clear(FledastyLinkedList_##name *current_linked_list) { \ + if (current_linked_list == NULL) { \ + return FLEDASTY_ERROR_INVALID_POINTER; \ + } \ + \ + FledastyLinkedListNode_##name *previous_node = NULL; \ + FledastyLinkedListNode_##name *current_node = current_linked_list->start; \ + while (current_node != NULL) { \ + previous_node = current_node; \ + current_node = current_node->next; \ + \ + if (hallocy_free(previous_node) != HALLOCY_ERROR_NONE) { \ + return FLEDASTY_ERROR_FAILED_ALLOCATION; \ + } \ + } \ + \ + current_linked_list->start = NULL; \ + current_linked_list->end = NULL; \ + \ + current_linked_list->size = 0; \ + return FLEDASTY_ERROR_NONE; \ +} \ + \ +bool fledasty_linked_list_##name##_has_value(const FledastyLinkedList_##name *current_linked_list, type value) { \ + if (current_linked_list == NULL) { \ + return false; \ + } \ + \ + FledastyLinkedListNode_##name *current_node = current_linked_list->start; \ + while (current_node != NULL) { \ + if (compare_function(current_node->value, value)) { \ + return true; \ + } \ + \ + current_node = current_node->next; \ + } \ + \ + return false; \ +} #endif diff --git a/Include/Fledasty/Core/Queue.h b/Include/Fledasty/Core/Queue.h index a6a1a03..1d59790 100644 --- a/Include/Fledasty/Core/Queue.h +++ b/Include/Fledasty/Core/Queue.h @@ -33,22 +33,22 @@ static const size_t FLEDASTY_QUEUE_DEFAULT_ALLOCATION_SIZE = 16; -#define FLEDASTY_QUEUE_DEFINE(type, name) \ -typedef struct { \ - size_t size, capacity; \ - size_t head, tail; \ - type *buffer; \ -} FledastyQueue_##name; \ - \ -FledastyError fledasty_queue_##name##_free(FledastyQueue_##name *current_queue); \ - \ -FledastyError fledasty_queue_##name##_push(FledastyQueue_##name *current_queue, type value); \ -type fledasty_queue_##name##_pop(FledastyQueue_##name *current_queue); \ - \ -FledastyError fledasty_queue_##name##_clear(FledastyQueue_##name *current_queue); \ -FledastyError fledasty_queue_##name##_shrink_to_fit(FledastyQueue_##name *current_queue); \ - \ -static inline type fledasty_queue_##name##_peek(const FledastyQueue_##name *current_queue) { return (current_queue != NULL && current_queue->size > 0) ? current_queue->buffer[current_queue->head] : 0; } \ +#define FLEDASTY_QUEUE_DEFINE(type, name) \ +typedef struct { \ + size_t size, capacity; \ + size_t head, tail; \ + type *buffer; \ +} FledastyQueue_##name; \ + \ +FledastyError fledasty_queue_##name##_free(FledastyQueue_##name *current_queue); \ + \ +FledastyError fledasty_queue_##name##_push(FledastyQueue_##name *current_queue, type value); \ +type fledasty_queue_##name##_pop(FledastyQueue_##name *current_queue); \ + \ +FledastyError fledasty_queue_##name##_clear(FledastyQueue_##name *current_queue); \ +FledastyError fledasty_queue_##name##_shrink_to_fit(FledastyQueue_##name *current_queue); \ + \ +static inline type fledasty_queue_##name##_peek(const FledastyQueue_##name *current_queue) { return (current_queue != NULL && current_queue->size > 0) ? current_queue->buffer[current_queue->head] : 0; } \ static inline bool fledasty_queue_##name##_is_empty(const FledastyQueue_##name *current_queue) { return current_queue == NULL || current_queue->size == 0; } #define FLEDASTY_QUEUE_IMPLEMENT(type, name) \ diff --git a/Src/Core/LinkedList.c b/Src/Core/LinkedList.c deleted file mode 100644 index 609658c..0000000 --- a/Src/Core/LinkedList.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * ----------------------------------------------------------------------------- - * File: LinkedList.c - * Description: - * This file contains the functions for modifying the Linked List. It includes - * functions to append, Insert before, Insert after, Insert at index, - * Get, Remove element, Remove at index, Check if has element and Check if is empty. - * - * Author: Mineplay - * ----------------------------------------------------------------------------- - */ -#include "../../Include/Fledasty/Core/LinkedList.h" - -#include -#include -#include - -FledastyError fledasty_linked_list_initialize(FledastyLinkedList *new_linked_list, void *values, const size_t values_size, const size_t element_byte_size) { - if (new_linked_list == NULL) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - new_linked_list->element_byte_size = element_byte_size; - if (values == NULL || values_size == 0) { - new_linked_list->size = 0; - new_linked_list->start = NULL; - new_linked_list->end = NULL; - } else { - new_linked_list->size = values_size; - - new_linked_list->start = (FledastyLinkedListNode*)hallocy_malloc(sizeof(FledastyLinkedListNode)); - if (new_linked_list->start == NULL) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - new_linked_list->start->value = hallocy_malloc(new_linked_list->element_byte_size); - if (new_linked_list->start->value == NULL) { - hallocy_free(new_linked_list->start); - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - hallocy_copy_memory(new_linked_list->start->value, values, new_linked_list->element_byte_size); - new_linked_list->start->next = NULL; - - FledastyLinkedListNode *last_node = new_linked_list->start; - for (size_t index = new_linked_list->element_byte_size; index < new_linked_list->size * new_linked_list->element_byte_size; index += new_linked_list->element_byte_size) { - FledastyLinkedListNode *new_node = (FledastyLinkedListNode*)hallocy_malloc(sizeof(FledastyLinkedListNode)); - if (new_node == NULL) { - FledastyLinkedListNode *previous_node = NULL; - FledastyLinkedListNode *current_node = new_linked_list->start; - while (current_node != NULL) { - previous_node = current_node; - current_node = current_node->next; - - hallocy_free(previous_node->value); - hallocy_free(previous_node); - } - - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - new_node->value = hallocy_malloc(new_linked_list->element_byte_size); - if (new_node->value == NULL) { - hallocy_free(new_node); - - FledastyLinkedListNode *previous_node = NULL; - FledastyLinkedListNode *current_node = new_linked_list->start; - while (current_node != NULL) { - previous_node = current_node; - current_node = current_node->next; - - hallocy_free(previous_node->value); - hallocy_free(previous_node); - } - - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - hallocy_copy_memory(new_node->value, (unsigned char*)values + index, new_linked_list->element_byte_size); - - new_node->next = NULL; - last_node->next = new_node; - last_node = new_node; - } - - new_linked_list->end = last_node; - } - - return FLEDASTY_ERROR_NONE; -} - -FledastyError fledasty_linked_list_destroy(FledastyLinkedList *current_linked_list) { - if (current_linked_list == NULL) { - return FLEDASTY_ERROR_INVALID_POINTER; - } - - FledastyLinkedListNode *previous_node = NULL; - FledastyLinkedListNode *current_node = current_linked_list->start; - while (current_node != NULL) { - previous_node = current_node; - current_node = current_node->next; - - if (hallocy_free(previous_node->value) != HALLOCY_ERROR_NONE) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - if (hallocy_free(previous_node) != HALLOCY_ERROR_NONE) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - } - - return FLEDASTY_ERROR_NONE; -} - -FledastyError fledasty_linked_list_append(FledastyLinkedList *current_linked_list, void *value) { - if (current_linked_list == NULL || value == NULL) { - return FLEDASTY_ERROR_INVALID_POINTER; - } - - FledastyLinkedListNode *new_node = (FledastyLinkedListNode*)hallocy_malloc(sizeof(FledastyLinkedListNode)); - if (new_node == NULL) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - new_node->value = hallocy_malloc(current_linked_list->element_byte_size); - if (new_node->value == NULL) { - hallocy_free(new_node); - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - hallocy_copy_memory(new_node->value, value, current_linked_list->element_byte_size); - new_node->next = NULL; - - current_linked_list->end->next = new_node; - current_linked_list->end = new_node; - current_linked_list->size += 1; - - return FLEDASTY_ERROR_NONE; -} - -FledastyError fledasty_linked_list_insert_at_index(FledastyLinkedList *current_linked_list, const size_t index, void *value) { - if (current_linked_list == NULL || value == NULL) { - return FLEDASTY_ERROR_INVALID_POINTER; - } - - if (index > current_linked_list->size) { - return FLEDASTY_ERROR_INDEX_OUT_OF_RANGE; - } - - FledastyLinkedListNode *new_node = (FledastyLinkedListNode*)hallocy_malloc(sizeof(FledastyLinkedListNode)); - if (new_node == NULL) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - new_node->value = hallocy_malloc(current_linked_list->element_byte_size); - if (new_node->value == NULL) { - hallocy_free(new_node); - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - hallocy_copy_memory(new_node->value, value, current_linked_list->element_byte_size); - if (index == 0) { - new_node->next = current_linked_list->start; - current_linked_list->start = new_node; - } else if (index == current_linked_list->size) { - new_node->next = NULL; - current_linked_list->end->next = new_node; - current_linked_list->end = new_node; - } else { - FledastyLinkedListNode *current_node = current_linked_list->start; - for (size_t node = 0; node < index - 1; node += 1) { - current_node = current_node->next; - } - - new_node->next = current_node->next; - current_node->next = new_node; - } - - current_linked_list->size += 1; - return FLEDASTY_ERROR_NONE; -} - -FledastyError fledasty_linked_list_insert_before_value(FledastyLinkedList *current_linked_list, void *before_value, void *value) { - if (current_linked_list == NULL || before_value == NULL || value == NULL) { - return FLEDASTY_ERROR_INVALID_POINTER; - } - - FledastyLinkedListNode *previous_node = NULL; - FledastyLinkedListNode *current_node = current_linked_list->start; - while (current_node != NULL) { - if (hallocy_compare_memory(current_node->value, before_value, current_linked_list->element_byte_size)) { - FledastyLinkedListNode *new_node = (FledastyLinkedListNode*)hallocy_malloc(sizeof(FledastyLinkedListNode)); - if (new_node == NULL) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - new_node->value = hallocy_malloc(current_linked_list->element_byte_size); - if (new_node->value == NULL) { - hallocy_free(new_node); - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - hallocy_copy_memory(new_node->value, value, current_linked_list->element_byte_size); - if (previous_node == NULL) { - new_node->next = current_linked_list->start; - current_linked_list->start = new_node; - } else { - new_node->next = current_node; - previous_node->next = new_node; - } - - current_linked_list->size += 1; - return FLEDASTY_ERROR_NONE; - } - - previous_node = current_node; - current_node = current_node->next; - } - - return FLEDASTY_ERROR_VALUE_NOT_FOUND; -} - -FledastyError fledasty_linked_list_insert_after_value(FledastyLinkedList *current_linked_list, void *after_value, void *value) { - if (current_linked_list == NULL || after_value == NULL || value == NULL) { - return FLEDASTY_ERROR_INVALID_POINTER; - } - - FledastyLinkedListNode *current_node = current_linked_list->start; - while (current_node != NULL) { - if (hallocy_compare_memory(current_node->value, after_value, current_linked_list->element_byte_size)) { - FledastyLinkedListNode *new_node = (FledastyLinkedListNode*)hallocy_malloc(sizeof(FledastyLinkedListNode)); - if (new_node == NULL) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - new_node->value = hallocy_malloc(current_linked_list->element_byte_size); - if (new_node->value == NULL) { - hallocy_free(new_node); - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - hallocy_copy_memory(new_node->value, value, current_linked_list->element_byte_size); - if (current_node == current_linked_list->end) { - new_node->next = NULL; - - current_linked_list->end->next = new_node; - current_linked_list->end = new_node; - } else { - new_node->next = current_node->next; - current_node->next = new_node; - } - - current_linked_list->size += 1; - return FLEDASTY_ERROR_NONE; - } - - current_node = current_node->next; - } - - return FLEDASTY_ERROR_VALUE_NOT_FOUND; -} - -FledastyError fledasty_linked_list_remove_at_index(FledastyLinkedList *current_linked_list, const size_t index) { - if (current_linked_list == NULL) { - return FLEDASTY_ERROR_INVALID_POINTER; - } - - if (index >= current_linked_list->size) { - return FLEDASTY_ERROR_INDEX_OUT_OF_RANGE; - } - - FledastyLinkedListNode *previous_node = NULL; - FledastyLinkedListNode *current_node = current_linked_list->start; - for (size_t node = 0; node < index; node += 1) { - previous_node = current_node; - current_node = current_node->next; - } - - if (current_node == current_linked_list->end) { - current_linked_list->end = previous_node; - } - - if (previous_node == NULL) { - current_linked_list->start = current_node->next; - } else { - previous_node->next = current_node->next; - } - - if (hallocy_free(current_node->value) != HALLOCY_ERROR_NONE) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - if (hallocy_free(current_node) != HALLOCY_ERROR_NONE) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - current_linked_list->size -= 1; - return FLEDASTY_ERROR_NONE; -} - -FledastyError fledasty_linked_list_remove_value(FledastyLinkedList *current_linked_list, void *value) { - if (current_linked_list == NULL || value == NULL) { - return FLEDASTY_ERROR_INVALID_POINTER; - } - - FledastyLinkedListNode *previous_node = NULL; - FledastyLinkedListNode *current_node = current_linked_list->start; - while (current_node != NULL) { - if (hallocy_compare_memory(current_node->value, value, current_linked_list->element_byte_size)) { - if (current_node == current_linked_list->end) { - current_linked_list->end = previous_node; - } - - if (previous_node == NULL) { - current_linked_list->start = current_node->next; - } else { - previous_node->next = current_node->next; - } - - if (hallocy_free(current_node->value) != HALLOCY_ERROR_NONE) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - if (hallocy_free(current_node) != HALLOCY_ERROR_NONE) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - current_linked_list->size -= 1; - return FLEDASTY_ERROR_NONE; - } - - previous_node = current_node; - current_node = current_node->next; - } - - return FLEDASTY_ERROR_VALUE_NOT_FOUND; -} - -FledastyError fledasty_linked_list_clear(FledastyLinkedList *current_linked_list) { - if (current_linked_list == NULL) { - return FLEDASTY_ERROR_INVALID_POINTER; - } - - FledastyLinkedListNode *previous_node = NULL; - FledastyLinkedListNode *current_node = current_linked_list->start; - while (current_node != NULL) { - previous_node = current_node; - current_node = current_node->next; - - if (hallocy_free(previous_node->value) != HALLOCY_ERROR_NONE) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - - if (hallocy_free(previous_node) != HALLOCY_ERROR_NONE) { - return FLEDASTY_ERROR_FAILED_ALLOCATION; - } - } - - current_linked_list->start = NULL; - current_linked_list->end = NULL; - - current_linked_list->size = 0; - return FLEDASTY_ERROR_NONE; -} - -bool fledasty_linked_list_has_value(const FledastyLinkedList *current_linked_list, void *value) { - if (current_linked_list == NULL || value == NULL) { - return false; - } - - FledastyLinkedListNode *current_node = current_linked_list->start; - while (current_node != NULL) { - if (hallocy_compare_memory(current_node->value, value, current_linked_list->element_byte_size)) { - return true; - } - - current_node = current_node->next; - } - - return false; -} diff --git a/Tests/Main.c b/Tests/Main.c index d0f8498..e13c48a 100644 --- a/Tests/Main.c +++ b/Tests/Main.c @@ -45,6 +45,9 @@ FLEDASTY_DYNAMIC_ARRAY_IMPLEMENT(int, int, compare_integers) FLEDASTY_HASH_TABLE_DEFINE(int, int, int_int, compare_integers) FLEDASTY_HASH_TABLE_IMPLEMENT(int, int, int_int, compare_integers) +FLEDASTY_LINKED_LIST_DEFINE(int, int) +FLEDASTY_LINKED_LIST_IMPLEMENT(int, int, compare_integers) + int main() { FledastyQueue_int test_queue = { 0, 0, 0, 0, NULL }; for (int i = 0; i < 10; i += 1) { @@ -117,41 +120,34 @@ int main() { fledasty_dynamic_array_int_free(&test_dynamic_array); - FledastyLinkedList test_linked_list; - fledasty_linked_list_initialize(&test_linked_list, (int[]){11, 12, 13, 14, 15}, 5, sizeof(int)); - + FledastyLinkedList_int test_linked_list = { 0, NULL, NULL }; for (int i = 0; i < 10; i += 1) { - fledasty_linked_list_append(&test_linked_list, &i); + fledasty_linked_list_int_append(&test_linked_list, i); } - int insert_value = 35; - fledasty_linked_list_insert_at_index(&test_linked_list, 1, &insert_value); - insert_value = 28; - int insert_at_value = 35; - fledasty_linked_list_insert_before_value(&test_linked_list, &insert_at_value, &insert_value); - insert_value = 90; - fledasty_linked_list_insert_after_value(&test_linked_list, &insert_at_value, &insert_value); + fledasty_linked_list_int_insert_at_index(&test_linked_list, 1, 35); + fledasty_linked_list_int_insert_before_value(&test_linked_list, 35, 28); + fledasty_linked_list_int_insert_after_value(&test_linked_list, 35, 90); - fledasty_linked_list_remove_at_index(&test_linked_list, 2); - int remove_value = 0; - fledasty_linked_list_remove_value(&test_linked_list, &remove_value); + fledasty_linked_list_int_remove_at_index(&test_linked_list, 2); + fledasty_linked_list_int_remove_value(&test_linked_list, 0); - FledastyLinkedListNode *test_linked_list_node = test_linked_list.start; + FledastyLinkedListNode_int *test_linked_list_node = test_linked_list.start; for (int i = 0; i < test_linked_list.size; i += 1) { - printf("Linked list get: %d\n", *(int*)test_linked_list_node->value); + printf("Linked list get: %d\n", test_linked_list_node->value); test_linked_list_node = test_linked_list_node->next; } - if (fledasty_linked_list_has_value(&test_linked_list, &insert_value)) { - printf("Linked list contains %d\n", insert_value); + if (fledasty_linked_list_int_has_value(&test_linked_list, 90)) { + printf("Linked list contains 90\n"); } - fledasty_linked_list_clear(&test_linked_list); - if (fledasty_linked_list_is_empty(&test_linked_list)) { + fledasty_linked_list_int_clear(&test_linked_list); + if (fledasty_linked_list_int_is_empty(&test_linked_list)) { printf("Linked list is empty\n"); } - fledasty_linked_list_destroy(&test_linked_list); + fledasty_linked_list_int_free(&test_linked_list); FledastyDoublyLinkedList test_doubly_linked_list; fledasty_doubly_linked_list_initialize(&test_doubly_linked_list, (int[]){11, 12, 13, 14, 15}, 5, sizeof(int)); @@ -159,16 +155,16 @@ int main() { fledasty_doubly_linked_list_append(&test_doubly_linked_list, &i); } - insert_value = 35; + int insert_value = 35; fledasty_doubly_linked_list_insert_at_index(&test_doubly_linked_list, test_doubly_linked_list.size - 1, &insert_value); insert_value = 28; - insert_at_value = 35; + int insert_at_value = 35; fledasty_doubly_linked_list_insert_before_value(&test_doubly_linked_list, &insert_at_value, &insert_value); insert_value = 90; fledasty_doubly_linked_list_insert_after_value(&test_doubly_linked_list, &insert_at_value, &insert_value); fledasty_doubly_linked_list_remove_at_index(&test_doubly_linked_list, 2); - remove_value = 0; + int remove_value = 0; fledasty_doubly_linked_list_remove_value(&test_doubly_linked_list, &remove_value); FledastyDoublyLinkedListNode *test_doubly_linked_list_node = test_doubly_linked_list.start;