123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- /* vim: tabstop=4 shiftwidth=4 noexpandtab
- * This file is part of ToaruOS and is released under the terms
- * of the NCSA / University of Illinois License - see LICENSE.md
- * Copyright (C) 2013-2018 K. Lange
- */
- #include <toaru/list.h>
- #include <toaru/hashmap.h>
- unsigned int hashmap_string_hash(void * _key) {
- unsigned int hash = 0;
- char * key = (char *)_key;
- int c;
- /* This is the so-called "sdbm" hash. It comes from a piece of
- * public domain code from a clone of ndbm. */
- while ((c = *key++)) {
- hash = c + (hash << 6) + (hash << 16) - hash;
- }
- return hash;
- }
- int hashmap_string_comp(void * a, void * b) {
- return !strcmp(a,b);
- }
- void * hashmap_string_dupe(void * key) {
- return strdup(key);
- }
- unsigned int hashmap_int_hash(void * key) {
- return (unsigned int)key;
- }
- int hashmap_int_comp(void * a, void * b) {
- return (int)a == (int)b;
- }
- void * hashmap_int_dupe(void * key) {
- return key;
- }
- static void hashmap_int_free(void * ptr) {
- (void)ptr;
- return;
- }
- hashmap_t * hashmap_create(int size) {
- hashmap_t * map = malloc(sizeof(hashmap_t));
- map->hash_func = &hashmap_string_hash;
- map->hash_comp = &hashmap_string_comp;
- map->hash_key_dup = &hashmap_string_dupe;
- map->hash_key_free = &free;
- map->hash_val_free = &free;
- map->size = size;
- map->entries = malloc(sizeof(hashmap_entry_t *) * size);
- memset(map->entries, 0x00, sizeof(hashmap_entry_t *) * size);
- return map;
- }
- hashmap_t * hashmap_create_int(int size) {
- hashmap_t * map = malloc(sizeof(hashmap_t));
- map->hash_func = &hashmap_int_hash;
- map->hash_comp = &hashmap_int_comp;
- map->hash_key_dup = &hashmap_int_dupe;
- map->hash_key_free = &hashmap_int_free;
- map->hash_val_free = &free;
- map->size = size;
- map->entries = malloc(sizeof(hashmap_entry_t *) * size);
- memset(map->entries, 0x00, sizeof(hashmap_entry_t *) * size);
- return map;
- }
- void * hashmap_set(hashmap_t * map, void * key, void * value) {
- unsigned int hash = map->hash_func(key) % map->size;
- hashmap_entry_t * x = map->entries[hash];
- if (!x) {
- hashmap_entry_t * e = malloc(sizeof(hashmap_entry_t));
- e->key = map->hash_key_dup(key);
- e->value = value;
- e->next = NULL;
- map->entries[hash] = e;
- return NULL;
- } else {
- hashmap_entry_t * p = NULL;
- do {
- if (map->hash_comp(x->key, key)) {
- void * out = x->value;
- x->value = value;
- return out;
- } else {
- p = x;
- x = x->next;
- }
- } while (x);
- hashmap_entry_t * e = malloc(sizeof(hashmap_entry_t));
- e->key = map->hash_key_dup(key);
- e->value = value;
- e->next = NULL;
- p->next = e;
- return NULL;
- }
- }
- void * hashmap_get(hashmap_t * map, void * key) {
- unsigned int hash = map->hash_func(key) % map->size;
- hashmap_entry_t * x = map->entries[hash];
- if (!x) {
- return NULL;
- } else {
- do {
- if (map->hash_comp(x->key, key)) {
- return x->value;
- }
- x = x->next;
- } while (x);
- return NULL;
- }
- }
- void * hashmap_remove(hashmap_t * map, void * key) {
- unsigned int hash = map->hash_func(key) % map->size;
- hashmap_entry_t * x = map->entries[hash];
- if (!x) {
- return NULL;
- } else {
- if (map->hash_comp(x->key, key)) {
- void * out = x->value;
- map->entries[hash] = x->next;
- map->hash_key_free(x->key);
- map->hash_val_free(x);
- return out;
- } else {
- hashmap_entry_t * p = x;
- x = x->next;
- do {
- if (map->hash_comp(x->key, key)) {
- void * out = x->value;
- p->next = x->next;
- map->hash_key_free(x->key);
- map->hash_val_free(x);
- return out;
- }
- p = x;
- x = x->next;
- } while (x);
- }
- return NULL;
- }
- }
- int hashmap_has(hashmap_t * map, void * key) {
- unsigned int hash = map->hash_func(key) % map->size;
- hashmap_entry_t * x = map->entries[hash];
- if (!x) {
- return 0;
- } else {
- do {
- if (map->hash_comp(x->key, key)) {
- return 1;
- }
- x = x->next;
- } while (x);
- return 0;
- }
- }
- list_t * hashmap_keys(hashmap_t * map) {
- list_t * l = list_create();
- for (unsigned int i = 0; i < map->size; ++i) {
- hashmap_entry_t * x = map->entries[i];
- while (x) {
- list_insert(l, x->key);
- x = x->next;
- }
- }
- return l;
- }
- list_t * hashmap_values(hashmap_t * map) {
- list_t * l = list_create();
- for (unsigned int i = 0; i < map->size; ++i) {
- hashmap_entry_t * x = map->entries[i];
- while (x) {
- list_insert(l, x->value);
- x = x->next;
- }
- }
- return l;
- }
- void hashmap_free(hashmap_t * map) {
- for (unsigned int i = 0; i < map->size; ++i) {
- hashmap_entry_t * x = map->entries[i], * p;
- while (x) {
- p = x;
- x = x->next;
- map->hash_key_free(p->key);
- map->hash_val_free(p);
- }
- }
- free(map->entries);
- }
- int hashmap_is_empty(hashmap_t * map) {
- for (unsigned int i = 0; i < map->size; ++i) {
- if (map->entries[i]) return 0;
- }
- return 1;
- }
|