init commit
This commit is contained in:
commit
9904bd2212
16 changed files with 846 additions and 0 deletions
21
hashtable/Makefile
Normal file
21
hashtable/Makefile
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -Wextra
|
||||
|
||||
OBJS=test.o hashtable.o llist.o
|
||||
|
||||
all: test
|
||||
|
||||
test: $(OBJS)
|
||||
gcc -o $@ $^
|
||||
|
||||
test.o: test.c http.h
|
||||
|
||||
hashtable.o: hashtable.c hashtable.h
|
||||
|
||||
llist.o: llist.c llist.h
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS)
|
||||
rm -f test
|
||||
|
||||
.PHONY: all, clean
|
||||
153
hashtable/hashtable.c
Normal file
153
hashtable/hashtable.c
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* hashtable.c - A basic hashtable implementation
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "llist.h"
|
||||
#include "hashtable.h"
|
||||
|
||||
#define SIZE 128
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* key;
|
||||
void* data;
|
||||
}
|
||||
HTEntry;
|
||||
|
||||
/**
|
||||
* Simple hash function used
|
||||
*/
|
||||
int hash(char* key, int ht_size)
|
||||
{
|
||||
int h = 0;
|
||||
|
||||
// basic modulo hash
|
||||
for (size_t i = 0; i < strlen(key); i++)
|
||||
{
|
||||
h = (31 * h + key[i]) % ht_size;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare function for searching a bucket
|
||||
*/
|
||||
int compare(void* data, void* arg)
|
||||
{
|
||||
char* key = arg;
|
||||
HTEntry* entry = data;
|
||||
return strcmp(entry->key, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete HT entry from bucket
|
||||
*/
|
||||
int delete_entry(void* data, void* arg)
|
||||
{
|
||||
(void) arg;
|
||||
HTEntry* entry = data;
|
||||
free(entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new hashtable
|
||||
*/
|
||||
HT* ht_create(void)
|
||||
{
|
||||
HT* ht = malloc(sizeof(HT));
|
||||
|
||||
ht->size = SIZE;
|
||||
ht->entries = 0;
|
||||
ht->store = malloc(ht->size * sizeof(LL*));
|
||||
|
||||
for (int i = 0; i < ht->size; i++)
|
||||
{
|
||||
ht->store[i] = ll_create();
|
||||
}
|
||||
|
||||
return ht;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new key value pair to a hashtable
|
||||
*/
|
||||
int ht_put(HT* ht, char* key, void* data)
|
||||
{
|
||||
int addr = hash(key, ht->size);
|
||||
|
||||
LL* bucket = ht->store[addr];
|
||||
|
||||
HTEntry* entry = malloc(sizeof(HTEntry));
|
||||
entry->key = strdup(key);
|
||||
entry->data = data;
|
||||
|
||||
ll_push(bucket, entry);
|
||||
|
||||
ht->entries++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from a hashtable with a key
|
||||
*/
|
||||
void* ht_get(HT* ht, char* key)
|
||||
{
|
||||
int addr = hash(key, ht->size);
|
||||
|
||||
LL* bucket = ht->store[addr];
|
||||
|
||||
HTEntry* entry = ll_search(bucket, compare, (void*) key);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return entry->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a key value pair from a hashtable
|
||||
*/
|
||||
void* ht_delete(HT* ht, char* key)
|
||||
{
|
||||
int addr = hash(key, ht->size);
|
||||
|
||||
LL* bucket = ht->store[addr];
|
||||
|
||||
HTEntry* entry = ll_delete(bucket, compare, key);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ht->entries--;
|
||||
|
||||
return entry->data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destroy/free an entire hashtable
|
||||
*/
|
||||
int ht_free(HT* ht)
|
||||
{
|
||||
for (int i = 0; i < ht->size; i++)
|
||||
{
|
||||
LL* bucket = ht->store[i];
|
||||
ll_loop(bucket, delete_entry, NULL);
|
||||
ll_free(bucket);
|
||||
}
|
||||
|
||||
free(ht);
|
||||
|
||||
return 0;
|
||||
}
|
||||
24
hashtable/hashtable.h
Normal file
24
hashtable/hashtable.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef _HASHTABLE_H_
|
||||
#define _HASHTABLE_H_
|
||||
|
||||
#include "llist.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int size;
|
||||
int entries;
|
||||
LL** store;
|
||||
}
|
||||
HT;
|
||||
|
||||
HT* ht_create(void);
|
||||
|
||||
int ht_put(HT* ht, char* key, void* data);
|
||||
|
||||
void* ht_get(HT* ht, char* key);
|
||||
|
||||
void* ht_delete(HT* ht, char* key);
|
||||
|
||||
int ht_free(HT* ht);
|
||||
|
||||
#endif
|
||||
34
hashtable/test.c
Normal file
34
hashtable/test.c
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "hashtable.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
puts("Creating new hashtable...");
|
||||
|
||||
HT* ht = ht_create();
|
||||
|
||||
char* login_data = "This is the login data!";
|
||||
char* register_data = "This is the register data!";
|
||||
|
||||
puts("Putting in some data...");
|
||||
|
||||
ht_put(ht, "/login", login_data);
|
||||
ht_put(ht, "/register", register_data);
|
||||
|
||||
puts("Getting values and asserting they are correct...");
|
||||
|
||||
assert(login_data == ht_get(ht, "/login"));
|
||||
assert(register_data == ht_get(ht, "/register"));
|
||||
|
||||
puts("Checking that delete works...");
|
||||
|
||||
ht_delete(ht, "/login");
|
||||
|
||||
assert(ht_get(ht, "/login") == NULL);
|
||||
|
||||
puts("Tests complete!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue