diff --git a/headers/hashtable.h b/headers/hashtable.h index 7845391..4545c9a 100644 --- a/headers/hashtable.h +++ b/headers/hashtable.h @@ -24,12 +24,11 @@ struct HashTable { }; uint64_t hash(char *key); -struct HashTable *create_hashtable(uint64_t default_size, double grow_factor); +struct HashTable *create_hashtable(uint32_t default_size, double grow_factor); struct FVPair *get_fv_from_hashtable(struct HashTable *table, char *name); void free_hashtable(struct HashTable *table); -void set_fv_value(struct FVPair *pair, void *value); -void free_fv(struct FVPair *pair); +void set_fv_value(struct FVPair *fv, void *value); +void free_fv(struct FVPair *fv); -// void grow_hashtable(struct HashTable *table); -void set_fv_of_hashtable(struct HashTable *table, char *name, void *value, enum TellyTypes type); +void add_fv_to_hashtable(struct HashTable *table, char *name, void *value, enum TellyTypes type); diff --git a/src/commands/hashtable/hlen.c b/src/commands/hashtable/hlen.c index e5a83fd..0d45de7 100644 --- a/src/commands/hashtable/hlen.c +++ b/src/commands/hashtable/hlen.c @@ -2,6 +2,7 @@ #include "../../../headers/database.h" #include "../../../headers/commands.h" #include "../../../headers/hashtable.h" +#include "../../../headers/utils.h" #include #include @@ -15,18 +16,35 @@ static void run(struct Client *client, respdata_t *data) { const char *key = data->value.array[1]->value.string.value; const struct KVPair *kv = get_data(key); - const uint64_t count = (kv && kv->type == TELLY_HASHTABLE) ? kv->value->hashtable->size.all : 0; - const uint32_t buf_len = 3 + get_digit_count(count); - char buf[buf_len + 1]; - sprintf(buf, ":%ld\r\n", count); - _write(client, buf, buf_len); + if (kv) { + if (kv->type == TELLY_HASHTABLE) { + struct HashTable *table = kv->value->hashtable; + + const uint32_t buf_len = 59 + get_digit_count(table->size.allocated) + + get_digit_count(table->size.filled) + get_digit_count(table->size.all); + + char buf[buf_len + 1]; + sprintf(buf, ( + "*3\r\n" + "+Allocated: %d\r\n" + "+Filled: %d\r\n" + "+All (includes next count): %d\r\n" + ), table->size.allocated, table->size.filled, table->size.all); + + _write(client, buf, buf_len); + } else { + _write(client, "-Invalid type for 'HLEN' command\r\n", 34); + } + } else { + _write(client, "$-1\r\n", 5); + } } } struct Command cmd_hlen = { .name = "HLEN", - .summary = "Returns field count of the hash table for the key.", + .summary = "Returns field count information of the hash table for the key.", .since = "0.1.3", .complexity = "O(1)", .subcommands = NULL, diff --git a/src/commands/hashtable/hset.c b/src/commands/hashtable/hset.c index 0de50aa..1f2f726 100644 --- a/src/commands/hashtable/hset.c +++ b/src/commands/hashtable/hset.c @@ -22,7 +22,7 @@ static void run(struct Client *client, respdata_t *data) { if (kv && kv->type == TELLY_HASHTABLE) { table = kv->value->hashtable; } else { - table = create_hashtable(32, 0.6); + table = create_hashtable(16, 0.5); set_data(kv, key, (value_t) { .hashtable = table }, TELLY_HASHTABLE); @@ -38,13 +38,13 @@ static void run(struct Client *client, respdata_t *data) { if (is_integer(value)) { int value_as_int = atoi(value); - set_fv_of_hashtable(table, name, &value_as_int, TELLY_INT); + add_fv_to_hashtable(table, name, &value_as_int, TELLY_INT); } else if (is_true || streq(value, "false")) { - set_fv_of_hashtable(table, name, &is_true, TELLY_BOOL); + add_fv_to_hashtable(table, name, &is_true, TELLY_BOOL); } else if (streq(value, "null")) { - set_fv_of_hashtable(table, name, NULL, TELLY_NULL); + add_fv_to_hashtable(table, name, NULL, TELLY_NULL); } else { - set_fv_of_hashtable(table, name, value, TELLY_STR); + add_fv_to_hashtable(table, name, value, TELLY_STR); } } diff --git a/src/hashtable/grow.c b/src/hashtable/grow.c index 761886d..6103a6e 100644 --- a/src/hashtable/grow.c +++ b/src/hashtable/grow.c @@ -1,16 +1,42 @@ #include "../../headers/hashtable.h" #include "../../headers/utils.h" -#include #include #include #include #include -void set_fv_of_hashtable(struct HashTable *table, char *name, void *value, enum TellyTypes type) { - // if (table->size.filled == table->size.allocated) grow_hashtable(table); +void grow_hashtable(struct HashTable *table) { + const uint32_t allocated_size = (table->size.allocated * (1 + table->grow_factor)); + struct FVPair **fvs = calloc(allocated_size, sizeof(struct FVPair *)); + table->size.filled = 0; - const uint64_t index = hash(name) % table->size.allocated; + for (uint32_t i = 0; i < table->size.allocated; ++i) { + struct FVPair *fv = table->fvs[i]; + + while (fv) { + struct FVPair *next = fv->next; + fv->next = NULL; + const uint32_t index = hash(fv->name.value) % allocated_size; + struct FVPair **area = &fvs[index]; + + if (!*area) table->size.filled += 1; + while (*area) area = &(*area)->next; + + *area = fv; + fv = next; + } + } + + free(table->fvs); + table->size.allocated = allocated_size; + table->fvs = fvs; +} + +void add_fv_to_hashtable(struct HashTable *table, char *name, void *value, enum TellyTypes type) { + if (table->size.filled == table->size.allocated) grow_hashtable(table); + + const uint32_t index = hash(name) % table->size.allocated; table->size.all += 1; table->size.filled += 1; diff --git a/src/hashtable/hashtable.c b/src/hashtable/hashtable.c index edcc2c0..79c67f9 100644 --- a/src/hashtable/hashtable.c +++ b/src/hashtable/hashtable.c @@ -9,11 +9,10 @@ uint64_t hash(char *key) { char c; while ((c = *key++)) hash = ((hash << 5) + hash) + c; - - return 8; + return hash; } -struct HashTable *create_hashtable(uint64_t default_size, double grow_factor) { +struct HashTable *create_hashtable(const uint32_t default_size, const double grow_factor) { struct HashTable *table = malloc(sizeof(struct HashTable)); table->fvs = calloc(default_size, sizeof(struct FVPair *)); table->size.allocated = default_size; @@ -25,7 +24,7 @@ struct HashTable *create_hashtable(uint64_t default_size, double grow_factor) { } struct FVPair *get_fv_from_hashtable(struct HashTable *table, char *name) { - const uint64_t index = hash(name) % table->size.allocated; + const uint32_t index = hash(name) % table->size.allocated; struct FVPair *fv = table->fvs[index]; while (fv && !streq(fv->name.value, name)) fv = fv->next; @@ -33,9 +32,9 @@ struct FVPair *get_fv_from_hashtable(struct HashTable *table, char *name) { } void free_hashtable(struct HashTable *table) { - const uint64_t allocated_size = table->size.allocated; + const uint32_t allocated_size = table->size.allocated; - for (uint64_t i = 0; i < allocated_size; ++i) { + for (uint32_t i = 0; i < allocated_size; ++i) { struct FVPair *fv = table->fvs[i]; while (fv) { diff --git a/src/utils/value.c b/src/utils/value.c index 7c15071..050a28d 100644 --- a/src/utils/value.c +++ b/src/utils/value.c @@ -3,7 +3,6 @@ #include #include -#include void write_value(struct Client *client, value_t value, enum TellyTypes type) { switch (type) { @@ -42,11 +41,11 @@ void write_value(struct Client *client, value_t value, enum TellyTypes type) { break; case TELLY_HASHTABLE: - _write(client, "+a hash table\r\n", 15); + _write(client, "+hash table\r\n", 13); break; case TELLY_LIST: - _write(client, "+a list\r\n", 9); + _write(client, "+list\r\n", 9); break; default: