bunkum

an old and silly c99 web server with some fun features
Log | Files | Refs | README

commit 07825c97b36a3820727ddd3a73067dd810830f10
parent bbadb5af33b03192d6ecd5e47d344dabedadbbe7
Author: quantumish <freifeld.david@gmail.com>
Date:   Wed, 12 Apr 2023 22:21:31 -0700

Experiment with variable-sized hashmap keys

Diffstat:
Mhttp.c | 4+---
Mhttp/request.c | 1+
Mutils/hashmap.c | 22+++++++++++++++++-----
Mutils/hashmap.h | 2++
4 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/http.c b/http.c @@ -54,9 +54,7 @@ response_t serve_file(request_t req) { bool ok = true; char* mtype = (char*)ext_to_mtype(ext); char* hdr; - char check[MAX_HEADER_NAME] = {0}; - strcpy(check, "Accept"); - if ((hdr = hashmap_get(&req.headers, check))) { + if ((hdr = hashmap_get(&req.headers, "Accept"))) { log_debug("Handling Accept header"); ok = false; shitvec_t mtypes = hdr_parse_accept(hdr); diff --git a/http/request.c b/http/request.c @@ -62,6 +62,7 @@ int req_parse(request_t* req) { req->method = method_enum((char*)method); req->headers = hashmap_new(MAX_HEADER_NAME, MAX_HEADER_VALUE); + req->headers.vark = true; char* start = memchr(req->buf, '\n', MAX_HEADER_NAME+MAX_HEADER_VALUE)+1; while (start+MAX_HEADER_NAME+MAX_HEADER_VALUE < req->buf+req->bufsize) { char name[MAX_HEADER_NAME] = {0}; diff --git a/utils/hashmap.c b/utils/hashmap.c @@ -4,6 +4,7 @@ #include <stdint.h> #include <stdbool.h> +#include "log.h" #include "hashmap.h" #define HASHMAP_INIT_SIZE 16 @@ -34,7 +35,6 @@ bool iszero(void *p, size_t len) { return iszero; } - // Initialize the hashmap pointed to by h. hashmap_t hashmap_new(size_t ksize, size_t vsize) { hashmap_t h; @@ -44,10 +44,22 @@ hashmap_t hashmap_new(size_t ksize, size_t vsize) { h.k_sz = ksize; h.v_sz = vsize; h.len = HASHMAP_INIT_SIZE; + h.vark = false; h.filled = 0; // Store # of filled keys for load factor calculation return h; } +int hashmap_kcmp(hashmap_t* h, void* a, void* b) { + log_debug("%s %s", a, b); + if (h->vark) return strcmp(a, b); + return memcmp(a, b, h->k_sz); +} + +void* hashmap_kcpy(hashmap_t* h, void* a, void* b) { + if (h->vark) return strcpy(a, b); + return memcpy(a, b, h->k_sz); +} + void hashmap_resize(hashmap_t* h) { void* tempk = h->keys; void* tempv = h->vals; @@ -76,7 +88,7 @@ int hashmap_set(hashmap_t* h, void* k, void* v) { // Start at the hashed index, iterate until own key or empty key is found for (size_t off = index; off < h->len; off+=1) { // Check if stored key at hashed index is equal to key: if so, replace value - if (memcmp(h->keys + (off*h->k_sz), k, h->k_sz) == 0) { + if (hashmap_kcmp(h, h->keys + (off*h->k_sz), k) == 0) { memcpy(h->vals + (off*h->v_sz), v, h->v_sz); return 0x0; } @@ -84,7 +96,7 @@ int hashmap_set(hashmap_t* h, void* k, void* v) { if (iszero(h->keys + (off*h->k_sz), h->k_sz)) { h->filled++; memcpy(h->vals + (off*h->v_sz), v, h->v_sz); - memcpy(h->keys + (off*h->k_sz), k, h->k_sz); + hashmap_kcpy(k, h->keys + (off*h->k_sz), k); return 0x0; } if (off == h->len-1 && looped_once == 0) { @@ -103,7 +115,7 @@ void* hashmap_get(hashmap_t* h, void* k) { // Start at the hashed index, iterate until wanted key or empty key is found for (size_t off = index; off < h->len; off+=1) { // Check if entry has correct key - if (memcmp(h->keys + (off * h->k_sz), k, h->k_sz) == 0) { + if (hashmap_kcmp(h, h->keys + (off * h->k_sz), k) == 0) { return h->vals + (off * h->v_sz); } // Empty entry means this key doesn't exist: return not found @@ -122,7 +134,7 @@ int hashmap_del(hashmap_t* h, void* k) { size_t index = hash(k, h->k_sz) % h->len; int looped_once = 0; for (size_t off = index; off < h->len; off+=1) { - if (memcmp(h->keys + (off * h->k_sz), k, h->k_sz) == 0) { + if (hashmap_kcmp(h, h->keys + (off * h->k_sz), k) == 0) { memset(h->keys + (off * h->v_sz), 0, h->k_sz); // No reason to delete value, will just be overwritten next time. return 0; diff --git a/utils/hashmap.h b/utils/hashmap.h @@ -2,6 +2,7 @@ #define HASHMAP_H #include <stddef.h> +#include <stdbool.h> typedef struct hashmap_t { void* keys; @@ -10,6 +11,7 @@ typedef struct hashmap_t { size_t v_sz; size_t len; size_t filled; + bool vark; } hashmap_t; // Generates a new hashmap_t.