From 797755502105cd5d67acf2834b3f08c1ca52f16c Mon Sep 17 00:00:00 2001 From: herbglitch Date: Fri, 28 Feb 2025 07:00:35 -0700 Subject: [PATCH] still working on the hashtable, writing a bandaid fix --- src/std/hashtable.c | 142 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 120 insertions(+), 22 deletions(-) diff --git a/src/std/hashtable.c b/src/std/hashtable.c index f1e3a27..b4fa673 100644 --- a/src/std/hashtable.c +++ b/src/std/hashtable.c @@ -1,6 +1,7 @@ #include "arc/std/hashtable.h" #include "arc/std/errno.h" +#include "arc/std/vector.h" #include #include @@ -196,37 +197,80 @@ void ARC_Hashtable_Add(ARC_Hashtable *hashtable, void *key, void *value){ hashtable->currentSize++; } -void ARC_Hashtable_UnsetNodeAtIndexFromArray(ARC_HashtableNode *nodes, uint32_t capacity, uint32_t index){ +void ARC_Hashtable_VectorDestroyHashtableNodeFn(void *data){ + free((ARC_HashtableNode *)data); +} + +void ARC_Hashtable_UnsetNodeAtIndexFromArray(ARC_HashtableNode *nodes, uint32_t capacity, uint32_t index, uint32_t previousIndex){ + //if the first index is the end index just set it to null and return + if(nodes[index].nextIndex == index && nodes[previousIndex].nextIndex == index){ + nodes[previousIndex].nextIndex = previousIndex; + nodes[index] = (ARC_HashtableNode){ NULL, NULL, 0, index }; + return; + } + + //loop through all remaining next nodes while(nodes[index].nextIndex != index){ //get the currently used next index uint32_t nextIndex = nodes[index].nextIndex; - //if the next index is an end, but it is in the right place this should break - uint32_t hashIndex = nodes[nextIndex].hashvalue % capacity; + //if the next index will be moved into the correct spot + if(index == nodes[nextIndex].hashvalue % capacity){ + //NOTE: I couldn't figure out an elegant way of handling this, so for now we remove all clashing nodes, then add them back + //copy the next index back + nodes[index] = nodes[nextIndex]; - printf("%02u -> %2u\t%2u\n", index, nextIndex, hashIndex); + //create the temporary node vector + ARC_Vector *conflictingNodes; + ARC_Vector_DestroyDataFn destroyDataFn = ARC_Hashtable_VectorDestroyHashtableNodeFn; + ARC_Vector_Create(&conflictingNodes, NULL, &destroyDataFn); - //move the current node back one - nodes[index] = nodes[nextIndex]; - - //if the end has been reached, set index to the end - if(nodes[nextIndex].nextIndex == hashIndex){ - //fix if moved back but next index not updated - nodes[nextIndex].nextIndex = hashIndex; - break; - } - - //move set the current index to the end - if(nodes[index].nextIndex == nextIndex){ - nodes[index].nextIndex = index; + //start the loop at the empty to avoid using a do while loop index = nextIndex; - break; + + //the last index copied, used for clearing + uint32_t lastIndex = index; + + //loop through remaining next nodes adding them to a temporary vector and clearing them from the nodes + while(nodes[index].nextIndex != index){ + lastIndex = index; + + //move to the nextIndex + index = nodes[index].nextIndex; + + //copy and add the nodes to the visted indexes + ARC_HashtableNode *nodeCopy = (ARC_HashtableNode *)malloc(sizeof(ARC_HashtableNode)); + *nodeCopy = nodes[index]; + printf("node: %u) %u\t%u\t%s\n", index, nodeCopy->nextIndex, nodeCopy->hashvalue % capacity, (char *)(nodeCopy->key)); + ARC_Vector_Add(conflictingNodes, nodeCopy); + + //clear the copied index + nodes[lastIndex] = (ARC_HashtableNode){ NULL, NULL, 0, lastIndex }; + } + + //clear the last copied node + nodes[index] = (ARC_HashtableNode){ NULL, NULL, 0, index }; + + //re add the nodes + for(uint32_t vectorIndex = 0; vectorIndex < ARC_Vector_GetSize(conflictingNodes); vectorIndex++){ + ARC_HashtableNode node = *(ARC_HashtableNode *)ARC_Vector_Get(conflictingNodes, vectorIndex); + printf("node: %u) %u\t%u\t%s\n", index, node.nextIndex, node.hashvalue % capacity, (char *)(node.key)); + ARC_HashtableNode_SetNearestNodeToArray(nodes, capacity, node); + } + + //cleanup + ARC_Vector_Destroy(conflictingNodes); + + return; } + //move the next node back + nodes[index] = nodes[nextIndex]; + //moves the next index into the next used slot nodes[index].nextIndex = nextIndex; - //get the next index to move back + //check the next index index = nextIndex; } @@ -234,10 +278,63 @@ void ARC_Hashtable_UnsetNodeAtIndexFromArray(ARC_HashtableNode *nodes, uint32_t nodes[index] = (ARC_HashtableNode){ NULL, NULL, 0, index }; } +//void ARC_Hashtable_UnsetNodeAtIndexFromArray(ARC_HashtableNode *nodes, uint32_t capacity, uint32_t index, uint32_t previousIndex){ +// while(nodes[index].nextIndex != index){ +// //get the currently used next index +// uint32_t nextIndex = nodes[index].nextIndex; +// +// //if the next index is an end, but it is in the right place this should break +// uint32_t hashIndex = nodes[nextIndex].hashvalue % capacity; +// +// printf("%02u -> %2u\t%2u\n", index, nextIndex, hashIndex); +// +// //move the current node back one +// nodes[index] = nodes[nextIndex]; +// +// //if the end has been reached, set index to the end +// if(nodes[nextIndex].nextIndex == hashIndex){ +// //fix if moved back but next index not updated +// nodes[nextIndex].nextIndex = hashIndex; +// break; +// } +// +// //move set the current index to the end +// if(nodes[index].nextIndex == nextIndex){ +// nodes[index].nextIndex = index; +// +// //check to see if the previous index is pointing to something it shouldn't be +// if(nodes[index].nextIndex == hashIndex){ +// nodes[previousIndex].nextIndex = previousIndex; +// } +// +// index = nextIndex; +// continue; +// } +// +// //moves the next index into the next used slot +// nodes[index].nextIndex = nextIndex; +// +// //set the previous index +// previousIndex = index; +// +// //get the next index to move back +// index = nextIndex; +// } +// +// //fix pointing at a nonexistant node if the index was the first node found +// if(previousIndex != index && nodes[previousIndex].nextIndex == index){ +// nodes[previousIndex].nextIndex = previousIndex; +// } +// +// //set the current value to an empty node +// nodes[index] = (ARC_HashtableNode){ NULL, NULL, 0, index }; +//} + void ARC_Hashtable_Remove(ARC_Hashtable *hashtable, void *key){ //get the index from a hashvalue - uint32_t initialIndex = hashtable->hashFn(key) % hashtable->currentCapacity; - uint32_t index = initialIndex; + uint32_t initialIndex = hashtable->hashFn(key) % hashtable->currentCapacity; + uint32_t index = initialIndex; + uint32_t previousIndex = initialIndex; //iterate through remaining possible nodes checking for a match ARC_Bool nodeFound = ARC_False; @@ -247,6 +344,7 @@ void ARC_Hashtable_Remove(ARC_Hashtable *hashtable, void *key){ break; } + previousIndex = index; index = hashtable->nodes[index].nextIndex; } @@ -272,7 +370,7 @@ void ARC_Hashtable_Remove(ARC_Hashtable *hashtable, void *key){ printf("MOVE:\n"); //move all next items back - ARC_Hashtable_UnsetNodeAtIndexFromArray(hashtable->nodes, hashtable->currentCapacity, index); + ARC_Hashtable_UnsetNodeAtIndexFromArray(hashtable->nodes, hashtable->currentCapacity, index, previousIndex); //we have removed the item so we can decrease the current size hashtable->currentSize--;