From 3e51422534f81fcc3178bb9516567ed0b15b8618 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Fri, 27 Sep 2024 23:38:51 +0200 Subject: [PATCH] enum-map: rewrite to use uthash --- include/libtrx/config/file.h | 7 +- include/libtrx/config/map.h | 4 +- include/libtrx/enum_map.h | 25 ++++++++ include/libtrx/enum_str.h | 23 ------- include/libtrx/game/objects/ids.def | 5 ++ include/libtrx/game/objects/ids.h | 6 +- meson.build | 2 +- src/config/file.c | 29 +++------ src/enum_map.c | 99 +++++++++++++++++++++++++++++ src/enum_str.c | 16 ----- src/game/console/cmd/config.c | 23 +++---- 11 files changed, 154 insertions(+), 85 deletions(-) create mode 100644 include/libtrx/enum_map.h delete mode 100644 include/libtrx/enum_str.h create mode 100644 include/libtrx/game/objects/ids.def create mode 100644 src/enum_map.c delete mode 100644 src/enum_str.c diff --git a/include/libtrx/config/file.h b/include/libtrx/config/file.h index 2ee98ed..e900273 100644 --- a/include/libtrx/config/file.h +++ b/include/libtrx/config/file.h @@ -1,6 +1,6 @@ #pragma once -#include "../enum_str.h" +#include "../enum_map.h" #include "../json.h" #include "./option.h" @@ -17,7 +17,6 @@ void ConfigFile_DumpOptions( int ConfigFile_ReadEnum( JSON_OBJECT *obj, const char *name, int default_value, - const ENUM_STRING_MAP *enum_map); + const char *enum_name); void ConfigFile_WriteEnum( - JSON_OBJECT *obj, const char *name, int value, - const ENUM_STRING_MAP *enum_map); + JSON_OBJECT *obj, const char *name, int value, const char *enum_name); diff --git a/include/libtrx/config/map.h b/include/libtrx/config/map.h index d48b55d..4444c52 100644 --- a/include/libtrx/config/map.h +++ b/include/libtrx/config/map.h @@ -1,4 +1,4 @@ -#include "../enum_str.h" +#include "../enum_map.h" #include "../utils.h" #include "./option.h" @@ -39,4 +39,4 @@ .type = COT_ENUM, \ .target = &parent.target_, \ .default_value = &(int32_t) { default_value_ }, \ - .param = ENUM_STRING_MAP(enum_map) }, + .param = ENUM_MAP_NAME(enum_map) }, diff --git a/include/libtrx/enum_map.h b/include/libtrx/enum_map.h new file mode 100644 index 0000000..d0fecff --- /dev/null +++ b/include/libtrx/enum_map.h @@ -0,0 +1,25 @@ +#include + +#define ENUM_MAP_DEFINE(enum_name, enum_value, str_value) \ + EnumMap_Define(ENUM_MAP_NAME(enum_name), enum_value, str_value); +#define ENUM_MAP_DEFINE_SELF(enum_name, enum_value) \ + EnumMap_Define(ENUM_MAP_NAME(enum_name), enum_value, #enum_value); + +#define ENUM_MAP_GET(enum_name, str_value, default_value) \ + EnumMap_Get(ENUM_MAP_NAME(enum_name), str_value, default_value) + +#define ENUM_MAP_TO_STRING(enum_name, enum_value) \ + EnumMap_ToString(ENUM_MAP_NAME(enum_name), enum_value) + +#define ENUM_MAP_NAME(enum_name) #enum_name + +// The function to put the EnumMap_Define calls in +extern void EnumMap_Init(void); + +void EnumMap_Shutdown(void); + +void EnumMap_Define( + const char *enum_name, int32_t enum_value, const char *str_value); +int32_t EnumMap_Get( + const char *enum_name, const char *str_value, int32_t default_value); +const char *EnumMap_ToString(const char *enum_name, int32_t enum_value); diff --git a/include/libtrx/enum_str.h b/include/libtrx/enum_str.h deleted file mode 100644 index 221c854..0000000 --- a/include/libtrx/enum_str.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -typedef struct { - const char *text; - int value; -} ENUM_STRING_MAP; - -#define ENUM_SELF(type) { #type, type } -#define ENUM_STRING_MAP(type) g_EnumStr_##type - -#ifdef ENUM_STR_IMPL - #define DECLARE_ENUM_STRING_MAP(type, ...) \ - const ENUM_STRING_MAP g_EnumStr_##type[] = { __VA_ARGS__ { NULL, -1 } }; -#else - #define DECLARE_ENUM_STRING_MAP(type, ...) \ - extern const ENUM_STRING_MAP g_EnumStr_##type[]; -#endif - -#define ENUM_STRING_GET(type, key, default_value) \ - EnumStr_GetImpl(ENUM_STRING_MAP(type), (key), (default_value)) - -int EnumStr_GetImpl( - const ENUM_STRING_MAP *enum_map, const char *key, int default_value); diff --git a/include/libtrx/game/objects/ids.def b/include/libtrx/game/objects/ids.def new file mode 100644 index 0000000..0d9a7fb --- /dev/null +++ b/include/libtrx/game/objects/ids.def @@ -0,0 +1,5 @@ +#if TR_VERSION == 1 + #include "./ids_tr1.def" +#elif TR_VERSION == 2 + #include "./ids_tr2.def" +#endif diff --git a/include/libtrx/game/objects/ids.h b/include/libtrx/game/objects/ids.h index 126e4f4..1e73690 100644 --- a/include/libtrx/game/objects/ids.h +++ b/include/libtrx/game/objects/ids.h @@ -3,10 +3,6 @@ typedef enum { NO_OBJECT = -1, #define OBJ_ID_DEFINE(object_id, enum_value) object_id = enum_value, -#if TR_VERSION == 1 - #include "./ids_tr1.def" -#elif TR_VERSION == 2 - #include "./ids_tr2.def" -#endif +#include "./ids.def" O_NUMBER_OF, } GAME_OBJECT_ID; diff --git a/meson.build b/meson.build index 71a5d25..96b8981 100644 --- a/meson.build +++ b/meson.build @@ -65,7 +65,7 @@ sources = [ 'src/engine/audio_sample.c', 'src/engine/audio_stream.c', 'src/engine/image.c', - 'src/enum_str.c', + 'src/enum_map.c', 'src/event_manager.c', 'src/filesystem.c', 'src/game/backpack.c', diff --git a/src/config/file.c b/src/config/file.c index 84acb54..096b3be 100644 --- a/src/config/file.c +++ b/src/config/file.c @@ -135,8 +135,7 @@ void ConfigFile_LoadOptions(JSON_OBJECT *root_obj, const CONFIG_OPTION *options) case COT_ENUM: *(int *)opt->target = ConfigFile_ReadEnum( root_obj, M_ResolveOptionName(opt->name), - *(int *)opt->default_value, - (const ENUM_STRING_MAP *)opt->param); + *(int *)opt->default_value, opt->param); } opt++; } @@ -173,7 +172,7 @@ void ConfigFile_DumpOptions(JSON_OBJECT *root_obj, const CONFIG_OPTION *options) case COT_ENUM: ConfigFile_WriteEnum( root_obj, M_ResolveOptionName(opt->name), *(int *)opt->target, - (const ENUM_STRING_MAP *)opt->param); + (const char *)opt->param); break; } opt++; @@ -181,30 +180,18 @@ void ConfigFile_DumpOptions(JSON_OBJECT *root_obj, const CONFIG_OPTION *options) } int ConfigFile_ReadEnum( - JSON_OBJECT *obj, const char *name, int default_value, - const ENUM_STRING_MAP *enum_map) + JSON_OBJECT *const obj, const char *const name, const int default_value, + const char *const enum_name) { const char *value_str = JSON_ObjectGetString(obj, name, NULL); - if (value_str) { - while (enum_map->text) { - if (!strcmp(value_str, enum_map->text)) { - return enum_map->value; - } - enum_map++; - } + if (value_str != NULL) { + return EnumMap_Get(enum_name, value_str, default_value); } return default_value; } void ConfigFile_WriteEnum( - JSON_OBJECT *obj, const char *name, int value, - const ENUM_STRING_MAP *enum_map) + JSON_OBJECT *obj, const char *name, int value, const char *enum_name) { - while (enum_map->text) { - if (enum_map->value == value) { - JSON_ObjectAppendString(obj, name, enum_map->text); - break; - } - enum_map++; - } + JSON_ObjectAppendString(obj, name, EnumMap_ToString(enum_name, value)); } diff --git a/src/enum_map.c b/src/enum_map.c new file mode 100644 index 0000000..ce61027 --- /dev/null +++ b/src/enum_map.c @@ -0,0 +1,99 @@ +#include "enum_map.h" + +#include "memory.h" + +#include +#include + +typedef struct { + char *key; + int32_t value; + UT_hash_handle hh; +} M_ENTRY; + +typedef struct { + char *key; + char *str_value; + UT_hash_handle hh; +} M_INVERSE_ENTRY; + +static M_ENTRY *m_Map = NULL; +static M_INVERSE_ENTRY *m_InverseMap = NULL; + +void EnumMap_Define( + const char *const enum_name, const int32_t enum_value, + const char *const str_value) +{ + { + const size_t key_len = strlen(enum_name) + strlen(str_value) + 2; + char *const key = Memory_Alloc(key_len); + snprintf(key, key_len, "%s|%s", enum_name, str_value); + + M_ENTRY *const entry = Memory_Alloc(sizeof(M_ENTRY)); + entry->key = key; + entry->value = enum_value; + HASH_ADD_KEYPTR(hh, m_Map, entry->key, strlen(entry->key), entry); + } + + { + const size_t key_len = + snprintf(NULL, 0, "%s|%d", enum_name, enum_value) + 1; + char *const key = Memory_Alloc(key_len); + snprintf(key, key_len, "%s|%d", enum_name, enum_value); + + M_INVERSE_ENTRY *const entry = Memory_Alloc(sizeof(M_INVERSE_ENTRY)); + entry->key = key; + entry->str_value = Memory_DupStr(str_value); + HASH_ADD_KEYPTR( + hh, m_InverseMap, entry->key, strlen(entry->key), entry); + } +} + +int32_t EnumMap_Get( + const char *const enum_name, const char *const str_value, + int32_t default_value) +{ + size_t key_len = strlen(enum_name) + strlen(str_value) + 2; + char key[key_len]; + snprintf(key, key_len, "%s|%s", enum_name, str_value); + + M_ENTRY *entry; + HASH_FIND_STR(m_Map, key, entry); + return entry != NULL ? entry->value : default_value; +} + +const char *EnumMap_ToString( + const char *const enum_name, const int32_t enum_value) +{ + size_t key_len = snprintf(NULL, 0, "%s|%d", enum_name, enum_value) + 1; + char key[key_len]; + snprintf(key, key_len, "%s|%d", enum_name, enum_value); + + M_INVERSE_ENTRY *entry; + HASH_FIND_STR(m_InverseMap, key, entry); + return entry != NULL ? entry->str_value : NULL; +} + +void EnumMap_Shutdown(void) +{ + { + M_ENTRY *current, *tmp; + HASH_ITER(hh, m_Map, current, tmp) + { + HASH_DEL(m_Map, current); + Memory_Free(current->key); + Memory_Free(current); + } + } + + { + M_INVERSE_ENTRY *current, *tmp; + HASH_ITER(hh, m_InverseMap, current, tmp) + { + HASH_DEL(m_InverseMap, current); + Memory_Free(current->str_value); + Memory_Free(current->key); + Memory_Free(current); + } + } +} diff --git a/src/enum_str.c b/src/enum_str.c deleted file mode 100644 index e8aa667..0000000 --- a/src/enum_str.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "enum_str.h" - -#include - -int EnumStr_GetImpl( - const ENUM_STRING_MAP *enum_map, const char *const key, - const int default_value) -{ - while (enum_map->text) { - if (!strcmp(key, enum_map->text)) { - return enum_map->value; - } - enum_map++; - } - return default_value; -} diff --git a/src/game/console/cmd/config.c b/src/game/console/cmd/config.c index ef184fc..e752bf7 100644 --- a/src/game/console/cmd/config.c +++ b/src/game/console/cmd/config.c @@ -92,12 +92,9 @@ static bool M_GetCurrentValue( snprintf(target, target_size, "%.2f", *(double *)option->target); break; case COT_ENUM: - for (const ENUM_STRING_MAP *enum_map = option->param; - enum_map->text != NULL; enum_map++) { - if (enum_map->value == *(int32_t *)option->target) { - strncpy(target, enum_map->text, target_size); - } - } + snprintf( + target, target_size, "%s", + EnumMap_ToString(option->param, *(int32_t *)option->target)); break; } return true; @@ -149,16 +146,16 @@ static bool M_SetCurrentValue( break; } - case COT_ENUM: - for (const ENUM_STRING_MAP *enum_map = option->param; - enum_map->text != NULL; enum_map++) { - if (String_Equivalent(enum_map->text, new_value)) { - *(int32_t *)option->target = enum_map->value; - return true; - } + case COT_ENUM: { + const int32_t new_value_typed = + EnumMap_Get(option->param, new_value, -1); + if (new_value_typed != -1) { + *(int32_t *)option->target = new_value_typed; + return true; } break; } + } return false; }