/* * SPDX-FileCopyrightText: 2025 William Bell * * SPDX-License-Identifier: GPL-3.0-or-later */ #include "hashmap.h" #include "../../../memory.h" #include #include #include #include #include #include #include struct hashmap_GC *createHashmap_GC() { struct hashmap_GC *t = (struct hashmap_GC *)ar_alloc(sizeof(struct hashmap_GC)); t->size = 0; t->order = 1; t->list = NULL; t->hashmap_count = 0; t->count = 0; t->inline_count = 0; return t; } static int compare_node_asc(const void *a, const void *b) { const struct node_GC *na = *(const struct node_GC **)a; const struct node_GC *nb = *(const struct node_GC **)b; // Ascending order (smallest order first) if (na->order < nb->order) return -1; if (na->order > nb->order) return 1; return 0; } struct node_GC ** hashmap_GC_to_array(struct hashmap_GC *t, size_t *array_length) { size_t array_size = 8; *array_length = 0; struct node_GC ** array = ar_alloc(array_size * sizeof(struct node_GC*)); for (size_t i = 0; i < t->inline_count; i++) { if (*array_length >= array_size) { array_size *= 2; array = ar_realloc(array, array_size * sizeof(struct node_GC*)); } array[(*array_length)++] = &t->inline_values[i]; } for (size_t i = 0; i < t->size; i++) { struct node_GC *list = t->list[i]; struct node_GC *temp = list; while (temp) { if (*array_length >= array_size) { array_size *= 2; array = ar_realloc(array, array_size * sizeof(struct node_GC*)); } array[(*array_length)++] = temp; temp = temp->next; } } qsort(array, *array_length, sizeof(struct node_GC*), compare_node_asc); return array; } void clear_hashmap_GC(struct hashmap_GC *t) { if (!t->count) return; t->order = 1; t->count = 0; t->inline_count = 0; t->hashmap_count = 0; memset(t->list, 0, sizeof(struct node_GC *) * t->size); } void resize_hashmap_GC(struct hashmap_GC *t) { int old_size = t->size; int new_size = old_size * 2; if (new_size == 0) new_size = 8; struct node_GC **old_list = t->list; // Create new list t->list = (struct node_GC **)ar_alloc(sizeof(struct node_GC *) * new_size); memset(t->list, 0, sizeof(struct node_GC *) * new_size); t->size = new_size; if (!old_list) return; t->hashmap_count = 0; // Rehash old entries into new list for (int i = 0; i < old_size; i++) { struct node_GC *temp = old_list[i]; while (temp) { hashmap_insert_GC(t, temp->hash, temp->key, temp->val, temp->order); // Will increment count temp = temp->next; } } } int hashCode_GC(struct hashmap_GC *t, uint64_t hash) { return hash & (t->size - 1); } int hashmap_remove_GC(struct hashmap_GC *t, uint64_t hash) { for (size_t i = 0; i < t->inline_count; i++) { if (t->inline_values[i].hash == hash) { size_t length = t->inline_count - i; if (length > 1) { memmove(&t->inline_values[i], &t->inline_values[i + 1], (length - 1) * sizeof(struct node_GC)); } t->inline_count--; return 1; } } int pos = hashCode_GC(t, hash); struct node_GC *list = t->list[pos]; struct node_GC *temp = list; struct node_GC *prev = NULL; while (temp) { if (temp->hash == hash) { if (prev) prev->next = temp->next; else t->list[pos] = temp->next; return 1; } prev = temp; temp = temp->next; } return 0; } void hashmap_insert_GC(struct hashmap_GC *t, uint64_t hash, void *key, void *val, size_t order) { if (!order) { order = t->order++; } for (size_t i = 0; i < t->inline_count; i++) { if (t->inline_values[i].hash == hash) { t->inline_values[i].val = val; return; } } if (!t->list && t->inline_count < INLINE_HASHMAP_ARRAY_SIZE) { t->inline_values[t->inline_count].hash = hash; t->inline_values[t->inline_count].key = key; t->inline_values[t->inline_count].val = val; t->inline_values[t->inline_count].order = order; t->inline_count++; t->count++; return; } if ((t->hashmap_count + 1) > t->size * 0.75) { resize_hashmap_GC(t); } int pos = hashCode_GC(t, hash); struct node_GC *list = t->list[pos]; struct node_GC *temp = list; // Check if key exists → overwrite while (temp) { if (temp->hash == hash) { temp->val = val; return; } temp = temp->next; } // Insert new node struct node_GC *newNode = (struct node_GC *)ar_alloc(sizeof(struct node_GC)); newNode->hash = hash; newNode->key = key; newNode->val = val; newNode->order = order; newNode->next = list; t->list[pos] = newNode; t->hashmap_count++; t->count++; } void *hashmap_lookup_GC(struct hashmap_GC *t, uint64_t hash) { size_t stop = t->inline_count; for (size_t i = 0; i < stop; i++) { if (t->inline_values[i].hash == hash) return t->inline_values[i].val; } if (!t->list) return NULL; int pos = hashCode_GC(t, hash); struct node_GC *list = t->list[pos]; struct node_GC *temp = list; while (temp) { if (temp->hash == hash) { return temp->val; } temp = temp->next; } return NULL; }