diff --git a/.gitmodules b/.gitmodules index c27065533de..ef1e15bf7b6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,9 +31,9 @@ [submodule "third_party/capstone"] path = third_party/capstone url = https://github.com/xenia-project/capstone.git -[submodule "third_party/cpptoml"] - path = third_party/cpptoml - url = https://github.com/skystrife/cpptoml.git +[submodule "third_party/tomlplusplus"] + path = third_party/tomlplusplus + url = https://github.com/marzer/tomlplusplus.git [submodule "third_party/cxxopts"] path = third_party/cxxopts url = https://github.com/jarro2783/cxxopts.git diff --git a/premake5.lua b/premake5.lua index 6739d6dba19..a4a720a83fa 100644 --- a/premake5.lua +++ b/premake5.lua @@ -246,7 +246,7 @@ workspace("xenia") include("third_party/dxbc.lua") include("third_party/discord-rpc.lua") include("third_party/cxxopts.lua") - include("third_party/cpptoml.lua") + include("third_party/tomlplusplus.lua") include("third_party/FFmpeg/premake5.lua") include("third_party/fmt.lua") include("third_party/glslang-spirv.lua") diff --git a/src/xenia/base/cvar.cc b/src/xenia/base/cvar.cc index 219f033aeaf..d5d3685c456 100644 --- a/src/xenia/base/cvar.cc +++ b/src/xenia/base/cvar.cc @@ -101,7 +101,7 @@ void ParseLaunchArguments(int& argc, char**& argv, } } -namespace toml { +namespace toml_internal { std::string EscapeBasicString(const std::string_view view) { std::string result; @@ -202,7 +202,7 @@ std::string EscapeString(const std::string_view view) { if (xe::utf8::find_any_of(view, escape_chars) == std::string_view::npos) { return "'" + std::string(view) + "'"; } else { - return "\"" + toml::EscapeBasicString(view) + "\""; + return "\"" + toml_internal::EscapeBasicString(view) + "\""; } } else { // multi line @@ -210,11 +210,12 @@ std::string EscapeString(const std::string_view view) { xe::utf8::find_first_of(view, u8"'''") == std::string_view::npos) { return "'''\n" + std::string(view) + "'''"; } else { - return u8"\"\"\"\n" + toml::EscapeMultilineBasicString(view) + u8"\"\"\""; + return u8"\"\"\"\n" + toml_internal::EscapeMultilineBasicString(view) + + u8"\"\"\""; } } } -} // namespace toml +} // namespace toml_internal } // namespace cvar diff --git a/src/xenia/base/cvar.h b/src/xenia/base/cvar.h index 61b8faf113e..710efc5b39a 100644 --- a/src/xenia/base/cvar.h +++ b/src/xenia/base/cvar.h @@ -15,9 +15,9 @@ #include #include -#include "third_party/cpptoml/include/cpptoml.h" #include "third_party/cxxopts/include/cxxopts.hpp" #include "third_party/fmt/include/fmt/format.h" +#include "third_party/tomlplusplus/include/toml++/toml.hpp" #include "xenia/base/assert.h" #include "xenia/base/filesystem.h" #include "xenia/base/platform.h" @@ -29,7 +29,7 @@ namespace cvar { -namespace toml { +namespace toml_internal { std::string EscapeString(const std::string_view str); } @@ -48,8 +48,8 @@ class IConfigVar : virtual public ICommandVar { virtual const std::string& category() const = 0; virtual bool is_transient() const = 0; virtual std::string config_value() const = 0; - virtual void LoadConfigValue(std::shared_ptr result) = 0; - virtual void LoadGameConfigValue(std::shared_ptr result) = 0; + virtual void LoadConfigValue(const toml::node* result) = 0; + virtual void LoadGameConfigValue(const toml::node* result) = 0; virtual void ResetConfigValueToDefault() = 0; }; @@ -87,8 +87,8 @@ class ConfigVar : public CommandVar, virtual public IConfigVar { const std::string& category() const override; bool is_transient() const override; void AddToLaunchOptions(cxxopts::Options* options) override; - void LoadConfigValue(std::shared_ptr result) override; - void LoadGameConfigValue(std::shared_ptr result) override; + void LoadConfigValue(const toml::node* result) override; + void LoadGameConfigValue(const toml::node* result) override; void SetConfigValue(T val); void SetGameConfigValue(T val); // Changes the actual value used to the one specified, and also makes it the @@ -146,24 +146,24 @@ inline void CommandVar::LoadFromLaunchOptions( SetCommandLineValue(value); } template -void ConfigVar::LoadConfigValue(std::shared_ptr result) { - SetConfigValue(*cpptoml::get_impl(result)); +void ConfigVar::LoadConfigValue(const toml::node* result) { + SetConfigValue(result->value().value()); } template <> inline void ConfigVar::LoadConfigValue( - std::shared_ptr result) { + const toml::node* result) { SetConfigValue( - xe::utf8::fix_path_separators(*cpptoml::get_impl(result))); + xe::utf8::fix_path_separators(result->as_string()->value_or(""))); } template -void ConfigVar::LoadGameConfigValue(std::shared_ptr result) { - SetGameConfigValue(*cpptoml::get_impl(result)); +void ConfigVar::LoadGameConfigValue(const toml::node* result) { + SetGameConfigValue(result->value().value()); } template <> inline void ConfigVar::LoadGameConfigValue( - std::shared_ptr result) { + const toml::node* result) { SetGameConfigValue( - xe::utf8::fix_path_separators(*cpptoml::get_impl(result))); + xe::utf8::fix_path_separators(result->as_string()->value_or(""))); } template CommandVar::CommandVar(const char* name, T* default_value, @@ -215,12 +215,12 @@ inline std::string CommandVar::ToString(bool val) { } template <> inline std::string CommandVar::ToString(std::string val) { - return toml::EscapeString(val); + return toml_internal::EscapeString(val); } template <> inline std::string CommandVar::ToString( std::filesystem::path val) { - return toml::EscapeString( + return toml_internal::EscapeString( xe::utf8::fix_path_separators(xe::path_to_utf8(val), '/')); } diff --git a/src/xenia/config.cc b/src/xenia/config.cc index dcdc5ac2b58..d3a641cde80 100644 --- a/src/xenia/config.cc +++ b/src/xenia/config.cc @@ -9,8 +9,8 @@ #include "config.h" -#include "third_party/cpptoml/include/cpptoml.h" #include "third_party/fmt/include/fmt/format.h" +#include "third_party/tomlplusplus/include/toml++/toml.hpp" #include "xenia/base/assert.h" #include "xenia/base/cvar.h" #include "xenia/base/filesystem.h" @@ -18,23 +18,8 @@ #include "xenia/base/string.h" #include "xenia/base/string_buffer.h" -std::shared_ptr ParseFile( - const std::filesystem::path& filename) { - std::ifstream file(filename); - if (!file.is_open()) { - throw cpptoml::parse_exception(xe::path_to_utf8(filename) + - " could not be opened for parsing"); - } - // since cpptoml can't parse files with a UTF-8 BOM we need to skip them - char bom[3]; - file.read(bom, sizeof(bom)); - if (file.fail() || bom[0] != '\xEF' || bom[1] != '\xBB' || bom[2] != '\xBF') { - file.clear(); - file.seekg(0); - } - - cpptoml::parser p(file); - return p.parse(); +toml::parse_result ParseFile(const std::filesystem::path& filename) { + return toml::parse_file(xe::path_to_utf8(filename)); } CmdVar(config, "", "Specifies the target config to load."); @@ -51,14 +36,13 @@ std::filesystem::path config_folder; std::filesystem::path config_path; std::string game_config_suffix = ".config.toml"; -std::shared_ptr ParseConfig( - const std::filesystem::path& config_path) { +toml::parse_result ParseConfig(const std::filesystem::path& config_path) { try { return ParseFile(config_path); - } catch (cpptoml::parse_exception e) { + } catch (toml::parse_error& e) { xe::FatalError(fmt::format("Failed to parse config file '{}':\n\n{}", xe::path_to_utf8(config_path), e.what())); - return nullptr; + return toml::parse_result(); } } @@ -67,7 +51,7 @@ void ReadConfig(const std::filesystem::path& file_path, if (!cvar::ConfigVars) { return; } - const auto config = ParseConfig(file_path); + const toml::table config = ParseConfig(file_path); // Loading an actual global config file that exists - if there's no // defaults_date in it, it's very old (before updating was added at all, thus // all defaults need to be updated). @@ -77,9 +61,12 @@ void ReadConfig(const std::filesystem::path& file_path, defaults_date_cvar->SetConfigValue(0); for (auto& it : *cvar::ConfigVars) { auto config_var = static_cast(it.second); - auto config_key = config_var->category() + "." + config_var->name(); - if (config->contains_qualified(config_key)) { - config_var->LoadConfigValue(config->get_qualified(config_key)); + toml::path config_key = + toml::path(config_var->category() + "." + config_var->name()); + + const auto config_key_node = config.at_path(config_key); + if (config_key_node) { + config_var->LoadConfigValue(config_key_node.node()); } } uint32_t config_defaults_date = defaults_date_cvar->GetTypedConfigValue(); @@ -96,9 +83,12 @@ void ReadGameConfig(const std::filesystem::path& file_path) { const auto config = ParseConfig(file_path); for (auto& it : *cvar::ConfigVars) { auto config_var = static_cast(it.second); - auto config_key = config_var->category() + "." + config_var->name(); - if (config->contains_qualified(config_key)) { - config_var->LoadGameConfigValue(config->get_qualified(config_key)); + toml::path config_key = + toml::path(config_var->category() + "." + config_var->name()); + + const auto config_key_node = config.at_path(config_key); + if (config_key_node) { + config_var->LoadConfigValue(config_key_node.node()); } } XELOGI("Loaded game config: {}", xe::path_to_utf8(file_path)); diff --git a/third_party/cpptoml b/third_party/cpptoml deleted file mode 160000 index fededad7169..00000000000 --- a/third_party/cpptoml +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fededad7169e538ca47e11a9ee9251bc361a9a65 diff --git a/third_party/tomlplusplus b/third_party/tomlplusplus new file mode 160000 index 00000000000..30172438cee --- /dev/null +++ b/third_party/tomlplusplus @@ -0,0 +1 @@ +Subproject commit 30172438cee64926dc41fdd9c11fb3ba5b2ba9de diff --git a/third_party/cpptoml.lua b/third_party/tomlplusplus.lua similarity index 78% rename from third_party/cpptoml.lua rename to third_party/tomlplusplus.lua index 5e7d6d74a5e..25860b01c53 100644 --- a/third_party/cpptoml.lua +++ b/third_party/tomlplusplus.lua @@ -1,5 +1,5 @@ group("third_party") -project("cpptoml") +project("tomlplusplus") uuid("1e86cc51-3f8b-476d-9249-3b200424846b") if os.istarget("android") then -- ndk-build only supports StaticLib and SharedLib. @@ -9,5 +9,5 @@ project("cpptoml") end language("C++") files({ - "cpptoml/include/cpptoml.h", + "tomlplusplus/include/toml++/toml.hpp" })