diff --git a/src/command.c b/src/command.c index 9e0f929..d3aa4a0 100644 --- a/src/command.c +++ b/src/command.c @@ -127,17 +127,31 @@ int success_handler(const void *key, size_t size, uintptr_t val, void *usr) { return 0; } -int suggest_command(char *command, char *command_re, hashmap *polls, - char *name) { - char *invs = "/suggest "; - - char *page; - +char *handle_pages(char *command, char *invs) { if (strncmp(command, invs, strlen(invs)) == 0) { - page = &command[strlen(invs)]; + return &command[strlen(invs)]; } else { return 0; } +} + +int handle_pages_int(char *command, char *invs) { + if (strncmp(command, invs, strlen(invs)) == 0) { + return stoi(&command[strlen(invs)]); + } else if (strncmp(command, invs, strlen(invs) - 1) == 0) { + return 1; + } else { + return 0; + } +} + +int suggest_command(char *command, char *command_re, hashmap *polls, + char *name) { + + char *page = handle_pages(command, "/suggest "); + + if (!page) + return 0; page[strlen(page) - 1] = '\0'; if (strstr(page, "\n") || strstr(page, ";") || strstr(page, ",") || @@ -199,35 +213,21 @@ int suggest_command(char *command, char *command_re, hashmap *polls, } int help_command(char *command) { - char *invs = "/help"; + char *page = handle_pages(command, "/help"); - int page; - - if (strncmp(command, invs, strlen(invs)) == 0) { - - printf("Available " - "commands:\n- elem1;elem2...\n- elem1+elem2...\n- elem1,elem2...\n- " - "/help\n- /inv [page]\n- /suggest [combo]\n- /polls [page]\n"); - } else { + if (!page) return 0; - } - + printf("Available " + "commands:\n- elem1;elem2...\n- elem1+elem2...\n- elem1,elem2...\n- " + "/help\n- /inv [page]\n- /suggest [combo]\n- /polls [page]\n"); return 1; } int polls_command(char *command, hashmap *polls, hashmap *cmd) { - char *invs = "/polls "; - - int page; - - if (strncmp(command, invs, strlen(invs)) == 0) { - page = stoi(&command[strlen(invs)]); - } else if (strncmp(command, invs, strlen(invs) - 1) == 0) { - page = 1; - } else { + int page = handle_pages_int(command, "/polls "); + if (page == 0) return 0; - } printf("Current polls (page %i):\n", page); struct pager i = {.page = page - 1, .i = -1, .is_poll = 1, .cmd = cmd}; @@ -238,17 +238,9 @@ int polls_command(char *command, hashmap *polls, hashmap *cmd) { int slash_command(char *command, hashmap *inv) { - char *invs = "/inv "; - - int page; - - if (strncmp(command, invs, strlen(invs)) == 0) { - page = stoi(&command[strlen(invs)]); - } else if (strncmp(command, invs, strlen(invs) - 1) == 0) { - page = 1; - } else { + int page = handle_pages_int(command, "/inv "); + if (page == 0) return 0; - } printf("Your inventory (page %i):\n", page); struct pager i = {.page = page - 1, .i = -1, .is_poll = 0}; diff --git a/src/main.c b/src/main.c index 2ad9aa7..615b201 100644 --- a/src/main.c +++ b/src/main.c @@ -8,7 +8,7 @@ #include "main.h" -// todo: polls, help commands, spacing in combos, clean init_tables +// todo: spacing in combos, clean init_tables void init_tables(hashmap *elements, hashmap *inv, hashmap *polls, int do_inv) { load_elements(elements, "../elem_data/" combo_file, 0); diff --git a/src/map.c b/src/map.c index 5f362bd..6f0aad3 100644 --- a/src/map.c +++ b/src/map.c @@ -199,67 +199,6 @@ int hashmap_set(hashmap *m, const void *key, size_t ksize, uintptr_t val, return 0; } -int hashmap_get_set(hashmap *m, const void *key, size_t ksize, - uintptr_t *out_in) { - if (m->count + 1 > HASHMAP_MAX_LOAD * m->capacity) { - if (hashmap_resize(m) == -1) - return -1; - } - - uint32_t hash = hash_data(key, ksize); - struct bucket *entry = find_entry(m, key, ksize, hash); - if (entry->key == NULL) { - m->last->next = entry; - m->last = entry; - entry->next = NULL; - - ++m->count; - - entry->value = *out_in; - entry->key = key; - entry->ksize = ksize; - entry->hash = hash; - - return 0; - } - *out_in = entry->value; - return 1; -} - -int hashmap_set_free(hashmap *m, const void *key, size_t ksize, uintptr_t val, - hashmap_callback c, void *usr) { - if (m->count + 1 > HASHMAP_MAX_LOAD * m->capacity) { - if (hashmap_resize(m) == -1) - return -1; - } - - uint32_t hash = hash_data(key, ksize); - struct bucket *entry = find_entry(m, key, ksize, hash); - if (entry->key == NULL) { - m->last->next = entry; - m->last = entry; - entry->next = NULL; - - ++m->count; - - entry->key = key; - entry->ksize = ksize; - entry->hash = hash; - entry->value = val; - // there was no overwrite, exit the function. - return 0; - } - // allow the callback to free entry data. - // use old key and value so the callback can free them. - // the old key and value will be overwritten after this call. - int error = c(entry->key, ksize, entry->value, usr); - - // overwrite the old key pointer in case the callback frees it. - entry->key = key; - entry->value = val; - return error; -} - int hashmap_get(hashmap *m, const void *key, size_t ksize, uintptr_t *out_val) { uint32_t hash = hash_data(key, ksize); struct bucket *entry = find_entry(m, key, ksize, hash); @@ -270,40 +209,6 @@ int hashmap_get(hashmap *m, const void *key, size_t ksize, uintptr_t *out_val) { return entry->key != NULL ? 1 : 0; } -// doesn't "remove" the element per se, but it will be ignored. -// the element will eventually be removed when the map is resized. -void hashmap_remove(hashmap *m, const void *key, size_t ksize) { - uint32_t hash = hash_data(key, ksize); - struct bucket *entry = find_entry(m, key, ksize, hash); - - if (entry->key != NULL) { - - // "tombstone" entry is signified by a NULL key with a nonzero value - // element removal is optional because of the overhead of tombstone checks - entry->key = NULL; - entry->value = 0xDEAD; // I mean, it's a tombstone... - - ++m->tombstone_count; - } -} - -void hashmap_remove_free(hashmap *m, const void *key, size_t ksize, - hashmap_callback c, void *usr) { - uint32_t hash = hash_data(key, ksize); - struct bucket *entry = find_entry(m, key, ksize, hash); - - if (entry->key != NULL) { - c(entry->key, entry->ksize, entry->value, usr); - - // "tombstone" entry is signified by a NULL key with a nonzero value - // element removal is optional because of the overhead of tombstone checks - entry->key = NULL; - entry->value = 0xDEAD; // I mean, it's a tombstone... - - ++m->tombstone_count; - } -} - int hashmap_size(hashmap *m) { return m->count - m->tombstone_count; } int hashmap_iterate(hashmap *m, hashmap_callback c, void *user_ptr) { diff --git a/src/map.h b/src/map.h index 775b62d..ca305c8 100644 --- a/src/map.h +++ b/src/map.h @@ -11,10 +11,6 @@ #define hashmap_str_lit(str) (str), sizeof(str) - 1 #define hashmap_static_arr(arr) (arr), sizeof(arr) -// removal of map elements is disabled by default because of its slight -// overhead. if you want to enable this feature, uncomment the line below: -// #define __HASHMAP_REMOVABLE - #include #include @@ -44,69 +40,17 @@ struct hashmap { struct bucket *last; }; -// hashmaps can associate keys with pointer values or integral types. typedef struct hashmap hashmap; -// a callback type used for iterating over a map/freeing entries: -// `int (const void* key, size_t size, uintptr_t value, void* -// usr)` `usr` is a user pointer which can be passed through `hashmap_iterate`. typedef int (*hashmap_callback)(const void *key, size_t ksize, uintptr_t value, void *usr); hashmap *hashmap_create(void); - -// only frees the hashmap object and buckets. -// does not call free on each element's `key` or `value`. -// to free data associated with an element, call `hashmap_iterate`. void hashmap_free(hashmap *map); - -// does not make a copy of `key`. -// you must copy it yourself if you want to guarantee its lifetime, -// or if you intend to call `hashmap_key_free`. -// returns -1 on error. int hashmap_set(hashmap *map, const void *key, size_t ksize, uintptr_t value, int free_old); - -// adds an entry if it doesn't exist, using the value of `*out_in`. -// if it does exist, it sets value in `*out_in`, meaning the value -// of the entry will be in `*out_in` regardless of whether or not -// it existed in the first place. -// returns -1 on error. -// returns 1 if the entry already existed, returns 0 otherwise. -int hashmap_get_set(hashmap *map, const void *key, size_t ksize, - uintptr_t *out_in); - -// similar to `hashmap_set()`, but when overwriting an entry, -// you'll be able properly free the old entry's data via a callback. -// unlike `hashmap_set()`, this function will overwrite the original key -// pointer, which means you can free the old key in the callback if applicable. -int hashmap_set_free(hashmap *map, const void *key, size_t ksize, - uintptr_t value, hashmap_callback c, void *usr); - int hashmap_get(hashmap *map, const void *key, size_t ksize, uintptr_t *out_val); - -#ifdef __HASHMAP_REMOVABLE -void hashmap_remove(hashmap *map, const void *key, size_t ksize); - -// same as `hashmap_remove()`, but it allows you to free an entry's data first -// via a callback. -void hashmap_remove_free(hashmap *m, const void *key, size_t ksize, - hashmap_callback c, void *usr); -#endif - int hashmap_size(hashmap *map); - -// iterate over the map, calling `c` on every element. -// goes through elements in the order they were added. -// the element's key, key size, value, and `usr` will be passed to `c`. -// if `c` returns -1 the iteration is aborted. -// returns the last result of `c` int hashmap_iterate(hashmap *map, hashmap_callback c, void *usr); - -// dumps bucket info for debugging. -// allows you to see how many collisions you are getting. -// `0` is an empty bucket, `1` is occupied, and `x` is removed. -// void bucket_dump(hashmap *m); - #endif // map_h