improve hash maps
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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__)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user