mirror of
https://github.com/libretro/RetroArch
synced 2025-03-02 19:13:34 +00:00
Merge pull request #12295 from jdgleaver/config-file-hash-map
This commit is contained in:
commit
7a5559aba0
libretro-common
@ -39,6 +39,7 @@
|
||||
#include <file/file_path.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <array/rhmap.h>
|
||||
|
||||
#define MAX_INCLUDE_DEPTH 16
|
||||
|
||||
@ -48,6 +49,15 @@ struct config_include_list
|
||||
struct config_include_list *next;
|
||||
};
|
||||
|
||||
static uint32_t config_file_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);
|
||||
}
|
||||
|
||||
/* Forward declaration */
|
||||
static bool config_file_parse_line(config_file_t *conf,
|
||||
struct config_entry_list *list, char *line, config_file_cb_t *cb);
|
||||
@ -273,6 +283,8 @@ static char *config_file_extract_value(char *line, bool is_value)
|
||||
static void config_file_add_child_list(config_file_t *parent, config_file_t *child)
|
||||
{
|
||||
struct config_entry_list *list = child->entries;
|
||||
bool merge_hash_map = false;
|
||||
|
||||
if (parent->entries)
|
||||
{
|
||||
struct config_entry_list *head = parent->entries;
|
||||
@ -286,6 +298,8 @@ static void config_file_add_child_list(config_file_t *parent, config_file_t *chi
|
||||
list = list->next;
|
||||
}
|
||||
head->next = child->entries;
|
||||
|
||||
merge_hash_map = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -298,8 +312,6 @@ static void config_file_add_child_list(config_file_t *parent, config_file_t *chi
|
||||
parent->entries = child->entries;
|
||||
}
|
||||
|
||||
child->entries = NULL;
|
||||
|
||||
/* Rebase tail. */
|
||||
if (parent->entries)
|
||||
{
|
||||
@ -312,6 +324,44 @@ static void config_file_add_child_list(config_file_t *parent, config_file_t *chi
|
||||
}
|
||||
else
|
||||
parent->tail = NULL;
|
||||
|
||||
/* Update hash map */
|
||||
if (merge_hash_map)
|
||||
{
|
||||
size_t i;
|
||||
size_t cap;
|
||||
|
||||
/* We are merging two lists - if any child entry
|
||||
* (key) is not present in the parent list, add it
|
||||
* to the parent hash map */
|
||||
for (i = 0, cap = RHMAP_CAP(child->entries_map); i != cap; i++)
|
||||
{
|
||||
uint32_t child_hash = RHMAP_KEY(child->entries_map, i);
|
||||
|
||||
if (!RHMAP_HAS(parent->entries_map, child_hash))
|
||||
{
|
||||
struct config_entry_list *entry =
|
||||
RHMAP_GET(child->entries_map, child_hash);
|
||||
|
||||
if (entry)
|
||||
RHMAP_SET(parent->entries_map, child_hash, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/* Child entries map is no longer required,
|
||||
* so free it now */
|
||||
RHMAP_FREE(child->entries_map);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If parent list was originally empty,
|
||||
* take map from child list */
|
||||
RHMAP_FREE(parent->entries_map);
|
||||
parent->entries_map = child->entries_map;
|
||||
child->entries_map = NULL;
|
||||
}
|
||||
|
||||
child->entries = NULL;
|
||||
}
|
||||
|
||||
static void config_file_get_realpath(char *s, size_t len,
|
||||
@ -426,8 +476,21 @@ static int config_file_load_internal(
|
||||
|
||||
conf->tail = list;
|
||||
|
||||
if (cb && list->key && list->value)
|
||||
cb->config_file_new_entry_cb(list->key, list->value) ;
|
||||
if (list->key)
|
||||
{
|
||||
/* Only add entry to the map if an entry
|
||||
* with the specified value does not
|
||||
* already exist */
|
||||
uint32_t hash = config_file_hash_string(list->key);
|
||||
|
||||
if (!RHMAP_HAS(conf->entries_map, hash))
|
||||
{
|
||||
RHMAP_SET(conf->entries_map, hash, list);
|
||||
|
||||
if (cb && list->value)
|
||||
cb->config_file_new_entry_cb(list->key, list->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(line);
|
||||
@ -628,6 +691,16 @@ static int config_file_from_string_internal(
|
||||
conf->entries = list;
|
||||
|
||||
conf->tail = list;
|
||||
|
||||
if (list->key)
|
||||
{
|
||||
/* Only add entry to the map if an entry
|
||||
* with the specified value does not
|
||||
* already exist */
|
||||
uint32_t hash = config_file_hash_string(list->key);
|
||||
if (!RHMAP_HAS(conf->entries_map, hash))
|
||||
RHMAP_SET(conf->entries_map, hash, list);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != conf->tail)
|
||||
@ -705,6 +778,9 @@ bool config_file_deinitialize(config_file_t *conf)
|
||||
|
||||
if (conf->path)
|
||||
free(conf->path);
|
||||
|
||||
RHMAP_FREE(conf->entries_map);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -718,9 +794,22 @@ void config_file_free(config_file_t *conf)
|
||||
bool config_append_file(config_file_t *conf, const char *path)
|
||||
{
|
||||
config_file_t *new_conf = config_file_new_from_path_to_string(path);
|
||||
size_t i;
|
||||
size_t cap;
|
||||
|
||||
if (!new_conf)
|
||||
return false;
|
||||
|
||||
/* Update hash map */
|
||||
for (i = 0, cap = RHMAP_CAP(new_conf->entries_map); i != cap; i++)
|
||||
{
|
||||
uint32_t new_hash = RHMAP_KEY(new_conf->entries_map, i);
|
||||
struct config_entry_list *entry = RHMAP_GET(new_conf->entries_map, new_hash);
|
||||
|
||||
if (entry)
|
||||
RHMAP_SET(conf->entries_map, new_hash, entry);
|
||||
}
|
||||
|
||||
if (new_conf->tail)
|
||||
{
|
||||
new_conf->tail->next = conf->entries;
|
||||
@ -818,6 +907,7 @@ void config_file_initialize(struct config_file *conf)
|
||||
return;
|
||||
|
||||
conf->path = NULL;
|
||||
conf->entries_map = NULL;
|
||||
conf->entries = NULL;
|
||||
conf->tail = NULL;
|
||||
conf->last = NULL;
|
||||
@ -844,16 +934,18 @@ static struct config_entry_list *config_get_entry_internal(
|
||||
struct config_entry_list *entry = NULL;
|
||||
struct config_entry_list *previous = prev ? *prev : NULL;
|
||||
|
||||
for (entry = conf->entries; entry; entry = entry->next)
|
||||
{
|
||||
if (string_is_equal(key, entry->key))
|
||||
return entry;
|
||||
entry = RHMAP_GET(conf->entries_map, config_file_hash_string(key));
|
||||
|
||||
previous = entry;
|
||||
}
|
||||
if (entry)
|
||||
return entry;
|
||||
|
||||
if (prev)
|
||||
{
|
||||
for (entry = conf->entries; entry; entry = entry->next)
|
||||
previous = entry;
|
||||
|
||||
*prev = previous;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -861,16 +953,9 @@ static struct config_entry_list *config_get_entry_internal(
|
||||
struct config_entry_list *config_get_entry(
|
||||
const config_file_t *conf, const char *key)
|
||||
{
|
||||
struct config_entry_list *entry = NULL;
|
||||
for (entry = conf->entries; entry; entry = entry->next)
|
||||
{
|
||||
if (string_is_equal(key, entry->key))
|
||||
return entry;
|
||||
}
|
||||
return NULL;
|
||||
return RHMAP_GET(conf->entries_map, config_file_hash_string(key));
|
||||
}
|
||||
|
||||
|
||||
bool config_get_double(config_file_t *conf, const char *key, double *in)
|
||||
{
|
||||
const struct config_entry_list *entry = config_get_entry(conf, key);
|
||||
@ -1141,6 +1226,8 @@ void config_set_string(config_file_t *conf, const char *key, const char *val)
|
||||
conf->entries = entry;
|
||||
|
||||
conf->last = entry;
|
||||
|
||||
RHMAP_SET(conf->entries_map, config_file_hash_string(entry->key), entry);
|
||||
}
|
||||
|
||||
void config_unset(config_file_t *conf, const char *key)
|
||||
@ -1157,6 +1244,8 @@ void config_unset(config_file_t *conf, const char *key)
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
(void)RHMAP_DEL(conf->entries_map, config_file_hash_string(entry->key));
|
||||
|
||||
if (entry->key)
|
||||
free(entry->key);
|
||||
|
||||
@ -1376,16 +1465,7 @@ void config_file_dump(config_file_t *conf, FILE *file, bool sort)
|
||||
|
||||
bool config_entry_exists(config_file_t *conf, const char *entry)
|
||||
{
|
||||
struct config_entry_list *list = conf->entries;
|
||||
|
||||
while (list)
|
||||
{
|
||||
if (string_is_equal(entry, list->key))
|
||||
return true;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
return (bool)RHMAP_HAS(conf->entries_map, config_file_hash_string(entry));
|
||||
}
|
||||
|
||||
bool config_get_entry_list_head(config_file_t *conf,
|
||||
|
@ -55,6 +55,7 @@ struct config_file
|
||||
{
|
||||
char *path;
|
||||
char *reference;
|
||||
struct config_entry_list **entries_map;
|
||||
struct config_entry_list *entries;
|
||||
struct config_entry_list *tail;
|
||||
struct config_entry_list *last;
|
||||
|
Loading…
x
Reference in New Issue
Block a user