This commit is contained in:
aiden 2021-11-19 18:50:57 +00:00
commit 23bb827fd8
4 changed files with 199 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.DS_Store

13
LICENSE Normal file
View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

143
hashmap.c Normal file
View File

@ -0,0 +1,143 @@
#include "hashmap.h"
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
unsigned int hashmap_hash(char *key, size_t key_length) {
unsigned int hash = 0;
while (key_length--) {
hash += *(key++);
hash += hash << 10;
hash ^= hash >> 6;
}
hash += hash << 3;
hash ^= hash >> 11;
hash += hash << 15;
return hash;
}
struct hashmap *hashmap_create(void (*entry_deletion_processor)(void *value)) {
struct hashmap *hashmap = malloc(sizeof(struct hashmap));
if (hashmap == NULL) {
return NULL;
}
hashmap->entry_deletion_processor = entry_deletion_processor;
pthread_mutex_init(&(hashmap->mutex), NULL);
return hashmap;
}
void hashmap_destroy(struct hashmap *hashmap) {
pthread_mutex_lock(&(hashmap->mutex));
pthread_mutex_destroy(&(hashmap->mutex));
for (unsigned short int entry = 0; entry < HASHMAP_N_ENTRIES; ++entry) {
while (hashmap->entries[entry] != NULL) {
hashmap_internal_delete(&(hashmap->entries[entry]), hashmap->entry_deletion_processor);
}
}
free(hashmap);
}
void hashmap_lock(struct hashmap *hashmap) {
pthread_mutex_lock(&(hashmap->mutex));
}
void hashmap_unlock(struct hashmap *hashmap) {
pthread_mutex_unlock(&(hashmap->mutex));
}
struct hashmap_entry **hashmap_internal_find(struct hashmap_entry **entry, char *key, size_t key_length) {
for (; *entry != NULL; entry = &((*entry)->next)) {
if (key_length == (*entry)->key_length && strncmp(key, (*entry)->key, key_length) == 0) {
return entry;
}
}
return NULL;
}
unsigned char hashmap_internal_set_wl(struct hashmap *hashmap, char *key, size_t key_length, void *value, unsigned char fast) {
key = strndup(key, key_length);
if (key == NULL) {
return 0;
}
struct hashmap_entry *new_entry = malloc(sizeof(struct hashmap_entry));
if (new_entry == NULL) {
free(key);
return 0;
}
struct hashmap_entry **entries = &(hashmap->entries[hashmap_hash(key, key_length) % HASHMAP_N_ENTRIES]);
if (!fast) {
struct hashmap_entry **entry = hashmap_internal_find(entries, key, key_length);
if (entry != NULL) {
hashmap_internal_delete(entry, hashmap->entry_deletion_processor);
}
}
new_entry->key = key;
new_entry->key_length = key_length;
new_entry->value = value;
new_entry->next = *entries;
*entries = new_entry;
return 1;
}
unsigned char hashmap_set_wl(struct hashmap *hashmap, char *key, size_t key_length, void *value, unsigned char fast) {
pthread_mutex_lock(&(hashmap->mutex));
unsigned char r = hashmap_internal_set_wl(hashmap, key, key_length, value, fast);
pthread_mutex_unlock(&(hashmap->mutex));
return r;
}
unsigned char hashmap_set(struct hashmap *hashmap, char *key, void *value, unsigned char fast) {
return hashmap_set_wl(hashmap, key, strlen(key), value, fast);
}
unsigned char hashmap_internal_set(struct hashmap *hashmap, char *key, void *value, unsigned char fast) {
return hashmap_internal_set_wl(hashmap, key, strlen(key), value, fast);
}
void *hashmap_internal_get_wl(struct hashmap *hashmap, char *key, size_t key_length) {
struct hashmap_entry **value = hashmap_internal_find(&(hashmap->entries[hashmap_hash(key, key_length) % HASHMAP_N_ENTRIES]), key, key_length);
if (value == NULL) {
return NULL;
}
return (*value)->value;
}
void *hashmap_get_wl(struct hashmap *hashmap, char *key, size_t key_length) {
pthread_mutex_lock(&(hashmap->mutex));
void *value = hashmap_internal_get_wl(hashmap, key, key_length);
pthread_mutex_unlock(&(hashmap->mutex));
return value;
}
void *hashmap_get(struct hashmap *hashmap, char *key) {
return hashmap_get_wl(hashmap, key, strlen(key));
}
void *hashmap_internal_get(struct hashmap *hashmap, char *key) {
return hashmap_internal_get_wl(hashmap, key, strlen(key));
}
void hashmap_internal_delete(struct hashmap_entry **entry, void (*processor)(void *)) {
struct hashmap_entry *d_entry = *entry;
free(d_entry->key);
if (processor != NULL) {
processor(d_entry->value);
}
*entry = d_entry->next;
free(d_entry);
}
void hashmap_delete_wl(struct hashmap *hashmap, char *key, size_t key_length) {
pthread_mutex_lock(&(hashmap->mutex));
struct hashmap_entry **entry = hashmap_internal_find(&(hashmap->entries[hashmap_hash(key, key_length) % HASHMAP_N_ENTRIES]), key, key_length);
if (entry != NULL) {
hashmap_internal_delete(entry, hashmap->entry_deletion_processor);
}
pthread_mutex_unlock(&(hashmap->mutex));
}
void hashmap_delete(struct hashmap *hashmap, char *key) {
hashmap_delete_wl(hashmap, key, strlen(key));
}
#ifdef HASHMAP_MAIN
#include <stdio.h>
int main(void) {
struct hashmap *hashmap = hashmap_create(NULL);
hashmap_set(hashmap, "test", (void *)0xabcd, 0);
printf("%p\n", hashmap_get(hashmap, "test"));
hashmap_destroy(hashmap);
return 0;
}
#endif

41
hashmap.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef HASHMAP_H
#define HASHMAP_H
#ifndef HASHMAP_N_ENTRIES
#define HASHMAP_N_ENTRIES 6151
#endif
#include <pthread.h>
struct hashmap_entry {
char *key;
size_t key_length;
void *value;
struct hashmap_entry *next;
};
struct hashmap {
pthread_mutex_t mutex;
struct hashmap_entry *entries[HASHMAP_N_ENTRIES];
void (*entry_deletion_processor)(void *value);
};
unsigned int hashmap_hash(char *key, size_t key_length);
struct hashmap *hashmap_create(void (*entry_deletion_processor)(void *value));
void hashmap_destroy(struct hashmap *hashmap);
struct hashmap_entry **hashmap_internal_find(struct hashmap_entry **entry, char *key, size_t key_length);
unsigned char hashmap_internal_set_wl(struct hashmap *hashmap, char *key, size_t key_length, void *value, unsigned char fast);
unsigned char hashmap_set_wl(struct hashmap *hashmap, char *key, size_t key_length, void *value, unsigned char fast);
unsigned char hashmap_set(struct hashmap *hashmap, char *key, void *value, unsigned char fast);
unsigned char hashmap_internal_set(struct hashmap *hashmap, char *key, void *value, unsigned char fast);
void *hashmap_internal_get_wl(struct hashmap *hashmap, char *key, size_t key_length);
void *hashmap_get_wl(struct hashmap *hashmap, char *key, size_t key_length);
void *hashmap_get(struct hashmap *hashmap, char *key);
void *hashmap_internal_get(struct hashmap *hashmap, char *key);
void hashmap_internal_delete(struct hashmap_entry **entry, void (*processor)(void *));
void hashmap_delete_wl(struct hashmap *hashmap, char *key, size_t key_length);
void hashmap_delete(struct hashmap *hashmap, char *key);
void hashmap_lock(struct hashmap *hashmap);
void hashmap_unlock(struct hashmap *hashmap);
#endif