improve hash maps

This commit is contained in:
2025-05-03 18:01:50 +02:00
parent ad21ec0fa4
commit 8e880f59be
6 changed files with 88 additions and 9 deletions

View File

@@ -32,7 +32,7 @@ And then open the `docs/html/index.html`.
## Roadmap ## Roadmap
- Implement Keep-Alive - Implement Keep-Alive
- Support for virtual hosting - Support for virtual hosts
- HTTPS support with TLS - HTTPS support with TLS
## Future ## Future
@@ -41,3 +41,4 @@ And then open the `docs/html/index.html`.
- Multithreading to handle concurrent requests - Multithreading to handle concurrent requests
- Logging - Logging
- Compression (Gzip) - Compression (Gzip)
- Reverse proxy

View File

@@ -27,8 +27,6 @@
#define CWS_LOG_DEBUG(msg, ...) #define CWS_LOG_DEBUG(msg, ...)
#endif #endif
#define CWS_LOG(level, msg, ...)
#define CWS_LOG_ERROR(msg, ...) fprintf(stderr, _ERR " " msg "\n", ##__VA_ARGS__) #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_WARNING(msg, ...) fprintf(stdout, _WARNING " " msg "\n", ##__VA_ARGS__)
#define CWS_LOG_INFO(msg, ...) fprintf(stdout, _INFO " " msg "\n", ##__VA_ARGS__) #define CWS_LOG_INFO(msg, ...) fprintf(stdout, _INFO " " msg "\n", ##__VA_ARGS__)

View File

@@ -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); 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 * @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 #endif

View File

@@ -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); 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); char *cws_strip(char *str);
/* Functions used for hash maps */ /* Functions used for hash maps */

View File

@@ -57,6 +57,10 @@ void cws_hm_free(cws_hashmap *hashmap) {
} }
bool cws_hm_set(cws_hashmap *hashmap, void *key, void *value) { bool cws_hm_set(cws_hashmap *hashmap, void *key, void *value) {
if (hashmap == NULL || key == NULL || value == NULL) {
return false;
}
/* Get hash index */ /* Get hash index */
int index = hashmap->hash_fn(key) % CWS_HASHMAP_SIZE; int index = hashmap->hash_fn(key) % CWS_HASHMAP_SIZE;
cws_bucket *bucket = &hashmap->map[index]; 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) { cws_bucket *cws_hm_get(cws_hashmap *hashmap, void *key) {
/* Return if key is null */ /* Return if hash map or key is null */
if (key == NULL) { if (hashmap == NULL || key == NULL) {
return NULL; return NULL;
} }
int index = hashmap->hash_fn(key); int index = hashmap->hash_fn(key) % CWS_HASHMAP_SIZE;
cws_bucket *bucket = &hashmap->map[index]; cws_bucket *bucket = &hashmap->map[index];
/* Key is not in the hash map */ /* Key is not in the hash map */
if (bucket == NULL || bucket->key == NULL) { if (bucket->key == NULL) {
return NULL; return NULL;
} }
@@ -135,3 +139,56 @@ cws_bucket *cws_hm_get(cws_hashmap *hashmap, void *key) {
/* Key not found */ /* Key not found */
return NULL; 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;
}

View File

@@ -42,14 +42,17 @@ int main(void) {
return 1; return 1;
} }
/* Add a new key-value */
ret = cws_hm_set(str_hashmap, (void *)key, (void *)value); ret = cws_hm_set(str_hashmap, (void *)key, (void *)value);
if (!ret) { if (!ret) {
CWS_LOG_WARNING("Unable to set %s:%s", key, value); 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_bucket *bucket = cws_hm_get(str_hashmap, key);
CWS_LOG_DEBUG("Set %s:%s", (char *)bucket->key, (char *)bucket->value); CWS_LOG_DEBUG("Set %s:%s", (char *)bucket->key, (char *)bucket->value);
/* Update the value */
char *another_value = strdup("another value1"); char *another_value = strdup("another value1");
ret = cws_hm_set(str_hashmap, (void *)key, (void *)another_value); ret = cws_hm_set(str_hashmap, (void *)key, (void *)another_value);
if (!ret) { if (!ret) {
@@ -59,6 +62,17 @@ int main(void) {
bucket = cws_hm_get(str_hashmap, key); bucket = cws_hm_get(str_hashmap, key);
CWS_LOG_DEBUG("Set %s:%s", (char *)bucket->key, (char *)bucket->value); 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); cws_hm_free(str_hashmap);
return 0; return 0;