#include "../include/hash_table.h" #include "../include/helpers.h" #include "../include/list.h" #include #include 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(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; }