diff --git a/FEXCore/Source/Interface/Config/Config.cpp b/FEXCore/Source/Interface/Config/Config.cpp index dba0ba687..0394e12d6 100644 --- a/FEXCore/Source/Interface/Config/Config.cpp +++ b/FEXCore/Source/Interface/Config/Config.cpp @@ -38,8 +38,16 @@ namespace detail { #define OPT_STRARRAY(group, enum, json, default) OPT_STR(group, enum, json, default) #define OPT_STRENUM(group, enum, json, default) const uint64_t P(enum) = FEXCore::ToUnderlying(P(default)); #include + constexpr static std::array option_names = { +#define OPT_BASE(type, group, enum, json, default) #json, +#include + }; } // namespace detail +std::string_view GetConfigJSONName(FEXCore::Config::ConfigOption option) { + return FEXCore::Config::detail::option_names[option]; +} + enum Paths { PATH_DATA_DIR_LOCAL = 0, PATH_DATA_DIR_GLOBAL, @@ -511,4 +519,44 @@ void Value::GetListIfExists(FEXCore::Config::ConfigOption Option, StringArray } } template void Value::GetListIfExists(FEXCore::Config::ConfigOption Option, StringArrayType* List); + +fextl::string SerializeForCache() { + fextl::string Config {}; + + auto append_string_triple = [](fextl::string& Config, std::string_view Key, ConfigOption Option, auto Value) { + Config.append(Key); + Config.append(1, '\0'); + Config.append(fextl::fmt::format("{}", FEXCore::ToUnderlying(Option))); + Config.append(1, '\0'); + Config.append(fextl::fmt::format("{}", Value)); + Config.append(1, '\0'); + }; + + const auto SerializeValue = [&Config, append_string_triple](auto ConfigVal, const auto Default) { + if constexpr (Option == ConfigOption::CONFIG_ENV || Option == ConfigOption::CONFIG_HOSTENV || Option == ConfigOption::CONFIG_ADDITIONALARGUMENTS || + Option == ConfigOption::CONFIG_APP_CONFIG_NAME || Option == ConfigOption::CONFIG_APP_FILENAME || + Option == ConfigOption::CONFIG_IS64BIT_MODE || Option == ConfigOption::CONFIG_INTERPRETER_INSTALLED || + Option == ConfigOption::CONFIG_DISABLE_VIXL_INDIRECT_RUNTIME_CALLS || Option == ConfigOption::CONFIG_HOSTFEATURES) { + // Skip environment variables, meta arguments, and HostFeatures. + return; + } + + append_string_triple(Config, FEXCore::Config::GetConfigJSONName(Option), Option, ConfigVal()); + }; + +#define OPT_BASE(type, group, enum, json, default) \ + SerializeValue.template operator()(FEXCore::Config::Get_##enum(), default); +#define OPT_STR(group, enum, json, default) \ + SerializeValue.template operator()(FEXCore::Config::Get_##enum(), default); +#define OPT_STRARRAY(group, enum, json, default) // Unsupported. +#define OPT_STRENUM(group, enum, json, default) // Unsupported. +#include + return Config; +} + +FEX_DEFAULT_VISIBILITY bool CheckConfigMatches(std::string_view Config) { + // Serialize current config and just check if it matches. + return SerializeForCache() == Config; +} + } // namespace FEXCore::Config diff --git a/FEXCore/include/FEXCore/Config/Config.h b/FEXCore/include/FEXCore/Config/Config.h index dae94634c..eb09f21a3 100644 --- a/FEXCore/include/FEXCore/Config/Config.h +++ b/FEXCore/include/FEXCore/Config/Config.h @@ -36,6 +36,7 @@ namespace Handler { enum ConfigOption { #define OPT_BASE(type, group, enum, json, default) CONFIG_##enum, #include + CONFIG_MAX, }; #define ENUMDEFINES @@ -230,6 +231,8 @@ FEX_DEFAULT_VISIBILITY std::optional GetConv(ConfigOption Option); FEX_DEFAULT_VISIBILITY std::optional Get(ConfigOption Option); FEX_DEFAULT_VISIBILITY void Set(ConfigOption Option, std::string_view Data); FEX_DEFAULT_VISIBILITY void Erase(ConfigOption Option); +FEX_DEFAULT_VISIBILITY fextl::string SerializeForCache(); +FEX_DEFAULT_VISIBILITY bool CheckConfigMatches(std::string_view Config); template class FEX_DEFAULT_VISIBILITY Value {