From e20de151ec8f4932b48e9303badee8811323a7b7 Mon Sep 17 00:00:00 2001 From: Vftdan Date: Tue, 30 Apr 2024 17:50:01 +0200 Subject: [PATCH] Replaced qsort by a lazy update of a bare-bones BST when using 'list' --- src/sfxd.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/src/sfxd.c b/src/sfxd.c index 1a6780d..01fb461 100644 --- a/src/sfxd.c +++ b/src/sfxd.c @@ -46,8 +46,13 @@ struct sfx_pool { float volume; float pitch_min, pitch_max; + + int bst_parent, bst_left, bst_right; + bool inside_bst; } *sounds; int cap, use; + + int bst_root; }; ssize_t send_data(struct msg_target tgt, const void *data, ssize_t len); @@ -69,7 +74,7 @@ struct sfx_pool_item *sfx_pool_load(const char *key, const char *path); struct ipc_data ipc = { 0 }; struct audio_data audio = { 0 }; -struct sfx_pool sounds_pool = { 0, 0, 0 }; +struct sfx_pool sounds_pool = { 0, 0, 0, .bst_root = -1 }; #ifndef NO_COUNTERS struct global_counters { @@ -82,10 +87,80 @@ struct global_counters { } global_counters = { 0 }; #endif -static int qsort_compare_index_of_key(const void *p1, const void *p2) { - struct sfx_pool_item *it1 = &sounds_pool.sounds[*(int *)p1]; - struct sfx_pool_item *it2 = &sounds_pool.sounds[*(int *)p2]; - return strcmp(it1->key, it2->key); +void sfx_pool_bst_insert(struct sfx_pool_item* lst, int *root_idx_ptr, int new_idx) { + // TODO balanced + struct sfx_pool_item *new_item = lst + new_idx; + int *new_idx_ptr = root_idx_ptr; + int parent_idx = -1; + int depth = 0; + + int next_parent_idx; + while ((next_parent_idx = *new_idx_ptr) >= 0) { + depth++; + parent_idx = next_parent_idx; + struct sfx_pool_item *parent_item = lst + parent_idx; + if (strcmp(new_item->key, parent_item->key) < 0) { + new_idx_ptr = &parent_item->bst_left; + } else { + new_idx_ptr = &parent_item->bst_right; + } + } + + *new_idx_ptr = new_idx; + new_item->bst_parent = parent_idx; + new_item->bst_left = -1; + new_item->bst_right = -1; + new_item->inside_bst = true; + send_txt((struct msg_target){ stdout, 0, 0, 0 }, "INF: Sorting element at index %d with key '%s' under the element at index %d with depth of %d\n", new_idx, lst[new_idx].key, parent_idx, depth); +} + +// We don't need deletion support + +void sfx_pool_bst_insert_all(struct sfx_pool_item *lst, int *root_idx_ptr, int size) { + for (int i = 0; i < size; i++) { + if (!lst[i].inside_bst && lst[i].key[0] != '\0') { + sfx_pool_bst_insert(lst, root_idx_ptr, i); + } + } +} + +int sfx_pool_bst_leftmost(const struct sfx_pool_item *lst, int parent_idx) { + if (parent_idx < 0) { + return parent_idx; + } + + int next_idx; + while ((next_idx = lst[parent_idx].bst_left) >= 0) { + parent_idx = next_idx; + } + return parent_idx; +} + +int sfx_pool_bst_go_right(const struct sfx_pool_item *lst, int cur_idx) { + if (cur_idx < 0) { + return cur_idx; + } + const struct sfx_pool_item *cur_item = lst + cur_idx; + if (cur_item->bst_right >= 0) { + return sfx_pool_bst_leftmost(lst, cur_item->bst_right); + } + + while (true) { + int parent_idx = cur_item->bst_parent; + if (parent_idx < 0) { + // We are a root => end iterator + return parent_idx; + } + + if (lst[parent_idx].bst_left == cur_idx) { + // We are a left child + return parent_idx; + } + + // We are a right child + cur_idx = parent_idx; + cur_item = lst + cur_idx; + } } void usage(int argc, char **argv) { @@ -331,18 +406,14 @@ void execute_command(struct msg_target tgt, const char *command, const char *par } } } else if (0 == strcmp(command, "list") || 0 == strcmp(command, "ls")) { - // TODO: find a better way to do this! - int *indices = calloc(sounds_pool.cap, sizeof(int)); - for (int i = 0; i < sounds_pool.cap; i++) indices[i] = i; - qsort(indices, sounds_pool.cap, sizeof(int), qsort_compare_index_of_key); - for (int i = 0; i < sounds_pool.cap; i++) { - struct sfx_pool_item *item = &sounds_pool.sounds[indices[i]]; + sfx_pool_bst_insert_all(sounds_pool.sounds, &sounds_pool.bst_root, sounds_pool.cap); + for (int i = sfx_pool_bst_leftmost(sounds_pool.sounds, sounds_pool.bst_root); i >= 0; i = sfx_pool_bst_go_right(sounds_pool.sounds, i)) { + struct sfx_pool_item *item = &sounds_pool.sounds[i]; if (item->key[0] == '\0') continue; if (0 == fnmatch(params, item->key, 0) || strlen(params) == 0) { send_txt(tgt, "%s\n", item->key); } } - free(indices); } else if (0 == strcmp(command, "source")) { if (strlen(params) == 0) { send_txt(tgt, "ERR: argument required: PATH\n");