From 97ec7166b7cfc1f8e9a95be7bf484b538d4f52d1 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Sat, 2 Sep 2017 12:37:34 -0700 Subject: [PATCH] libobs/util: Optimize strlist_* functions When splitting a string in to a string list via stringlist_split, it would previously allocate memory for each sub-string and again for the list itself. This optimizes that function to use a single contiguous chunk of memory for the sake of access optimization and memory allocation efficiency. --- libobs/util/dstr.c | 73 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/libobs/util/dstr.c b/libobs/util/dstr.c index ac56be716..97645045c 100644 --- a/libobs/util/dstr.c +++ b/libobs/util/dstr.c @@ -262,49 +262,78 @@ wchar_t *wcsdepad(wchar_t *str) char **strlist_split(const char *str, char split_ch, bool include_empty) { - const char *cur_str = str; - const char *next_str; - const char *new_str; - DARRAY(char*) list; - - da_init(list); + const char *cur_str = str; + const char *next_str; + char * out = NULL; + size_t count = 0; + size_t total_size = 0; if (str) { + char **table; + char *offset; + size_t cur_idx = 0; + size_t cur_pos = 0; + next_str = strchr(str, split_ch); while (next_str) { size_t size = next_str - cur_str; if (size || include_empty) { - new_str = bstrdup_n(cur_str, size); - da_push_back(list, &new_str); + ++count; + total_size += size + 1; } - cur_str = next_str+1; + cur_str = next_str + 1; next_str = strchr(cur_str, split_ch); } if (*cur_str || include_empty) { - new_str = bstrdup(cur_str); - da_push_back(list, &new_str); + ++count; + total_size += strlen(cur_str) + 1; } + + /* ------------------ */ + + cur_pos = (count + 1) * sizeof(char *); + total_size += cur_pos; + out = bmalloc(total_size); + offset = out + cur_pos; + table = (char **)out; + + /* ------------------ */ + + next_str = strchr(str, split_ch); + cur_str = str; + + while (next_str) { + size_t size = next_str - cur_str; + + if (size || include_empty) { + table[cur_idx++] = offset; + strncpy(offset, cur_str, size); + offset[size] = 0; + offset += size + 1; + } + + cur_str = next_str + 1; + next_str = strchr(cur_str, split_ch); + } + + if (*cur_str || include_empty) { + table[cur_idx++] = offset; + strcpy(offset, cur_str); + } + + table[cur_idx] = NULL; } - new_str = NULL; - da_push_back(list, &new_str); - - return list.array; + return (char**)out; } void strlist_free(char **strlist) { - if (strlist) { - char **temp = strlist; - while (*temp) - bfree(*(temp++)); - - bfree(strlist); - } + bfree(strlist); } void dstr_init_copy_strref(struct dstr *dst, const struct strref *src)