diff --git a/README.md b/README.md index 6f3ffb7..a11e068 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ And then open the `docs/html/index.html`. ## Roadmap - Implement Keep-Alive -- Support for virtual hosting +- Support for virtual hosts - HTTPS support with TLS ## Future @@ -41,3 +41,4 @@ And then open the `docs/html/index.html`. - Multithreading to handle concurrent requests - Logging - Compression (Gzip) +- Reverse proxy diff --git a/include/utils/colors.h b/include/utils/colors.h index c648910..496abc7 100644 --- a/include/utils/colors.h +++ b/include/utils/colors.h @@ -27,8 +27,6 @@ #define CWS_LOG_DEBUG(msg, ...) #endif -#define CWS_LOG(level, msg, ...) - #define CWS_LOG_ERROR(msg, ...) fprintf(stderr, _ERR " " msg "\n", ##__VA_ARGS__) #define CWS_LOG_WARNING(msg, ...) fprintf(stdout, _WARNING " " msg "\n", ##__VA_ARGS__) #define CWS_LOG_INFO(msg, ...) fprintf(stdout, _INFO " " msg "\n", ##__VA_ARGS__) diff --git a/include/utils/hashmap.h b/include/utils/hashmap.h index dffaabf..a7ef13b 100644 --- a/include/utils/hashmap.h +++ b/include/utils/hashmap.h @@ -95,8 +95,12 @@ bool cws_hm_set(cws_hashmap *hashmap, void *key, void *value); cws_bucket *cws_hm_get(cws_hashmap *hashmap, void *key); /** - * TODO: Implement cws_hm_remove() * @brief Removes a key-value pair from the hash map + * + * @param[in] hashmap Pointer to the hash map + * @param[in] key Pointer to the key to remove, this pointer will be freed so pay attention + * @return False if the key is not found, otherwise true */ +bool cws_hm_remove(cws_hashmap *hashmap, void *key); #endif diff --git a/include/utils/utils.h b/include/utils/utils.h index 451773e..e6bfa07 100644 --- a/include/utils/utils.h +++ b/include/utils/utils.h @@ -24,7 +24,12 @@ void cws_utils_print_ips(const char *hostname, const char *port); */ void cws_utils_get_client_ip(struct sockaddr_storage *sa, char *ip); -/* TODO: add docs */ +/** + * @brief Remove whitespaces from a string + * + * @param[in] str The string pointer + * @return Returns the new string without whitespaces + */ char *cws_strip(char *str); /* Functions used for hash maps */ diff --git a/src/utils/hashmap.c b/src/utils/hashmap.c index 61ffcab..9008cc2 100644 --- a/src/utils/hashmap.c +++ b/src/utils/hashmap.c @@ -57,6 +57,10 @@ void cws_hm_free(cws_hashmap *hashmap) { } bool cws_hm_set(cws_hashmap *hashmap, void *key, void *value) { + if (hashmap == NULL || key == NULL || value == NULL) { + return false; + } + /* Get hash index */ int index = hashmap->hash_fn(key) % CWS_HASHMAP_SIZE; cws_bucket *bucket = &hashmap->map[index]; @@ -111,16 +115,16 @@ bool cws_hm_set(cws_hashmap *hashmap, void *key, void *value) { } cws_bucket *cws_hm_get(cws_hashmap *hashmap, void *key) { - /* Return if key is null */ - if (key == NULL) { + /* Return if hash map or key is null */ + if (hashmap == NULL || key == NULL) { return NULL; } - int index = hashmap->hash_fn(key); + int index = hashmap->hash_fn(key) % CWS_HASHMAP_SIZE; cws_bucket *bucket = &hashmap->map[index]; /* Key is not in the hash map */ - if (bucket == NULL || bucket->key == NULL) { + if (bucket->key == NULL) { return NULL; } @@ -135,3 +139,56 @@ cws_bucket *cws_hm_get(cws_hashmap *hashmap, void *key) { /* Key not found */ return NULL; } + +bool cws_hm_remove(cws_hashmap *hashmap, void *key) { + if (hashmap == NULL || key == NULL) { + return false; + } + + int index = hashmap->hash_fn(key) % CWS_HASHMAP_SIZE; + cws_bucket *bucket = &hashmap->map[index]; + + if (bucket->key == NULL) { + return false; + } + + if (hashmap->equal_fn(bucket->key, key)) { + if (hashmap->free_key_fn != NULL) { + hashmap->free_key_fn(bucket->key); + } + if (hashmap->free_value_fn != NULL) { + hashmap->free_value_fn(bucket->value); + } + + if (bucket->next != NULL) { + bucket->key = bucket->next->key; + bucket->value = bucket->next->value; + bucket->next = bucket->next->next; + } else { + bucket->key = NULL; + } + + return true; + } + + cws_bucket *next = bucket->next; + + while (next) { + if (hashmap->equal_fn(next->key, key)) { + if (hashmap->free_key_fn != NULL) { + hashmap->free_key_fn(next->key); + } + if (hashmap->free_value_fn != NULL) { + hashmap->free_value_fn(next->value); + } + bucket->next = next->next; + free(next); + + return true; + } + bucket = next; + next = next->next; + } + + return false; +} diff --git a/test/hashmap_test.c b/test/hashmap_test.c index 652de70..19667ef 100644 --- a/test/hashmap_test.c +++ b/test/hashmap_test.c @@ -42,14 +42,17 @@ int main(void) { return 1; } + /* Add a new key-value */ ret = cws_hm_set(str_hashmap, (void *)key, (void *)value); if (!ret) { CWS_LOG_WARNING("Unable to set %s:%s", key, value); } + /* Get the added key-value */ cws_bucket *bucket = cws_hm_get(str_hashmap, key); CWS_LOG_DEBUG("Set %s:%s", (char *)bucket->key, (char *)bucket->value); + /* Update the value */ char *another_value = strdup("another value1"); ret = cws_hm_set(str_hashmap, (void *)key, (void *)another_value); if (!ret) { @@ -59,6 +62,17 @@ int main(void) { bucket = cws_hm_get(str_hashmap, key); CWS_LOG_DEBUG("Set %s:%s", (char *)bucket->key, (char *)bucket->value); + /* Remove the key-value */ + ret = cws_hm_remove(str_hashmap, (void *)key); + if (ret) { + CWS_LOG_DEBUG("test1 removed"); + } + /* Can't use key, it has been freed */ + bucket = cws_hm_get(str_hashmap, (void *)"test1"); + if (bucket == NULL) { + CWS_LOG_DEBUG("test1 not found"); + } + cws_hm_free(str_hashmap); return 0;