init commit

This commit is contained in:
Andrew Gundersen 2022-05-02 08:00:44 -05:00
commit 9904bd2212
16 changed files with 846 additions and 0 deletions

21
hashtable/Makefile Normal file
View 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
View 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
View 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
View 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;
}