Merge pull request #12777 from jdgleaver/core-option-hash

Optimise core option/core option category look-ups using hash tables
This commit is contained in:
Autechre 2021-08-10 18:58:49 +02:00 committed by GitHub
commit 82e53d3db8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 27 deletions

View File

@ -597,6 +597,16 @@ void core_option_manager_free_converted(
/* Initialisation / De-Initialisation */ /* Initialisation / De-Initialisation */
/**************************************/ /**************************************/
/* Generates a hash key for the specified string */
static uint32_t core_option_manager_hash_string(const char *str)
{
unsigned char c;
uint32_t hash = (uint32_t)0x811c9dc5;
while ((c = (unsigned char)*(str++)) != '\0')
hash = ((hash * (uint32_t)0x01000193) ^ (uint32_t)c);
return (hash ? hash : 1);
}
/* Sanitises a core option value label, handling the case /* Sanitises a core option value label, handling the case
* where an explicit label is not provided and performing * where an explicit label is not provided and performing
* conversion of various true/false identifiers to * conversion of various true/false identifiers to
@ -677,7 +687,11 @@ static bool core_option_manager_parse_variable(
option->visible = true; option->visible = true;
if (!string_is_empty(var->key)) if (!string_is_empty(var->key))
{
option->key = strdup(var->key); option->key = strdup(var->key);
option->key_hash = core_option_manager_hash_string(var->key);
}
if (!string_is_empty(var->value)) if (!string_is_empty(var->value))
value = strdup(var->value); value = strdup(var->value);
@ -949,7 +963,8 @@ static bool core_option_manager_parse_option(
strstr(key, CORE_OPTION_MANAGER_MAP_DELIM)) strstr(key, CORE_OPTION_MANAGER_MAP_DELIM))
return false; return false;
option->key = strdup(key); option->key = strdup(key);
option->key_hash = core_option_manager_hash_string(key);
} }
/* Get number of values */ /* Get number of values */
@ -1130,11 +1145,12 @@ core_option_manager_t *core_option_manager_new(
!string_is_empty(option_cat->desc); !string_is_empty(option_cat->desc);
cats_size++, option_cat++) cats_size++, option_cat++)
{ {
opt->cats[cats_size].key = strdup(option_cat->key); opt->cats[cats_size].key = strdup(option_cat->key);
opt->cats[cats_size].desc = strdup(option_cat->desc); opt->cats[cats_size].key_hash = core_option_manager_hash_string(option_cat->key);
opt->cats[cats_size].desc = strdup(option_cat->desc);
if (!string_is_empty(option_cat->info)) if (!string_is_empty(option_cat->info))
opt->cats[cats_size].info = strdup(option_cat->info); opt->cats[cats_size].info = strdup(option_cat->info);
} }
} }
@ -1284,22 +1300,24 @@ void core_option_manager_free(core_option_manager_t *opt)
const char *core_option_manager_get_category_desc(core_option_manager_t *opt, const char *core_option_manager_get_category_desc(core_option_manager_t *opt,
const char *key) const char *key)
{ {
uint32_t key_hash;
size_t i; size_t i;
if (!opt || if (!opt ||
string_is_empty(key)) string_is_empty(key))
return NULL; return NULL;
key_hash = core_option_manager_hash_string(key);
for (i = 0; i < opt->cats_size; i++) for (i = 0; i < opt->cats_size; i++)
{ {
const char *cat_key = opt->cats[i].key; struct core_catagory *catagory = &opt->cats[i];
if (string_is_empty(cat_key)) if ((key_hash == catagory->key_hash) &&
continue; !string_is_empty(catagory->key) &&
string_is_equal(key, catagory->key))
if (string_is_equal(key, cat_key))
{ {
return opt->cats[i].desc; return catagory->desc;
} }
} }
@ -1323,22 +1341,24 @@ const char *core_option_manager_get_category_desc(core_option_manager_t *opt,
const char *core_option_manager_get_category_info(core_option_manager_t *opt, const char *core_option_manager_get_category_info(core_option_manager_t *opt,
const char *key) const char *key)
{ {
uint32_t key_hash;
size_t i; size_t i;
if (!opt || if (!opt ||
string_is_empty(key)) string_is_empty(key))
return NULL; return NULL;
key_hash = core_option_manager_hash_string(key);
for (i = 0; i < opt->cats_size; i++) for (i = 0; i < opt->cats_size; i++)
{ {
const char *cat_key = opt->cats[i].key; struct core_catagory *catagory = &opt->cats[i];
if (string_is_empty(cat_key)) if ((key_hash == catagory->key_hash) &&
continue; !string_is_empty(catagory->key) &&
string_is_equal(key, catagory->key))
if (string_is_equal(key, cat_key))
{ {
return opt->cats[i].info; return catagory->info;
} }
} }
@ -1423,6 +1443,7 @@ bool core_option_manager_get_category_visible(core_option_manager_t *opt,
bool core_option_manager_get_idx(core_option_manager_t *opt, bool core_option_manager_get_idx(core_option_manager_t *opt,
const char *key, size_t *idx) const char *key, size_t *idx)
{ {
uint32_t key_hash;
size_t i; size_t i;
if (!opt || if (!opt ||
@ -1430,14 +1451,15 @@ bool core_option_manager_get_idx(core_option_manager_t *opt,
!idx) !idx)
return false; return false;
key_hash = core_option_manager_hash_string(key);
for (i = 0; i < opt->size; i++) for (i = 0; i < opt->size; i++)
{ {
const char *opt_key = opt->opts[i].key; struct core_option *option = &opt->opts[i];
if (string_is_empty(opt_key)) if ((key_hash == option->key_hash) &&
continue; !string_is_empty(option->key) &&
string_is_equal(key, option->key))
if (string_is_equal(key, opt_key))
{ {
*idx = i; *idx = i;
return true; return true;
@ -1702,21 +1724,23 @@ void core_option_manager_set_default(core_option_manager_t *opt, size_t idx)
void core_option_manager_set_visible(core_option_manager_t *opt, void core_option_manager_set_visible(core_option_manager_t *opt,
const char *key, bool visible) const char *key, bool visible)
{ {
uint32_t key_hash;
size_t i; size_t i;
if (!opt || string_is_empty(key)) if (!opt || string_is_empty(key))
return; return;
key_hash = core_option_manager_hash_string(key);
for (i = 0; i < opt->size; i++) for (i = 0; i < opt->size; i++)
{ {
const char *opt_key = opt->opts[i].key; struct core_option *option = &opt->opts[i];
if (string_is_empty(opt_key)) if ((key_hash == option->key_hash) &&
continue; !string_is_empty(option->key) &&
string_is_equal(key, option->key))
if (string_is_equal(opt_key, key))
{ {
opt->opts[i].visible = visible; option->visible = visible;
return; return;
} }
} }

View File

@ -45,6 +45,7 @@ struct core_option
* option *value* indices */ * option *value* indices */
size_t default_index; size_t default_index;
size_t index; size_t index;
uint32_t key_hash;
bool visible; bool visible;
}; };
@ -53,6 +54,7 @@ struct core_catagory
char *key; char *key;
char *desc; char *desc;
char *info; char *info;
uint32_t key_hash;
}; };
/* TODO/FIXME: This struct should be made /* TODO/FIXME: This struct should be made