Replaced qsort by a lazy update of a bare-bones BST when using 'list'

This commit is contained in:
Vftdan 2024-04-30 17:50:01 +02:00
parent 11fc655bb7
commit e20de151ec
1 changed files with 83 additions and 12 deletions

View File

@ -46,8 +46,13 @@ struct sfx_pool {
float volume; float volume;
float pitch_min, pitch_max; float pitch_min, pitch_max;
int bst_parent, bst_left, bst_right;
bool inside_bst;
} *sounds; } *sounds;
int cap, use; int cap, use;
int bst_root;
}; };
ssize_t send_data(struct msg_target tgt, const void *data, ssize_t len); 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 ipc_data ipc = { 0 };
struct audio_data audio = { 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 #ifndef NO_COUNTERS
struct global_counters { struct global_counters {
@ -82,10 +87,80 @@ struct global_counters {
} global_counters = { 0 }; } global_counters = { 0 };
#endif #endif
static int qsort_compare_index_of_key(const void *p1, const void *p2) { void sfx_pool_bst_insert(struct sfx_pool_item* lst, int *root_idx_ptr, int new_idx) {
struct sfx_pool_item *it1 = &sounds_pool.sounds[*(int *)p1]; // TODO balanced
struct sfx_pool_item *it2 = &sounds_pool.sounds[*(int *)p2]; struct sfx_pool_item *new_item = lst + new_idx;
return strcmp(it1->key, it2->key); 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) { 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")) { } else if (0 == strcmp(command, "list") || 0 == strcmp(command, "ls")) {
// TODO: find a better way to do this! sfx_pool_bst_insert_all(sounds_pool.sounds, &sounds_pool.bst_root, sounds_pool.cap);
int *indices = calloc(sounds_pool.cap, sizeof(int)); 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)) {
for (int i = 0; i < sounds_pool.cap; i++) indices[i] = i; struct sfx_pool_item *item = &sounds_pool.sounds[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]];
if (item->key[0] == '\0') continue; if (item->key[0] == '\0') continue;
if (0 == fnmatch(params, item->key, 0) || strlen(params) == 0) { if (0 == fnmatch(params, item->key, 0) || strlen(params) == 0) {
send_txt(tgt, "%s\n", item->key); send_txt(tgt, "%s\n", item->key);
} }
} }
free(indices);
} else if (0 == strcmp(command, "source")) { } else if (0 == strcmp(command, "source")) {
if (strlen(params) == 0) { if (strlen(params) == 0) {
send_txt(tgt, "ERR: argument required: PATH\n"); send_txt(tgt, "ERR: argument required: PATH\n");