aboutsummaryrefslogtreecommitdiff
path: root/src/common/hash_table.c
diff options
context:
space:
mode:
authorPreston Pan <ret2pop@gmail.com>2025-01-09 16:32:55 -0800
committerPreston Pan <ret2pop@gmail.com>2025-01-09 16:32:55 -0800
commitef9ab1fd141f4057d41f2d6ed8ab8d67c44894d5 (patch)
treee4005b7a641303b021eb54c2aae5676b5f92a72d /src/common/hash_table.c
parent1fd608288ee47c2c560817f12f14b21069fed2f6 (diff)
save stateHEADmain
Diffstat (limited to 'src/common/hash_table.c')
-rw-r--r--src/common/hash_table.c140
1 files changed, 138 insertions, 2 deletions
diff --git a/src/common/hash_table.c b/src/common/hash_table.c
index 2f66d45..6b4c014 100644
--- a/src/common/hash_table.c
+++ b/src/common/hash_table.c
@@ -1,12 +1,148 @@
#include "../include/hash_table.h"
#include "../include/helpers.h"
-
+#include "../include/list.h"
#include <stdlib.h>
+#include <string.h>
+
+pair_t *init_pair(char *key, void *v) {
+ pair_t *pair = safe_calloc(1, sizeof(pair_t));
+ pair->key = key;
+ pair->v = v;
+ return pair;
+}
+
+void *bucket_pop(list_t *b, char *key) {
+ node_t *cur = b->head;
+ node_t *prev;
+ pair_t *cur_pair;
+ node_t *tmp;
+
+ if (b->size == 0)
+ return NULL;
+
+ while (cur) {
+ cur_pair = cur->item;
+ if (strcmp(cur_pair->key, key) == 0) {
+ prev = cur->prev;
+ if (prev) {
+ tmp = cur->next;
+ prev->next = tmp;
+
+ if (tmp)
+ tmp->prev = prev;
+ else {
+ b->tail = prev;
+ }
+
+ b->size--;
+
+ if (b->size <= 1)
+ b->head = b->tail;
+
+ return cur;
+ } else {
+ tmp = cur->next;
+ if (tmp)
+ tmp->prev = NULL;
+
+ b->head = tmp;
+ b->size--;
+
+ if (b->size <= 1)
+ b->tail = b->head;
+
+ return cur;
+ }
+ }
+ }
+ return NULL;
+}
+
+void *bucket_get(list_t *b, char *key) {
+ node_t *cur = b->head;
+ pair_t *cur_pair;
+
+ while (cur) {
+ cur_pair = cur->item;
+ if (strcmp(key, cur_pair->key) == 0) {
+ return cur_pair->v;
+ }
+ }
+ return NULL;
+}
+
+void bucket_free(void *x, void (*freefunc)(void *)) {
+ list_t *b = x;
+ node_t *cur = b->head;
+ node_t *tmp;
+ pair_t *cur_pair;
+
+ if (!x)
+ return;
+
+ while (cur) {
+ cur_pair = cur->item;
+
+ freefunc(cur_pair->v);
+ free(cur_pair->key);
+ free(cur_pair);
+
+ tmp = cur->next;
+ free(cur);
+ cur = tmp;
+ }
+ free(b);
+}
ht_t *init_ht(size_t size) {
ht_t *ht = safe_calloc(1, sizeof(size));
size_t realsize = size == 0 ? DEFAULT_HT_SIZE : size;
- ht->buckets = safe_calloc(realsize, sizeof(sll_t *));
+ ht->buckets = safe_calloc(realsize, sizeof(list_t *));
ht->size = realsize;
return ht;
}
+
+void ht_insert(ht_t *ht, char *key, void *value) {
+ unsigned long bn = hash(key) % ht->size;
+ list_t *bucket = ht->buckets[bn];
+ if (!bucket)
+ ht->buckets[bn] = init_list();
+
+ list_push_back(bucket, init_pair(key, value));
+}
+
+void *ht_pop(ht_t *ht, char *key) {
+ unsigned long bn = hash(key) % ht->size;
+ list_t *bucket = ht->buckets[bn];
+ if (!bucket)
+ return NULL;
+ return bucket_pop(bucket, key);
+}
+
+void *ht_get(ht_t *ht, char *key) {
+ unsigned long bn = hash(key) % ht->size;
+ list_t *bucket = ht->buckets[bn];
+ if (!bucket)
+ return NULL;
+ return bucket_get(bucket, key);
+}
+
+void ht_free(void *x, void (*freefunc)(void *)) {
+ ht_t *ht = x;
+ for (int i = 0; i < ht->size; i++)
+ bucket_free(ht->buckets[i], freefunc);
+
+ free(ht->buckets);
+ free(ht);
+}
+
+/* DJB2 hash function */
+unsigned long hash(char *str) {
+ unsigned long hash = 5381;
+ int c;
+
+ while ((c = *str++))
+ hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
+
+ return hash;
+}